JeuxOnLineForumsPlusConnectés : 806 (sites) | 1459 (forums)Créer un compte
Forum jeux-vidéo>Neverwinter Nights
Maskado
Les forums JOL > Forum jeux-vidéo > Neverwinter Nights > NWN - Maskado > Cours de Scripts pour les Quiches. Leçon Six. RSS
   
Répondre
Partager Outils Rechercher
GrandKhan
Dauphin / Dauphine
 
Code PHP:
// Script « OnUserDefined »
// tm_flechette_ud
// Jeu de flechette
// Appelé par le OnHeartBeat script.
//
// Le joueur de fléchettes lance les dards de son inventaire ( 3 au départ ) 
// Va jusqu'à la cible. Récupère ses dards, revient et recommence.
// 
void main()
{
    
int nAppelePar GetUserDefinedEventNumber();
    
object oCible GetNearestObjectByTag("CIBLE");
    
int nCiblePrete GetLocalInt(OBJECT_SELF"ETATCIBLE");
//
    
switch(nAppelePar)
    {
     case 
1001:  // Appelé par OnHeartbeat
       //
       // nCiblePrete est a 1 si la cible est prête.
       //
       
if ((GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND)))
            && (
nCiblePrete == 1))
          {
             
// Si on a des dards dans la main droite et qu’on est prêt a les lancer, alors faisons le. 
             
ClearAllActions();
             
ActionAttack(oCibleTRUE);
           }
       else
          {
             
// Sinon, soit nous n’avons plus de dards, soit nous sommes déjà en train d’aller les chercher.
if (nCiblePrete == 1)
              {
                
SetLocalInt(OBJECT_SELF"ETATCIBLE"2);
                
ActionMoveToObject(oCible);
                
ActionWait(0.5);
                
ActionPlayAnimation(ANIMATION_LOOPING_GET_MID1.01.0);
                
ActionWait(0.5);
                
ActionPlayAnimation(ANIMATION_LOOPING_GET_MID1.01.0);
                
ActionWait(0.5);
                
ActionPlayAnimation(ANIMATION_LOOPING_GET_MID1.01.0);
                
object oDestination=GetNearestObjectByTag("CIBLEWP001");
                
ActionMoveToObject(oDestination);
                
CreateItemOnObject("nw_wthdt001"OBJECT_SELF3);
                
ActionEquipMostDamagingRanged();
                
ActionDoCommand(SetLocalInt(OBJECT_SELF"ETATCIBLE"1));
              }
            }
       break;
    }

C'est curieux, ça ne marche pas. Le tireur lance ses dards, se dirige vers la cible et la dégaine d'autre dards (premier bug, il ne devrait les sortir qu'après les avoir enlevé de la cible), arrive près de la cible, récupère ses trois dards (qu'il a déjà en mains ^^), et ne revient pas, et recommence à tirer juste devant la cible.
Je suis un peu dérouté, j'ai tenté (vainement) quelques variantes, mais j'ai fait pire que mieux.
Quelqu'un saurait d'où viennent ces bugs ?
d'avance !
Amicalement, Grand Khân.
Lien direct vers le message - Vieux
Avatar de eMRaistlin
eMRaistlin
Alpha & Oméga
 
Avatar de eMRaistlin
 
Je dirai, a priori : verifie que tout les Waypoint aient le bon Tag : en particulier, le tag de destination, qui expliquerait pourquoi il tire devant la cible, sans repartir...
Lien direct vers le message - Vieux
Azmathiel
Alpha & Oméga
 
En première lecture, je me suis dit que le "ClearAllActions()" de la section où le PNJ peut attaquer la cible brisait son retour au point de départ. Tu as déjà essayé sans ?

Pour le WayPoint de départ, j'aurai peut-être aussi essayé un tag "POST_tagduPNJ" qui m'aurait assuré que le PNJ retournait bien au point de départ.

