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

Panneau de contrôle

Recherche | Retour aux forums

JOL Archives

Interaction entre script et conversation

Par Le Hamster le 19/9/2002 à 14:18:53 (#2188204)

Un PNJ s'occupe en attendant le client. En clair, il est animé par un petit script qui tourne en boucle. (voir ci dessous). Or ce PNJ est primordial dans l'histoire. Les dialogues avec lui sont donc assez importants (taille et intrigue).

Quand un PJ vient parler avec Ce PNJ, pas de problème le dialogue démarre (conversation). Mais en cours de dialogue, le script d'animation continue et interrompt le dialogue en cours. De plus il faut un temps avant que le script ne refonctionne normalement (en l'occurence, tant que le perso ne lance pas wall of fire, il fait les gestes mais reste muet et ne lance ni magic missile ni fireball).

Je précise que ce dialogue est initié dans celui par défaut du PNJ, que le script est sur le OnSpawn.

void main()
{
object oTarget = GetNearestObjectByTag("Toto");

ClearAllActions();
ActionCastSpellAtObject(SPELL_MAGIC_MISSILE, oTarget);
ActionSpeakString("J'aime bien ! C'est beau! ");

DelayCommand(15.0,ExecuteScript("laure_boule2",OBJECT_SELF));
}

"Toto" est un dummy.

