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

Panneau de contrôle

Recherche | Retour aux forums

JOL Archives

Traduction du tutorial bioware sur les scripts.

Par Théranthil le 17/8/2002 à 9:06:39 (#1973788)

Liste des tutoriaux traduits :
-Stocker des variables
-Définir un objet
-Créations des objets
-A propos des animations
-Explication à propos des Waypoint et des WalkWaypoint
-UserDefinedEvent est votre ami
-Un script OnSpawn mieux commenté
-Récompenser avec de lor et de lXP
-Faire des jets de compétences
-Créer des objets uniques
-Sasseoir sur une chaise et dormir
-Comment faire pour quun NPC entame le dialogue tout seul
-Comment faire pour que mon NPC attaque le PC avec lequel il est en train de parler
-Comment puis je ouvrir mon magasin
-Utiliser les « Modules Events »
-Utiliser les « Area Events »
-Utiliser les « Creature Events »
-Utiliser les « Placeable object Events »
-Utiliser les « Trigger Events »
-Ajouter et enlever des effets
-Utiliser les dialogues avec les objets placeables et les déclencheurs (trigger)
-Factions, cris et attaque des ennemis
- Comment faire un mercenaire

D'autres tutoriaux devraient venir par la suite

Voila la première partie concernant l'utilisation de variable. Le tutorial est très simple et peut aider les débutant. Il est très complet. Je conseille plutôt de le lire avant de faire celui de Lumina, car il présente mieux (d'apres moi) les premières notions.

Pour ceux qui le veulent en format Word allez faire un tour sur le site de Kemay (qui est omniprésent sur le forum ;)

Le voila:c'est par ici

Tutorial sur les scripts :Stocker des variables.
Ecrit par David Gaider
Neverwinter Nights: Print Page - Scripting Tutorial: Setting Variables

Une des choses les plus courantes que vous aurez à faire est de stocker des variable et de les retrouver Cest la seul manière de déterminer comment la plupart des événements vont prendre place ou bien de changer/garder létat dune quête.
La commande que vous utiliserez le plus fréquemment pour stocker des variables est celle ci:
void SetLocalInt(object oObject, string sVarName, int nValue)
Cette commande stocke une local integer (un entier local). Quest ce que local veut bien dire ? Cela veut dire que lentier est référencé, ou stocké, dans « l oObject » que vous avez spécifié. (Il nest pas enregistré la physiquement, mais il est plus facile de penser que cest le cas.)
Il y a trois choses qui sont importantes à retenir ici :
-le « oObject » doit être un objet valide. Vous verrez beaucoup de commandes qui renvoient un objet au début de leur structure (comme il est marqué « void » au début de la commande « SetLocalInt ») Cela signifie que ces commandes retournent comme donnée le type de lobjet.
Dans tous les cas, lobjet que vous spécifié est la où « linteger » est référencé. Si vous êtes dans un dialogue, utiliser GetPCSpeaker() retournera le PC qui est en train de parler au NPC qui est lobjet. Vous pouvez utiliser GetModule() pour enregistrer « linteger » dans le module lui même Vous pouvez utiliser OBJECT_SELF pour nommer lobjet qui est utilisé dans le script actuel, etc.
Cest important parce que la variable que vous choisissez deviens unique pour cet objet. Si vous stockez une variable avec le nom « VARIABLE 1 » avec la valeur 1 dans le module, cest la seule variable qui peut être appelée par ce nom. Vous pouvez avoir une « VARIABLE 1 » enregistrée dans un autre objet, comme un PC, et il peut avoir des valeurs complètement différentes.
-La « string sVarName » est le nom que vous donnez à votre variable. Vérifiez bien quil est unIQUE. Comme toutes les strings (chaînes de caractères), il doit être entouré de guillemets (comme « VARIABLE 1 » ci dessus). Les noms de variables ne différencient pas les majuscules des minuscules.
-La « int nValue » est linformation que vous voulez stocker dans la variable. Tant que cest un entier nous utiliserons cette commande, mais ca doit être un entier (sans décimales) (NdT cest pas moi qui insiste autant, cest Bioware)
comme 1, 15 ou 320. Si vous voulez entrer différentes informations ici, vous avez besoin dautres commandes :
SetLocalFloat = enregistrer un « float number » (un nombre avec une partie décimale)
SetLocalString = enregistrer une « string » (comme un mot, une phrase ou le nom dun objet Elle doit juste être écrite entre guillemets, comme le nom de la variable.)
SetLocalLocation = enregistrer une localisation
SetLocalObject = enregistrer un objet (comme un « placeable object », un objet dinventaire ou une créature.)

NdT : à partir de maintenant, par soucis de clarté, jutiliserais le terme dinteger (ou int) et non ça traduction

Comment dois je utiliser les variables ?
Bien, une fois que vous avez enregistré une variable dans quelque chose, elle reste la jusquà ce quelle soit remplacée ou détruite. Nimporte quand, dans un autre script (ou dans le même) vous pouvez rappeler cette variable et linformation quelle contient.

Si je veux rappeler le nombre que je viens denregistrer dans la variable, je dois utiliser cela :
int GetLocalInt(object oObject, string sVarName)
Cest quasiment la même commande que celle que vous avez utilisé pour enregistrer la variable moins la valeur actuelle de la variable (cest ce que nous attendons)
Remarquez que ce nest pas une commande « void »Elle retourne un entier. Cela veut dire que vous nutilisez pas seulement toute seule. Utilisez la pour définir tout autre « int » nécessaire dans une autre commande ou variable comme cela :
int nValue = GetLocalInt(OBJECT_SELF, "VARIABLE1")
Cela signifie que vous avez spécifié une nouvelle variable appelée « nValue » qui est équale à linteger qui était stocké dans lOBJECT_SELF sous le nom « VARIABLE 1 »

Cest encore un peu confus ? voici des exemples.
Un bonne exemple pour comprendre comment une variable peut être utilisé est de suivre la progression dune quête. Je veux avoir une variable qui sappelle « STORY » quand le joueur accepte la quête, je veux lui attribuer la valeur 1. Quand il la fini, je lui attribue la valeur 2.

Le joueur accepte la quête
Au moment du dialogue ou le joueur accepte, je vais dans « Actions Taken » et fait un script qui entre 1 dans la variable « STORY » du PC.
NWScript:
void main()
{
SetLocalInt(GetPCSpeaker(), "STORY", 1);
}

Le joueur termine la quête
Une fois que le PC est revenu et a fait ce que le NPC veut, le NPC le félicite et la valeur 2 est stockée dans la variable « STORY » du PC.
NWScript:
void main()
{
SetLocalInt(GetPCSpeaker(), "STORY", 2);
}

Comment je sais si le joueur a accepté ou terminé la quête ?
Au moment voulu dans le dialoque, vous avez juste besoin de créer un nouveau nud pour chaque condition. Lordinateur commencera par le haut et vérifiera tous les scripts dans la section « Text Appears When » et regarde si ils sont vrai (TRUE) (si il ny a pas de scripts, il considérera automatiquement que cest vrai.)
Dans ce cas, il commence ce nud. Sinon, il passe au suivant.

Cest pourquoi, vous devez lister ces nud du dernier au premier.

#1. (quête terminée) "Merci davoir accompli cette tache."
#2. (quête acceptée) "Avez vous terminé cette quête ?"
#3. (ni acceptée, ni terminée) "Bonjour"

Maintenant, vous avez besoin dun script qui renvoie TRUE pour #1 si la variable « STORY » est égale à 2, nest ce pas ?Et pour #2, le script doit retourner TRUE si la variable est égale à 1. Aucun script nest nécessaire pour #3 car si #1 et #2 sont faux (FALSE pour le script), cest que la quête na été ni acceptée, ni terminée.

Est ce que la quête est terminée ?

NWScript:
int StartingConditional()
{
int nDone = GetLocalInt(GetPCSpeaker(), "STORY") == 2;
return nDone;
}

Est ce que la quête a été acceptée ?

NWScript:
int StartingConditional()
{
int nAccept = GetLocalInt(GetPCSpeaker(), "STORY") == 1;
return nAccept;
}

Normalement, vous devriez arriver à ceci:
#1. (1er script dans "Text Appears When") " Merci davoir accompli cette tache."
#2. (2nd script dans "Text Appears When") " Avez vous terminé cette quête ?"
#3. (no script) " Bonjour "

Dans le script ci dessus, je voulais seulement que le NPC donne la quête à 1

Au moment ou il fixe la variable « STORY » à 1, pourquoi est ce quil na pas crée une variable « PLOT_GIVEN » rattachée à OBJECT_SELF (c.a.d le NPC) ?

