Bienvenue sur JeuxOnLine - MMO, MMORPG et MOBA !
Les sites de JeuxOnLine...
 

Panneau de contrôle

Recherche | Retour aux forums

JOL Archives

Procto, au sujet des udf...

Par miriandel le 9/11/2002 à 0:14:13 (#2517261)

Donc en rapport avec ce post que Raistlin s'est amusé à saloper *brandit le poing*

Au sujet des executescript, nous somme bien d'accord. C'est de la programmation spaghetti qui n'apporte rien, à éviter.

Au sujet de l'analyse de Bioware (David, mais un codeur de préférence) au sujet des udf, fais-moi un plaisir, retrouve moi le thread, ça m'intéresse hautement :)

Pour le passage des variables par les Delaycommand, je ne suis pas convaincu qu'il y ait passage de variables, bien au contraire.
Réfléchissons ensemble.
Les variables dont les objets ont besoin de manière récurrente sont stockées sur eux, dans leur structure d'objet, il n'y a aucune nécessité de les "recopier". Personnellement, j'en utilise d'ailleurs fort peu, puisque toute ma programmation est basée sur des événements.
Les DelayCommand/SignalEvent ne passent que des numéros d'udf, qui sont stockés dans la pile d'événements avec seulement deux paramètres: l'objet auquel ils se rapportent, et le numéro d'udf. Pour cette raison, je pense très sérieusement qu'une ohb est un udf retardé de 6 secondes, ni plus, ni moins.
Si tu as une référence de post donnant des informations à ce sujet, je serais intéréssé de le lire.

Mais tu n'as pas répondu sur le sujet principal de ma réponse, à savoir la structure en moteur de base de données de la gestion de la pile.
Si j'étais à leur place (oh que je voudrais bien :p ), c'est ainsi que je procéderais, et tout me porte à croire que c'est le cas.
Ce serait de la programmation à la fois très élégante, et très performante.

Dans tous les cas de figure, je ne connaîs aucun autre moyen que les udf pour programmer la complexité des actions que je gère dans le temps, j'ose espérer que leur code est propre et fiable, sinon... on est pas dans la merde :monstre:

Par LeProctophantasmiste le 9/11/2002 à 2:24:12 (#2517785)


Au sujet de l'analyse de Bioware (David, mais un codeur de préférence) au sujet des udf, fais-moi un plaisir, retrouve moi le thread, ça m'intéresse hautement


Tu veux dire les messages que j'ai mentionnés au sujet de FRED sur le forum de NWVault? Franchement tu n'y apprendrais rien (en plus tu verrais ce que je proposais et cette idée ne m'enchante pas :o), les information, comme les réflexions sont un peu ...datées . Il n'y avait que David qui intervenait, c'était avant même la sorti du bêta toolset... Si tu y tiens absolument j'ai peur que tu ne doives lire tous les messages du forum officiel de script de NWVault en partant des plus anciens (plus faire le tri parmi les persistants où David donnait les infos), il n'y a pas tant de fil que ça mais ils concernent tous le sujet en question :D. FRED était (au moins pendant le temps durant lequel je l'ai suivi) une monstruosité qui passait son temps à aller vérifier la valeur de LocalInts via son OnHeartBeat pour savoir ce qu'il devait faire à un instant donné, remarque que bien que j'étais vigoureusement opposé à cette approche, mes quelques propositions n'avaient ni queue ni tête, si je me souviens bien, j'ai même fini par abandonner et me ranger à l'opinion dominante :D.


Pour le passage des variables par les Delaycommand, je ne suis pas convaincu qu'il y ait passage de variables, bien au contraire.


Pardon, j'ai été très peu clair aucune variable n'est passé jusqu'a l'UDE. Par contre elles sont passées au DelayCommand pour l'exécution du code qui se trouve à l'intérieur, d'avance, pardonne moi pour l'horreur que je vais écrire mais au moins cela à la mérite d'être clair pour tout ceux qui pourrait lire ce message, je pense:


int i;

void AssignI()
{
--i;
SendMessageToPC(GetFirstPC(), IntToString(i));
}
void SendI()
{
SendMessageToPC(GetFirstPC(), IntToString(i));
}
void main()
{
i = 2;
DelayCommand(1.0f, AssignI());
DelayCommand(2.0f, SendI());
}


A l'exécution de ce script le PJ recevra le message "1" puis le message "2". La variable i a donc été passée au DelayCommands avec la valeur qu'elle avait au moment de l'appel. Quelqu'un de chez Bioware avait signalé il y a quelque temps que l'état d'un script était sauvegardé pour les DelayCommand et ActionDoCommand.
La question est de savoir si le moteur fait cela pour toutes les variables ou seulement pour celles qui sont utilisées à l'intérieur du DelayCommand, supprimer toutes les variables non utilisées ne serait pas possible (puisque pour savoir lesquels ce sont il faudrait exécuter le code) en revanche un analyseur syntaxique pourrait peut-être limiter les dégâts ( ne serait-ce qu'en ne passant pas celles dont le nom n'est même pas utilisé) mais compliquerait un peu la phase de compilation pour l'analyse, et surtout il faudrait une implémentation du DelayCommand et du passage de variable qui en tienne compte, le gain au final ne serait peut-être pas évident (mais là je parle vraiment sans savoir). Je crois d'ailleurs que la plupart des langages laissent ce problème à l'utilisateur, c'est lui qui doit demander le passage de variables. Bref selon Torlack ce n'est pas fait, comme c'est invérifiable par quelqu'un qui n'a pas mis les mains dans le cambouis, et que son compilateur est assez nettement plus performant que celui de Bioware, je n'ai pas d'autre choix que de le croire :D.

Tout ça pour dire que les UDFs ne sont pas en cause en eux même, ce sont les DelayCommand et ActionDoCommand, en particulier dans le cas d'appels récursifs qui posent problème.


Si j'étais à leur place (oh que je voudrais bien ), c'est ainsi que je procéderais, et tout me porte à croire que c'est le cas.
Ce serait de la programmation à la fois très élégante, et très performante.

Dans tous les cas de figure, je ne connaîs aucun autre moyen que les udf pour programmer la complexité des actions que je gère dans le temps, j'ose espérer que leur code est propre et fiable, sinon... on est pas dans la merde


Pour la structure de la pile d'événement je te fais confiance, étant donné que je n'en sais rien :D, ton explication parait claire, maintenant mes expériences les plus avancées de programmation c'était du LISP et du PROLOG (et javascript/PHP aussi :bouffon:) donc je ne suis pas certain d'être un très bon juge pour ce genre d'algorithme. En revanche je ne vois pas très bien pourquoi cela rendrait l'appel d'un UDF intrinsèquement plus efficace que celui du OnHeartBeat. Encore une fois je suis d'accord pour dire "ne faisons pas n'importe quoi avec le OnHeartBeat", mais si c'est pour faire des appels récursifs de DelayCommand à la place, je ne vois pas bien l'intérêt(je ne m'adresse pas à toi là, c'est juste que le conseil général "n'abusez pas du OnHeartbeat" peut avoir des conséquences aussi désastreuse que la vache folle en a eu sur la consommation du boeuf). Au moins, avec le OnHeartbeat, c'est fait proprement. Je crois que le meilleur conseil c'est de réfléchir à une structure adaptée à ce que l'on veut faire et non pas de réappliquer systématiquement la même méthode. Autrement dit que la structure des scripts reflète ce que l'on veut faire (la c'est mon côté théorie des modèles qui ressort), je me rend bien compte que c'est précisément ce que tu fais, tout ce que je dis c'est que si on a besoin d'une horloge, on peut en faire une avec un OnHeartBeat.

Pour les ListenningPattern et les SilentShout j'ai l'impression que c'est en général assez peu utilisé dans les scripts de type IA que produit la communauté, pourtant cela fait du code propre et compréhensible (quand on travaille sur plusieurs objets à la fois bien entendu) un cri pour donner un ordre cela me semble approprié, quant à l'efficacité, encore une fois je préfère utiliser les algos de Bioware plutôt que d'avoir à parser des listes d'objets "à la main".

Il est vraiment tard là, et je n'ai presque plus assez de volonté pour m'arrêter d'écrire.
Bonne nuit

Par miriandel le 9/11/2002 à 11:21:37 (#2518604)

Ok, je comprends mieux ce que tu veux dire :eureka:

En fait, tu as parfaitement raison sur la sauvegarde de paramètres temporaires quand ils sont passés dans un DelayCommand. Comme ils n'existent que dans le scope de la fonction qui les crée, ils doivent être "mis de côté" pour quand la commande s'exécutera réellement.

En ce qui concerne les variables stockées sur les objets (donc les commandes SetLocalxxx ), elles fonctionnent comme des "List" en Object Pascal. Ces "List" sont des récipients de pointeurs.
Quand tu assignes une variable locale à un objet, la "List" de cet objet s'agrandit d'un élément qui est lui-même un objet pointant vers une zone mémoire. A partir de là, on peut considérer ces variables comme globales, il n'est donc plus nécessaires de les manipuler, quel que soit le segment de code où elles sont utilisées.
Dans ton exemple du SpeakString, en revanche, le texte à énoncer n'est pas un objet et doit être traité différemment, et c'est vrai que cela peut être lourd, car mal structuré, donc non optimisé.
Dans le cas d'un udf event, un objet de type "event" est créé contenant un timestamp (moment d'exécution) et un entier (numéro d'événement).

Encore une fois, je n'ai pas écrit ce compilateur, c'est juste mon expérience de la programmation objet qui me pousse à croire ça, et l'omniprésence des structures de type événement dans Aurora.
C'est d'ailleurs bien Bioware qui parle "d'event queue" et de priorisation dans les événements.

C'est pour cela (et je ne moquais pas de toi :p ) que j'ai avancé que la OnHeartBeat était un udf simplifié, car je ne vois aucune raison logique, si on admet la pile d'événements comme une réalité, que cet événement soit traité différemment des autres.
En fait, tous les événements sont identiques, qu'il s'agisse des événements de combat, de dialogue ou de tout ce qu'on veut.
Ils sont empilés, triés en fonction du moment d'exécution, et exécutés séquentiellement.
Donc oui, je partage totalement ton opinion, la ohb est le moyen le plus simple de répéter une action à intervalle régulier, et ne marque ses limites que lorsque les PNJs sont trop nombreux (perte de cycles CPU) ou que l'on programme une intelligence artificielle.

Mmh... ça devient de plus en plus clair :D

Pour les ListeningPatterns, en suivant le même raisonnement, chaque objet de la zone capable d'écouter (et là, si 15 créatures sont présentes, ça commence à multiplier !), reçoit un événement chaque fois que quelqu'un parle, ce qui génère pas mal de checks inutiles, à première vue.
Mais j'aime bien les listening patterns quand même, c'est la solution la plus élégante pour les mots de pouvoirs, et carrément la seule pour les énigmes où tu dois énoncer une solution non suggérée.

Tu travailles sur quoi toi pour le moment *à tout hasard* ? :ange:

Par LeProctophantasmiste le 9/11/2002 à 15:07:25 (#2519784)


Pour les ListeningPatterns, en suivant le même raisonnement, chaque objet de la zone capable d'écouter (et là, si 15 créatures sont présentes, ça commence à multiplier !), reçoit un événement chaque fois que quelqu'un parle, ce qui génère pas mal de checks inutiles, à première vue.

Ha, Ha, non, l'événement OnConversation n'est lancé que si le pattern est reconnu. Je me rend bien compte que cela veut dire que les objets sont parsés, d'une façon ou d'une autre, et que la phrase "entendue" est comparée aux patterns fixées, mais aucun code utilisateur n'est exécuté. Dans la plupart des cas l'autre option sera de parser la liste d'objet à la recherche de ceux que l'on veut commander et de lancer des SignalEvent, donc si l'alternative est GetNearestObject... ou GetFirstObjectInShape/Area je préfère les ListeningPattern, qui en plus peuvent passer l'info de manière intelligente.
En gros pour moi cela s'applique au situation dans lesquels Bioware l'utilise (quelle surprise :D) du genre SHOUT_ATTACK_MY_TARGET, ou l'on veut un effet local. Il est vrai que dans le cas de SHOUT_ATTACK tous les PNJs "entendent" le cri et regardent ensuite dans leur OnConversation s'ils doivent réagir (en fonction de leur relation à celui qui a crié), mais ce n'est pas obligatoire, on peut singulariser les patterns... GetLastShouter est à la fois un bon point et un inconvénient des patterns, l'objet qui crie est "passé" (alloc dynamique en fait heureusement, mais bon c'est du détail :D) au OnConversation, mais encore une fois au moins c'est fait de façon efficace: avec GetLastShouter (et tous les GetLast... dans les événements) je pense que l'on a l'équivalent d'un pointeur (tu dirais peut-être une méthode du module :D, mais je suis un peu hésitant à parler comme ça, car si il y a des traces d'orientation objet qui reste dans NWScript, le tout fait plutôt une structure originale).
Pour donner un exemple un peu concret je ne sais pas si tu as vu le post mais je cherche (un peu passivement faute de solution très satisfaisante) à implémenter un système de faction plus souple. Pour ce qui est des effets locaux, j'utiliserais des pattern pour prévenir les témoins du type LAW_SHOUT_*n ou le *n récupère le type d'action commise (codée, à l'origine du moins, en bit à bit, pour pouvoir flagger les PC), on peut aussi décliner la racine du cri selon la faction de l'émetteur. Du point de vue local, mon système à l'air de bien marcher, je n'ai pas fait de test complet ou à grande échelle néanmoins, c'est la question de la mémoire des actions des PJs qui me pose plus de problème.

Sinon pour ce que je fais, je me suis un peu remis à mon projet d'origine, à moitié découragé car le truc est énorme et que je change le scénario tout les quatre matins parce quelque chose ne me plaît plus :bouffon: . Je suis aussi sensé aider quelqu'un à mettre en place la base de scripts de son module (reste assis, avec le HCR, mais tout ce qu'il m'a demandé comme personnalisation pour l'instant c'est d'enlever des trucs, ça me semble une bonne approche :D) Si tu disais ça pour me débaucher, auquel cas j'en suis flatté, je finirais peut-être par craquer (j'ai failli plusieurs fois) et essayer de rejoindre une équipe de module permanent, mais des équipes comme celle là il en existe déjà pas mal. Je me fais peut-être une fausse idée sur ce que sont les modules permanents, mais a priori je serais plus intéressé par un scénario qui se concentre autant sur les joueurs que sur le développement d'un monde. J'aurais préférer rejoindre, ou co-créer, une équipe qui ferait des modules non permanents (campagnes...) avec pour but de les distribuer, sur le modèle de ce que l'on a vu pour le moteur Infinity (pas en France...). J'ai lancé cet appel plusieurs fois, sans succès...

Par miriandel le 9/11/2002 à 15:14:49 (#2519817)

Le développement d'un monde permanent, soyons clairs, c'est l'enfer.

Et encore davantage si les développeurs ne sont pas très à l'aise dans Aurora.

Donc, les places ouvertes dans Althea sont réservées à des gens qui ont prouvé autant leur intérêt pour le JDR que pour Aurora.
Notre objectif est de tout mettre dans ce module.
Des systèmes fondamentaux, comme l'artisanat et le housing (déjà fait ça), mais aussi des quêtes qui ont un sens plus profond que "va chercher le petit pot de beurre et apporte-le à mère grand", si tu vois ce que je veux dire.

De plus, faut pas se leurrer, ça demande des disponiblités, sinon le temps que tu comprennes ce qui se passe dans l'équipe, il ne t'en reste plus pour produire les résultats.

Faut être un peu :rasta: pour se lancer dans un brol pareil...

JOL Archives 1.0.1
@ JOL / JeuxOnLine