Le script "laure_boule2" est le même que celui-ci (mais avec sort fireball), il lance "boule 3" (wall of fire), qui relance à son tour le script ci dessus. D'où la boucle d'animation. Le speakstring est différent pour chaque script (mais bon, ça on, s'en fout)

Voilà, je rajoute que la case "No interrupt" cochée ou pas ne change rien à l'affaire.

D'ailleurs c'est quoi "no interrupt" ?

C'est quoi que j'ai oublié dans un coin ?


Bises à toutes et à tous.

ooooooooinnnnnnnnnnnnnnn

Par Le Hamster le 20/9/2002 à 13:55:27 (#2194855)

Elles sont si nulles que ça mes questions que personne y répond ?

Par miriandel le 20/9/2002 à 14:24:43 (#2195052)

Je vois un gros problème dans ton approche, elle est procédurale, pas événementielle.

Pour tout ce qui implique de la cinématique, utilise les userdefined events, tu n'auras aucun problème, d'aucune sorte, et tu éviteras de tuer le serveur avec des OnHeartBeat qui bouffent du CPU même quand y a pas un chat dans la zone.

Par exemple, lorsque ton PJ entre dans la zone (event OnEnter de la zone), envoie un événement à ton PNJ.

Dans le script des UserDefined Events de ton PNJ, tu n'as plus qu'a créer autant d'événements que ton PNJ exécute d'actions, et à lui faire s'envoyer à lui-même des userdefined en fonction de ce qui se passe.

Si tu veux voir un exemple simple, regarde l'animation de mines que j'ai postée sur ce board y a pas longtemps (pas plus de dix jours).

A première vue, l'approche "user defined events" a l'air lourde, mais:
1° C'est la plus légère pour le processeur
2° C'est la seule qui permette de découper les actions en phases de temps
3° C'est la plus élégante, et donc la plus lisible.
4° C'est la plus facile à maintenir dans le temps.

Par Fredegar le 20/9/2002 à 14:25:03 (#2195054)

Bon je ne sais pas si ce que je vais te dire te conviendra mais je pense qu'il faut que tu mettes un script dans ta conversation. Ainsi dans le "Action Taken" de la première phrase de la conversation tu mets un simple script :


void main
{
ClearAllActions();
}


A+

Par Sempai le 20/9/2002 à 14:25:06 (#2195056)

"no interrupt" signifie qu'on ne peut pas quitter la conversation tant qu'elle n'est pas finie. Autrement dit, s'éloigner de son interlocuteur ne suffit pas, il faut terminer la conversation.

void main()
{
object oTarget = GetNearestObjectByTag("Toto");

ClearAllActions();
ActionCastSpellAtObject(SPELL_MAGIC_MISSILE, oTarget);
ActionSpeakString("J'aime bien ! C'est beau! ");

DelayCommand(15.0,ExecuteScript("laure_boule2",OBJECT_SELF));
}

A mon avis, le problème vient du "ClearAllActions" qui ordonne au PNJ de cesser de dialoguer. Si les autres scripts sont identiques, la conversation s'arrêtera d'elle-même si elle dure plus de 15 secondes (cf ligne "DelayCommand(15.0, [...]")

Je suppose qu'ajouter un "if (le personnage n'est pas en conversation)" juste avant le "ClearAllActions();", comme suit


void main()
{
object oTarget = GetNearestObjectByTag("Toto");

if (le personnage n est pas en conversation)
{
ClearAllActions();
ActionCastSpellAtObject(SPELL_MAGIC_MISSILE, oTarget);
ActionSpeakString("J aime bien ! C'est beau! ");
}

DelayCommand(15.0,ExecuteScript "laure_boule2",OBJECT_SELF));
}

Par miriandel le 20/9/2002 à 14:29:26 (#2195093)

Tiens, voilà le link sur le module de démo

ah lala

Par Le Hamster le 22/9/2002 à 14:30:50 (#2209508)

Merci d'avoir répondu. Malheureusement, j'ai essayé les solutions de Fredegar et Sempaï sans succès. Miriandel, j'avais déjà vu ta démo (je lis tout et essaye tout ce que je peux), mais je joue dans la catégorie "Nullard invétéré". Je ne suis qu'un vieux machin dépassé par tout ça. Je suis incapable de mettre en oeuvre ta solution.

Bon, on s'en fout de mes états d'âme.

Moi, j'ai essayé de virer tous les scripts (mis à part le mien) du NPC : même résultat.

J'ai essayé de virer les delay command de mes scripts en mettant des actionwait et des Do machin et des assign trucs bref tout des trucs que j'y comprends rien. et bien sûr, ça ne donne rien.

On rigole bien hein ?


Bon, quelqu'un a-t-il une idée de ce que je peux faire ? Cause que : j'aime bien mon animation et deuze j'aime bien mon dialogue !!! et je veux les deux !!!

Voili voilà.


Bises à toutes et à tous.

Par miriandel le 22/9/2002 à 15:10:53 (#2209799)

Bon.... je vois un truc qui peut t'aider.

Pour éviter que l'animation s'enclenche pendant la conversation, tu peux utiliser la fonction IsInConversation(tonPNJ) et tu n'envoies l'naimation que si le résulat est faux.

Car je suppose que ton animation est placée onHeartBeat.

Euh... entre vieux jetons visiblement, faut s'entr-aider, à ta place je ferais vraiment l'effort de rentrer dans la mécanique des userdefined events, je peux t'assurer que passé les grosses sueurs, tu feras ce que tu veux avec le toolset.
Je dis ça, je dis rien :)

le hamster tu es nul

Par Blam le 22/9/2002 à 17:38:37 (#2211121)

presque autant que moi, j'ai du mal a imprimer :)
viens on va faire un club "le beurre sous la quiche"

bon courage a toi, laisses pas tomber c un tres beau jeu.

puis meme si ce qu'on crée est nul, le fait de créer est génial

:)

après j'embète plus sur ce sujet (peut-être)

Par Le Hamster le 23/9/2002 à 10:37:55 (#2215059)

Ben non, pas d'animation sur le onHeartBeat, y'a assez de posts sur ce forum qui le déconseillent, d'ailleurs, je vire tous les scripts des pnj sur le onheart.

mon scrpit est sur le OnSpawn (je l'avais marqué héhé).

Bon, bref deux choses :

1 -comment écrire les 2 lignes avec le IsInConversation ? où ? faut que je mette un if ? pas de if else ?

2 - JE JURE QUE JE VAIS REESSAYER DE COMPRENDRE LES ONUSERDEFINED (hum, tant pis pour ma santé mentale)

merci !

Bises à toutes et à tous

alllllllllllllllllllllllllllllllllllllooooooo

Par Le Hamster le 25/9/2002 à 9:34:03 (#2227607)

ça doit pas bien beaucoup prendre de temps pour des caïds.
Comment je fais mon if(IsInConversation ) ? ?
Allez, juste une fois, après j'aurais compris (peut-être) !



Miriandel !!! Les UserDefined , Ayé j'ai compris "l'essence" de ce truc ! :monstre:

Mais alors pour en faire un, même petit --> Pffffffffffffffffffffffff :bouffon: :bouffon: :bouffon: :bouffon: :bouffon:


Bises

Par miriandel le 25/9/2002 à 12:29:46 (#2228452)

Ouais, désolé, j'étais en voyage...

Dans l'ordre.

1° Si tu utilises DealyCommand(x.xxf, ExecuteScript("yyy", PJ)) tu te mets dans une boucle infinie.
Le serveur te dit merci :p
Donc, je crois que c'est pas la bonne méthode.

2° Comment résoudre ton problème par userdefined events... je suis au boulot, mais je vais essayer de t'aider de mémoire.

- La première chose que tu dois faire, c'est décider comment tu vas démarrer l'animation de ton PNJ, pour éviter cette boucle.
Je te donne 3 suggestions:
a) Dans l'event "OnEnter" de ta zone, tu mets ceci:
SignalEvent(PNJ, EventUserDefined(2000));
ce qui va signifier au PNJ de commencer sa petite affaire.
b) Tu utilises le "Onperceive" event du PNJ. Moi j'aime pas, c'est pas fiable, et il y a des effets qui peuvent contrarier cela comme invisibilité apr exemple. Mais y en a qui aiment...
La commande resterait la même dès que le PNJ "perçoit" le PJ
c) Tu crées un "generic trigger" autour du PNJ et quand le PJ rentre, ça envoie la commande (toujours la même)

Dans les cas a) et c) tu dois t'assurer que l'événement n'est envoyé qu'une fois. Si une équipe de 10 PJs rentre dans la zone et que chacun envoie un événement, ça va faire un feu d'artifice de tous les diables.
Ce que je fais généralement, c'est incrémenter un compteur dans la routine OnEnter de la zone.
ça donne donc ceci:

// onter event de la zone

void main() {
if (GetIsPC(GetEnteringObject())) {
SetLocalInt(OBJECT_SELF, "compteur", GetLocalInt(OBJECT_SELF, "compteur")+1);
if (GetLocalInt(OBJECT_SELF, "compteur")==1) { // ne provoquer l'action qu'une seule fois
object PNJ = GetObjectByTag("marcel");
SignalEvent(PNJ, EventUserDefined(2000));
}
}
}

// onexit event de la zone

void main() {
if (GetIsPC(GetExitingObject())) {
SetLocalInt(OBJECT_SELF, "compteur", GetLocalInt(OBJECT_SELF, "compteur")-1);
if (GetLocalInt(OBJECT_SELF, "compteur")==0) { // plus personne dans le coin, arreter les frais
object PNJ = GetObjectByTag("marcel");
AssignCommand(PNJ, ClearAllActions()); // Stopper les userdefined events de Marcel.
}
}
}


- Maintenant que ton PNJ a reçu un événement, il faut le traiter.
Tu définis donc dans l'event "Userdefined" du PNJ un truc de ce style:

void main(){
int n = GetUserDefinedEventNumber(); // pour récupérer l'événement reçu
if (n == 2000) {
if (!IsInConversation(OBJECT_SELF)) // si on n'est pas en conversation.
{
// declencher ici ton animation
}
}
// se renvoyer un événement à soi-même
DelayCommand(20.0f, SignalEvent(OBJECT_SELF, EventUserDefined(2000)));}


Bon, je vais pas plus loin pour le moment, dis-moi déjà si ceci t'aide.

Edit: j'arrive pas à placer les {} correctements, je fais du copier-coller de mon éditeur UNIX sur windaube, et il aime pas...

merci merci merci

Par Le Hamster le 25/9/2002 à 13:41:32 (#2228966)

bon, ça marche pas mais c'est puis j'ai un axemple précis maintenant.

J'ai tout recopié tes trois scripts dans mon module. J'ai bien remplacé le Tag "marcel" par le Tag "Laurence" qui est celui du PNJ qui fait des jolis lancers de boules magiques.

Bon, je lui ai viré tous les scripts et mis le suivant dans le OnUserDefined.

J'ai essayé le tout avec un trigger (donc un script sur le OnEnter et l'autre sur le OnExit) rien.
Bon je me dis, "mon pov' chéri (je suis très lié avec moi même), il t'a dit sur le OnEnter de la zone. Bon, je fais ça, résultat >> rien.

Bref, j'en suis venu à penser qu'encore une fois c'est mon animation qui fout le bazar ! (j'ai l'habitude).

Le OnUserDef du PNJ est :

void main(){
int n = GetUserDefinedEventNumber(); // pour récupérer l'événement reçu
if (n == 2000) {
if (!IsInConversation(OBJECT_SELF)) // si on n'est pas en conversation.
{
// declencher ici ton animation
object oTarget = GetNearestObjectByTag("Toto");


ActionCastSpellAtObject(SPELL_MAGIC_MISSILE, oTarget);
ActionSpeakString("Et hop, ouh lala que j'aime !");

DelayCommand(10.0, ActionCastSpellAtObject(SPELL_FIREBALL, oTarget));
DelayCommand(10.2, ActionSpeakString("Et hop, dans ta tronche de cake !"));

DelayCommand(15.0, ActionCastSpellAtObject(SPELL_WALL_OF_FIRE, oTarget));
DelayCommand(15.1, ActionSpeakString("Pourquoi es-tu parti ?"));
DelayCommand(16.0, ActionSpeakString("JE NE SUIS PAS LE MAILLON FAIBLE "));

}
}
// se renvoyer un événement à soi-même
DelayCommand(20.0f, SignalEvent(OBJECT_SELF, EventUserDefined(2000)));}


C'est quoi t'est-ce donc que j'aurai-t-il mal fait ?


Arf, pourtant, je sens que je suis à 2 doigts de pondre un truc MONTHY PYTHONNESQUE !

Bises

Par miriandel le 25/9/2002 à 14:05:12 (#2229150)

Bien... tu vas y arriver, à condition de débugger ton bazar méthodiquement.

Quand tu me dis "ça marche pas", je ne peux évidemment pas savoir où ça ne marche pas, puisque:
1° tu me dis pas ce qui marche pas
2° je suis pas devant ta bécane
3° je n'ai évidemment absolument rien testé de ce que j'ai écrit, piske je fais ça du boulot :chut:

Alors, solution magique et universelle: le debugging.

Tu places cette commande un peu partout:

SendMessageToPC(GetFirstPC(), "test N° xxx"));

Un peu partout veut dire à l'entrée de chacun des scripts.
Tu verras déjà un peu mieux quel code s'exécute, et quel code n'est pas déclenché du tout.

A partir de là, on pourra voir ;)

BOUM Je tombe de ma chaise là... tu as mis le script de sortie de zone dans la sortie de trigger ??
Ah mais mais mais, ça va pas du tout ça, paske dès que tu sors du trigger, tu flingues les événements avec le ClearAllActions() :rasta:

Mets les scripts dans les entrées-sortie de zone, c'est mieux.
Et place les petits pièges :)

quelle difference technique mj ou pas mj

Par Lys le 25/9/2002 à 14:24:07 (#2229299)

quelle difference entre un module avec ou sans maitre de jeu, dans la conception du module ?

mais ...

Par Le Hamster le 25/9/2002 à 18:18:30 (#2230828)

Bon Miriandel, remonte sur ta chaise, c'est pas grave.

1 - Ce qui ne marche pas, c'est que le PNJ ne bouge pas. Donc pas d'animation.

2 - Eh l'ôtre euh, j'ai bien pensé que si le PJ sortait du trigger ça arrêterait tout. Alors sans rire, j'en ai fait un balaise (de trigger) qui englobe le PNJ, comme ça quand le PJ va lui parler il est toujours dans le trigger. Pas con hein , si ? bon, j'écrase.

3 - En fait, j'ai essayé aussi sur le OnEnter de la zone (ou alors je suis fou, c'est possible), le PNJ ne bouge pas plus. Euh dans ce cas de figure, j'avais enlevé le trigger hein !

4 - Je crois que c'est mon animation qui est vérolée. (j'ai tellement confiance en mon savoir programmatif)

5 - je vais essayer le debug, mais bon, je préfère aller acheter de l'aspirine avant.

Plus sérieusement, je trouvais le truc du trigger sympa cause que l'action se situe dans la zone principale de mon module (et qu'il doit y avoir plusieurs endroits où je pourrais utiliser cette solution). Si tout doit se mettre dans le OnEnter de la zone, je vais jamais m'y retrouver.

Si tu as le temps de jeter un oeil sur mon trucmachinbidulechose (script)

Y'a pas un bouquin "Aurora pour les boulets !" ?

Bises.

Par miriandel le 26/9/2002 à 15:27:38 (#2236576)

C'est relax le débug.

Parfois, on fait une connerie insignifiante, qu'on peut passer dessus 100 fois sans la voir.
En mettant des "trace" dans le code, on voit immédiatement ce qui s'exécute ou pas.
Et alors ça saute aux yeux.

JOL Archives 1.0.1
@ JOL / JeuxOnLine