Dans ce cas, lorsquun autre PC qui naurait pas de variable « STORY » parle au NPC, vous pourriez avoir à la place du texte par défault (#3) un dialogue divisé en 2 :
|
|
--> (script dans "Text Appears When" qui renvoie TRUE si "PLOT_GIVEN" de « OBJECT_SELF » a pour valeur 1)
"Désole, je nai pas de travail pour vous aujourdhui"
|
|
--> (pas de script) "Est ce que vous êtes intéressé par un travail ?"


UN EXEMPLE TRES SIMPLE DE DIALOGUE DE QUETE.

La chose à se souvenir est que quand vous créez votre premier nud, juste en dessous de Root, les propositions doivent être dans lordre inverse de lordre dans lequel elles seront complétées. (cf exemple ci dessus)

Admettons maintenant que notre NPC donne 3 boulots. Imaginez la structure suivante sous le « root » :

#1. "Je nai plus aucun travail pour vous."
#2. "Avez vous fini le travail #3?"
#3. " Avez vous fini le travail #2?"
#4. " Avez vous fini le travail #1?"
#5. "Est ce que vous cherchez un travail ?"
#6. "Salut!"

Il faut se souvenir que lorsquon clique sur un NPC, lordinateur commence à vérifier le script « Text Appears When » des parties du noeud. Si le script renvoie TRUE (ou si il ny a pas de script), ce nud est initialisé. Si il retourne FALSE, il passe à la suite.

Voici la liste des script qui sont attribué à chaque nud.

#1 - script dans 'Text Appears When' qui renvoie TRUE si la variable "Job" du PC a pour valeur 4:

int StartingConditional()
{
int nJob = GetLocalInt(GetPCSpeaker(), "Job") == 4;
return nJob;
}

#2 - script dans 'Text Appears When' qui renvoie TRUE si la variable "Job" du PC a pour valeur 3 (cf. ci dessus). Si le PC a fini le travail, le NPC donne la récompense et fixe la variable « Job » à 4 (plus de travail) dans « Action Taken » comme ceci :

void main()
{
SetLocalInt(GetPCSpeaker(), "Job", 4);
}

#3 - script dans 'Text Appears When' qui renvoie TRUE si la variable "Job" du PC a pour valeur 2 (cf. ci dessus). Si le PC a fini le travail, le NPC donne la récompense et le travail #3 et fixe la variable « Job » à 3 dans « Action Taken »

#4 - script dans 'Text Appears When' qui renvoie TRUE si la variable "Job" du PC a pour valeur 1 (cf. ci dessus). Si le PC a fini le travail, le NPC donne la récompense et le travail #2 et fixe la variable « Job » à 2 dans « Action Taken »

#5 - Script dans 'Text Appears When' renvoie TRUE si la variable "TalkedToJoe" du PC est fixée à 1 (cf. ci dessus). Dans le dialoque, si le PC accepte le travail #1, fixe la variable « Job » du PC à 1 dans 'Actions Taken'.

#6 Pas de script dans 'Text Appears When' (si tous les autres scripts qu dessus sont « FALSE », cest que le PC a parlé pour la première fois au NPC). Sur la première ligne, placez un script dans « Action Taken » qui fixe la variable "TalkedToJoe" du PC à 1.


Voilà comment stocker et rappeler des variables. Utiliser les « strings », les « object data » et autres données est un peu plus compliqué... mais ça paraîtra plus aisé maintenant que vous êtes habitué à manipuler les « integers ». En espérant que ca vous aidera à débuter.


This page printed from the BioWare Neverwinter Nights Community Site: http://nwn.bioware.com
Powered by BioBoards Version 2.05.010
Please read our Copyright and Trademark Information

PS: la traduction est parfois un peu approximative, mais l'ensemble devrais être clair et cohérent. Sinon envoyez moi un MP (même si je ne pourrais peut être pas repondre tout de suite.)

La suite devrais suivre d'ici peu de temps. Mais un peu de patience quand même car ce tutorial fait 68 pages...c'est par ici

Par Théranthil le 17/8/2002 à 10:46:51 (#1973949)

Et voila la suite dédiée aux fonctions:GetNearestCreature, GetNearestObject et GetDistanceBetween.

Tutorial pour les scripts : définir un objet.
Ecrit par David Gaider
Traduit par Théranthil
Neverwinter Nights: Print Page - Scripting Tutorial: Defining An Object


Maintenant, ce topic est un peu plus compliqué…mais je me suis trouvé plusieurs fois fonçant dans un mur alors que j’essayais de faire quelque chose.

Beaucoup d’action requièrent un objet comme cible. La manière la plus facile de définir un objet est de lui avoir donné un tag particulièrement pratique…c’est génial si l’on sait quel est l’objet qui servira de cible. Mais comment faire si on ne le sait pas ? Comment faire si on veut trouver le PC le plus proche du personnage…où qu’il soit ? Comment faire si on veut cibler la créature la plus proche ? Comment faire si on veut vérifier à quelle distance se trouve quelque chose ?

Il y a de nombreuses manières de vérifier des choses comme ça… Je vais ici me focaliser sir trois :
GetNearestCreature, GetNearestObject et GetDistanceBetween.

GetNearestCreature

Cette commande vous permet de trier des créature selon leur proximité par rapport à un objet et cela en suivant 3 paramêtres. Notez que la cible ne doit pas être l’objet de ce type le plus proche…Si vous voulez, par exemple, localiser le second non PC voleur humain le plus proche vous devez utiliser cette commande.
La syntaxe est la suivante :

object GetNearestCreature (int nFirstCreatureType, int nFirstParameter, object
oTarget=OBJECT_SELF, int nNth=1, int nSecondCreatureType = -1, int nSecondParameter = -1, int
nThirdCreatureType = -1, int nThirdParameter = -1 )

Ca peut paraître un peu confus, mais nous allons y aller petit à petit.

'nFirstCreatureType' et 'nFirstParameter' sont les premières caractéristiques que nous recherchons. Admettons que nous cherchons l’humain le plus proche… « nFirstCreatureType » sera l’attribut CREATURE_TYPE_ RACIAL_TYPE, et 'nFirstParameter' sera RACIAL_TYPE_HUMAN.

Qu’est ce que ça veut dire ? Vous avez jusqu’à trois qualités que vous pouvez utiliser pour affiner la recherche… en utilisant pour chacun un attribut et un paramètre.

L’objet « oTarget » est bien évidemment l’objet qui sert de centre à la recherche. Ca peut être OBJECT_SELF (et c’a l’est par défault) si vous voulez cibler la recherche sur l’objet auquel appartient le script. Vous pouvez aussi faire quelque chose d’autre comme par exemple vérifier la créature la plus proche du PC le plus proche…Mais ça vous trouverez vous même comment le faire.
L’integer 'nNth' est ce que vous utilisez pour déterminer si vous voulez le premier objet le plus proche, le second…Par défault, le script cherche le premier. Mais n’importe quel nombre que vous mettez ici déterminera combien de créature plus proche ne seront pas retenue par la recherche. Notez que n’importe quelle fonction peut être utilisée à la place du moment qu’elle renvoie un entier… Vous pouvez mettre d4() par exemple, si vous voulez chercher aléatoirement du premier au quatrième objet le plus proche.

Ici, vous avez la liste de arguments que vous pouvez utiliser pour la recherche.
l CREATURE_TYPE_CLASS = classe de personnage ou de monstre
l CREATURE_TYPE_DOES_ NOT_HAVE_SPELL_EFFECT = Si vous recherchez une créature qui n’est pas affectée par un sort (spécifié par la constante SPELL_*) J’imagine qu’elle ne doit pas servir souvent.
l CREATURE_TYPE_SPELL_EFFECT = Voici l’inverse, si vous recherchez une créature affectée par tels ou tels sorts. Notez que tous les effets de sorts ne viennent pas de sorts.
l CREATURE_TYPE_IS_ALIVE = Ca s’explique tout seul ; si vous voulez ne pas tenir compte des créatures mortes.
l CREATURE_TYPE_PERCEPTION = C’est un cas particulier, car techniquement ce n’es pas un attribut de la créature, il dépend de la nature de la perception de l’objet cible…si il a par exemple été vu ou entendu.
l CREATURE_TYPE_PLAYER_CHAR = Cela détermine si la créature est un PC ou non.. l
l CREATURE_TYPE_RACIAL_TYPE = race de la créature.
l CREATURE_TYPE_REPUTATION = classe d’après sa réputation envers la cible.

Je ne citerais pas tout les classes particulières, les races et les effets qui peuvent être utilisé parce qu’ils sont assez évidents. Quelque autres le sont moins, les voici :

CREATURE_TYPE_IS_ALIVE:
l TRUE ou FALSE (facile)
CREATURE_TYPE_PERCEPTION:
l PERCEPTION_HEARD
l PERCEPTION_HEARD_ AND_NOT_SEEN
l PERCEPTION_NOT_HEARD
l PERCEPTION_NOT_SEEN
l PERCEPTION_NOT_SEEN_ AND_NOT_HEARD
l PERCEPTION_SEEN
l PERCEPTION_SEEN_AND_HEARD
l PERCEPTION_SEEN_ AND_NOT_HEARD
CREATURE_TYPE_PLAYER_CHAR:
l PLAYER_CHAR_IS_PC
l PLAYER_CHAR_NOT_PC
CREATURE_TYPE_REPUTATION:
l REPUTATION_TYPE_ENEMY
l REPUTATION_TYPE_FRIEND
l REPUTATION_TYPE_NEUTRAL

(je pense que là, même sans être une bilingue en anglais vous comprenez.)


Bon, et maintenant, si je veux trouver le PC le plus proche de moi ?

GetNearestCreature (CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC);

Le mage ennemi le plus proche de moi ?

GetNearestCreature (CREATURE_TYPE_ REPUTATION, REPUTATION_ENEMY, OBJECT_SELF,
1, CREATURE_TYPE_CLASS, CLASS_TYPE_WIZARD);

L’ennemi vivant le plus proche du plus proche PC allié ?
GetNearestCreature (CREATURE_TYPE_ REPUTATION, REPUTATION_ENEMY,
GetNearestCreature (CREATURE_TYPE_ PLAYER_CHAR, PLAYER_CHAR_IS_PC,
OBJECT_SELF, 1, CREATURE_TYPE_ REPUTATION, REPUTATION_FRIENDLY), 1,
CREATURE_TYPE_ IS_ALIVE, TRUE);

Le non PC que je peux voir le plus proche ?
GetNearestCreature (CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_NOT_PC,
OBJECT_SELF, 1, CREATURE_TYPE_ PERCEPTION, PERCEPTION_TYPE_ SEEN);

GetNearestObject
C’est beaucoup moins compliqué parce que vous pouvez seulement trier les objets par leur type…vous n’avez pas les multiples paramètres qu’on les créatures. Mais ca marche de la même manière :

object GetNearestObject (int nObjectType=OBJECT_TYPE_ALL, object oTarget=OBJECT_SELF, int
nNth=1)

'nObjectType' est évidemment le type d’objet que vous recherchez. Si vous ne marquez rien, ce sera l’objet le plus proche, quel qu’il soit.
L’objet « oTarget » correspont toujours au centre des recherches. Par défault, c’est « OBJECT_SELF ».
L’integer « nNth » n’a pas changé non plus, il correspond au nième objet par ordre de proximité. (le troisième si nNth=3)

Les types d’objet sont donc ::
l OBJECT_TYPE_ALL
l OBJECT_TYPE_AREA_OF_EFFECT
l OBJECT_TYPE_CREATURE
l OBJECT_TYPE_DOOR
l OBJECT_TYPE_INVALID
l OBJECT_TYPE_ITEM
l OBJECT_TYPE_PLACEABLE
l OBJECT_TYPE_STORE
l OBJECT_TYPE_TRIGGER
l OBJECT_TYPE_WAYPOINT

La non plus, je pense que la traduction n’est pas nécessaire.


GetDistanceBetween

Ca donne la distance en mètre entre 2 objets valides. Il est important que les 2 objet soient valides, sinon la distance reportée est de 0.

float GetDistanceBetween(object oObjectA, object oObjectB)

(Qu’est ce que float ? Un « float » comme un integer est juste un nombre, mais il possede toujours une partie décimale. 50 est un integer, 50.0 est un « float ». Si vous avez besoin, vous pouvez utiliser la commande
int FloatToInt(float fFloat) pour convertir un float en integer.)
Si vous voulez simplement connaître la distance entre un objet et celui à qui appartient le script, il est actuellement plus facile d’utiliser cette commande :

float GetDistanceToObject(object oObject)

De cette manière, vous n’êtes pas constamment obligé de spécifier OBJECT_SELF dans la commande GetDistanceBetween.


This page printed from the BioWare Neverwinter Nights Community Site: http://nwn.bioware.com
Powered by BioBoards Version 2.05.010
Please read our Copyright and Trademark Information

Par Théranthil le 17/8/2002 à 15:15:49 (#1974950)

Et hop, encore un. Cette fois, la lecon porte sur la création d'objet.

Tutorial sur les scripts : création d’objets
Ecrit par David Gaider
Traduit par Théranthil

object CreateItemOnObject(string sItemTemplate, object oTarget = OBJECT_SELF, int nStackSize = 1)

Cette commande crée un objet (avec le tag « sItemTemplate ») dans l’inventaire de l’objet « oTarget ». On l’utilise souvent quand des objets sont « donnez » à un PC…ou si un NPC est supposé avoir un objet seulement pendant un certains temps. Si je suis dans un dialogue et que le NPC recompense le PC avec qui il parle avec une épée longue non magique, je mettrais un script avec la commande ci dessous dans « Action Taken » :


CreateItemOnObject ("NW_WSWLS001", GetPCSpeaker());

Si je veux mettre 12 flêches normales dans un coffre qui a le tag "CHEST05":

CreateItemOnObject ("NW_WAMAR001", GetObjectByTag ("CHEST05"), 12);

(NOTE : Si vous utilisez ActionGivenItempour pour qu’un NPC donne à un PC un objet dans son inventaire, cet objet doit déjà exister dans l’inventaire du NPC pour que l’action soit complétée. ActionGivenItem transfert l’objet de l’inventaire du NPC à celui du PC…CreateItemOnObject crée un nouvel objet dans celui ci.)

(2ième NOTE : Je rajoute que le « sItemTemplate » utilisé dans cette commande est le tag de l’objet…C’est vrai UNIQUEMENT avec les objet standard inclus dans le jeu. Désolé, c’est tout ce que j’ai l’habitude d’utiliser avec cette commande. Si vous essayez d’utiliser cette commande avec des objets personnalisés (custom items), vous devez utiliser le blueprint resref de l’objet… et non le tag.)


La commande « CreateObject » est un petit peu différente. Elle crée un objet sur la map. Elle est souvent référencée comme « spawning ». L’ « objet » peut être une créature ou un objet (inerte). Sa structure est la suivante :

object CreateObject (int nObjectType, string sTemplate, location lLoc, int bUseAppearAnimation = FALSE)

'nObjectType' est une constante qui défini quel type d’objet va être crée.
Par exemple, OBJECT_TYPE_CREATURE ou OBJECT_TYPE_ITEM. Elle viens de la liste des constantes « Constants » du script editor.

La string 'sTemplate' est son 'blueprint resref'. Oui, je sais…quasiment toutes les autres commandes utilisent le tag de l’objet.
Celle ci se réfère au resref, trouvé habituellement sous l’onglet « Advance » de l’objet.

NOTE: cette particularité est très souvent source d’erreur ! Si vous utilisez le tag à la place du resref, ca ne marchera pas !

Un emplacement(location) consiste en une zone (area), et des coordonnées xyz sur la carte (qui sont chacune connue en tant que vecteur) et d’une orientation. Il est plus facile d’utiliser la commande GetLocation(object oObject) pour obtenir toutes ces informations à partir d’un waypoint ou d’un autre objet (si vous utilisez un objet comme une créature, l’apparition se fera à l’endroit « valide » le plus proche.) Si nécessaire, vous pouvez aussi construire un emplacement en utilisant Location(object oArea, vector vPosition, float fOrientation)…

Par défault, l’animation standart de l’apparition n’est pas utilisée… si vous voulez qu’elle le soit, spécifiez TRUE après « bUbeAppearAnimation »

Donc…pour créer un hobgobelin sur un waypoint déjà placé et qui a le tag « WAYPOINT1 »…

location spawn1 = GetLocation (GetWaypointByTag ("WAYPOINT1"));
CreateObject (OBJECT_TYPE_CREATURE, "NW_BUGBEARA", spawn1);

Pour faire apparaître un magicien (avec le tag "wizard01") avec l’effet activé, à côté du PC le plus proche…

NWScript:
void main()
{
object oWay = GetWaypointByTag("WAYPOINT1");
vector vPos = GetPosition(oWay);
vector vPC = GetNearestCreatureToLocation(CREATURE_TYPE_PLAYER_CHAR,
PLAYER_CHAR_IS_PC, vPos);
location lPos = Location(GetArea(oWay), vPos, SetFacingPoint(vPC));
CreateObject(OBJECT_TYPE_CREATURE, "wizard01", lPos, TRUE);
}

UNE DERNIERE CHOSE A PROPOS DES TAGS: Rappelez vous qu’ils font la différence entre les majuscules et les minuscules ! Si le tag de votre créatureest « wizard01 », ne l’appalez pas dans votre script « WIZARD01 » ou même « Wizard01 »…Vous verrez alors apparaître à la place un blaireau (badger). Pourquoi un blaireau ? Par ce que c’est simplement la créature convoquée par défault et donc utilisée quand l’objet qui doit apparaître est invalide.


This page printed from the BioWare Neverwinter Nights Community Site: http://nwn.bioware.com
Powered by BioBoards Version 2.05.010
Please read our Copyright and Trademark Information

Par Théranthil le 17/8/2002 à 19:27:23 (#1975865)

Tutorial sur les scripts :A propos des animations.
Ecrit par David Gaider
Traduit par Théranthil
Neverwinter Nights: Print Page - Scripting Tutorial: Regarding Animations


Vous avez fondamentalement deux choix quand vous ajoutez des animations aux créatures dans le jeu. Les ajouter directement ou utiliser des fonctions automatiques dans l’IA générique.

Ajouter des animations directement.
La première chose à comprendre quand vous avez affaire à des scripts d’animation est que toutes les créatures n’ont pas toutes les animations. En règle générale, si la créature est une race jouable (humain, elfe, nain, demi-orc, gnome ou halfelin), elle aura toutes les animations. Si la créature est un monstre humanoïde (orc, gobelin…) elle a la plupart des animations, ci ce n’est toutes. Les races non-humanoïdes et spécialement les oiseaux, seront très limités dans leurs animations.

La file des actions (Action Queue)
La seconde chose à savoir quand vous scriptez des animations est comment utiliser la file des actions . Il y a certaines commandes de scripts qui commence par le mot « Action »…quand une créature appelle ces commandes sur elle même, elle place l’action dans une file. Le script ne passera pas à la ligne suivante avant que l’action soit terminée…jusqu’à ce qu’il n’y ait plus d’action ou la commande « ClearAllActions() ».

La raison pour laquelle c’est important est qu’il y a 2 commandes principales qui sont utilisées avec les animations :
ActionPlayAnimation et juste PlayAnimation. ActionPlayAnimation place la commande de l’animation dans la file…PlayAnimation demande à la créature de jouer l’animation immédiatement dès que c’est inscrit dans le script, en étant « prioritaire » sur tout autre commande placée dans la file.

Si je veux dans un script dire à quelqu’un de bouger jusqu’à un waypoint particulier puis de méditer 6 secondes, il ressemblera à ça :

NWScript:
void main()
{
object oTarget = GetNearestObjectByTag("WAYPOINT1");
ActionMoveToObject(oTarget);
ActionPlayAnimation(ANIMATION_LOOPING_MEDITATE, 1.0, 6.0);
}

La créature se déplacera jusqu’au waypoint et attendra d’être arriver avant de commencer à jouer l’animation « meditate ».

Si je veux fixer une variable quand il aura terminé tout cela, je devrais l’ajouter aussi dans la file. Vous pouvez faire cela avec la commande ActionDoCommand(). Cela place une commande « non-Action » (sans « Action » au début) dans la file.

NWScript:
void main()
{
object oTarget = GetNearestObjectByTag("WAYPOINT1");
ActionMoveToObject(oTarget);
ActionPlayAnimation(ANIMATION_LOOPING_MEDITATE, 1.0, 6.0);
ActionDoCommand(SetLocalInt OBJECT_SELF, "Done_Meditation", 1);
}

Si j’avais fait la commande SetLocalInt sans la mettre dans la file, il se serait déclenché dès que ce point aurait été atteint dans le script…probablement avant que la créature soit arrivée au waypoint.

Les deux commandes pour les animations sont les suivantes :

void ActionPlayAnimation (int nAnimation, float fSpeed=1.0, float fSeconds=0.0)
-'nAnimation' est la constante pour que l’animation soit jouée (c’est l’animation que vous voulez jouer)
-'fSpeed' est la vitesse à laquelle l’animation est jouée…la créature peut, par exemple, tourner la tête très rapidement ou très lentement…1.0 est la vitesse normale.
-'fSeconds' est uniquement utilisée pour les animations en boucle (comme la méditation)…elle détermine combien de temps vous souhaitez que l’information soit jouée. Si elle est laissée nulle dans une animation en boucle, celle ci sera jouée jusqu’à ce qu’on demande de faire autre chose.

void PlayAnimation (int nAnimation, float fSpeed=1.0, float fSeconds=0.0)

Comme expliqué ci dessus, c’est la même commande que ActionPlayedAnimation, execpté que l’animation n’est pas placée à la suite…elle est jouée immédiatement.

Constantes des Animation (Animation Constants)
Vous pouvez trouver une liste de toute les animations (utilisée dans la partie « nAnimation » de la commande) en sélectionnant le bouton « Constants » dans le script editor…toutes les constantes commencent par ANIMATION_*
Il y a deux types d’animations : « fire-and-forget » ou FNF (tire et oublie), qui sont jouées une fois et aucune durée n’est nécessaire.
Encore un rappel : TOUS LES MODELES N’ONT PAS TOUTES LES ANIMATIONS.Juste pour mentionner aussi que les animations listées dans « Constants » ne sont pas toutes les animations que le modèle est capable de jouer (il y a une animation de mort, après tout, aussi bien qu’une animation de combat)…C’est juste la liste de toutes celles qui peuvent être jouées par le script.

Utiliser les Animation de l’IA générique.
Pour une solution rapide et facile pour rajouter un peu de vie dans vos créatures placées, l’IA générique a 2 fonctions que vous pouvez utiliser.

Dans le script générique OnSpawn ("nw_c2_default9"), il y a une liste complète des commandes qui sont toutes commentées (les commentaires sont précédés par un « // » double qui les colorie en vert et évite qu’ils soient compilés). Pour utiliser l’animation pré construite, vous n’avez qu’à enlever le « // » devant une des commandes suivantes :

NWScript:
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);

Ne vous tracassez pas à propos des commentaires qui sont sur la même ligne avec ces commandes…ils disent juste ce qu’ils font. Effacez simplement le double slash au début de la ligne.
Ensuite vous re-compilez le script et vous le sauvegardez dans un autre fichier. Et…c’est tout ce que vous avez à faire.

Qu’est ce que cela va faire ?
Fondamentalement, elles sont appellé par le OnHeartbeat (ce qui veut dire que le script est activé toutes les 6 secondes). Le script vérifie que la créature n’est pas en train de dormir, de combattre, de parler et que aucun ennemi n’est dans la ligne de vue…Si tout est okay, il joue l’animation.

'Ambient animations' signifit que la créature se déplacera aléatoirement, s’arretant de temps en temps pour se tourner vers les amis proches (créatures avec une réputation amicale) et jouer les animations « sociales » qu’il a (et, oui, ca marche avec tous les types de créature…et qu’il fera ce qu’il peut pour les créatures qui n’ont pas toutes les animations.)

'Immobile ambient animation' fait la même chose… sans le mouvement aléatoire. La créature reste sur place.

Vous pouvez donc placer plusieur crétures de ce type, par exemple, et elle se tourneront l’une vers l’autre à un interval aléatoire et sembleront parler, discuter, débattre…et même mélangeront, avec les animation ambiantes (ambient animations)

Est ce que ca marche de la même manière avec les objets placable (placeable objects)?

Oui. Vous pouvez demander à un coffre de s’ouvrir en utilisant ANIMATION_PLACEABLE_OPEN, ou éteindre une lampe en utilisant ANIMATION_PLACEABLE_DESACTIVATE. Vous devez juste garder quelques conseils à l’esprit :

1) Pour les objets placable qui sont source de lumière (comme les lampes), ce n’est suffisant de juste utiliser
ANIMATION_PLACEABLE_DEACTIVATE ou ANIMATION_PLACEABLE_ACTIVATE.
Ca affecte juste l’apparence de l’objet. Vous devez aussi utiliser la commande SetPlaceableIllumination
fixée à TRUE et préciser la zone concernée par RecomputeStaticLighting.
Voici un exemple d’utilisation d’une lumière plaçable:

NWScript:
// allume ou éteit les objets lumineux quand sélectionné
// à placer dans OnUsed
void main()
{
if (GetLocalInt (OBJECT_SELF,"NW_L_AMION") == 0)
{
SetLocalInt (OBJECT_SELF,"NW_L_AMION",1);
PlayAnimation (ANIMATION_PLACEABLE_ACTIVATE);
SetPlaceableIllumination (OBJECT_SELF, TRUE);
RecomputeStaticLighting (GetArea(OBJECT_SELF));
}
else
{
SetLocalInt (OBJECT_SELF,"NW_L_AMION",0);
PlayAnimation (ANIMATION_PLACEABLE_DEACTIVATE);
SetPlaceableIllumination (OBJECT_SELF, FALSE);
RecomputeStaticLighting (GetArea(OBJECT_SELF));
}
}

2) Les portes ne sont pas des objets placables. La première chose que vous devez savoir à propos de ces dernières est que si une porte est déverrouillée, une créature qui doit aller à un point de l’autre côté de celle ci l’ouvrira automatiquement.
A part ça, les commandes pour les portes sont les suivantes :
l - ActionOpenDoor: Si utilisée dans le script d’une créature, elle se déplacera jusqu’à la porte et l’ouvrira (si elle est ouverte). Si utilisée dans le script d’une porte (ou si la commande est envoyée à la porte via AssignCommand), la porte s’ouvrira toute seule.
l - ActionCloseDoor: Comme ci dessus, seulement la porte est fermée.
l - ActionLockObject: Si utilié dans le script d’une créature, elle se déplacera jusqu’à l’objet (ca peut être une porte ou un objet placable.) et tentera d’utiliser sa compétence de crochetage pour l’ouvrir. A utiliser UNIQUEMENT dans le script d’une créature !
l - ActionUnlockObject: Comme au dessus, sauf que l’objet est déverrouillé.
l - SetLocked: C’est la commande à utiliser si vous voulez verrouiller ou déverrouiller une porte ou un objet sans l’aide d’une créature ou d’une compétence. Si 'bLocked' est fixé sur TRUE, l’objet sera fermé... Si il est fixé sur FALSE, il sera déverrouillé. (exemple: Utilisé dans le propre script d’une porte, SetLocked (OBJECT_SELF, TRUE) la fermera.)

NWScript:
// A mettre dans le OnHeartbeat d’une porte, il la fermera au crépuscule
// et l’ouvrira à l’aube.
void main()
{
if (GetIsDusk() && GetIsOpen (OBJECT_SELF))
{
ActionCloseDoor (OBJECT_SELF)
// SetLocked est mise dans une ActionDoCommand parce que nous
// voulons qu’elle soit dans la file de la porte... Nous voulons
// que ActionCloseDoor soit fini avant de fermer la porte.
ActionDoCommand (SetLocked (OBJECT_SELF, TRUE))
}
else if (GetIsDawn() && GetLocked (OBJECT_SELF))
{
SetLocked (OBJECT_SELF, FALSE);
}
}


This page printed from the BioWare Neverwinter Nights Community Site: http://nwn.bioware.com
Powered by BioBoards Version 2.05.010
Please read our Copyright and Trademark Information

Et zou encore un

Par Théranthil le 17/8/2002 à 22:40:25 (#1976637)

Tutorial sur les scripts : Explication des Waypoints et Walkwaypoints.
Ecrit par David Gaider
Traduit par Théranthil
Neverwinter Nights: Print Page - Scripting Tutorial: Explaining Waypoints and Walkwaypoints

Un waypoint est un objet invisible qui est placé dans une zone (area) pour marquer un emplacement spécifique. Il a son propre tag (que vous pouvez choisir quand vous le créez) et peut optionellement être fait dans une « map note » (Il peut par exemple être nommé « General Store » et dans la mini map une icône apparaîtra à son emplacement…si le joueur déplace son curseur sur cette icône, ce label s’affichera).

L’IA générique qui vient avec NWN est telle que vous pouvez attribuer un circuit à une créature pour qu’elle marche en suivant ces waypoints automatiquement.

Comment cela se passe t’il ? Tout ce fait avec le tag du waypoint. Prenez le tag des ou de la créature(s) qui doivent utiliser les waypoints…ajoutez le préfixe « WP_ » et le suffixe « _0X »…et la créature commencera automatiquement à les suivre dans l’ordre.

Exemple :
Si j’ai un NPC guarde à qui j’ai donné le tag « GUARD ». J’ai posé 4 waypoints qui forment son circuit de patrouille.Je leur ai donné les tags "WP_GUARD_01", "WP_GUARD_02", "WP_GUARD_03" et
"WP_GUARD_04".
D’après l’IA par défaut, quand le jeu commence, il se rendra au waypoint le plus proche (que ce soit "WP_GUARD_01" ou non) puis il se rend au waypoint suivant dans l’ordre numérique. Il continue en suivant l’ordre et en faisant une pause de une seconde à chaque waypoint. Une fois arrivé au waypoint "WP_GUARD_04" il rebroussera chemin jusqu’au "WP_GUARD_01". Si il voit quelque chose d’hostile, il se déplacera pour combattre…Après avoir terminé le combat, il reviendra à sa patrouille.

L’exemple ci dessus montre évidemment un usage simple des waypoints, bien évidemment…il y a beaucoup de manières de l’améliorer. Voici néanmoins quelques questions fréquemment posées qui pourrait vous aider :

1.Si j’utilise beaucoup de waypoint pour mes NPC, il y aura BEAUCOUP de waypoints à l’écran !
Un waypoint ne peut pas uniquement être utilisé par une seule créature… mais un tag de créatures. Plusieurs créatures peuvent avoir le même tag, si vous le voulez. Il y a aussi quatre couleurs différentes que vous pouvez utiliser pour différencier les waypoints. Cependant, il peut arriver que vous ayez un certain nombre dans une zone donnée, selon ce que vous faites. Heureusement, les waypoint n’utilisent pas de scripts et n’utilise pas la puissance graphique. Si ils gênent l’affichage dans le toolset, il y a un bouton qui permet de les masquer (il y a aussi un bouton pour masquer d’autres chose, comme les créatures, les objet…).

2.Cela doit faire beaucoup de travail de renommer tous cess waypoints.
Vous pouvez éditer chaque waypoint et changer son tag si vous voulez. Heureusement, vous pouvez maintenir la touche SHIFT et selectionner les waypoints dans l’ordre dans lequel vous voulez…puis faite un click droit et sélectionnez « CreateSet ». Si vous entrez le nom du tag ('WP_GUARD' dans l’exemple ci dessus), le Toolset changera automatiquement leur tag et rajoutera le suffixe numéroté pour vous.

3. Et si je veux faire un circuit traversant une zone de transition…comme entrer dans une maison ou autre chose ?
Ca marche très bien. Je suposse que vous avez une zone de transition normale avec le wizard (avec un suspect you would have to have a regular area transition created by the wizard, ou n’importe comment …du moment que vous ne l’avez pas scriptée vous même.
J’ai récemment crée un paysan qui avait quatre waypoints, dont deux dans une autre zone (dans une maison). J’ai posé la maison dans la zone principale et connecté les deux avec une porte. Il laissa la porte ouverte après l’avoir utilisé la première fois, mais autrement ça marche très bien.

Utilisations avancées

Posts: Au lieu de lui attribuer un waypoint, vous pouvez attribuer un « post » à une créature. Créez un seul waypoint avec le préffixe « POST_ » suivi du nom de la créature.

La créature restera à son poste. Si elle engage un combat, elle y reviendra dès la fin de celui ci.

Activitées de jour et de nuit: Dans le script OnSpawn par défaut, vous pouvez « décommenter » (enlever le « // »)une fonction qui s’appelle 'SetSpawnInCondition (NW_FLAG_DAY_NIGHT_POSTING)'. Cela dit à la créature de différentier le jour et la nuit.
Comment ça affecte les WP? Et bien, vous pouvez attribuer à la créature différents set de waypoints (ou un post différent) pour le jour et la nuit en changeant leur préfixe:
waypoin de jourt: préfixe "WP_"
waypoint de nuit: préfixe "WN_"
post de jour: préfixe "POST_"
post de nuit: préfixe "NIGHT_"
Par exemple, vous pouvez dire au garde de suivre ses waypoints le jour. Alors, si le drapeau est décommenté (faudrait quand même que je trouve une autre traduction.) vous pouvez créer un waypoint "NIGHT_GUARD" dans la caserne pour qu’une fois la nuit venue, il rentre dedans.

Une dernière chose à se souvenir : quand vous faites un changement dans le script OnSpawn par défaut, vérifiez bien que vous le sauvegardez sous un nom différent…sinon ça affectera toutes les créatures de votre module.


This page printed from the BioWare Neverwinter Nights Community Site: http://nwn.bioware.com
Powered by BioBoards Version 2.05.010
Please read our Copyright and Trademark Information

et voila la suile

Par Théranthil le 18/8/2002 à 9:21:46 (#1977981)

Scripting Tutorial: Userdefined Event est votre ami.
Ecrit par David Gaider
Traduit par Théranthil
Neverwinter Nights: Print Page - Scripting Tutorial: The Userdefined Event Is Your Friend

Sérieusement. Il ny a pas du tout de blague la dedans. Il y aura naturellement des utilisateurs qui préfèreront aller plus en profondeur et personnaliser différents scripts pour remplacer lIA génériqueCertain voudront aller plus vite que ça monter leur propre version des fichier de lIA qui sont inclus. Cest génial, et il ny a rien de faux à faire ça.
Une des meilleur chose est : vous nêtes pas obligé de.98% des scripts des créatures de la campagne officielle ont été fait en utilisant UserDefinedEvent. Je me suis assis avec Preston (un de nos scripteurs et un de nos principaux gars derrière lIA) et jai posé une rapide série de choses que je voulais scripterà propos de ce que chacun était capable de faire en utilisant UserDefinedEvent. Et cest facile à utiliser.
Faisons une pause une seconde ici et discutons de ce que sont les événements. Fondamentalement une créature a des scripts numérotés (des ensembles dinstructions)et chaque script est lié à des évènements. Quand un événement a lieu, il dit à la créature de lancer le bon script. Pas dévénement=le script ne marche pas.
Il y a un nombre dévènements qui sont très souvent mentionnés ici. Lévènement « OnHeartbeat » a lieu toutes les 6 secondesdonc le script lié à cet événement se lance aussi souvent. Lévènement « OnPerceived » a lieu à chaque fois que le NPC perçoit quelque chosele script correspondant se lance.
Ces scripts peuvent aussi entraîner dautre événement qui lanceront eux même dautres scriptset cest ici que lon place le UserDefinedEvent.

Fondamentalement , UserDefinedEvent permet daccéder aux évènements normaux quune créature utilise (OnPerception,OnDeath,etc.) sans déranger lIA normale ou modifier les scripts déjà existant.


Utiliser UserDefinedEvent
Il y a un script sur chaque créature qui a déjà été souvent mentionné, et cest un de ceux que vous devriez bien connaître. Cest le script OnSpawn. Cest un événement qui marche seulement quand la créature apparaît la première foisimaginez que cest un script dinitialisation.
Le script OnSpawn générique a une série de commandes qui sont inactivées (précédées par « // »)mais en réalité, sans que lutilisateur change quelque chose, tout ce long script nexécute en fait que trois commandes : il dit à la créature de suivre les waypoint qui se réfère spécifiquement à son tag, lui donne son comportement (il répondra aux attaque des autres NPC) et génère un faible montant de trésor générique dans linventaire (de lor)
Il est écrit pour permettre à lutilisateur de définir les condition pour accéder à lIA générique comme il le veut. Tout ce quil y a à faire est de repérer le « state flag » que vous voulez utiliser et denlever le « // » au début de la commande pour lactiver Puis sauvez le script OnSpawn sous un nom différent et utilisez le à la place de script normalvoilà, le comportement générique a été modifié.


Les « state flags » auquels nous avons besoin de faire attention sont ceux la :
SetSpawnInCondition (NW_FLAG_PERCIEVE_EVENT);
//OPTIONAL BEHAVIOR - Fire User Defined Event 1002
SetSpawnInCondition (NW_FLAG_ATTACK_EVENT);
//OPTIONAL BEHAVIOR - Fire User Defined Event 1005
SetSpawnInCondition (NW_FLAG_DAMAGED_EVENT);
//OPTIONAL BEHAVIOR - Fire User Defined Event 1006
SetSpawnInCondition (NW_FLAG_DISTURBED_EVENT);
//OPTIONAL BEHAVIOR - Fire User Defined Event 1008
SetSpawnInCondition (NW_FLAG_END_COMBAT_ROUND_EVENT);
//OPTIONAL BEHAVIOR - Fire User Defined Event 1003
SetSpawnInCondition (NW_FLAG_ON_DIALOGUE_EVENT);
//OPTIONAL BEHAVIOR - Fire User Defined Event 1004
SetSpawnInCondition (NW_FLAG_DEATH_EVENT);
//OPTIONAL BEHAVIOR - Fire User Defined Event 1007

Et après?

Okay... Vous avez activé les « flags » que vous voulez scriptez et re sauvé la script OnSpawn. Ca vous a pris 2 minutes. Maintenant, comment lutiliser ?
Chaque créature a une section OnUserDefined dans laquelle vous pouvez mettre un script. Pour toutes les créatures que vous avez faites, elle est complètement videcest la ou nous allons faire notre script. Tout script que vous mettez ici sera lancé à chaque fois quun événement que vous avez « activé » (en enlevant le « // » dans le OnSpawn) se produira. Donc, si vous avez activé 'SetSpawnInCondition (NW_FLAG_DISTURBED_EVENT)', alors a chaque fois que linventaire de la créature est « perturbé » (quand quelquun vole un objet) le script OnUserDefined sera lancé.

Le script OnUserDefined basique ressemblerait à ça :

NWScript:
void main()
{
int nUser = GetUserDefinedEventNumber();
if (nUser == le nombre dans le OnSpawn, de 1001 à 1007)
{
(faire qqch)
}
}

Admettons que je veuille quune créature fasse signe au premier PC quelle voit. Je vais dans OnSpawn, « jactive » 'SetSpawnInCondition (NW_FLAG_PERCIEVE_EVENT)' et je le re sauvegarde comme un nouveau script.
Puis je crée un script dans OnUserDefined:
NWScript:
// Ce script fera que le NPC salut le PC en lapercevant
// souvenez vous que si le PC commence le module dans la zone de perception du
// NPC, le script ne se lancera pas (la perception na pas changée)
void main()
{
int nUser = GetUserDefinedEventNumber();
if (nUser == 1002) // OnPerception event
{
object oCreature = GetLastPerceived();
int nWave = GetLocalInt(OBJECT_SELF, "Wave_Once");
//vérifie que ce soit bien un PC vu la première fois
if (GetLastPerceptionSeen() && GetIsPC(oCreature) && (nWave == 0))
{
// salut quune fois
SetLocalInt(OBJECT_SELF, "Wave_Once", 1);
// fixe un temps pour que le NPC puisse re saluer 15 sec plus tard
DelayCommand(15.0, SetLocalInt(OBJECT_SELF, "Wave_Once", 0));
// se tourne face au PC
ActionDoCommand(SetFacingPoint(GetPosition(oCreature)));
// salut
ActionPlayAnimation(ANIMATION_FIREFORGET_GREETING);
SpeakString("Hello!");
}
}
}
Et cest tout. Je peux ajouter dautres condition comme une distance minimale, voir si le PC est en face de moiou lui donner un comportement aussi complexe que je le souhaiteet je nai pas à me préoccuper du script qui est déjà dans la case OnPerceive.


This page printed from the BioWare Neverwinter Nights Community Site: http://nwn.bioware.com
Powered by BioBoards Version 2.05.010
Please read our Copyright and Trademark Information

Par Théranthil le 18/8/2002 à 10:34:22 (#1978086)

Scripting Tutorial: Un script OnSpawn plus commenté
Intended Audience: For
Builders By David Gaider
Neverwinter Nights: Print Page - Scripting Tutorial: More Fully-Commented OnSpawn Script

Not all the lines in the regular OnSpawn script ("nw_c2_default9") explain how their functions are actually used. This is an updated
version that you may use if you wish.
NWScript:
//::///////////////////////////////////////////////
//:: Custom On Spawn In
//:: File Name
//:: Copyright (c) 2002 Bioware Corp.
//:://////////////////////////////////////////////
/*
*/
//:://////////////////////////////////////////////
//:: Created By:
//:: Created On:
//:://////////////////////////////////////////////
#include "NW_O2_CONINCLUDE"
#include "NW_I0_GENERIC"
void main()
{
// OPTIONAL BEHAVIORS (Comment In or Out to Activate )
****************************************************************************
//SetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION);
// Cela demande à un NPC de dire une ligne de son dialogue quand il percoit
// un joueur. Vérifiez que la ligne que vous voulez quil dise est tout en haut
// du dialogue du NPC qui démarre les nuds et que vous avez placé
// le script "nw_d2_gen_check" dans la case 'Text Appears When' de ce texte.
// Nutilisez pas ce « flag » pour des créatures hostiles.
//SetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVERSATION);
// Ce « flag » est similaire à celui ci dessus... ci ce nest quil permet à un NPC
// hostile de faire apparaître une ligne avant dattaquer. Mettez la phrase tout en haut
// du dialogue du NPC, mais placez le script "nw_d2_gen_combat" dans 'Text Appears When'
//SetSpawnInCondition(NW_FLAG_SHOUT_ATTACK_MY_TARGET);
// Cela dira au NPC que lorsquun NPC appartenant à une faction amie est attaqué ou
// attaque un ennemi (et utilise lIA générique), ce NPC attaquera à son tour.
//SetSpawnInCondition(NW_FLAG_STEALTH);
// Si le NPC possède laptitude se cacher dans lombre (hide skill), elle sera utilisée
// automatiquement, mais seulement quand la commande WalkWayPoints est appelée (ci dessous)
//SetSpawnInCondition(NW_FLAG_SEARCH);
// Si le NPC possède laptitude fouille (search), elle sera utilisée automatiquement,
// mais seulement quand la commande WalkWayPoints est appelée (ci dessous)
//SetSpawnInCondition(NW_FLAG_SET_WARNINGS);
//Le NPC donnera un avertissement aux non ennelis avant dattaquer.
//SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
// Cela sépare les waypoint du NPC entre le jour et la nuit. Normalement, un waypoint
// avec le préfixe « WP » ou « POST » sera utilisé en permanance. Si ce « flag » est // activé ces préfixes seront utilisés de jour et les préfixes « WN » ou « NIGHT » le // seront la nuit.
//SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
// Quand la créature est invoquée, il utilise EffectAppear() au lieu de faire un effet de // fondue, mais seulement si SetListeningPatterns est activé (ci dessous)
//SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
// Le NPC utilisera les animations communes quil a, et il apparaîtra plus « social »
// si il est placé près dun NPC ami.
//SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
//Pareil quau dessus, mais la créature bouge aussi aléatoirement.
//NOTE ces animations sont automatiquement jouées pour les créatures des « Encounter ».
// NOTE: VOUS NE POUVEZ ACTIVER QUUNE DES DEUX COMMANDES CI DESSUS A LA FOIS.
//SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // OPTIONAL BEHAVIOR (Fuis jusquà un waypoint et reviens peu de temps après.)
//SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // OPTIONAL BEHAVIOR (Fuis jusquà un waypoint mais ne reviens pas.)
//SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // OPTIONAL BEHAVIOR (se téléporte en suretée mais ne reviens pas.)
//SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // OPTIONAL BEHAVIOR (idem, mais reviens peu de temps après.)
// Pour utiliser 'escape', vous avez besoin dun waypoint vers lequel le NPC fuira avec comme tag « EXIT_ »+le tag du NPC
// Cette commande peut être utilisée dans un script avec la commande ActivateFleeToExit(), "NW_IO_GENERIC" doit être inclus
// Pour les commandes « escape » qui ont « return », le NPC re spawnera à son lieu de départ.
// CUSTOM USER DEFINED EVENTS
/*
Les paramètres suivant permettent à lutilisateur dactiver un événement dans le NW_D2_DefaultD. Comme le script OnSpawn, ce script est fait pour être customisé pour permettre des comportements uniques. Lutilisateur défini les événement de 1000 à 1010
*/
//SetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT); //OPTIONAL BEHAVIOR - Fire
User Defined Event 1001
//SetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT); //OPTIONAL BEHAVIOR - Fire
User Defined Event 1002
//SetSpawnInCondition(NW_FLAG_ATTACK_EVENT); //OPTIONAL BEHAVIOR - Fire
User Defined Event 1005
//SetSpawnInCondition(NW_FLAG_DAMAGED_EVENT); //OPTIONAL BEHAVIOR - Fire
User Defined Event 1006
//SetSpawnInCondition(NW_FLAG_DISTURBED_EVENT); //OPTIONAL BEHAVIOR - Fire
User Defined Event 1008
//SetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT); //OPTIONAL BEHAVIOR - Fire
User Defined Event 1003
//SetSpawnInCondition(NW_FLAG_ON_DIALOGUE_EVENT); //OPTIONAL BEHAVIOR - Fire
User Defined Event 1004
//SetSpawnInCondition(NW_FLAG_DEATH_EVENT); //OPTIONAL BEHAVIOR - Fire
User Defined Event 1007
// DEFAULT GENERIC BEHAVIOR (NE PAS MODIFIER)
*****************************************************************************************
SetListeningPatterns(); // détermine quels cris le NPC entendra.
WalkWayPoints(); // Optional Parameter: void WalkWayPoints(int nRun =
FALSE, float fPause = 1.0)
// 1. Regarde si un waypoint possède le tag "WP_" + TAG DU NPC + "_0X", si cest le cas, marche jusquà eux.
// 2. Si le tag du waypoint est "POST_" + NPC TAG la créature y retournera après un
// combat.
// Pour quun NPC recommence à suivre les waypoint après une conversation, vous devez
// aller dans son fichier dialogue, dans « Other Files », appellez aussi cette commande // dans les sections « End » et « Aborted » du script
GenerateNPCTreasure(); //* Cest pour créer un trésor de faible montant sur la créature
}


This page printed from the BioWare Neverwinter Nights Community Site: http://nwn.bioware.com
Powered by BioBoards Version 2.05.010
Please read our Copyright and Trademark Information

et deux d'un coup...

Par Théranthil le 18/8/2002 à 12:35:41 (#1978421)

Scripting Tutorial: Récompenser avec de lor et de lXP
Ecrit par David Gaider
Traduit par Théranthil
Neverwinter Nights: Print Page - Scripting Tutorial: Rewarding Gold et XP

Les deux principales commandes que vous avez à utiliser .

void GiveGoldToCreature(object oCreature, int nGP)

void GiveXPToCreature( object oCreature, int nXpAmount)

Il y a aucun problème pour la provenance de lXP et de lor. Seule la destination peut changeercest pourquoi on peut utiliser ces commandes de nimporte où.
Pour donner 100 po au PC avec lequel je parle (placé dans un script à lintérieur de « Action Taken ») :

GiveGoldToCreature (GetPCSpeaker(), 100);

Pour donner 100 XP à chaque membre de la partie, en commençant par le plus proche :

NWScript:
object oFirstMember = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR,
PLAYER_CHAR_IS_PC);
object oPartyMember = GetFirstFactionMember(oFirstMember, TRUE);
while (GetIsObjectValid(oPartyMember) == TRUE)
{
GiveXPToCreature(oPartyMember,100);
oPartyMember = GetNextFactionMember(oFirstMember, TRUE);
}
}

(Personellement, je voulais mettre cela dans une fonction pour ne pas avoir besoin de tout recopier à chaque fois.)
Quelques autres conseil quil est pratique de connaître en rapport avec lexpérience et lor :
- Quand vous écrivez le journal dans le « journal editor », vous pouvez assigner une « XP Value » à chaque entrée. Ce nombre peut être rappelé avec la fonction suivante :
int GetJournalQuestExperience(string szPlotID)

Dans la campagne, vous avez un PlotID pour chaque quête (qui peut consister en plusieurs entrées de journal jusquà 'completion') et chaque PlotID a une valeur dXP. Et nous donnons lXP en pourcentage de quête réalisé. 50% du total pour ceci, 25% pour cela,etc.

- Combien dor quelquun a?

int GetGold( object oTarget = OBJECT_SELF)

Pour trouver combien dor quelquun a, lancez le script en lancant GetGold()mais il ne peut littéralement cibler personne.

- Si vous voulez enlever de lor à quelquun dautre :

void TakeGoldFromCreature( int nAmount, object oCreatureToTakeFrom, int bDestroy = FALSE)

Si vous mettez TRUE après 'bDestroy', lor reprise sera enlevée du module et plus personne ne pourra lutiliser.)


This page printed from the BioWare Neverwinter Nights Community Site: http://nwn.bioware.com
Powered by BioBoards Version 2.05.010
Please read our Copyright and Trademark Information

Par Théranthil le 18/8/2002 à 12:36:47 (#1978427)

Scripting Tutorial: Faire des jets de compétence.
Ecrit par David Gaider
Traduit par Théranthil
Neverwinter Nights: Print Page - Scripting Tutorial: Making Skill Checks

Tout dabord, si vous ne savez pas comment un jet de compétence est fait dans D&D 3, voilà une rapide explication :
A chaque fois que vous essayez daccomplir une action en utilisant vos compétences, vous lancez un d20 (un dé à 20 faces numérotées de 1 à 20) et vous rajoutez à ce résultat votre rang dans cette compétence et votre bonus dans la caractéristique liée à cette compétence. Plus le résultat est élevé mieux cest, et vous essayez dégaler ou de dépasser un DC « difficulty class » (en français DD « degré de difficulté ») un nombre qui a été décidé par le DM.
Admettons quun joueur veut utiliser sa compétence de désamorçage (Disable Traps skill) sur un piège quil a découvert. Le DM fixe le DC à 25 (une tache moyennement difficile). Le joueur a un rang de 8 dans cette compétence et un modificateur de +3 en dextérité (la caractéristique lié à la compétence de désamorçage). Il lance un d20 et ajoute +11 à ce jet, il a besoin de faire 14 ou plus pour réussir cette tache.
Pour des choses tels que le désamorçage et beaucoup dautres compétences, le jet est pris en main par le moteur du jeu et souvent, la seule chose demandée au DM est le DC.
Cependant, Il ny a pas dans les scripts de NWN une commande automatique qui fait ces jets pour vous si vous utilisez une compétence dans un script (que ce soit pour vérifier le succès dune persuasion dans un dialogue ou tout autre utilisation de compétence qui nest pas pris en charge automatiquement). Si vous voulez les utiliser, vous devez soit avoir un script qui le fait, soit utiliser la fonction que nous avons faite dans la campagne officielle.

La campagne de la campagne officielle
La chose que certain peuvent ne pas aimer à propos de la commande AutoDC est que le DC est généré automatiquementil nest pas spécifié à chaque fois. Quand le scripteur utilise cette commande, il spécifie DC_EASY, DC_MEDIUM ou DC_HARD et le DC est généré en fonction du niveau du PC.

La syntaxe est la suivante:

int AutoDC(int DC, int nSkill, object oTarget)

Donc si je veux faire une persuasion difficile avec le NPC avec qui le PC parle, je peux utiliser ceci:

AutoDC(DC_HARD, SKILL_PERSUADE, GetPCSpeaker());

Un commentaire ici, le let de compétence renvoie un integer (the int) parce que la commande doit renvoyer soit TRUE soit FALSE. False (ou un « 0 » integer) signifie que le jet est un échec. True (ou un '1' integer) signifie quil est réussi.
Si vous voulez utiliser un jet de compétence dans le « dialogue editor », vous devez « séparer » la conversationca veut dire que pour une même réponse du PC, il doit y avoir plus dun dialogue du NPC. Quand le dialoque est présenté comme ceci, il regarde le script dans « Text Appears when », en commençant par le nud du haut et descendant jusquen bas. Le premier script qui renvoie TRUE (ou qui na pas de script), il lutilise.
Un exemple de script avec un jet de persuasion facile :
NWScript:
#include "NW_I0_PLOT"
int StartingConditional()
{
int iCheck = AutoDC(DC_HARD, SKILL_PERSUADE, GetPCSpeaker()) == TRUE;
return iCheck;
}
So you could have something like this:
"Oh,Je ne peux certainement pas vous le dire, cest confidentiel."
A. "Oh, Je suis sur quil ny a aucun mal à me le dire."
B. "Dite le moi ou vous en surpoterez les conséquences, jeune fille."
C. "Laissez moi vous dire quelque chose dautre, alors."

Si je sélectionne loption B, le dialoque se sépare en 2:
|
|
--> #1. (avec le script de persuasion dans 'Text Appears When') "Je suppose que vous avez raison. Ok, cest comme ça..."
|
|
--> #2. (sans script) "Oubliez ça, je ne vous le dirais pas."
#1 si le jet a été réussi, #2 la partie en cas déchec. Si le script en #1 renvoie TRUE, cette voie est suivie est le joueur aura réussi. Lautre voie na pas besoin de scriptsi la première voie était fause, ca voudrais dire que le PC a manqué son jet.

Ecrire votre propre fonction

Pour écrire votre propre jet de compétence, vous devez suivre la même logique que si vous vouliez faire le jet un JdR sur table. Vous avez besoin du bonus du PC pour le jet de dé, du dé et du DC (choisi par le DM)

Quelques commandes que vous pouvez utiliser :

int GetSkillRank(int nSkill, object oTarget=OBJECT_SELF)
Elle renvoie le rang + le bonus de caractéristique de la cible

int GetLevelByClass(int nClassType, object oCreature = OBJECT_SELF)
Elle renvoie le niveau de la créature dans une classe particulière (comme par exemple CLASS_TYPE_FIGHTER).

int GetHitDice(object oCreature)
Cest pratique si vous voulez le niveau du PC sans tenir compte des classes.

int GetAbilityModifier(int nAbility, object oCreature=OBJECT_SELF)
Donne le modificateur dune caractéristique particulière, pratique si vous voulez faire un jet de force uniquement, ou quelquechose de similaire..
De toute manière, voici un exemple de jet de premier secour (Heal skill) fait à la main (à placer à lendroit voulu dans le dialogue):
NWScript:
int StartingConditional()
{
int iDC = 20; // ou ce que le DM veut mettre
int iBonus = GetSkillRank(SKILL_HEAL, GetPCSpeaker());
if ((d20() + iBonus) >= iDC)
{
return TRUE;
}
return FALSE;
}

Bien évidemment, ce nest quun exempleil y a une méthode pré construite pour utiliser les soins normalement (avec la commande ActionUseSkill)ce type de script est fait pour les jets de dé personnalisés, que, je sais, les gens veulent faire.


This page printed from the BioWare Neverwinter Nights Community Site: http://nwn.bioware.com
Powered by BioBoards Version 2.05.010
Please read our Copyright and Trademark Information

Par Théranthil le 18/8/2002 à 17:42:05 (#1979693)

Scripting Tutorial: Créer des objets uniques
Ecrit par David Gaider
Traduit par Théranthil
Neverwinter Nights: Print Page - Scripting Tutorial: Making Unique Items

NdT :il est ici difficile de différencier les termes « object » (qui désigne quasiment tous modèles 3D, des chaises aux personnages et aux pièges) et « item » (qui désigne ce quon peut avoir dans son inventaire (épée, armure). Pour les différencier, quand jutiliserais « objet » (entre guillemets) ça désigne le terme « object », et sans guillemets, il désigne les « items ».

Comment un script crée ces propres objets qui vont au dela des objets standartsComment par exemple faire un effet conditionnel ? Comment puis je scripter une baguette de souhait ou une épée parlante ?
Bien, la première a réaliser est que, par opposition aux « objets » (chaise, lampe) et aux créatures, ils nont pas de script propre. Vous ne pouvez pas aller dans les propriétés des objets et spécifier quels scripts utiliseril ne peut en utiliser aucun.

La seule manière par laquelle vous pouvez affecter des scripts à des objets, cest dans le « module level ». Dans les propriétées du module, vous avez 3 évènements qui affectent les objets.
Deux de ces énènements sont OnAquireItem et OnUnAcquireItem. Cela veut dire quà chaque fois quun objet est pris ou laissé tomber, un événement est lancer qui démarre le script approprié. Si il ny a pas de script, rien ne se passe.
Donc, si je veux fixer une variable quand une épée particuliaire (qui a le tag « SWORD01 ») est prise, je peux mettre ce script dans le section OnAcquireItem du module :

NWScript:
void main ()
{
object oItem = GetObjectByTag("SWORD01");
int iVar = GetLocalInt(GetItemPossessor(oItem), "VARIABLENAME");
// ci dessous est spécifié : « Si le déclenchement est bien celui voulu, et que aucune // variable na été spécifiée, fixez la variable sur le possesseur de lobjet.
if ((GetModuleItemAcquired() == oItem) && (iVar == 0))
{
SetLocalInt(GetItemPossessor(oItem), "VARIABLENAME", 1);
}
}

Cependant, ce nest pas très utile pour scripter vos propres objets, nest ce pas ? Por cela, vous devez tirer avantage du troisième événement du module : OnActivateItem().
Activer un objet requière un événement spécifique. Quand vous créez un objet, vous pouvez lui assigner une propriétée « Cast Spell » (lancer un sort)et deux des choix peuvent être Unique Power et Unique Power :Self Only. La différence entre eux est que le second est simplement un déclencheur de lévénement « OnActivateItem »le premier vous demande dabord la cible du pouvoir unique.
Ce « Unique Power » apparaît dans le menu radial de lobjet comme nimporte quel autre caractéristique. Si vous voulez spécifier à lutilisateur ce quest cette caractéristique, vous devez linclure dans la description de lobjet (il y a une description pour lobjet « identifié » et « non identifié », vous pouvez aussi utiliser les 2).
Quand vous écrivez le script à placer dans OnActivateItem(), il y a juste quelques références que vous devez garder à lesprit :

object GetItemActivated()
cela renvoie lobjet qui a déclenché lévénement OnActivateItem().

object GetItemActivatedTarget()
Cela renvoie la cible du pouvoir unique, si il est ciblé comme un objet spécifique.

location GetItemActivatedTargetLocation()
Cela renvoie la cible du pouvoir unique, si il est ciblé comme un emplacement plutôt quun objet spécifique.

object GetItemActivator()
Renvoie la créature qui a activée lobjet... un peu plus pratique que dutiliser GetItemPossessedBy.

Et cest tout ce dont vous avez besoin. Avec ça, vous pouvez scriptez autant de propriétées pour autant dobjets que vous le souhaitez. Gardez quand même à lesprit que ces scripts sont spécifiques au module. Si vous prenez lobjet dun autre module qui naura pas ce script in le OnActivateItem(), alors rien ne se passera.

NOTE: Il y a actuellement un bug avec OnActivateItem en ce qui concerne les objet à usage unique (et qui arrive aussi aux objet qui nont plus quune charge). Quand un objet est usé, il disparaîtlévénement se lance, mais toutes les commandes comme GetItemActivate renvoie un objet invalide (car lobjet nexiste plus.)


This page printed from the BioWare Neverwinter Nights Community Site: http://nwn.bioware.com
Powered by BioBoards Version 2.05.010
Please read our Copyright and Trademark Information

Par Théranthil le 18/8/2002 à 17:42:46 (#1979695)

Scripting Tutorial: Sitting In Chairs and Sleeping
Ecrit par David Gaider
Traduit par Théranthil
Neverwinter Nights: Print Page - Scripting Tutorial: Sitting In Chairs and Sleeping

Comment puis je dire à mon PC de sasseoir sur une chaise ?

Il ny a actuellement pas d « emote » pour faire asseoir un PC sur une chaise. Jusquà ce quun soit ajouté pour les PC, le script pour faire asseoir un PC sur une chaise doit être placé dans lobjet lui même.
Si vous mettez un objet placable utilisable « chaise » (la chaise doit avoir la case « Useable » cochée, et vérifiez que le PC à la place de sasseoir), mettez le script dans la partie OnUsed de longlet des scripts :

NWScript:
void main()
{
object oChair = OBJECT_SELF;
if(!GetIsObjectValid(GetSittingCreature(oChair)))
{
AssignCommand(GetLastUsedBy(), ActionSit(oChair));
}
}

Quand je place un NPC dans le toolset, il reste debout. Il ny a aucun moyen de la mettre assise ?
Pas dans le toolset,nonla créature doit être debout. Elle doit être scriptée pour que quand le jeu démarre, elle trouve une chaise et sasseye dessus grâce à la commande ActionSit.
Créez un objet placable « chaise » (chair) et donnez lui le tag « CHAIR ». Placez le NPC près de la chaise. Copiez et sauvez son script sous un autre nom en rajoutant cette ligne en haut du script :

ActionSit (GetNearestObjectByTag ("CHAIR", OBJECT_SELF));

Notez que quand un PC parle au NPC, il se lèvent. Pour quil se rasseye, vous devez aller dans longlet « Other Files » dans leur dialogue. Vous devez voir des emplacements pour deux scripts ici, qui sont activés quand le dialogue est fini ou interrompu.
Faire un script qui appelle la ligne ci dessus et il se rasseira quand le dialogue se terminera.

Cest bien tout ça, mais je veux déjà asseoir le PNC dans le tileset ?

Quelques utilisateurs ont remporté du succès un suivant la même processus en lasseyant sur une chaisemais en trouvant un objet placable « invisible object » , placez le à la place de la chaise. Donnez lui le tag « CHAIR » et utilisez la même ligne quau dessus et il sasseira la pour vous.

Et si je veux que mon PC dorme su un lit ?
Il ny a actuellement aucun moyen de dire à une créature de lallonger sur un lit ou un « tileset » lit. Un objet placable peut être placé sur un lit, mais pas une créature.
Une créature peut cependant dormir sur un objet placable « bedroll » (paillasse) ou sur le sol. Si vous voulez quune créature commence le jeu en dormant, vous devez faire une copie du script OnSpawn de la créature et le sauvegarder sous un autre nom, et ensuite rajouter en haut du script les lignes suivantes :

effect eLieDown = EffectSleep();
effect eSnore = EffectVisualEffect (VFX_IMP_SLEEP);
effect eSleep = EffectLinkEffects (eLieDown, eSnore);
ApplyEffectToObject (DURATION_TYPE_PERMANENT, eSleep, OBJECT_SELF);

Réveiller votre NPC
Si vous voulez quun NPC se réveille à un certain moment, vous devez utiliser la commande RemoveEffect. Un effet, une fois appliqué, ne peut pas avoir une variable définie comme EffectSleep, et le désactiver par cette commande.
Le « pointeur » doit être sur cet effet particulier. Si leffet est la même variable dans le même script que quand il est utilisé, vous pouvez simplement utiliser ceci :
RemoveEffect (OBJECT_SELF, eSleep);

Cependant, vous devez scanner les effets dun objet et trouver celui que vous cherchez parmi tous les autres. Le script ci dessous est un script simple pour enlever leffet sleep à un objet. (Il est dans le OnHeartbeat de la créature et la réveille si un hostile approche à moins de 5m.):
NWScript:
// script de réveil
#include "NW_I0_GENERIC"
void main()
{
// si je dors
if (GetHasEffect(EFFECT_TYPE_SLEEP))
{
// donne lennemi le plus proche de moi
object oTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION,
REPUTATION_TYPE_ENEMY);
// si il y en a un et quil est à moins de 5 mètres
if ((GetDistanceToObject(oTarget) < 5.0) && (GetIsObjectValid(oTarget)))
{
effect eSleep = GetFirstEffect(OBJECT_SELF);
// regarde les effets actuels
while (GetIsEffectValid(eSleep))
{
// et si lun deux est sommeil, mais ne viens pas dun sort de sommeil
if ((GetEffectType(eSleep) == EFFECT_TYPE_SLEEP) &&
(GetEffectSpellId(eSleep) != SPELL_SLEEP))
{
// enlevez le
RemoveEffect(OBJECT_SELF, eSleep);
}
eSleep = GetNextEffect(OBJECT_SELF);
}
}
}
}


This page printed from the BioWare Neverwinter Nights Community Site: http://nwn.bioware.com
Powered by BioBoards Version 2.05.010
Please read our Copyright and Trademark Information

et paff encore un

Par Théranthil le 18/8/2002 à 19:27:22 (#1980183)

Scripting Tutorial: Comment faire pour quun NPC entame un dialogue tout seul?
Ecrit par David Gaider
Traduit par Théranthil
Neverwinter Nights: Print Page - Scripting Tutorial: How Do I Make My NPC's Initiate Dialogue On Their Own?

OK, avant tout : avant de savoir EXACTEMENT ce que vous allez faire, ne touchez PAS au script qui est normalement dans OnPerception ("nw_c2_default2"). Laissez le tranquille. Si quelquun vous demande de changer quelque chose dans les scripts OnSpawn et OnUserDefined de votre NPC et que vous nêtes pas sur de ce que vous allez faire, ne le faite pas.
Comme mentionné plus haut, lIA générique est programmée pour permettre grâce à UserDefinedEvent dutiliser les évènements sans modifier les script par défaut.

Utiliser la méthode « OnPerceive » pour commencer une conversation.
1) Allez dans votre script OnSpawn. Sauvez le sous un nouveau nom. Puis, allez jusquà la ligne où il y a marqué 'SetSpawnInCondition (NW_FLAG_PERCIEVE_EVENT);' et activez la (enlevez le '//' double slashes au début de la ligne). Sauvegardez ce nouveau script.

2) Dans le fichier dialogue du NPC, allez à la toute première ligne, la où commence le dialogue avec le PC. Si vous voulez juste quil commence à parler avec un PC donné, ajoutez le script suivant dans « Action Taken » :

NWScript:
void main()
{
SetLocalInt(GetPCSpeaker(), "Dlg_Init_" + GetTag(OBJECT_SELF), TRUE);
}

Cela fixe la variable qui est utilisé dans le script que nous allons utiliser, pour quil ne lance pas le dialogue plus dune fois.

3) Maintenant, créez un nouveau script dans OnUserDefined event de votre NPC. Vous pouvez y mettre le script suivant:

NWScript:
void main()
{
int nEvent = GetUserDefinedEventNumber();
if (nEvent == 1002) // OnPerceive event
{
object oPC = GetLastPerceived();
if(GetIsPC(oPC) && GetLocalInt(oPC, "Dlg_Init_" + GetTag(OBJECT_SELF)) == FALSE
&& !IsInConversation(OBJECT_SELF))
{
ClearAllActions();
AssignCommand(oPC, ClearAllActions());
ActionMoveToObject(oPC);
ActionStartConversation(oPC);
}
}
}

UNE ERREUR POSSIBLE: Maintenant... une raison pourquoi ca ne marche pas ? Si votre PC commence le jeu dans la ligne de perception du NPC, il ny aura pas dévénement OnUserDefined. Lévénement a lieu uniquement si le PC était pas perçu et arrive à portée.

Utiliser la méthode des déclencheurs pour démarrer une conversation.
Cest celle que nous avons utilisé dans la campagne officielle. Elle vous permet de déterminer à partir de quel point le NPC va courir vers le PC, et aussi déterminer sur quelle distance le NPC va courir après le PC avant dabandonner.
Pour lutiliser, voici ce que vous devez faire :To set this up, you need to do the following:
1) Comment au paragraphe 2 ci dessus, dans le fichier du dialogue du NPC, allez à la toute première ligne la où le dialogue commence avec le PC. Si vous voulez seulement démarrer ce dialogue avec nimporte quel PC donné, ajoutez le script du paragraphe 2 ci dessus dans « Action Taken » :

NWScript:
void main()
{
SetLocalInt(GetPCSpeaker(), "Dlg_Init_" + GetTag(OBJECT_SELF), TRUE);
}

2) Allez dans votre toolset. Créez un waypoint à lendroit ou vous voulez que le NPC revienne. Mettez lui le tag « WP_RETURN_ »+ le tag du NPC (donc si le NPC sappelle Fred, le tag sera « WP_RETURN_Fred ». Souvenez vous que le tag différencie les majuscules des minuscules !

3) Pendant ce temps, créez un nouveau déclencheur (trigger) générique et dessinez un polygone autour du NPC. Quand le PC entrera dans cette zone, le NPC courra jusquà lui pour lui parler. Si le NPC quitte cette zone, il arretera de lui courir après et retournera au waypoint.

4) Allez dans longlet « Script » du déclencheur et ajoutez le script suivant dans OnEnter :

NWScript:
// Cest le script OnEnter du trigger si vous voulez
// que le NPC déclenche le dialogue.
// remplacez bien "NPC_TALKER" par le script du NPC
void main()
{
object oNPC = GetObjectByTag("NPC_TALKER");
object oPC = GetEnteringObject();
if(GetIsPC(oPC) &&
GetLocalInt(oPC,"Dlg_Init_" + GetTag(oNPC)) == FALSE &&
!IsInConversation(oNPC))
{
AssignCommand(oPC,ClearAllActions());
AssignCommand(oNPC,ClearAllActions());
AssignCommand(oNPC,ActionMoveToObject(oPC));
AssignCommand(oNPC,ActionStartConversation(oPC));
}
}

5) Maintenant, nous voulons éviter que le NPC poursuive le PC sans arrêt. Entrez le script suivant dans lemplacement OnExit du déclencheur (trigger):

NWScript:
// Cela va demander au NPC darrêter de poursuivre le PC
// si il quitte la zone du déclencheir (trigger)
// emplacez bien "NPC_TALKER" par le script du NPC.
// Vous devez aussi avoir un waypoint avec le tag "WP_RETURN_" + tag du NPC.
// Il doit être placé à lendroit de départ du NPC.
void main()
{
string sTag = "NPC_TALKER";
object oExit = GetExitingObject();
if(GetTag(oExit) == sTag)
{
AssignCommand(oExit,ClearAllActions());
AssignCommand(oExit,ActionMoveToObject(GetNearestObjectByTag("WP_RETURN_" +
sTag)));
}
}

Cette méthode ne tiens pas en compte si le PC est visible ou pastraverser la zone du déclencheur activera le NPC. Si vous voulez en tenir compte, ajoutez la ligne suivante juste après « if(GetIsPC(oPC) && » dans le script OnEnter:
GetObjectSeen(oPC, oNPC) &&

Mais, en multijoueur, le NPC essayera de parler avec chaque PC. Si vous voulez qui courre vers seulement un PC, faites ce qui suit :
1) Dans le script du dialogue, remplacez 'GetPCSpeaker()' par 'OBJECT_SELF'.
2) Dans le script OnUserDefined (pour la première méthode) ou le OnEnter (pour la seconde), remplacez « oPC » dans la commande GetLocalInt par « oNPC ».


This page printed from the BioWare Neverwinter Nights Community Site: http://nwn.bioware.com
Powered by BioBoards Version 2.05.010
Please read our Copyright and Trademark Information

Par Théranthil le 18/8/2002 à 19:57:10 (#1980309)

Scripting Tutorial: Comment faire pour que mon NPC attaque le PC avec lequel il est en train de parler?
Ecrit par David Gaider
Traduit par Théranthil
Neverwinter Nights: Print Page - Scripting Tutorial: How Do I Make My NPC Attack The PC He Is Talking To?

Je voudrais ajouter un script qui fait que le NPC devienne hostile. Placez le script dans la case « Action Taken » en bas à droite de léditeur de dialoguevérifiez que vous avez bien sélectionné le nud où vous voulez que la battaille commence.
Si vous voulez que la faction du NPC devienne hostile contre la cible, utilisez le script générique
"nw_d1_attonend":

NWScript:
//::///////////////////////////////////////////////
//:: Attaque à la fin de la conversation.
//:: NW_D1_AttOnEnd
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
Le script dit au NPC dattaque le PC avec lequel il est en train de parler.
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Nov 7, 2001
//:://////////////////////////////////////////////
#include "NW_I0_GENERIC"
void main()
{
AdjustReputation(GetPCSpeaker(), OBJECT_SELF, -100);
DetermineCombatRound();
}

Si vous voulez juste que seul le NPC devienne hostile et attaque, utilisez le script générique "nw_d1_attonend02":

NWScript:
//::///////////////////////////////////////////////
//:: Attaque à la fin de la conversation.
//:: NW_D1_AttOnEnd02
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
Le script dit au NPC dattaque le PC avec lequel il est en train de parler.Il ne change que lattitude du NPC, pas de la faction toute entière.*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Nov 7, 2001
//:://////////////////////////////////////////////
#include "NW_I0_GENERIC"
void main()
{
SetIsTemporaryEnemy(GetPCSpeaker());
DetermineCombatRound();
}

Une chose dont il faut se méfier: Si vous appliquez ce script au nud ou le NPC est en train de parler, il deviendra hostile tout de suite et le nud ne sera pas affiché. Comme si le NPC navait pas le temps de le lire entièrement, si cest une longue partie du dialogue.
Si vous êtes daccord avec ça, tant mieux. Sinon, utilisez le bouton Add pour rajouter un nud après le dernier nud du NPC. Effacez le texte de la réponse du PC et appuyez sur EnterCela affichera un nud [End Dialogue]. Ajoutez le script dans la zone « Action Taken » de la fin du dialogue à la place de lautre emplacement. Comme cela, le Pc peut lire ce que le NPC lui ditet quand il appuie sur « Enter » pour continuer, le NPC attaque.

PROBLEMES FREQUENTS: Verifiez que la créature qui doit entammer le combat na AUCUN niveau en « Commoner ». Les roturiers sont définis par lIA pour prendre la fuite face à quelquun hostile, et de former un groupe uniquement si il y a des roturiers de niveau 10 ou plus à proximitée.
Vérifiez aussi que si vous utilisez les « Special Behaviors » (comportements spéciaux) dans le script OnSpawn, vous nutilisez pas le comportement « Herbivore » (on ne sait jamais ;)). Les herbivores nengagent jamais le combat et prennent toujours la fuite.


This page printed from the BioWare Neverwinter Nights Community Site: http://nwn.bioware.com
Powered by BioBoards Version 2.05.010
Please read our Copyright and Trademark Information

Par Théranthil le 18/8/2002 à 22:29:22 (#1981117)

Scripting Tutorial: Comment puis je ouvrir mon magasin?
Ecrit par David Gaider
Traduit par Théranthil
Neverwinter Nights: Print Page - Scripting Tutorial: How Do I Start My Store?

Créer des magasin basiques est relativement simpletout ce que vous avez à faire est dutiliser le « store wizard » et ça vous crée un « objet » magasin basique avec un inventaire, un pourcentage daugmentation ou du réduction du prix, un nom et un tag. Mais quest ce que vous allez faire avec ?

Etape 1: Placez l « objet » magasin dans votre module. Un magasin est juste un blueprint non placé auquel on ne peut accéder par le module. Vous devez maintenant le placer quelque part. Vous noterez que quand vous le placez, il ressemble juste à un waypointcest bien. Les joueurs ne le verront pas et ne pourront pas interagir avecil a juste besoin dexister, de préférence près de lobjet qui va lappeler (le marchant par exemple).

Etape 2: Créez lobjet y accèdent. Habituellement, cest un NPC marchant... mais ce nest pas obligé.
Tout objet qui peut lancer un script peut ouvrir un magasin. Cependant, avoir un marchant PNC est le moyen le plus facile. Créez simplement votre marchant et allez créer un dialogue pour lui. La méthode la plus simple est de lui faire dire « Bienvenue ! Est ce que vous voulez jeter un il à mes marchandises ? » Puis dajouter deux réponses : « Oui » et « Non »

Etape 3: Ajouter le script qui ouvrira le magasin. Dans le dialogue ci dessus, vous devez entrer ce script dans « Action Taken » pour la réponse « oui » du joueurdonc quand le joueur sélectionnera cette réponse, le magasin est ouvert. Vous navez rien besoin dajouter dans « No »cela terminera simplement la conversation.
Le script basique pour ouvrir un magasin à la fin du dialogue est celui ci :

NWScript:
void main()
{
object oStore = GetObjectByTag("STORE_TAG_HERE");
OpenStore(oStore, GetPCSpeaker());
}
...et cest tout. Naturellement, vous devez remplacer "STORE_TAG_HERE" par le tag de votre magasin..
Si vous regardez la structure de la commande OpenStore, vous verrez que vous pouvez rajouter marque dune réduction et une augmentation du prixcest juste au cas ou vous voulez en faire une utilisation conditionnelle. Prenez le script qui suit par exemplele vendeur double les prix pour les elfes (il ne les aime pas) :

NWScript:
void main()
{
object oStore = GetObjectByTag("STORE_TAG_HERE");
if (GetRacialType(GetPCSpeaker()) == RACIAL_TYPE_ELF)
{
OpenStore(oStore, GetPCSpeaker(), 100);
}
else OpenStore(oStore, GetPCSpeaker());
}
Un dernier commentaire sur les magasins: Les magasins ne peuvent pour linstantoffrir que des objets génériques, cest un peu limité. Peut être que ça changera dans le futur. Sachez que vous ne pouvez pas ajuster le prix des objets individuellementun marchant applique les même majorations ou réductions à tous les objetsde même vous ne pouvez pas préciser quels types dobjets le marchant pourra acheter ou non. Cest tout ou rien. Une dernière chose, dans tous les scripts, les commande en rapport avec les objets comme CreateItemOnObject, GetFirstItemInInventory et GetNextItemInInventory doit avoir pour cible le magasin lui même. Souvenez vous : cest lui qui a linventaire, pas le marchant.


This page printed from the BioWare Neverwinter Nights Community Site: http://nwn.bioware.com
Powered by BioBoards Version 2.05.010
Please read our Copyright and Trademark Information

Par Théranthil le 18/8/2002 à 22:30:04 (#1981122)

Scripting Tutorial: Utiliser les « Module Events »
Ecrit par David Gaider
Traduit par Théranthil
Neverwinter Nights: Print Page - Scripting Tutorial: Using Module Events

Quand des évènements sont déclenchés (dans nimporte quel module, que ce soit objet valable, ou quelque chose dautre.), la part la plus importante de lutilisation des évènements via les scripts est dêtre capable didentifier qui ou quest ce qui a déclenché les évènements. Gardez à lesprit que cest séparé du UserDefinedEventce sont des événement qui sont « hard codés » dans chaque objet individuel. Vous assignez un script à cet événement et, quand il est déclenché, ce script se sancera.

Liste des « Module Event »

Evenement (event): OnAcquireItem, déclencheur: à chaque fois quun objet est ajouté à linventaire de quelquun., Quest ce qui le déclenche ? Utiliser GetModuleItemAcquired().Aussi utilisé dans: GetModuleItemAcquiredFrom() pour retourner l « objet » qui a donné lobjet , GetItemPossessor(object oItem) pour retourner celui qui a « gagné » lobjet.

Evenement (event): OnActivateItem, déclencheur: à chaque fois quun objet utilise une capacité spétiale de lobjet à fin dincantation, quil soit ciblé (Unique Power) ou non (Unique Power-Self Only) Quest ce qui le déclenche ? Use GetItemActivated().Aussi utilisé dans: GetItemActivatedTarget() pour déterminer la cible du sort si il est ciblé, GetItemActivatedTargetLocation() pour déterminer lemplacement du sort, si la cible est un point, GetItemActivator() pour déterminer le possesseur de lobjet au moment ou il a été activé.

Evenement (event): OnClientEnter, déclencheur: à chaque fois quun jour arrive dans le module, Quest ce qui le déclenche? Utiliser GetEnteringObject() pour renvoyer l« objet » joueur (savoir quel est le joueur qui est rentré.)

Evenement (event): OnClientLeave, déclencheur: à chaque fois quun joueur quitte le module, Quest ce qui le déclenche? Utiliser GetExitingObject() renvoie l« objet » joueur (savoir quel est le joueur qui est sorti.).

Evenement (event): OnModuleLoad, déclencheur: quand le module démarre la première fois, Quest ce qui le déclenche ? Le module lui même...
Il ny a pas dobjet spécifique qui rentre dans cette case. Cest le script OnSpawn du module, ill est lancé une fois, quand le module est chargé.

Evenement (event): OnPlayerDeath, déclencheur: un PC meurt, Quest ce qui le déclenche? Use object
GetLastPlayerDied() pour renvoyer le PC qui vient de mourir. Utilisation par défaut: le script "nw_o0_death" est généralement utilisé ici, qui annule toute relations avec la faction standard du joueur et détermine quand le panneau « death GUI » qui permet au joueur de quitter ou de respawn.

Evenement (event): OnPlayerDying, déclencheur: un joueur a été réduit en dessous de 0 point de vie, Quest ce qui le déclenche? Utiliser GetLastPlayerDying(). La différence entre celui la et OnPlayerDeath est que la lee PC na plus de points de vie, mais nest pas encore officiellement « mort ». Utilisation par défaut: Le script placé ici par défaut est "nw_o0_dying" qui applique les effets de la mort au joueur (EffectDeath) et le tue officiellement pour déclencher lévénement « OnPlayerDeath ». Si le script est enlevé, le joueur saignera jusquà sa mort à 10 points de vie.

Evenement (event): OnPlayerLevelUp, déclencheur: un joueur monte de niveau, Quest ce qui le déclenche? Utiliser lobjet GetPCLevellingUp(). Cela renvoie le joueur qui a monté de niveau... mais il ny a aucune manière dempêcher le joueur de terminer le processus, comme de le faire instantanément ainsi que de faire une action comme se reposer.

Par Théranthil le 19/8/2002 à 10:01:38 (#1983250)

Scripting Tutorial: Utiliser les « Area Events »
Ecrit par David Gaider
Traduit par Théranthil
Neverwinter Nights: Print Page - Scripting Tutorial: Using Area Events

Gardez à lesprit que quand vous créez des scripts pour les évènements de la zone (Area events) (ou pour les évènements du modules (Module events)) « léxécutant » par défaut de nimporte quelle « commande action » (toutes les commandes commençants par le mot Action) est la zone (area) elle même.
Si vous référez à OBJECT_SELF, vous vous référez à la zone.. Si vous utilisez une commande commençant par Action comme ActionMoveToObjet sans utiliser AssignCommand pour envoyer cette commande à une créature, vous demandez à la zone de bouger (qui, évidemment, ne le peut pas). Gardez ça simplement à lesprit quand vous codez, comme ça, vous pouvez faire la différence entre dire à la zone de faire quelque chose et dire à quelque chose de faire quelque chose (pas très précis hein ?).

Liste des évènements de la zone « Area Events »

Evènement: OnEnter, déclenché par: quelque chose (pas forcement un PC) qui est entré dans la zone, quest ce qui le déclenche? Utiliser GetEnteringObject() pour renvoyer lobjet dans la zone.
Un exemple :Disons que vous voulez fixer une variable « PC_Entered » qui était dans la zone à chaque fois quun PC entre dans celle ci (avec lobjet qui est égale à « PC »)et cela envoie un événement UserDefined à une créature particulière dans la zone avec le tag « HUNTER »(Je pouvais avoir un événement OnUserDefined pour cette créature qui lenvoie chercher le PC). Vous devez pour cela mettre le script suivant dans le OnEnter de la zone :

NWScript:
void main()
{
object oEntering = GetEnteringObject();
object oMonster = GetObjectByTag("HUNTER");
// si lojet entrant est un PC
if (GetIsPC(oEntering))
{
// fixer la variable à la valeur du PC
SetLocalObject(OBJECT_SELF, "PC_Entered", oEntering);
// envoyer un UserDefinedEvent numéro 100 au monstre
SignalEvent(oMonster, EventUserDefined(100));
}
}

Evenèment: OnExit, déclenché par: quelquun qui a quitté la zone actuelle, quest ce qui le déclenche? Utiliser
GetExitingObject().
Un exemple: Reprennons le script ci dessus et fixons la variable « PC_Entered » à OBJECT_INVALID si le PC qui la zone. Vérifions aussi si lobjet sortant est le monstre ci dessus (chassant le PC, sans doute)et si cest le cas, demandons lui de revenir dans la grotte (où il y a un waypoint avec le tag « HUNTER_CAVE »)

NWScript:
void main()
{
object oExiting = GetExitingObject();
object oMonster = GetObjectByTag("HUNTER");
object oCave = GetObjectByTag("HUNTER_CAVE");
// si lobjet sortant est un PC
if (GetIsPC(oExiting))
{
// fixer la variable de la zone à OBJECT_INVALID
SetLocalObject(OBJECT_SELF, "PC_Entered", OBJECT_INVALID);
}
// Si lobjet sortant est le monstre
if (oExiting == oMonster)
{
//demander lui darrêter ce quil est en train de faire.
AssignCommand(oMonster, ClearAllActions());
// demandez lui de retourner dans sa caverne.
AssignCommand(oMonster, ActionMoveToObject(oCave));
}
}

Evènement: OnHeartbeat, déclenché par: Rien nest requit pour déclencher cet évènement... tout script qui est placé ici se déclenchera toutes les 6 secondes. Comme avec les évènements du module, faite attention en plaçant ici un script qui se lancera constamment.

Evènement: OnUserDefined, déclenché par: Il peut seulement être déclenché par quelquun utilisant la commande SendSignal pour envoyer un UserDefined event à lobjet « zone » (Habituellement via la commande GetArea ou GetObjectByTag en utilisant les tags de la zone).


This page printed from the BioWare Neverwinter Nights Community Site: http://nwn.bioware.com
Powered by BioBoards Version 2.05.010
Please read our Copyright and Trademark Information

Par Théranthil le 19/8/2002 à 14:22:37 (#1984801)

Scripting Tutorial: Utiliser les « Creature Events »
Ecrit par David Gaider
Traduit par Théranthil
Neverwinter Nights: Print Page - Scripting Tutorial: Using Creature Events

Comme mentionné précédemment dans le post « UserDefinedEvent est votre ami », tant que vous ne savez pas exactement ce que vous faites, ne modifiez pas lIA par défaut qui est utilisé pour les créatures (excepté le script OnSpawn qui est fait pour ça). Il est parfaitement possible dactiver tous les « flag » du script OnSpawn et décrire un script OnUserDefined associé à chaque numéro dévénement (Tous les exemples ci dessous sont des script OnUserDefined qui le font).

Liste des évènements des créatures. (Creature event)
Evènement: OnPerception, déclenché par: quelque chose qui entre dans la zone de perception de la créature.
Ca ne veut pas dire que la créature entend ou voit quelque chosemais juste quand cest possible pour lui de la percevoir. Quest ce quil a déclenché? Utilisez GetLastPerceived() pour renvoyer la dernière créature percus. (quelle soit encore en vue ou non).
Aussi utilisé dans: GetLastPerceptionHeard() renvoie TRUE ou FALSE selon que le dernier objet perçu ai été entendu ou non, , GetLastPerceptionInaudible() renvoie TRUE ou FALSE selon que le dernier objet perçu soit devenu inaudible ou non, , GetLastPerceptionSeen() idem que GetLastPerceptionSeen() pour la vue, GetLastPerceptionVanished() renvoie TRUE ou FALSE selon que lobjet soit encore visible ou non. Une chose dont il faut se servir : Toutes les commandes ci dessus sont en rapport uniquement avec le OnPerception event. Ne les utilisez pas nimporte où.
Quest ce que fait le script dIA par défaut ? LIA générique de OnPerception dit en priorité à la créature de se mettre en mode recherche si un ennemi disparaît subitement, puis de lattaquer dès quelle réapparaît.
Exemple : Je veux que mon humain se tourne vers tous ceux quil voit, mais si cest une femme, il sincline devant elle :

NWN script
void main()
{
int nEvent = GetUserDefinedEventNumber();
// si lévénement OnPerception est lancé
if (nEvent == 1004) // OnPerception event
{
object oTarget = GetLastPerceived();
// si je peux voir la personne dans la limite de perception
if (GetLastPerceptionSeen())
{
// mettre la commande pour se tourner dans la file
ActionDoCommand(SetFacingPoint(GetPosition(oTarget)));
}
// si il sagit dune femme
if (GetGender(oTarget) == GENDER_FEMALE)
{
// pause de 0,5 seconde
ActionWait(0.5);
// puis salue
ActionPlayAnimation(ANIMATION_FIREFORGET_BOW);
}
}
}

Evènement: OnSpellCastAt, déclenché par: un sort a été lancé sur la créature... notez que ce nest pas le sort lui même qui cause cet événement. Vous verrez dans votre liste de commande « EventSpelllCastAt. Le script du sort utilise cette commande sur la cible pour lui spécifié que le sort a été lancéet la commande lui demande alors si le sort est hostile ou non. Quest ce quil a déclenché? Utilisez GetLastSpell() renvoie la constante du sort utilisé. (SPELL_*). Aussi utilisé dans : GetLastSpellCaster() pour retourner « lobjet » qui a lancé le sort, GetLastSpellHarmful() renvoie TRUE ou FALSE selon que lévénement soit ou non marqué hostile.
Que fait le script dIA par défaut ? Si un sort « nuisible » a été lancé sur la créature et quelle nétait pas en combat, elle devient hostile.

Evènement: OnPhysicalAttacked, déclenché par: the creature has been attacked in melee, quest ce quil a déclenché?Utilisez GetLastAttacker(). Aussi utilisé dans: GetLastDamager()
Quest ce que fait le script dIA par défaut? Si la créature est est attaquée et quelle nest pas encore en combat, elle devient hostile, et émet le cri apprprié pour alerter les alliés à proximité.

Evènement: OnDamaged, déclenché par: la créature pert des points de vie, quest ce quil a déclenché? Utilisez GetLastDamager().
Aussi utilisé dans: GetTotalDamageDealt(), GetDamageDealtByType(int nDamageType),
GetCurrentHitPoints(object oObject = OBJECT_SELF), GetMaxHitPoints(object oObject =
OBJECT_SELF)
Que fait le script dIA par défaut? Si la créature est attaquée par quelquun quelle ne peut voir, elle essaye de le trouver. Dans les autres cas, elle trouve une cible appropriée et devient hostile.
Exemple : avec cette créature particulière, si elle pert plus de la moitié de ces points de vie, elle crie quelque chose, courre au waypoint appellé « CAVE_EXIT » et disparaît.

NWScript:
void main()
{
int nEvent = GetUserDefinedEventNumber();
if (nEvent == 1006) // OnDamaged event
{
int nMaxHP = GetMaxHitPoints();
int nCurHP = GetCurrentHitPoints();
// si elle a moins de la moitié de ses points de vie.
if (nCurHP < (nMaxHP / 2))
{
// arrête ce que je suis en train de faire
ClearAllActions();
// crie
ActionSpeakString("Ahhh! Run!!");
// court vers la sortie
ActionMoveToObject(GetObjectByTag("CAVE_EXIT"), TRUE);
// et sautodétruit
ActionDoCommand(DestroyObject(OBJECT_SELF));
// naccepte plus de commande de lIA à partir de maintenant
SetCommandable(FALSE);
}
}
}

Evènement: OnDisturbed, déclenché par: quelque chose a été rajouté ou enlevé de linventaire de la créature, quest ce quil a déclenché? Utilisez GetLastDisturbed() to return the creature object who disturbed the
inventory.
Aussi utilisé dans: GetInventoryDisturbType() retournera soit INVENTORY_DISTURB_TYPE_ADDED, soit INVENTORY_DISTURB_TYPE_REMOVED, soit
INVENTORY_DISTURB_TYPE_STOLEN, GetInventoryDisturbItem() donne lobjet qui a été ajouté, enlevé ou volé de linventaire.
Que fait le script de lIA par défaut? Puisquune créature ne peut avoir un objet ajouté ou enlevé de son inventaire (ce nest pas un contenaire), si son inventaire est modifié, il a du être voléelle deviens hostile si il y a une cible valide.

Evènement: OnCombatRoundEnd, déclenché par: A la fin dun round de combat, lévénement est déclenché automatiquement..
Que fait le script de lIA par défaut? Si il ny a pas de comportement spécial spécifié ou que le « flag » du script OnSpawn na été modifié, un nouveau round de combat commence.

Evènement: OnConversation, déclenché par: On a cliqué sur la créature pour une conversation OU quelquun a parlé audiblement, quest ce quil a déclenché? Utilisez GetLastSpeaker() pour renvoie la créature qui a cliqué dessus ou celle qui vient de crier.
Aussi utilisé dans: GetListenPatternNumber() renvoie un numéro de « pattern » si il y en a un qui a été entré.
Que fait le script de lIA par défaut? Si quelquun a cliqué sur la créature, elle arrête ce quelle faisait et commence le dialogue (si elle le peut). Sinon le script vérifie si la phrase prononcée est reconnaissable, et si la créature a été paramêtrée pour reconnaître un cri de combat.

Evènement: OnRested, déclenché par: la créature se repose via ActionRest(). Les créature du jeu ne se reposent pas, cest pourquoi il ny a pas de script dIA.

Evènement: OnDeath, déclenché par: la créature a été tuée, quest ce quil a déclenché? Utilisez GetLastKiller() pour renvoyer « lobjet » (au sens large) qui a tué la créature. Notez que tout script lancé par cet événement doit être immédiatutiliser DelayCommand ne marchera pas car la créature ne peut pas accomplir une commande une fois morte.
Que fait le script de lIA par défaut? Il vérifie si la créature était non mauvaise et avais des niveaux de Commoner (roturier)et si cest le cas change le niveau du tueur un peu plus vers mauvais. Il émet aussi un cri « standard » pour demander de laide à toutes les créatures à lintérieur de la zone de perception auditive (toutes les créatures qui peuvent lentendre)

Evènement : OnBlocked, déclenché par: une porte bloque le mouvement de la créature, quest ce quil a déclenché? Utilisez GetBlockingDoor() renvoie la porte qui gène.. Notez que seule les portes déclenchent lévènement OnBlocked event... il ne peut pas être utilisé pour détecter une collision (du moins pas encore)
Que fait le script de lIA par défaut? Si la créature est assez astucieuse pour utiliser la porte (Intelligence de 5 ou plus) elle essayera dabord de louvrir, et si ce nest pas possible dela casser.

Evènement: OnHeartbeat, déclenché par: Il ne nécessite pas de déclencheurs... nimporte quel script placé ici se déclenchera toutes les 6 secondes. Il est important que vous nutilisiez pas des script qui marchent en permanence dans le OnHeartBeat, lordinateur serait très vite dépassé (surtout si vous avez un grand nombre de créatures dans la zone.
Que fait le script de lIA par défaut? Il vérifie quelques conditions qui sont précisées dans le OnSpawn et les éxécute si elles sont applicablescomme les poste de jour et de nuit (post) pour la fonction WalkWayPoints et les animation ambientes utilisées par les créatures quand elles restent debout.


This page printed from the BioWare Neverwinter Nights Community Site: http://nwn.bioware.com
Powered by BioBoards Version 2.05.010
Please read our Copyright and Trademark Information

Par Théranthil le 19/8/2002 à 14:23:24 (#1984804)

Scripting Tutorial: Utiliser les « Placeable Object Events »
Ecrit par David Gaider
Traduit par Théranthil
Neverwinter Nights: Print Page - Scripting Tutorial: Using Placeable Object Events

Comme avec les zones, la chose dont il faut se souvenir est que quand vous écrivez des scripts pour les objets placables et que vous utilisez des commandes commançant par « Action » léxécutant par défaut est lobjet lui même. Si vous voulez que le script demande à lobjet daccomplir une autre commande, vous devez utiliser AssignCommand. Donc gardez à lesprit qui si les objet placables sont capable daccomplir des actions (comme ActionPlayAnimation avec la référence ANIMATION_PLACEABLE_*comme Open/close ou activate/desactivate quoique tous les placables ne le peuvent pas), leur demander de faire des choses qui leur sont impossible peut causer des problèmes (ActionLockObject, ActionUnlockObjet, ActionEquipItem, ActionPickUpItem sont des exemple que vous devez pas utiliser pour des objets placables.).

Liste des évènements des objets placables (placeable object)
Evènement: OnClose, déclencheur: lobjet a été fermé (notez que seuls les objet qui peuvent être fermé ou ouvert peuvent lancer cet événementcomme un coffre ou une armoire.), quest ce quil a déclenché? Utilisez GetLastClosedBy() renvoie « lobjet » qui a fermé lobjet placable.
Exemple: Voici un script OnClose qui permet de vérifier si linventaire est vide après quil soit ferméet dans ce cas, il crée 100 po à lintérieur.

NWScript:
void main()
{
// donner le premier objet dans linventaire
object oInside = GetFirstItemInInventory();
// et si il ny en a pas
if (!GetIsObjectValid(oInside))
{
// créer des pièces dor au nombre de 100
CreateItemOnObject("NW_IT_GOLD001", OBJECT_SELF, 100);
}
}

Evènement: OnDamaged, déclencheur: lobjet placable a pris des dégats, quest ce quil a déclenché? Utilisez GetLastDamager() pour renvoyer « lobjet » qui lui a infligé des dommages. Aussi utilisé dans: GetTotalDamageDealt(), GetDamageDealtByType (int nDamageType),
GetCurrentHitPoints(), GetMaxHitPoints().

Evènement: OnDeath, déclencheur: lobjet a été détruit (jouer lanimation « destruction » est automatique), quest ce quil a déclenché? GetLastKiller() renvoie « lobjet » qui la détruit.

Evènement: OnHeartbeat, déclencheur: Il ne nécessite pas de déclencheurs... nimporte quel script placé ici se déclenchera toutes les 6 secondes. Il est important que vous nutilisiez pas des script qui marchent en permanence dans le OnHeartBeat, lordinateur serait très vite dépassé.

Evènement: OnDisturbed, déclencheur: Un objet a été ajouté ou enlevé de linventaire de lobjet placable, quest ce quil a déclenché? Utilisez GetInventoryDisturbType(). Le résultat est une de ces constantes: INVENTORY_DISTURB_TYPE_ADDED,
INVENTORY_DISTURB_TYPE_REMOVED, ou INVENTORY_DISTURB_TYPE_STOLEN. Aussi utilisé dans:
GetLastDisturbed() renvoie « lbjet » quia enlevé ou rajouté un objet, GetInventoryDisturbItem() renvoie lobjet qui a été ajouté/enlevé.
exemple: Voici un script OnDisturbed qui envoie un évènement UserDefinedEvent #500 qui signale a un magicien (avec le tag "WIZARD1") si quelquun enlève une potion particulière (avec le tag « PRECIOUS_POTION ») de lobjet placable.

NWScript:
void main()
{
object oWizard = GetObjectByTag("WIZARD1");
object oPC = GetLastDisturbed();
object oPotion = GetObjectByTag("PRECIOUS_POTION");
// si lobjet enlevé est valable et a le tag « PRECIOUS_POTION »
if (GetIsObjectValid(oPC) &&
(GetInventoryDisturbType() == INVENTORY_DISTURB_TYPE_REMOVED) &&
(GetInventoryDisturbItem() == oPotion))
{
// envoie le signal au mage
SignalEvent(oWizard, EventUserDefined(500));
}
}

Evènement: OnLock, déclencheur: Lobjet a été fermé (ou refermé), quest ce quil a déclenché? Utilisez GetLastLocked() pour renvoyer « lobjet » qui la fermé. Aussi utilisé dans: GetLockLockDC() renvoie le DC pour fermer lobjet placable.
**NOTE** Jai eu quelques messages selon lesquel cet événement ne marche pas.

Evènement: OnPhysicalAttacked, déclencheur: lobjet a été attaqué physiquement (mais na pas forcement reçu de dommage), quest ce quil a déclenché? Utilisez GetLastAttacker().

Evènement: OnOpen, déclencheur: lobjet a été ouvert (pour les placables qui peuvent être ouvert et ont la case « inventory » cochée), quest ce quil a déclenché? Utilisez GetLastOpenedBy().

Evènement: OnSpellCastAt, déclencheur: un sort a été lancé sur lobjet placable, quest ce quil a déclenché? Utilisez GetLastSpellCaster(). Aussi utilisé dans: GetLastSpell() retournera la constante du sort lancé (SPELL_*), GetLastSpellHarmful() renverra TRUE ou FALSE selon que le dernier sort lancé était hostile.

Evènement: OnUnlock, déclencheur: lobjet placable a été déverouillé, quest ce quil a déclenché? Utilisez GetLastUnlocked() pour renvoyer « lobjet » qui la dévérouillé.
**NOTE** Jai eu quelques messages selon lesquel cet événement ne marche pas.

Evènement: OnUsed, déclencheur: si un objet placable a la case « Useable », alors cliquer sur cette objet lancera cet événement, quest ce quil a déclenché? Utilisez GetLastUsedBy().
Exemple : un script pour un objet qui soigne quiconque lutilise.

NWScript:
void main()
{
object oUser = GetLastUsedBy();
effect eHeal = EffectHeal(GetMaxHitPoints(oUser));
effect eVis = EffectVisualEffect(VFX_IMP_PULSE_HOLY);
// si lutilisateur de lobjet est valide
if (GetIsObjectValid(oUser))
{
// applique leffet usuel
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oUser);
// et une seconde plus tard, soigne lutilisateur
DelayCommand(1.0, ApplyEffectToObject(DURATION_TYPE_INSTANT, eHeal, oUser));
}
}

Evènement: OnUserDefined, déclencheur: Cet événement se lancera uniquement si un usage particuliera été défini qui enverra un « UserDefinedEvent » à lobjet placable.


This page printed from the BioWare Neverwinter Nights Community Site: http://nwn.bioware.com
Powered by BioBoards Version 2.05.010
Please read our Copyright and Trademark Information

Par Théranthil le 19/8/2002 à 18:26:39 (#1986274)

Scripting Tutorial: Utilisation des « Trigger Events »
Ecrit par David Gaider
Traduit par Théranthil
Neverwinter Nights: Print Page - Scripting Tutorial: Using Trigger Events

Encore une fois, soyez sur que toutes les actions que vous souhaitez que le déclencheur (trigger) mette en place sont envoyées à la cible spécifique via AssignCommandcar sinon vous demandez au déclencheur de faire quelque chose par lui même, et il ne peut pas faire grand chose.

Liste des événement des déclencheurs (Trigger Event)

Evènement: OnClick, déclencheur: Si vous voulez que le déclencheur cause en effet quand le joueur clique dessus, un script doit être entré dans la zone. Beaucoup de sorte de transitions de zones (area transition) utilisent cet événement (bien quun déclencheur qui est paramêtré comme une zone de transition peut utiliser le wizard pour faire cela. quest ce qui la déclenché? Utilisez GetClickingObject() pour renvoyer « lobjet » joueur qui a cliqué dessus.

Evènement: OnEnter, déclencheur: tout objet traversant la limite de la zone du déclencheur. quest ce qui la déclenché? Utilisez GetEnteringObject().
Exemple: Le script OnEnter suivant ferra « sauter » tous les membres de la partie qui sont dans la même zone jusquau waypoint avec le tag « JUMP_HERE ».
NWScript:
void main()
{
object oWP = GetObjectByTag("JUMP_HERE");
object oParty = GetFirstFactionMember(GetEnteringObject(), TRUE);
// cicle qui passe en revue tous les membres de la partie.
while (GetIsObjectValid(oParty))
{
// si ils sont dans la même zone
if (GetArea(oParty) == GetArea(GetEnteringObject()))
{
// jump the party member to the waypoint
AssignCommand(oParty, JumpToObject(oWP));
}
// va jusquau prochain membre de la party
oParty = GetNextFactionMember(GetEnteringObject(), TRUE);
}
oParty = GetFirstFactionMember(GetEnteringObject(), FALSE);
// maintenant, passe en revu tous les membres non-joueurs de la partie(comme les familiers)
while (GetIsObjectValid(oParty))
{
// et si ils sont dans la même zone
if (GetArea(oParty) == GetArea(GetEnteringObject()))
{
// faites « sauter » les membres de la partie jusquau waypoint
AssignCommand(oParty, JumpToObject(oWP));
}
// aller au prochain membre de la partie
oParty = GetNextFactionMember(GetEnteringObject(), FALSE);
}
// maintenant, fait sauter le PC entrant jusquau Waypoint
// cette ligne nest pas nécessairelinclure
// permet juste dêtre certain de déplacer aussi le PC qui a activé le déclencheur
AssignCommand(GetEnteringObject(), JumpToObject(oWP));
}

Evènement: OnExit, déclencheur: à chaque fois quun ennemi traverse la limite de la zone du déclencheur pour la quitter, quest ce qui la déclenché? Utilisez GetExitingObject() pour renvoyer lobjet sortant.
Exemple: Ce script OnExit pour le déclencheur envoie une commande à nimporte quel géant sortant pour retourner à un waypoint.

NWScript:
void main()
{
object oWP = GetObjectByTag("RETURN_HERE");
object oCreature = GetExitingObject();
// si la créature sortante est un géant
if (GetRacialType(oCreature) == RACIAL_TYPE_GIANT)
{
// lui demande darrêter ce quil fait
AssignCommand(oCreature, ClearAllActions());
// et de bouger au waypoint
AssignCommand(oCreature, ActionMoveToObject(oWP));
}
}

Evènement: OnHeartbeat, déclencheur: comme les autres heartbeat, Le Heartbeat du déclencheur est activé toutes les 6 secondes. Un déclencheur nest cependant pas comme tous les autres objetsil est seulement activé quand quelque chose est à lintérieur de ces limites ou quon clique dessus. Vous ne pouvez placer un déclencheur et lui donner un script pour constamment commander un ordresi vous voulez faire ça, utilisez à la place un objet invisible.

Evènement: OnUserDefined, déclencheur: encore, cet événement se lancera uniquement si un UserDefinedEvent a été spécifiquement envoyé au déclencheur par la commande SignalEvent.


This page printed from the BioWare Neverwinter Nights Community Site: http://nwn.bioware.com
Powered by BioBoards Version 2.05.010
Please read our Copyright and Trademark Information

Par Théranthil le 20/8/2002 à 9:20:10 (#1989405)

Scripting Tutorial: Ajouter et enlever des effets
Ecrit par David Gaider
Traduit par Théranthil
Neverwinter Nights: Print Page - Scripting Tutorial: Adding & Removing Effects

Si vous faîtes défiler la liste des commandes dans votre « script editor », vous pouvez voir une longue liste de commandes qui commencent par le mot « Effect ». Ceux sont les commandes pour faire tous les sorts, les capacilés spétiales et les effets visuels dans le jeu. Il y a deux commandes qui permettent de les utiliser : ApplyEffectToObject et ApplyEffectAtLocation. Toutes les deux sont très similaires dans leur structure, à lexception que la cible de la première est un objet spécifique (créature, objets placables, etc) et la cible de la deuxième est un emplacement spécifique (un point dans lespace)

void ApplyEffectToObject (int nDurationType, effect eEffect, object oTarget, float fDuration=0.0f)

Duration Type: « nDurationType » demande une constante commencant par DURATION_TYPE_*, il ny en a en fait que trois possibles. DURATION_TYPE_INSTANT sapplique à tous les effets qui sont instantannés, permanents et ne peuvent être annulés. EffectDamage serait un exemple, ainsi que tous les objets « fire-and-forget » (tire et oublie). Si elle nest pas « instant », la constante doit être soit DURATION_TYPE_PERMANEN leffet reste jusquà se quil soit enlevé ou dissipé. Une durée temporaire signifie que leffet doit avoir une durée spécifique dans la commande (et cest le seul moment où cest le cas)

Effect: Cest leffet spécifique que vous voulez utiliser Il est courant de définir dabord une variable qui contient toutes les informations pertinentes, et ensuite de lutiliser cette variable quand vous le voulezmais ce nest pas nécessaire. Chaque effet varie dans ces conditions. Quelques uns sont simplement appellés EffectSleep ou EffectCharmed et nont besoin de rien dautre. Dautres ont besoin de paramêtres additionnels, comme EffectDamage ou EffectPolymorph. Je ne détaillerais pas tous les effets ici, mais il est important que vous fournissiez tous les paramêtres requis par un effet ou il sera non valide.

Target: Cela doit être soit un objet (dans ApplyEffectToObject) ou un emplacement (dans ApplyEffectAtLocation). Il peut être déclaré séparement dans une variable ou défini dans la commande.

Duration: Une durée (en seconds) est uniquement requise pour les effets avec DURATION_TYPE_TEMPORARY. Quand elle est spécifié, ce doit être un « float » (et non un integer). Donc mettez « 3.0 » pour 3 secondes, ou « 10.5 » pour 10 secondes et demi.

Quelques exemples deffets
- Dans le OnUsed dun objet, il transforme lutilisateur en pixie :

NWScript:
void main()
{
effect ePixie = EffectPolymorph(POLYMORPH_TYPE_PIXIE);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, ePixie, GetLastUsedBy());
}

- un objet avec en capacité un sort unique (avec le tag "WONDERFUL_WAND" qui soigne le « hâte » la cible pour 30 secondes:
NWScript:
void main()
{
object oWand = GetItemActivated();
if (oWand == GetObjectByTag("WONDERFUL_WAND"))
{
object oTarget = GetItemActivatedTarget();
int nMaxHP = GetMaxHitPoints(oTarget);
int nCurHP = GetCurrentHitPoints(oTarget);
effect eHeal = EffectHeal(nMaxHP - nCurHP);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eHeal, oTarget);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectHaste(), oTarget, 30.0);
}
}

- Dans le OnUserDefined dune créature, quand un événement #100 est envoyé, un blaireau générique est convoqué au waypoint avec le tag « SUMMON_POINT »:

NWScript:
void main()
{
int nUser = GetUserDefinedEventNumber();
if(nUser == 100)
{
effect eSummon = EffectSummonCreature("bugbeara001");
location lWP = GetLocation(GetObjectByTag("SUMMON_POINT"));
ApplyEffectAtLocation(DURATION_TYPE_PERMANENT, eSummon, lWP);
}
}

Effets visuels
Les effets visuels sont très similaires aux effets normaux, vous les appliquez de la même manière. Vous utilisez EffectVisualEffect et fournissez lui fournissez le paramêtre dune des constantes des effets visuelselles commencent toutes par VFX_*. Cependant, il y en a un certain nombre, et elles sont différenciées par des mentions différentes.

VFX_BEAM_* = il y a différents types de beam (poutres) visuels, et bien quelles soient groupées avec les autres effets visuels, ces constantes sont utilisées avec EffectBeam et non avec EffectVisualEffect.
VFX_COM_* = ce sont les effets visuels de combat, presque tous sont utilisés avec une durée instantanée(INSTANT).
VFX_DUR_* = beaucoup sont des effets utilisés pour les sorts. Ils doivent tous être applqiés avec une durée soit permanente, soit temporaire (PERMANENT OU TEMPORARY)
VFX_FNF_* = Ils sont appellés les effets « fire-and-forget » (tire et oublie) dans le sens ou ils ne sont joués quune fois. Ils doivent avoir une durée instantannée (INSTANT)
VFX_IMP_* = Ce sont les effets « impact », ils sont habituellement utilisés pour des effets de courte durée quand un sort frappe une cible. Ins ont une durée instantannée (INSTANT).
Voici un exemple dun puit de sorcière magique, quand il est utilisé, il crée un effet sur lui même et augmente la force avec un effet sur la cible (mais il ne peut seulement être utilisé une foissi il est utilisé une seconde fois, il attaque avec un éclair de 8d6 de dégats) :

NWScript:
void main()
{
effect eFirst;
effect eSecond;
effect eStrength = EffectAbilityIncrease(ABILITY_STRENGTH, (d4() + 1));
object oTarget = GetLastUsedBy();
int nOnce = GetLocalInt(oTarget, "Use_Pool_Once");
// si le PC na pas utilisé la fontaine auparavant
if (nOnce == FALSE)
{
eFirst = EffectVisualEffect(VFX_IMP_GOOD_HELP);
eSecond = EffectVisualEffect(VFX_IMP_IMPROVE_ABILITY_SCORE);
// crée leffet sur la fontaine
ApplyEffectToObject(DURATION_TYPE_INSTANT, eFirst, OBJECT_SELF);
// applique laugmentation de la force avec un effet 3 secondes plus tard
DelayCommand(3.0, ApplyEffectToObject(DURATION_TYPE_INSTANT, eSecond,
oTarget));
DelayCommand(3.0, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eStrength,
oTarget, 300.0));
// se fixe la variable pour que le PC ne puisse pas lutiliser une seconde fois
SetLocalInt(oTarget, "Use_Pool_Once", TRUE);
}
// Si il a utilisé la fontaine
else
{
eFirst = EffectVisualEffect(VFX_IMP_LIGHTNING_M);
// permet un jet de sauvegarde pour éviter léclair
int nDamage = GetReflexAdjustedDamage(d6(8), oTarget, 25,
SAVING_THROW_TYPE_ELECTRICITY);
eSecond = EffectDamage(nDamage, DAMAGE_TYPE_ELECTRICAL);
// and then cause the visual effect of the bolt strike and apply the damage
ApplyEffectToObject(DURATION_TYPE_INSTANT, eFirst, oTarget);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eSecond, oTarget);
}
}

Enlever des effets
La chose pour enlever des effets est quun effet a un « pointeur » unique qui a été établie quand il a été appliqué. Si vous définissez un nouvel effet de variable plus tard et que vous le définissez comme un effet du même type, RemoveEffect ne le ciblera pas.
La voie la plus facile pour enlever un effet est de parcourir les effets actifs quils sont appliqués à la cible en utilisant GetFirstEffect et GetNextEffect... et ensuite de filtrer leffet spécifique que vous recherchez. Une fois que vous lavez trouvé (ou les avez trouvés si vous voulez en enlever plus dun) le pointeur est fixé sur le bon effet et vous pouvez lenlever.
Les commandes suivantes sont utile pour filtrer :
GetEffectCreator = Si vous voulez spécifier seulement les effets qui ont été appliqués par une créture ou un objet spécifique
GetEffectDurationType = Cela retournera la constant du type de durée dun effet (soit « instant », « permanent », « temporary »). Très générales, mais utile dans certaines circonstances.
GetEffectSpellId = Cel retournera la constante du sort qui a appliqué leffet (SPELL_*). Très utile si vous cherchez tous les effets dun sort particulier ou si vous voulez les exclure.
GetEffectSubType = Cela renverra la constante SUBTYPE_MAGICAL, SUBTYPE_SUPERNATURAL ou
SUBTPE_EXTRAORDINARY. Tous les effets par défaut dun sous type sans les spécifier exactement.
GetEffectType = Cest le filtre le plus utilisé quand vous cherchez un objet spécifique. Il renvoie une constante du type EFFECT_TYPE_*, qui est presque la même que la liste de commande des effets. Seul les effets visuels nont pas un type deffet (effect type).
Le script basique pour enlever un effet ressemble à ceci:
effect eEffect = GetFirstEffect(oTarget);
while (GetIsValidEffect(eEffect))
{
if (eEffect == filter used)
{
RemoveEffect(oTarget, eEffect);
}
eEffect = GetNextEffect(oTarget);
}

Un exemple pour enlever une malédiction (curse) lancée par une sorcière (avec le tag "EVIL_WITCH") à la fin dun dialogue:

NWScript:
void main()
{
effect eEffect = GetFirstEffect(GetPCSpeaker());
while (GetIsEffectValid(eEffect))
{
if ((GetEffectType(eEffect) == EFFECT_TYPE_CURSE) &&
(GetEffectCreator(eEffect) == GetObjectByTag("EVIL_WITCH")))
{
RemoveEffect(GetPCSpeaker(), eEffect);
}
eEffect = GetNextEffect(GetPCSpeaker());
}
}

Quelque chose à retenir
- EffectKnockdown cause un crasch quand il est appliqué par autrechose que par une créature (ce sera fixé par le prochain patch) NdT ça devrais être fait.
- EffectHitPointChangeWhenDying ne marche pas (ce sera fixé par le prochain patch) NdT idem
- Tous les effets ne sont pas permanent... Ils ne sont pas sauvé quand le personnage retourne au menu, mais il persiste tant quil est sur le module.
Le plus long type deffet est leffet extroardinaire, qui résiste à la dissipation de la magie et au repos. Les ExtraordinaryEffect et les SupernaturalEffect sont appliqué quand le commande suivante est dite:
effect eEffect = ExtraordinaryEffect (EffectSilence());


This page printed from the BioWare Neverwinter Nights Community Site: http://nwn.bioware.com
Powered by BioBoards Version 2.05.010
Please read our Copyright and Trademark Information

Par Théranthil le 20/8/2002 à 18:56:14 (#1992658)

Scripting Tutorial: Utilisez les dialogue avec les objets placables et les déclencheurs
Ecrit par David Gaider
Traduit par Théranthil
Neverwinter Nights: Print Page - Scripting Tutorial: Using Dialogue With Placeables and Triggers

Il y a beaucoup deffets quun MD intelligent peut simuler juste en utilisant un petit peu les dialogue en même temps que les objets placables et les déclencheurs.
Vous pouvez avoir une description ambiente dune zone ou dun objet, commencer un « dialogue » avec un objet étrange qui permet au joueur dinteragir avec lui, avoir quelquun de lautre côté dune porte qui parle à travers elle, informer les joueur des événements qui peuvent arriveril y a beaucoup de possibilitées.

La première chose que vous devez savoir est quelles options vous avez. Ci dessous, vous avez des commandes qui peuvent être utilisées pour initier un dialogue ou afficher un texte :

Action Speak String et SpeakString
La seule différence entre ces deux actions est que ActionSpeakString pousse la commande dans la file des actions (ça veut dire quelle ne sera pas effectuée avant que les actions placées au dessus dans la liste, comme ActionWait ou ActionMoveToObject, naient été effectuées) et que SpeakString est effectuée immédiatement.
Quest ce que ca fait: une ligne de texte est affichée au dessus de celui qui a effectué cette commande. Cela est affiché pour le joueur comme un dialogue normal, le texte apparaît derrière le nom du personnage et son portrait (si cest possible)
Advantages: Un volume peut être appliqué au texte en placant la constante TALKVOLUME_* appliquée dans la commande. TALKVOLUME_TALK est utilisé par défaut et est entendu par tous avec une portée normale. TALKVOLUME_SHOUT est entendu par tout le monde dans le module. TALKVOLUME_WHISPER est entendu par tout la monde dans une zone réduite. TALKVOLUME_SILENT_TALK et TALKVOLUME_SILENT_SHOUT sont des variante du « talk » et du « shout » normal... mais il sera affiché et entendu uniquement par les NPC.
La particularité davoir un module est que le texte est aussi « entendu » par les objets du jeu. Les créatures sans portée auditive tourneront la tête, et si vous faite un script qui reconnais le texte via SetListenPattern et GetListenPatternNumber (comme les « cris » de combat), SpeakString peut être utilisé pour cela.

ActionStartConversation
Quest ce que ça fait : Ca demande à léxécuteur de la commande dinitier le dialogue avec la cible. Ca doit faire partie de lévénement OnDialogue de la cible (si elle en a un, et que le PC nen pas). Si aucun fichier de dialogue resref est spécifié, celui attaché à la créature ou à lobjet sera utilisé (celui que vous avez spécifié dans le toolset). Le
It will set off the target's OnDialogue event (if they have one, which PC's do not). If no dialogue file resref is specified, the one attached to the creature or object will be used (the one you specified in the toolset). Linterlocuteur dans la conversation doit toujours être lobjet cible.
Advantages: Vous pouvez démarrer un conversation entière de cette manière, avec des choix de réponse et de multiples conditions de départ et de script. Vous pouvez aussi spécifier dans la commande principale si cest ou non une conversation privéeSi cest le cas, seule la cible verra le texte apparaître sur lécran (cest bien pour interagir avec les objets sans que les autres joueurs entendent cette conversation).

BeginConversation
Quest ce que ça fait: Cette commande est normallement seulement utilisée dans le « OnDialogue event » de la créature. Cest la commande qui lui demande de débuter la conversation avec le joueur qui vient juste de lui cliquer dessus. Lutiliser sur un objet ne lancera pas son « OnDialgue event ». Si la cible de laction nest pas spécifiée, lobjet qui a initié le OnDialgue event sera utilisé.
Advantages: Peut être utilisé pour une conversation de NPC à NPC... autrement ActionStartConversation doit toujours être utilisé hors du OnDialogue event.

FloatingTextStringOnCreature
Quest ce que ça fait: Quand vous accomplissez de nombreuses actions dans le jeu, vous avez remarqué le texte qui apparaît au dessus de la tête du joueur flotte puis disparaît. Cette commande faît la même chose. Le texte est aussi montré dans la fenêtre du chat du joueurMais il nest pas montré comme originaire dune créature et ne montrera aucun portrait. Le texte est simplement marqué en jaune, comme la plupart des texts ambiants.
Advantages: Cest bien pour un texte dambiance ou simuler un message décrivant une action, puisquil najoute pas un préfixe au début du texte et ne ressemble pas au texte des dialogues.
Une chose dont il faut être conscient: Un texte flottant, par défault, ne peut être vu que par la créature au dessus de laquelle il flotte. Si vous sélectionnez la commande « display to faction », alors les membres de la même faction verront aussi le texte safficher. Cela veut dire que le texte flottant est utile uniquement pour les PC, puisque aucune créature non PC ne peut être attribuée à la faction PC.

SpeakOneLinerConversation
Quest ce que je fais: Cela marche presque comme ActionStartConversation, mais son usage est plus spécifique. Il est utilisé pour accèder au fichier dialogue, mais seulement pour une ligne de dialogue unique sans réponses ni liens.
Advantages: Vous pouvez encore scripter les conditions de lancement du dialogue , vous pouvez avoir une longue sélection de ligne simple. Le locuteur ne se tourne vers aucune cible avant de parleret lobjet identifié dans la commande (si il y en a un) devient la référence pour chaque marque utilisée dans le dialogue (seulement si elles ne sont pas présentes).

Faire dire un texte à un objet placable.
Pour lexemple que je vais utiliser ici, nous allons faire quun objet placable « signpost » affiche un texte quand on clique dessus.
**IMPORTANT!** Si vous voulez avoir un objet placable qui interagit avec les autres de cette manière, vérifiez que la case « Statique » est décochée !Si un objet placable est statique, il fera partit de larrière plan et ne sera pas sélectionnable. La plupart des objets sont marqués statique par défaut !

Donc sélectionnez un « signpost » (une pancarte) dans la liste des objets placables et placez le ou vous voulez. Ensuite allez dans ces propriétés et soyez sur que la case statique est décochée. Comme je veux que le joueur soit capable de cliquer dessus, la case « useable » (elle doit être cochée). Allez dans la section script et mettes le script suivant dans le OnUsed event :

NWScript:
void main()
{
SpeakString("North: Waterdeep, 20 miles");
}

Maintenant, quand vous êtes dans le jeu et que vous cliquez sur la pancarte, elle affichera le texte précédé de son portrait (qui est par défault une pancarte) et de son nom. Naturellement vous pouvez toujourzs changer le portrait comme vous voulez, ainsi que le nom, et laffichage sera différent.

Faire apparaître un texte flottant à un déclencheur (trigger)
Dans cet exemple nous voulons que quand un joueur traverse la zone du déclencheur, un texte ambient apparaît au dessus de sa tête.
Allez dans le menu déclencheur (trigger menu) et sélectionnez « generic trigger ». Ca vous permettra de dessiner les limites du trigger. Si je veux afficher une description de quelque chose que le joueur voit dans la zone, par exemple, je peux le mettre juste derrière la porte.
Allez dans la section script du trigger. Comme nous voulons que le texte apparaisse quand le joueur entre dans le déclencheur, nous mettrons le script dans la section OnEnter. Quelques choses à prendre en compte : est ce que nous voulons quil laffiche seulement pour les PC ou pour toutes les créatures entrantes ? Est ce que nous voulons quil saffiche à chaque fois que le PC entre, ou seulement une fois ? Cette fois, nous voulons que le texte apparaisse à tout le mondemais une fois seulement.

NWScript:
void main()
{
object oPC = GetEnteringObject();
if (GetLocalInt(oPC, "Saw_Trigger_Text") == FALSE)
{
FloatingTextStringOnCreature("The room is dark and spooky.", oPC);
SetLocalInt(oPC, "Saw_Trigger_Text", TRUE);
}
}

Quand le joueur entre dans le trigger pendant le jeu, le texte apparaît au dessus de sa tête et flotte, puis disparaît. Cela laffichera aussi dans la fenêtre de chat en jaune. Notez que le déclencheur ne peut pas utiliser SpeakString oou ActionSpeakString. Il ne peut tout simplement pas parler. Mais, il peut cependant demander à un autre objet de parleret cet objet peut aussi être invisible ou non. Si jai à proximité un objet placable avec le tag « DISPLAY_HERE » (qui souvenez vous a la case « Static » décochée) et que je veux que le déclencheur le fasse afficher un texte, jutiliserais le script suivant:

NWScript:
void main()
{
object oPC = GetEnteringObject();
object oDisplay = GetObjectByTag("DISPLAY_HERE");
if (GetLocalInt(oPC, "Saw_Trigger_Text") == FALSE)
{
AssignCommand(oDisplay, SpeakString("The room is dark and spooky."));
SetLocalInt(oPC, "Saw_Trigger_Text", TRUE);
}
}

Avoir un objet qui affiche un texte quand un personnage vient à proximité.
Dans cet exemple, je vais poser un objet invisible (que le personnage de peut ni voir ni toucher) qui va afficher un texte quand le joueur approche à moins de 10 mêtres.
Premièrement, sélectionnez lobjet invisible dans le menu des objets placables et placez le. Allez dans ces propriétées et vérifiez que « Static » est décoché. Je ne veux pas que le joueur puisse cliquer dessus, donc laissez « Useable » décoché. Changez le nom de lobjet en « Unknow Person » et laissez le portrait blanc.
Allez dans la section des scripts. Mettez le script suivant dans le OnHearbeat event:

NWScript:
void main()
{
object oPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC);
if (GetIsObjectValid(oPC) && (GetDistanceToObject(oPC) < 10.0))
{
SpeakString("Psst! Come over here!");
}
}

Dans le jeu, quand le player viens à moins de 10 mètres de lobjet, le texte apparaîtra à lécranet dans la fenêtre de chat et le PC pourra lire « Unknown Person : Psst ! Come over here ! ».
Je pourrais dévelloper un petit peu plus le scriptpar exemple, vérifier si le personnage sapproche à moins de 3 mètres la personne inconnu apparaîtra au dessus de lobjet placable.
Une chose que vous devez savoir est que lobjet placable est un petit peu petit et laffichage du texte est un peu bas sur le sol (ca dépend du zoom de la caméra). Il y a un truc pour lafficher un peu plus haut : avant de placer cet objet invisible, sélectionnez un autre objet placable qui est aussi haut que vous le souhaitezPlacez le en premier. Puis sélectionnez lobjet invisible dans le menu, placez le curseur directement au dessus du premier objet avant de cliquer pour le poser. Il apparaîtra au sommet du premier objet. Maintenant, effacez le premier objet et lobjet invisible flottera au milieu de la pièce (et y restera).

Avoir un objet placable qui lance un dialogue.
Admettons que je veuille un objet aue le joueur puisse sélectionner et avoir un dialogue interactifou peut être avoir un objet qui parle. Premièrement, allez dans la liste des objets placable et sélectionnez un objet. Par exemple un piédestal et placez le dans le module. Allez dans ces propriétés et vérifiez que « Static » est décoché et « Usable » est cochée.
Allez dans longlet advance. Ecrivez dans un fichier dialogue ce que nous allons créer et appuyez sur Edit. Vous pouvez commencer par une ligne comme « Il y a quelque chose décrit sur le piédestal dans un language étrange. Est ce que vous essyez de le déchiffrer ? » Vous pouvez ensuite continuer à donner des réponses et faire un dialogue aussi long que vous le voulez, comme un dialogue normal.
Allez dans longlet script et placez le script suivant dans OnUsed:

NWScript:
void main()
{
object oPC = GetLastUsedBy();
ActionStartConversation(oPC, ", TRUE);
}
Dans le jeu, quand le joueur clique sur le piédestal, il sapproche de lui et le dialogue commence normalement. Puisque jai spécifié TRUE dans le paramêtre bPrivateConversation de la commande, lui seul verra la commandeun autre joueur étant a proximité ne verra et nentendera rien.
Si je ne me souciais pas du texte affiché, jaurais pu simplement avoir écrit ActionStartConversation(oPC), puisque les « »
signifient que le fichier dialogue attaché est utilisé.

Commencer une conversation avec une porte
Admettons que je veuille simuler ça : le joueur essaie douvrir une porte mais la trouve fermée. Une voie parle de lautre côté : « Quel est le mot de passe ? »
Premièrement, placez la porte normalement. Allez dans ses propriétées et changez le nom. Une chose pratique dans le nom de la porte : cest quil nest montré à aucun endroit (même si on lexamine) sauf dans le dialoguedonc changez le en « Le garde de lautre côté », puisque cest ce que le joueur verra.
Marquez la porte comme « plot » pour quelle ne puisse être cassée (mais vous pouvez aussi la laisser comme tels, et écrire un script avec les évènements OnDamaged ou OnPhysicalAttacked). Allez dans longlet lock et cochez la case « Locked ». Si vous ne voulez pas quelle soit crochetable, cochez « Key required to lock or unlock » (encore une fois, vous pouvez faire comme vous voulez). Allez ensuite dans longlet advanced et mettez un nom dans conversation puis appyuez sur Edit. Nous pouvons créer la première ligne « Quel est le mot de passe ? » et continuez comme vous le souhaitezquand vous avez fini et que vous avez crée une réponse ou le garde accepte douvrir la porte, placez le script suivant dans la section « Action Taken » du nud ou ce dernier accepte douvrir.

NWScript:
void main()
{
ActionDoCommand(SetLocked(OBJECT_SELF, FALSE));
ActionOpenDoor(OBJECT_SELF);
}

Maintenant, nous devons placer le script qui démarre la conversation. Placez le script suivant dans le OnFailToOpen event:

NWScript:
void main()
{
object oPC = GetClickingObject();
if (!IsInConversation(OBJECT_SELF))
{
ActionStartConversation(oPC);
}
}

Dans le jeu, lorsque le joueur cliquera sur la porte et sen approchera, il entendra le son habituel quand une porte refuse de souvrir, et soudain le dialogue apparaît. Le joueur verra le portrait de la porte et « Le garde de lautre côté » safficher au dessus avec le texte « quel est le mot de passe ? » affiché. Quand le moment arrive dans le dialogu ou le guarde doit ouvrir la porte, elle est déverouillée puis souvre delle mêmele joueur peut maintenant entrer.


This page printed from the BioWare Neverwinter Nights Community Site: http://nwn.bioware.com
Powered by BioBoards Version 2.05.010
Please read our Copyright and Trademark Information

Et voila le dernier

Par Théranthil le 21/8/2002 à 11:37:43 (#1996438)

Scripting Tutorial: Factions, cri et attaquer mes ennemis
Ecrit par David Gaider
Traduit par Théranthil
Neverwinter Nights: Print Page - Scripting Tutorial: Factions, Shouts and Attacking My Enemy

(NdT : important différenciez bien « party » qui est un groupe de joueurs de « partie » qui a le sens habituel)

Quest ce quest au juste une faction?
Une faction est une de ces trois choses : une party de PC & leur associés (mercenaires, familiers), un joueur seul sans membre dans la partie & ses associés ou un groupe de NPC ou un NPC seul a qui ont été assignés des réactions par défault envers les autres factions. Cela ne doit pas être confondu avec une « organisation » comme une guilde de voleurs ou la garnison dun ville. Les joueurs de peuvent pas « rejoindre » une factions , et chaque organisation peut contenir plusieurs factions.

Que font donc les factions ?
Juste ce quelles sont supposé faire : fixer le comportement par défaut dun NPC face aux autres factions. LIA générique donne une position comme amical (Friendly) ou hostile (Hostile) et le NPC réagit conformement au script. Un NPC maintiendra cette position par défaut jusquà et à moins quil lui soit demandé de faire autre chose.
Ce qui est probablement le plus important à comprendre à propos des factions est quil y a cependant une différence entre ce que la faction « ressent » et ce que le NPC seul « ressent ». Si un NPC individuel sans faction est attaqué, il deviendra hostile et se défencra tout seul. Il restera aussi hostile jusquà ce quon lui demande autrechose. Cependant, les autres membres de la faction non prészent ne seront pas nécessairement hostile comme lui. La différence de réaction est du à la « réputation », qui est différent de la réputation de quelquun avec la faction.
La commande NWscript se réfère, malheureusement, aux deux types de réputation de la même manière, donc faire la distinction entre les deux peut être difficile.

Pour mieux expliquer la différence, considerez ceci :
Une party de PC sont dans une taverne. Le voleur de la party décide dattaquer un roturier à proximité (qui est membre de la faction Commoner). Puisquil est attaqué, le roturier devient hostile envers le voleurce qui entrainera aussi une attaque de la part de tous les NPC à proximité qui sont amicaux avec cette faction et qui deviendront aussi hostile envers le voleur.Le reste de la party na encore rien fait donc personne nest hostile envers elle. Si le reste de la party est engagée dans le combat, les NPC déjà hostile avec le voleur le seront avec toute la partie. Admettons maintenant que la party entière quitte la taverne tout de suite et échappe à ces poursuivantsces individus resteront hostile avec le voleur (et les autres membres de la party ayant réagit) jusquà ce quon leur dise de réagir autrement. Les autres membres de la faction Commoner réagiront normallement.

La seule raison que ce ne soit pas le cas est si la case « Global Effect » est cochée (Elle peut être trouvé dans le Faction Editor). Les individus écartés (dans lespace) dans une faction maintiendront des relations différentesmais, si vous en attaqué un et quil devient hostile, tous les membres de la faction seront hostiles. Tous les changement dans les relations dun membre seront appliqués à la faction entière. (Il y a certains moment où cest pratique dans un modulemais soyez conscient que toute nouvelle faction à cette option activée).

Que fait lIA standart avec les factions?
Pour mieux comprendre pourquoi quelque chose se passe ou ne se passe pas, voici un résumé détaillé de comment les factions affectent lIA standart :

l Dans lévénement OnPerception (qui se lance rappelez vous uniquement quand la cible entre dans la limite de perception, ou si le type de percepption change),si un NPC perçoit un hostile et quil nest pas encore en combat le lançe le cri « NW_I_WAS_ATTACKED » (regardez ci dessous) et attaque.

l Si la créature est attaquée mais pas encore en combat, elle lance les cris « NW_I_WAS_ATTACKED » et "NW_ATTACK_
MY_TARGET" puis attaque son attaquant.

l Si la créature est tuée ça lance automatiquement les cris "NW_ATTACK_MY_TARGET" et "NW_I_AM_DEAD".

Et que font ces cris ? Dune part, il y a les mots simplements parlés quon avait demandé à la créature de dire, les même que ceux que peut taper le PC dans son système de Chat. Ces cris cependant sont silencieuxles joueurs ne les entendent ou ne les voient pas flotter, mais les PC oui, et le script OnSpawn leur demande de les écouter et de réagir. Les cris ne sont pas entendus à travers les murs ou les portes, et ils ont une portée limitée.

l Le cri "NW_ATTACK_ MY_TARGET" a seulement un effet sur les NPC qui ont activé (enlevé les « // ») de la ligne « SetSpawnInCondition (NW_FLAG_SHOUT_ ATTACK_MY_TARGET) ; » dans leur script OnSpawn. Si il a été entendu par un allié (un membre dun faction amicale envers celui qui a poussé le cri), il fixe les relations de sa faction en hostile avec celui qui a attaqué le crieur (si ce nétait pas déjà le cas,) arrête ce quil fait et attaque tout ennemi à portée.

l Le cri "NW_I_WAS_ATTACKED" peut être entendu par nimporte qui. Si celui qui lentend est un allié du crieur et nest ni en combat ni a moins de 10 niveaux de roturier, il attaquera le crieur.

l Le cri "NW_I_AM_DEAD" peut aussi être entendu par nimporte qui. Son effet est le même que le cri « I was attacked » ci dessuss.

Comment puis-je faire attaquer mes NPC?
Si est cr éature démarre hostile et détecte un PC, son événement OnPerception se lancera et elle attaquera immédiatement. Pas de porblème dans ce cas. Cependant, la situation devient souvent plus compliquée si vous avez un NPC qui était neutre face au PC quand lévénement OnPerception se lance et elle deviendra hostile lors du dialogue ou du script.
Pour quun NPC devienne hostile face à un PC et lattaque, vous devez dabord identifier la cible. Dans le dialoque cest facile :
object oTarget = GetPCSpeaker();

En dehors dun dialogue, dans un script normal, ça peut varrier :

object oTarget = GetNearestCreature (CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC);
// la cible est le PC le plus proche de celuui à qui appartient le script.

object oTarget = GetLastPerceived();
// Cest le dernier objet perçu, doit être seulement utilisé dans le OnPerception.

Ci dessous, vous avez deux possibilitées.Sans problèmes, une fois que vous avez identifié votre cible, vous pouvez appeler le reste de la commande normallement. Pour le script suivant, nous nous assurons que nous allons commencer le combat à la fin du dialogue (en plaçant ce script dans la section « Action Taken » de la ligne de dialogue ou nous voulons que le combat commence).
Premièrement, est ce que je veux que lattaquant change la faction entière en hostile ? Si cest le cas, jutilise ça :
NWScript:
#include "NW_I0_GENERIC"
void main()
{
// Baisse la relation de ma faction avec le PC de 100 (jusquà hostile) AdjustReputation (GetPCSpeaker(), OBJECT_SELF, -100);
// Démarre le combat (Cela nécessite le fichier générique nw_i0_generic ci dessus)
DetermineCombatRound();
}

Et cest tout (cest aussi le script générique « nw_dl_attoned »). Maintenant, je veux juste que lattaqué soit hostile (et lui seul) :

NWScript:
#include "NW_I0_GENERIC"
void main()
{
// me fixe comme hostile face au PC
// Notez que le « temporary » (temporaire) dure 3 minutes sans une valeur
// de durée précisée dans la commande.
SetIsTemporaryEnemy (GetPCSpeaker());
// démarre le combat (ça nécessite le fichier générique nw_iO_generic, ci dessus)
DetermineCombatRound();
}

Mais je supose qui jai dautres amis à côté que je voudrais voir prendre part au combat. Si jutilise AdjustReputation pour rendre leur faction hostile, il nattaqueront toujours pas. Pourquoi ? Regardez dans le paragraphe à propos de lIA génériqueje nai pas attaqué le premier et je suis déjà en combat, cest pourquoi je ne pousserais pas de cri. Nous avons tous déjà perçut le PC et il nétait pas hostile. Et je ne suis pas mortdonc mes amis resteront la jusquà ce quils soient attaqué ou que je meurs.
Jai deux choix. Soit leur envoyer la commande via AssignCommande comme ceci :

NWScript:
#include "NW_I0_GENERIC"
void main()
{
// Ce script marche bien si vous savez exactement qui enroler dans le combat
// et quils ont des resrefs uniques
object oGoblin2 = GetObjectByTag ("GOBLIN2");
object oGoblin3 = GetObjectByTag ("GOBLIN3");
// Baisse ma valeur de réaction avec le PC de 100 (jusquà hostile)
AdjustReputation (GetPCSpeaker(), OBJECT_SELF, -100);
// demande à mes amis de débuter le combat
AssignCommand (oGoblin2, DetermineCombatRound());
AssignCommand (oGoblin3, DetermineCombatRound());
// démarre le combat (ça nécessite le fichier générique nw_iO_generic, ci dessus)
DetermineCombatRound();
}

Ou comme cela :

NWScript:
#include "NW_I0_GENERIC"
void main()
{
// Ce script fait que tous les allié dans la zone actuelle attaquent
location oHere = GetLocation (OBJECT_SELF);
// Baisse ma valeur de réaction avec le PC de 100 (jusquà hostile)
AdjustReputation (GetPCSpeaker(), OBJECT_SELF, -100);
// maintenant, cicle tous les objets dans la zone
object oFriend = GetFirstObjectInArea (GetArea(OBJECT_SELF));
while (GetIsObjectValid(oFriend))
{
// Si cest objet fait parti de ma faction et que cest une créature
if (GetFactionEqual(oFriend) && (GetObjectType(oFriend) ==
OBJECT_TYPE_CREATURE))
{
// et quils peuvent voi le PC
if (GetObjectSeen (GetPCSpeaker(), oFriend))
{
// leur demande de commancer le combat
AssignCommand (oFriend, DetermineCombatRound());
}
// si il ne peut pas le voir
else
{
// lui demande darrêter ce quil fait
AssignCommand (oFriend, ClearAllActions());
// and come to my location
AssignCommand (oFriend, ActionMoveToLocation(oHere, TRUE));
}
}
oFriend = GetNextObjectInArea (GetArea(OBJECT_SELF));
}
// maintenant, je démarre le combat moi même
DetermineCombatRound();
}

Il y a aussi des variation à fairece ne sont que des exemples. Une autre manière de faire commencer un combat à un groupe est de vérifier que tous ont la ligne « SetSpawnInCondition (NW_FLAG_SHOUT_ ATTACK_MY_TARGET); » activée dans leur script OnSpawn. Puis, quand vous commencez à attaquer, vous pouvez juste fare cela:

NWScript:
#include "NW_I0_GENERIC"
void main()
{
// Baisse ma valeur de réaction avec le PC de 100 (jusquà hostile)
AdjustReputation (GetPCSpeaker(), OBJECT_SELF, -100);
// démarre le combat (ça nécessite le fichier générique nw_iO_generic, ci dessus)
DetermineCombatRound();
// et cri à tous mes alliés dans le voisinage de se joindre à moi
SpeakString ("NW_ATTACK_MY_TARGET", TALKVOLUME_SILENT_TALK);
}

Vous ne verrez pas la phrase, mais tous les alliés avec une portée auditive qui peuvent voir la cible coureront à lattaque.

Comment je fais revenir mes NPC à une attitude neutre?
Si vous voulez rendre un NPC non hostile une fois quil est en combat avec les PC (si le PC est mort ou pour dautres raisons), vous devez être sur que deux choses se sont passées : un, que la faction ait une attitude non hostile face au joueur (soit neutre soit amicale). Deux, si la faction na pas « Global Effect » cochée, vous devez changer aussi tous les sentiments personnels des NPC face au PC.

Les factions « standard » dans le jeu (Commoner, Defender, etc) sont les seules pour lequels vous pouvez faire les deux dans une seule commande. Cela est fait à travers la commande SetStandardFaction, et un exemple de celle ci est dans le script par défault de mort ("nw_o0_death"), qui rement toutes les factions standarts à la neutralité à la mort du joueur. (NOTE : de nombreuses personnes ont rapportées que la faction defender nest pas remise à « zéro » avec cette commande, mais vous pouvez le faire en la traitant comme une faction personnalisée. Cf. ci dessous)

Pour les factions personnalisées (Custom factions), vous aveez besoin de deux commandes : AdjustReputation pour changer les relation de la faction avec la cible et ClearPersonnalReputation pour changer tous les sentiments du NPC. Dans les deux cas, vous devez isoler la cible qui esi un membre dun faction (ce qui peut être difficile si vous avez beaucoup de membres avec des tags différents ou qui peuvent être mort)les factions personnalisées ne sont pas identifiées par un nom, vous pouvez seulement dire « la faction a qui appartient un tel et un tel ». et si vous voulez effacer les réputations personnelles du PC avec une faction personnalisée entière, vous devez créer un cycle.

Voici un exemple de script qui ajustera la faction à neutre et fera un cycle à lintérieur de celle ci pour restaurer pour tous les membres une réaction normale avec le PC. Cette faction na pas « Global Effect » cochée, et a des membres avec le même tag « GOBLIN01 ». Le PC est mort et ce script est dans son OnDeath event:

NWScript:
// Je crée ici une commande « ClearAll FactionMembers » personnalisée
// premièrement déclarer les paramêtres de la nouvelle commande, puis ce quelle sera
// jaurais pu raisonnablement les membres dans un autre script et utiliser
// #include pour le mettre dans ce script (ou dans un autre)

void ClearAllFactionMembers (object oMember, object oPlayer)
{
object oClear = GetFirstFactionMember (oMember, FALSE);
while (GetIsObjectValid(oClear) == TRUE)
{
ClearPersonalReputation (oPlayer, oClear);
oClear = GetNextFactionMember (oMember, FALSE);
}
}
// Voici le corp principal de mon script
void main()
{
// identifie le joueur
object oPlayer = GetLastPlayerDied();
// identifie une membre de la faction, je massure que ces membres sont vivants.
// Ceêndant, je pourrais essyer plusieurs choses pour modifier un membre qui est
// valid puis dutiliser la commande if
object oGoblin = GetObjectByTag("GOBLIN1");
if (GetIsObjectValid(oGoblin))
{
// augmente la relation de la faction de 100
AdjustReputation (oPlayer, oGoblin, 100);
// utilise ma commande personnalisée dans la faction
ClearAllFactionMembers (oGoblin, oPlayer);
}
}

Ce quil y a de bien avec les cris

Quelques trucs à essayer ou à utiliser en rapport avec les cris.

Le premier: Jai toujours détesté le fait que un NPC qui entend le cri "NW_ATTACK_ MY_TARGET" mais ne voit pas le crieur ne fait rien. Il devient hostile mais nattaque pas tant que lennemi ne vient pas dans sa ligne de vue. Il yt a un moyen que jai utilisé pour quil vienne vers londroit doù provient le cri
.
Etape 1 La première chose qui doit être faite est qu tous les membres de la factions qui repondront au cri doivent avoir leur script OnSpawn paramêtré de la même manière. Allez dans leur script OnSpawn et activez les lignes suivantes (enlevez les « // »):
'SetSpawnInCondition (NW_FLAG_SHOUT_ ATTACK_MY_TARGET);'
'SetSpawnInCondition (NW_FLAG_ ON_DIALOGUE_EVENT);'
Puis re sauvez le script sous un nom différent.

Etape 2 Souvenez vous quune créature quune créature ne criera « attack myt target » uniquement si elle est attaquée en première ou si elle est tuée. Si vous voulez quelle crie, elle même, vous devez mettre ceci dans un script. Il y en a un fournit dans lexemple ci dessous dans lequel la créature devient hostile et pousse le cri à la fin du dialogue.

Etape 3 Mettez le script suivant dans le OnUserDefined event de chaque créature:

NWScript:
// Ce script fait que le récepteur dun cri"NW_ATTACK_MY_TARGET" vienne
// et regarde si il ne voit pas un ennemi. Une fois quil sest approché du crieur,
// si il voit un ennemi, son script OnPerception sera activé et il attaquera.
// Une modification interessante de ce script serait davoir que les récepteur du cri
// situé hors de vue pousse un deuxième cri qui porte plus loin que le cri original
// cela nécessiterait cependant un nouveau cri et une nouvelle définition du
// comportement
void main()
{
int nEvent = GetUserDefinedEventNumber();
if (nEvent == 1004) // OnDialog event
{
// Cela regarde si le cri correspont au comportement fixé par le
// 'SetListeningPatterns' dans OnSpawn
int nMatch = GetListenPatternNumber();
object oShouter = GetLastSpeaker();
object oIntruder;
// si je reconnais ce cri et que le crieur est valide et amical avec le NPC if(nMatch != -1 && GetIsObjectValid (oShouter) && !GetIsPC(oShouter) &&
GetIsFriend (oShouter))
{
// et que le cri est "NW_ATTACK_MY_TARGET"
if (nMatch == 5)
{
// essaie de trouver lennemi
oIntruder = GetLastHostileActor (oShouter);
if(!GetIsObjectValid (oIntruder))
{
oIntruder = GetAttemptedAttackTarget();
if(!GetIsObjectValid (oIntruder))
{
oIntruder = GetAttemptedSpellTarget();
if(!GetIsObjectValid (oIntruder))
{
oIntruder = OBJECT_INVALID;
}
}
}
// si je ne peux trouver ni le crieur ni son ennemi
if (GetIsObjectValid (oShouter) && !GetObjectSeen (oIntruder) &&
!GetObjectSeen (oShouter))
{
// défini lemeplacement du crieur
location lShouter = GetLocation(oShouter);
// arrête ce que je suis en train de faire
ClearAllActions();
// et bouge jusquà cette emplacement
ActionMoveToLocation (lShouter, TRUE);
}
// ou si je peux voir le crieur mais pas lennemi
else if (GetIsObjectValid (oShouter) && !GetObjectSeen (oIntruder) &&
GetObjectSeen (oShouter))
{
// arrête ce que je fais
ClearAllActions();
// et bouge plus près du crieur
ActionMoveToObject (oShouter, TRUE);
}
}
}
}
}


La seconde: Voici un exercice iteressant qui démontre comment faire votre propre cri. Dans cet exemple, je veux avoir un dialogue qui lance un cri et entraine que tous ceux qui lentendent joue lanimation « worship » (ils pensent que le PC est un devin.)

Etape 1 Nous allons faire le dialogue à la fin duquel le NPC poussera le cri. Faisons le très simpleune ligne seulement « Cest un devin ! » et puis le script suivant est attaché à la zone « Action Taken » de cette ligne:

NWScript:
void main()
{
// entre une variable sur moi même éguale au PC qui est en train de me parler SetLocalObject (OBJECT_SELF, "worship", GetPCSpeaker());
// lance le cri "BOWDOWN"
SpeakString ("BOWDOWN", TALKVOLUME_SILENT_TALK);
// faite lanimation worship pendant 30 secondes
ActionPlayAnimation (ANIMATION_LOOPING_WORSHIP, 0.5, 30.0);
}

Etape 2 Maintenatn, nous devons paramêtrer les autre NPC pour quils entendent le cri. Pour cela, nous devons activer la ligne « SetSpawnInCondition (NW_FLAG_ ON_DIALOGUE_EVENT); » dans leur scriptOnSpawn et ajouter la ligne suivant nimporte où :
SetListenPattern (OBJECT_SELF, "BOWDOWN", 100);
Cela rend la chaine de caractère « BOWDOWN » égale à 100 (pris au hasard) et reconnaissable par les NPC qui doivent lentendre (en utilisant la commande SetListening (OBJECT_SELF, TRUE)... qui est lancée par la commande du OnSpawn SetListeningPatterns).

Etape 3 Maintenat, nous devons juste demander au NPC que faire quand ils entendent cette commande. Toute chaine de caractères dite fait partie de leur OnDialogue event... donc le script suivant peut être placé dans le OnUserDefined event:

NWScript:
void main()
{
int nEvent = GetUserDefinedEventNumber();
// si je recois OnDialogue event
if (nEvent == 1004)
{
// regarde ce que jai entendu
int nMatch = GetListenPatternNumber();
// identifie le locuteur
object oShouter = GetLastSpeaker();
// et attrappe la variable du NPC qui sincline
object oWorship = GetLocalObject(oShouter, "worship");
// Si la chaine de caractèreest une que je reconnais et que lémetteur est un NPC valid
// et amical
if(nMatch != -1 && GetIsObjectValid (oShouter) && !GetIsPC (oShouter) &&
GetIsFriend (oShouter))
{
// et que la chaine de caractère "BOWDOWN" est égale à 100
if(nMatch == 100)
{
// se tourner face au PC avec lequel le NPC parle
ActionDoCommand (SetFacingPoint (GetPosition(oWorship)));
// puis joue lanimation worship pendant 30 secondes
ActionPlayAnimation (ANIMATION_LOOPING_WORSHIP, 0.5, 30.0);
}
}
}
}

Ce nest évidemmement pas tout ce quil faut savoir à propos des factions et des cris, mais ça devrais, je lespère être utile à un grand nombre de personnes.


This page printed from the BioWare Neverwinter Nights Community Site: http://nwn.bioware.com
Powered by BioBoards Version 2.05.010
Please read our Copyright and Trademark Information

En voila un sur les mercenaires

Par Théranthil le 21/8/2002 à 17:12:52 (#1998759)

Article écrit par Anthony Affrunti, traduit par Théranthil © 2002/07/22
Créer un mercenaire
Conversation et scripts basiques pour un mercenaire
Vous devez être quelque peut familier avec le Conversation Editor du Toolset avant de suivre ce tutorial. Si vous ne lêtes pas, je vous conseille fortement larticle dIskander HowTo qui introduit des concepts qui vous seront utile dans ce tutorial particulièrement dans la section « Starting the conversation »(le lien : Iskander's HowTo Article)
Au mimimum, vous voudrez un PC qui parle avec un NPC mercenaire et que ce NPC se joigne au PC, ou le quitte si le PC le veut. Un paiement est aussi une bonne idée. Vous voudrez aussi (souvent) que le mercenaire soit loyal, et prévienne le PC avant dêtre loué par un autre PC et de quitter le premier PC !
Ce qui veut dire que le mercenaire doit avoir une structure de dialoque qui ressemble à ça dans votre Conversation Editor:
Root
'- [OWNER] - Oui, ?
'- [OWNER] Désole, je suis déjà employé.
'- [OWNER] - Hello. Vous pouvez memployer pour 100po.
'- Je ne ai pas les moyens.
'- Je veux vous employer.
'- [OWNER] Content de lentendre
La première ligne apparaît uniquement si le PC lemploi, et offre une branche de conversation qui permet au PC de changer les options avec le mercenaire(comme le renvoyer). Pour ceci, sélectionnez longlet Text Appears When puis sélectionnez « nw_ch_tactic2 » comme script pour cette ligne.
La seconde ligne du mercenaire apparaît uniquement si le mercenaire est employé, mais pas nécessairement par le PC. Cela permet au locuteur de savoir si le mercenaire est déjà employé par quelquun dautre, et le préviendra de tout renvoie par le premier maitre. Pour celui ci, sélectionnez « nw_ch_tactics » dans longlet Text Appears When.
Si la première ou seconde ligne napparaît pas, cela veut dire que le mercenaire est libre, donc la troisième ligne apparaît, permettant au PC de le louer. Les options du PC doivent inclure choisir ou non de lemployer. Si vous voulez que le mercenaire coûte 100 po, vous pouvez créer ce script dans le Text Appears When du « Je veux vous employer » pour vérifier si le PC a assez dargent:
// * script: can_pay100
// * Est ce que le PC a 100 pièces dor?
// Utilisez dans [Text Appears When] de la ligne adéquatre du dialogue.

#include "NW_I0_PLOT"

int StartingConditional()
{
return (HasGold(100,GetPCSpeaker()));
}
Puis pour payer le mercenaire, voici le script qui va dans Action Taken de la même ligne du dialogue:
// * script: pay100
// *enlève 100 po du PC.
// A utiliser dans [Actions Taken] de la ligne adéquate.

void main()
{
TakeGoldFromCreature(100, GetPCSpeaker(), TRUE);
}
Maintenant, pour que le mercenaire se joigne au PC, ajoutez ce script dans [Actions Taken] de la ligne ou le mercenaire accepte:
// * script: henchman_joins
// * NPC mercenaire rejoint le PC, remplaçant un autre mercenaire si nécessaire.
// Utilisez dans [Actions Taken] à la ligne ou le mercenaire rejoint le PC.

#include "nw_i0_henchman"

void main()
{
if (GetIsObjectValid(GetHenchman(GetPCSpeaker())) == TRUE)
{ SetFormerMaster(GetPCSpeaker(), GetHenchman(GetPCSpeaker()));
object oHench = GetHenchman(GetPCSpeaker());
RemoveHenchman(GetPCSpeaker(), GetHenchman(GetPCSpeaker()));
AssignCommand(oHench, ClearAllActions());
}

SetWorkingForPlayer(GetPCSpeaker());
SetBeenHired();

ExecuteScript("NW_CH_JOIN", OBJECT_SELF);
}
Finallement, pour permettre au PC de renvoyer le mercenaire, nous allons ajouter loption dans la ligne de la branche de dialogue où le mercenaire est renvoyé.

Root
'- [OWNER] - Oui, ?
'- Bon travail. [End Dialog]
'- Vous êtes viré.
'- [OWNER] Je serais ici si vous avez encore besoin de moi.
Nous ajoutons ce script dans le Action Taken de la lligne ou le mercenaire dit au revoir:
// * script: henchman_leaves
// * NPC mercenaire quitte le PC.
// * A utiliser dans [Actions Taken] de la ligne ou le mercenaire part
#include "nw_i0_henchman"

void main()
{
SetFormerMaster(GetPCSpeaker(), OBJECT_SELF);
RemoveHenchman(GetPCSpeaker());
ClearAllActions();
}
Nous savons tout ce que nous avons besoin de savoir pour la conversation avec le mercenaire lui même. Nous allons maintenant créer le mercenaire lui même dans le Creature Wizard (ou copier une créature déjà crée) et ajouter quelques étapes supplémentaires.
Onglet Basic - Conversation: Utilisez le dialogue que nous venons de créer en létoffant un peu si nécessaire.
OngletAdvanced - Sound Set: Soyez sur de lui assigner un set de sons quil puisse dire en entier. Ca peut être nimporte lequel des mercenaires de la campagne officielle, ou un set de sons commencant par « Male » ou « Female »
Inventaire Quelques bonnes potions de soin sont indispensables. Si vous voulez quil ait une arme normalement non accessible pour son niveau (comme un arc avec des flèches illimitées comme ça ils nen ont pas besoin), créez larme comme un objet de créature (creature item), mais quippez le dans lemplacement normal des armes. Dans la campagne officielle, il y a aussi des objets avec des propriétés cachées qui immunusent les mercenaires contre Charme personne, domination et charme de masse. Personnellement, je préfère que mes mercenaires ne soient pas des sur hommes, cest pourquoi je ne leur donne pas des objets spéciaux.
Onglet Scripts mettez les scripts indiquez:
OnBlocked: nw_ch_ace
OnCombatRoundEnd: nw_ch_ac3
OnConversation: nw_ch_ac4
OnDamaged: nw_ch_ac6
OnDeath: nw_ch_ac7
OnDisturbed: nw_ch_ac8
OnHeartbeat: nw_ch_ac1
OnPerception: nw_ch_ac2
OnPhysicalAttacked: nw_ch_ac5
OnRested: nw_ch_aca *
OnSpawn: nw_ch_ac9
OnSpellCastAt: nw_ch_acb
OnUserDefined: nw_ch_acd
* Note: Le script OnRested (nw_ch_aca) peut être non existant, donc cest une bonne idée de laisser lemplacement vide, spéciallement si vous pensez exporter votre mercenaire.
Il y a une astuce pour remplacer tous les scripts par défaut surlignez le texte « nw_c2_default » dans chaque emplacement (enlevez la dernière lettre ou le dernier chiffre) et copiez « nw_ch_ac » à la place.
Maintenant, nous avons un mercenaire basic qui suit le PC. Il se joint à votre cause, contribut avec ces compétences, écoute les ordres, vous quitte quand vous lui demandé et peut être réemployé. Il ne monte pas de niveau, et quand il meurt il ne réapparait pass, il reste mort (mais peut être réssucité. Je préfère que les mercenaires soient comme ça, mais si vous êtes un bon scripteur, vous pouvez regarder dans le script nw_i0_henchman et le script OnDeath du mercenaire. Vous pouvez ainsi utiliser des options dans votre propre module. Ainsi, notez que pour que votre mercenaire passe de niveau, vous devez en faire une copie.
Vous pouvez télécharger un fichier de conversation avec le mercenaire en anglais (henchman conversation ßvoici le lien). Cest un fichier .erf que vous pouvez importer dans votre propre module, qui contient les conversations aussi bien que les sscripts utilisés dans ce tutorial, et qui ajoute dautres options tactiques non décrites dans ce tutorial.

JOL Archives 1.0.1
@ JOL / JeuxOnLine