Pour l'effet visuel des fléchettes dans la main, tu pourrais ne lui les créer qu'une fois au lieu où il doit les lancer.
Lien direct vers le message - Vieux
GrandKhan
Dauphin / Dauphine
 
Voila ce que j'ai tenté:

Code PHP:
string Flechette() //Ce que peut dire l'elfe joueur.
{
  
string txt;
  switch(
d8())
  {
     case 
1txt="Cette fois ci je l'aurais!";
     case 
2txt="Avec un peu d'chance...";
     case 
3txt="J'suis l'roi d'la flechette!";
     case 
4txt="Plus fort que Guillaume Tell!";
     case 
5txt="J'suis vraiment un bon!";
     case 
6txt="A moi Las Vegas !";
     case 
7txt="J'rate jamais mon coup!";
     case 
8txt="At..At..Atchoum!";
  }
  return 
txt;
}


void main()
{
    
object oCible=GetNearestObjectByTag("CIBLE");
    
int nCible=GetLocalInt(OBJECT_SELF,"pret");
    if (
GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND))&& nCible==1)
    
//On regarde si il a bien des dards dans la main droite et s'il est pret.
    
{
        
ClearAllActions();
        
SpeakString(Flechette(),TALKVOLUME_TALK);//Une phrase bidon au pif.
        
ActionAttack(oCible);//Il balance les dards sur la cible.
        
ActionEquipMostDamagingRanged();//On s'assure qu'il utilise bien toutes ses fleches.
    
}
    if (!(
GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND))) && nCible==1)
   
// Si le joueur n'a rien dans la main droite, et qu'il est pourtant toujours pret a tirer.
    
{
       
SetLocalInt(OBJECT_SELF"pret"2); //Alors l'elfe joueur n'est pas pret a tirer, il va bouger.
       
ActionMoveToObject(oCible); //Il se dirige vers la cible.
       
ActionWait(0.5);
       
AssignCommand(OBJECT_SELF,ActionPlayAnimation(ANIMATION_LOOPING_GET_MID,1.0,1.0));
       
ActionWait(0.5);
       
AssignCommand(OBJECT_SELF,ActionPlayAnimation(ANIMATION_LOOPING_GET_MID,1.0,1.0));
       
ActionWait(0.5);
       
AssignCommand(OBJECT_SELF,ActionPlayAnimation(ANIMATION_LOOPING_GET_MID,1.0,1.0));
       
object oPosition=GetNearestObjectByTag("flechette");
       
CreateItemOnObject("wthdt002"OBJECT_SELF);// On cree une flechette.
       
CreateItemOnObject("wthdt002"OBJECT_SELF);// Une autre.
       
CreateItemOnObject("wthdt002"OBJECT_SELF);// La 3eme...
       
ActionMoveToObject(oPosition); // Il revient a sa position de tir.
       
ActionEquipMostDamagingRanged();//Il prend ses flechette.
       
SetLocalInt(OBJECT_SELF"pret"1);//Il est pret a tirer.
   
}

Alors il y a un gros bug et un moins important.
Le gros problème vient du fait que le tireur ne fait pas les 3 animations voulues.
Le petit est que des fois sur la barre des dialogues on voit qu'il va parler mais en fait le texte est vide, on voit juste son nom s'afficher, pas de texte.
Aucun problèmes provenant des tags, waypoints et autres, j'ai tout vérifié une centaine de millions de fois (j'exagère ok ^^).
En tout cas merci pour votre aide, et j'espère pouvoir un jour finir ce foutu script
Amicalement, Grand Khân.
Lien direct vers le message - Vieux
Compte #39350
Invité
 
A vu de nez comme ça je dirai qu'il dit tout le temps atchoum (ok je sors ^^). Il faut des breaks après les 7 premiers case. Ensuite tes anims durent 1 seconde et sont espacées toutes les demi secondes donc ça peut être le problème. ActionWait je sais pas trop, j'utilise DelayCommand en général, mais j'ai des problèmes aussi à l'occasion.
Ah oui aussi:

AssignCommand(OBJECT_SELF,ActionPlayAnimation(ANIMATION_LOOPING_GET_MID,1.0,1.0));


Ca peut s'écrire:

ActionPlayAnimation(ANIMATION_LOOPING_GET_MID,1.0,1.0));

et même:

PlayAnimation(ANIMATION_LOOPING_GET_MID,1.0,1.0));
Lien direct vers le message - Vieux
Azmathiel
Alpha & Oméga
 
Olblach a tout dit, et je suis d'accord avec ce qu'il dit sur les ActionWait(). Ils ne temporisent rien du tout et je me suis toujours demandé à quoi elle peut bien servir cette fonction. Peut-être dans l'empilement des actions... Je ne sais pas...
J'utilise moi aussi des DelayCommand().

Code PHP:

switch (X)
{
     case 
Atxt "blabla"; break; // Toujours mettre des break ou il va jusqu'au bout
                                    //=> "atchoum" chez toi d'où la judicieuse plaisanterie d'Olblach
     
case Btxt "blibli"; break;
     case 
Ctxt "bloblo"// ici ça sort de toute façon, c'est la fin

Cet Enchaînement:

Code PHP:

ActionMoveToObject
(oCible); //Il se dirige vers la cible.
ActionWait(0.5);
AssignCommand(OBJECT_SELF,ActionPlayAnimation(ANIMATION_LOOPING_GET_MID,1.0,1.0)); 
personnellement, je ne le sens pas bien. Il marche, attend rien (ça ne l'arrêterait pas ça, déjà ?), et au cas où il aurait envie de continuer à marcher, l'animation lui donne le compte et il s'arrête.
Si je devais tester ça, je le mettrai dans un script séparé que j'appellerai avec un DelayCommand(X.0, ExecuteScript("nomduscriptdesanimations", object_personnage_anime) avec X aussi court que possible pour ne pas déborder des 6 secondes totales du OHB et là, je verrai s'il bouge de place ou non avant de faire ses beaux gestes

Autre suggestion: les 1.0 d'exécution des animations, c'est suffisant pour celles que tu as choisies ?

Et dernière impression mais elle est un peu au pif: Tout ça, ça ne prend pas plus de 6 secondes à faire justement ?
Lien direct vers le message - Vieux
Azmathiel
Alpha & Oméga
 
Ce script me plaisait bien et je le trouvais ingénieux. Mais quelle galère !

Il y avait un peu de tout là dedans. Il m'a donc fallu contourner l'interruption du script et son éternel recommencement à cause de sa durée. Certaines conditions ne se remplissaient jamais. J'en ai donc conservé l'esprit initial et j'y ai fait des retouches surtout sur la variable locale renseignée sur le personnage.

D'abord, c'était beaucoup trop long pour les 6 secondes. Le ClearAllAction() nuisait également au bon déroulement, et tel quel, ton script ne pouvait pas tourner. Sans compter les ActionWait()...
Il se déroule maintenant en gros sur 5 OHB. Je t'ai laissé le SpeakString() qui te donne la valeur de la variable locale pour que tu puisses facilement te rendre compte du temps que prend le script à se dérouler.

Voici une version pas vraiment optimisée mais qui tourne:
(normal, il est 5:50 )

Code PHP:

string Flechette
() //Ce que peut dire l'elfe joueur.
{
  
string txt;
  switch(
d8())
  {
     case 
1txt="Cette fois ci je l'aurais!";break;
     case 
2txt="Avec un peu d'chance...";break;
     case 
3txt="J'suis l'roi d'la flechette!";break;
     case 
4txt="Plus fort que Guillaume Tell!";break;
     case 
5txt="J'suis vraiment un bon!";break;
     case 
6txt="A moi Las Vegas !";break;
     case 
7txt="J'rate jamais mon coup!";break;
     case 
8txt="At..At..Atchoum!";
  }
  return 
txt;
}


void main()
{

    
object oCible=GetNearestObjectByTag("CIBLE");
    
//int nCible=GetLocalInt(OBJECT_SELF,"pret");


    
if ((GetLocalInt(OBJECT_SELF,"pret")>= 
&& (
GetLocalInt(OBJECT_SELF,"pret")<=
&& (
GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_RIGHTHANDOBJECT_SELF))))
    
//On regarde si il a bien des dards dans la main droite et s'il est pret. 
// NOTE: oui, mais c'est un peu plus compliqué à cause des 6 secondes
// et on va jouer sur les tests pour pouvoir repasser plusieurs fois 
// dans le OHB sans forcément tout recommencer grâce à la variable locale "pret"

    
{

        
SpeakString(Flechette(),TALKVOLUME_TALK);//Une phrase bidon au pif.
        
ActionAttack(oCible);//Il balance les dards sur la cible.
        
ActionEquipMostDamagingRanged();//On s'assure qu'il utilise bien toutes ses fleches.
        
SpeakStringIntToString(GetLocalInt(OBJECT_SELF"pret")), TALKVOLUME_TALK); // A supprimer. 
 // Il est là pour visualiser la durée du script
        
SetLocalInt(OBJECT_SELF"pret"GetLocalInt(OBJECT_SELF,"pret")+1);

    }

    if( ((
GetLocalInt(OBJECT_SELF,"pret")>= 3
&& (!
GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_RIGHTHANDOBJECT_SELF)))) 
|| (
GetLocalInt(OBJECT_SELF"pret") == 0))
   
// Si le joueur n'a rien dans la main droite, et qu'il est pourtant toujours pret a tirer.

// NOTE:  Idem que ci-dessus, on restreint les passages très précisément.
// Et le "==0" c'est pour le premier passage sinon, ça ne commence jamais
    
{

       
//SetLocalInt(OBJECT_SELF, "pret", 2); //Alors l'elfe joueur n'est pas pret a tirer, il va bouger.
       
ActionMoveToObject(oCibleFALSE1.0f); //Il se dirige vers la cible.
       //ActionWait(0.5);
       
ActionPlayAnimation(ANIMATION_LOOPING_GET_MID,1.0,1.0);
       
//ActionWait(0.5);
       //AssignCommand(OBJECT_SELF,ActionPlayAnimation(ANIMATION_LOOPING_GET_MID,1.0,1.0));
       //ActionWait(0.5);
       //AssignCommand(OBJECT_SELF,ActionPlayAnimation(ANIMATION_LOOPING_GET_MID,1.0,1.0));
       
object oPosition=GetNearestObjectByTag("flechette");
       
CreateItemOnObject("wthdt002"OBJECT_SELF);// On cree une flechette.
       
CreateItemOnObject("wthdt002"OBJECT_SELF);// Une autre.
       
CreateItemOnObject("wthdt002"OBJECT_SELF);// La 3eme...
       
DelayCommand(1.0ActionMoveToObject(oPositionFALSE1.0f)); // Il revient a sa position de tir.
       
ActionEquipMostDamagingRanged();//Il prend ses flechette.
       
SetLocalInt(OBJECT_SELF"pret"1);//Il est pret a tirer.
   
}

Il est malheureusement impossible, sans rentrer dans des complications infernales, de faire se succéder les 3 animations car le gaillard n'en fait qu'à sa tête et retourne au pas-de-tir avant d'avoir terminé de retirer ses fléchettes. De plus, tu remarqueras qu'il court vers la cible, mais ça aussi... Je n'ai pas su le supprimer correctement. C'est le reliquat de son attitude agressive et il s'attaquerait volontiers à la cible à mains nues.

Le waypoint taggé "flechette", je l'ai mis à environ un 3/4 de carré de la cible.

Pfiouuu... Quelle bourrique que cet elfe !

Tiens, pour te donner une idée du rythme, mets ce script dans ton OHB de la zone où il lance ses fléchettes:

Code PHP:
void main()
{
    
object oChanteur GetObjectByTag("CIBLE");
    
AssignCommand(oChanteurPlaySound("as_cv_brickscrp1"));


Et voilà. Bon amusement
Lien direct vers le message - Vieux
Avatar de eMRaistlin
eMRaistlin
Alpha & Oméga
 
Avatar de eMRaistlin
 
A noter que effectivement, ActionWait sert a timer des action dans une pile d'action. Il est important de noter que de tout prevoir en pile d'action est interessant, car cela assure une continuité des actions quelques soit les problemes de lag ou de timegap.

A noter aussi que chaque objet, bien sur, a sa propre pile d'action, qu'il execute independamment de la pile de son voisin.

Un script comme cela, par exemple :
Code:
ActionSpeakString("Bonjour");
AssignCommand(oPNJ2,SpeakString("Hello"));
ActionWait(0.5);
ActionSpeakString("Ca va ?");
AssignCommand(oPNJ2,SpeakString("l'a matelas et toi ?"));
ActionSpeakString("Yeau de poîle !");
ActionWait(0.5);
AssignCommand(oPNJ2,SpeakString("Hahaha"));
ne s'executera pas en ordre, et les actionWait feront tout foirer, par exemple...

Il devient important de charger la pile d'action d'une seule personne :

Code PHP:
ActionSpeakString("Bonjour");
ActionDoCommand(AssignCommand(oPNJ2,SpeakString("Hello")));
ActionWait(0.5);
ActionSpeakString("Ca va ?");
ActionDoCommand(AssignCommand(oPNJ2,SpeakString("l'a matelas et toi ?")));
ActionSpeakString("Yeau de poîle !");
ActionWait(0.5);
ActionDoCommand(AssignCommand(oPNJ2,SpeakString("Hahaha"))); 
et la, de suite, la scene se deroulera bien en ordre, et toujours beaucoups plus precisement qu'avec un DelayCommand.


Lien direct vers le message - Vieux
GrandKhan
Dauphin / Dauphine
 
Arf je suis en retard ^^
Bon, j'ai lu attentivement vos conseils, et j'ai appliquer autant que je pouvais, et rien à redire, ca marche plutôt bien ^^
Maintenant j'ai un joueur de flechettes qui s'il rate, peut dire 1 fois sur 3 une réplique du genre juron, s'il reussit peut dire 2 fois sur 3 une acclamation. De plus, il y a un spectateur, celui ci l'encourage si le lanceur rate deux fois de suite, et l'acclame avec un petite animation si celui ci reussit deux fois de suite.

*content*

Maintenant je vais faire en sorte que les PJs puissent y joueur eux aussi.

Encore merci pour votre aide et d'avoir pris la patience de me répondre.
Amicalement, Grand Khân.
Lien direct vers le message - Vieux
Avatar de Blam
Blam
Roi
 
Avatar de Blam
 
pas tout suivi
voila, je quitte neverwinter sur la version 1.28, je reviens on parle de la 1.31.
Faut pas sortir p....(uriner) car on est vite débordé.

plus sérieusement je me remet a étudier tous les pro du script

hors sujet ? ok je sort !!!!

Lien direct vers le message - Vieux
Azmathiel
Alpha & Oméga
 
*bump*
Remonte petit fil, on a besoin de toi en haut. Et puis il ne s'agit pas de sombrer dans le néant des archives.
Lien direct vers le message - Vieux
Avatar de Deyonara
Deyonara
Alpha & Oméga
 
Avatar de Deyonara
 
J'ai regardé pour ça :
Code PHP:
ActionSpeakString("Bonjour");
ActionDoCommand(AssignCommand(oPNJ2,SpeakString("Hello")));
ActionWait(0.5);
ActionSpeakString("Ca va ?");
ActionDoCommand(AssignCommand(oPNJ2,SpeakString("l'a matelas et toi ?")));
ActionSpeakString("Yeau de poîle !");
ActionWait(0.5);
ActionDoCommand(AssignCommand(oPNJ2,SpeakString("Hahaha"))); 

Ne vaudrait-il pas mieux l'écrire comme ça ?
Code PHP:
ActionSpeakString("Bonjour");
AssignCommand(oPNJ2,ActionDoCommand(ActionSpeakString("Hello")));
ActionWait(0.5);
ActionSpeakString("Ca va ?");
AssignCommand(oPNJ2,ActionDoCommand(ActionSpeakString("l'a matelas et toi ?")));
ActionSpeakString("Yeau de poêle !");
ActionWait(0.5);
AssignCommand(oPNJ2,ActionDoCommand(ActionSpeakString("Hahaha"))); 
Lien direct vers le message - Vieux
Azmathiel
Alpha & Oméga
 
Si tu utilises une fonction ActionXXXX(), tu n'as pas besoin de mettre un ActionDoCommand qui sert justement à empiler les actions qui ne sont pas prévues pour l'être, à la base, et généralement, on le fait via un AssignCommand(oXXX, ActionDoCommand(...))
Lien direct vers le message - Vieux
Avatar de Deyonara
Deyonara
Alpha & Oméga
 
Avatar de Deyonara
 
Et dans ce cas ?
Code PHP:
ActionSpeakString("Bonjour");
AssignCommand(oPNJ2,ActionDoCommand(SpeakString("Hello")));
ActionWait(0.5);
ActionSpeakString("Ca va ?");
AssignCommand(oPNJ2,ActionDoCommand(SpeakString("l'a matelas et toi ?")));
ActionSpeakString("Yeau de poêle !");
ActionWait(0.5);
AssignCommand(oPNJ2,ActionDoCommand(SpeakString("Hahaha"))); 
Ce qui m'étonnait le plus c'est de voir la fonction ActionDoCommand avant AssignCommand, ou alors peut-on les intervertir librement ?
Lien direct vers le message - Vieux
Azmathiel
Alpha & Oméga
 
Si tu utilises ActionDoCommand(AssignCommand()), tu affectes ça à la pile d'action de l'objet courant, pour faire effectuer une action à l'objet de AssignCommand().

Si tu utilises AssignCommand(ActionDoCommand()), tu maîtrises mieux dans quelle pile tu places l'action.

Tu peux faire aussi :

AssignCommand(oPJ1, ActionDoCommand(AssignCommand(oPJ1, SpeakString()))). (Bon ok, c'est tiré par les cheveux, mais ça marche )
Ca veux dire que tu empiles dans la pile de PJ2 une action à faire exécuter à PJ1 une fois arrivé à un certain stade dans cette pile et pas avant.
Evidemment, il faut éviter de vider les piles quand on en entasse beaucoup.
Et parfois, ça pose des soucis. Par exemple, dans le script de danse que j'avais fait, la danseuse perd un peu la boule en fin de script. Elle continue à hocher la tête alors que sa pile est vide.

Bref, tout dépend de l'enchaînement que tu veux réaliser. Le tout étant de rester logique.
Lien direct vers le message - Vieux
Répondre
Les forums JOL > Forum jeux-vidéo > Neverwinter Nights > NWN - Maskado > Cours de Scripts pour les Quiches. Leçon Six.
   

Outils Rechercher
Rechercher:

Recherche avancée

Les vidéos de Neverwinter Nights RSS
  • Aucune vidéo pour le moment...
Thème visuel : Fuseau horaire GMT +2. Il est actuellement 19h25.
   

© JeuxOnLine, le site des MMO, MMORPG et MOBA. Tous droits réservés. - Conditions générales d'utilisation - Conditions d'utilisation des forums - Traitement des données personnelles - ! Signaler un contenu illicite