[Tutoriel] Les chronos séquencés
-
- Moddeur aspirant
- Messages : 97
Les chronos séquencés
Voici ma traduction (sans doute imparfaite n'étant ni bilingue ni scripteur) d'un tuto diponible sur ce site :
http://www.cipscis.com/fallout/tutorial ... imers.aspx
Cela sert à organiser des séquences scriptées pour vos quêtes où vos donjons, un peu comme celles de la séquence d'anniversaire dans fallout 3.
Je profite de l'occasion pour lancer l'idée d'un topic banque de scripts où chacun pourrait mettre un script intéressant pour l'ensemble des moddeurs. L'idée pourrait être sympa et améliorerai le travail de chacun grâce au savoir faire de scripteur plus chevronnés non?
Chronos séquencés
Une bonne façon de créer un donjon, des effets ou une quête qui paraissait unique est d'utiliser une séquence scrpitée dans le but de créer un évènement qui ne sera pas vu régulièrement. Quelques exemple de ce type de séquences scriptées dans fallout 3 sont la sceène de l'aniversaire au début du jeu et les effet critiques de mort provoqués par les armes à énergie. Sans doute le structure de script la plus commode pour controler ce type de séquence est ce que j'aime appeler "Un chrono séquencé"
La structure de base dun chrono séquencé consiste en deux varaible de control, et une série d'étape conditionnée à l'intérieure d'un block GameMode. L'une de ces variables est une intégrale, et contrôle les "étapes" de la séquence, quant à l'autre variable, c'est une variable de typeFloat, qui contrôle le timing de la séquence.
Parce que le chrono utilisé dans un "chrono séquencé" est de relative courte durée et s'exécute dans un bloc GameMode, il est contrôlé via la fonction GetSecondsPassed. GetSecondsPassed est une fonction qui retourne le temps qui s'est écoulé, en secondes, depuis que le script s'est éxécuté pour la dernière fois. Pour les script d'effet ou les scripts d'objet, il s'agira du temps écoulé depuis la dernière frame, mais pour les scripts de quête cela sera affecté par le temps d'éxécution du script de quête.
Parce que la fonction GetSecondsPassed n'est pas cumulative ((càd que la valeur retournée est réinitialisée à chaque frame, au lieu d'augmenter), une variable de type Float est nécessaire pour stocker en mémoire l'accumulation de toutes ces valeurs retournées dans le but de déterminer le temps passé depuis un évènement particulier. Heureusement, le sode nécessaire pour réaliser cela est simple:
set fTimer to fTimer - GetSecondsPassed
Vous avez sans doute noté que mon chrono est un compte à rebours. Bien qu'un chrono qui compterait le temps qui s'accumule est tout à fait possible, je trouve que la méthode du compte à rebours est plus facile pour visualiser un "chrono séquencé"
Maintenant que nous savons grosso modo comment va fonctionner la partie "chrono" de notre "chrono séquencé", il est temps de regarder comment nous allons contrôler les différentes étapes de notre séquence. Une fois encore le code à utiliser est relativement simple, nous alons utiliser une variable de type intégrale pour stocker en mémoire l'étape actuelle de notre séquence et un groupe de condition pour vérifier la valeur de cette variable. Dans cet exemple, il y a trois étape, commençant par une étape que nous appellerons "stage 0" (la variable désignant l'étape est appelée "iStage") :
if iStage == 0
; Stage 0
elseif iStage == 1
; Stage 1
elseif iStage == 2
; Stage 2
endif
Maintenant, il y a encore une chose dont nous avons besoin pour organiser proprement les étapes de notre "chrono séquencé". Pour le moment, rien dans notre script ne fera changer d'étape. Cela veut dire que, parce que les variables sont automatiquement initialisée à la valeur 0, le "chrono séquencé" restera à l'étape 0 de la séquence éternellement. Pour changer cela, une commande appelée "Set" doit être utilisée pour incrémenter la valeur de notre variable "iStage" :
if iStage == 0
; Stage 0
set iStage to 1
elseif iStage == 1
; Stage 1
set iStage to 2
elseif iStage == 2
; Stage 2
set iStage to 3
endif
Avec le code ci dessus, l'étape est avancée de 1 à chaque frame. Alors que ce comportement n'est pas entièrement nécessaire (vous pouvez imposer d'autres conditions pour incrémenter la variable iStage et donc passer à l'étape suivante) cela est très simple donc je l'utilise pour notre exemple.
Maintenant la prochaine étape pour organiser la structure de notre "chrono séquencé" est la plus cruciale. Nous allons combiner la partie "chrono" et la partie "étape" de notre script. Afin de réaliser cela nous avons besoin d'inclure notre chrono dans les conditions d'étape. Donc notre script continuellement alterner entre décompter le chrono (le faire diminuer dans l'exemple), et exécuter le code pour une étape particulière (celle qui sera valide à ce moment là). Parce que notre chrono décroît, nous devons l'initialiser par une varaiable que nous appellerons 'fTimer" qui aura de ce fait une valeur supérieure à 0. Donc voilà comment nous combinons notre chrono et notre "compteur d'étape" :
if fTimer > 0
set fTimer to fTimer - GetSecondsPassed
elseif iStage == 0
; Stage 0
set iStage to 1
elseif iStage == 1
; Stage 1
set iStage to 2
elseif iStage == 2
; Stage 2
set iStage to 3
endif
Now, in order to utilise our timer, we need to initialise it by setting our timer variable to a value greater than 0. Because the code for each stage runs once the timer has run out, we can reset the timer within all of the stages. For example, this code will introduce a 3 second delay between stage 0 and stage 1, followed by a 1 second delay between stage 1 and stage 2:
Maintenant, afin d'utiliser notre chrono, nous avons besoin de l'initialiser en fixant la valeur de la variable représentant le chrono à une valeur supérieure à 0. Parce que le code pour chacune des étape s'exécute une fois que le chrono s'est écoulé, nous pouvons réinitialiser le chrono à une valeur différente pour chacune des étapes. Par exemple, ce code introduit un délai de 3 secondes entre l'étape 0 et l'étape 1, suivi par un délai d'une seconde entre stage 1 et stage 2.
if fTimer > 0
set fTimer to fTimer - GetSecondsPassed
elseif iStage == 0
; Stage 0
set iStage to 1
set fTimer to 3
elseif iStage == 1
; Stage 1
set iStage to 2
set fTimer to 1
elseif iStage == 2
; Stage 2
set iStage to 3
endif
La structure de base du code est maintenant mise en place, maintenant nous pouvons commencer à ajouter dans notre code ce qui fera quelque chose, pendant la séquence que nous pouvons désormais contrôler. Pour cet exemple, je vais faire un script attaché à un "token" qui, quand il est ajouter dans l'inventaire d'un pnj, l'oblige à jouer l'animation "Explosive Planted" (celle où le pnj se débat quand vous lui avez fourrer une grenade dans les poches pour le faire exploser), suivi dun son beep comme celui que fait une mine quand elle s'active, pour se terminer avec un pnj mourrant dans une explosion :
ScriptName PantsExplodedTokenScript
float fTimer
int iStage
ref rContainer
Begin OnAdd
set rContainer to GetContainer
if rContainer.IsActor
else ; if rContainer.IsActor == 0
RemoveMe
endif
End
Begin GameMode
if fTimer > 0
set fTimer to fTimer - GetSecondsPassed
elseif iStage == 0
if rContainer.GetIsCreature
; Creatures don't have the appropriate animations
elseif rContainer.GetEquipped AnimationRestrictedArmors
rContainer.PlayIdle PanicGrenadePlantPA
else
rContainer.PlayIdle PanicGrenadePlant
endif
set iStage to 1
set fTimer to 3
elseif iStage == 1
rContainer.PlaySound3D WPNMineTick
set iStage to 2
set fTimer to 1
elseif iStage == 2
; Ensure that the explosion kills the actor
rContainer.SetActorValue Health 1
rContainer.PlaceAtMe MineFragExplosion
RemoveMe
endif
End
Ne vous inquiètez pas si vous ne savez pas ce que font les divers ajouts que j'ai fait dans mon scrip. L'important est surtout de comprendre la structure d'un "chrono séquencé".
Quand vous mettez en place un "Chrono séquencé"pour contrôler une séquence scriptée, la première question que vous devez vous poser est : comment les évènement vont il s'enclencher. Si la séquence doit démarrer dès que le script s'exécute, comme avec un script d'effet, alors la première étape de votre séquence doit être le "stage 0". Si ce n'est pas le cas, et si la séquence doit être enclenchée par un évènement extérieur, comme par exemple lorsque une étape de quête est atteinte, alors dans ce cas la première étape doit être le "stage1" et la valeur de votre variable "iStage" doit être modfiée lorsque cet évènement arrive.
http://www.cipscis.com/fallout/tutorial ... imers.aspx
Cela sert à organiser des séquences scriptées pour vos quêtes où vos donjons, un peu comme celles de la séquence d'anniversaire dans fallout 3.
Je profite de l'occasion pour lancer l'idée d'un topic banque de scripts où chacun pourrait mettre un script intéressant pour l'ensemble des moddeurs. L'idée pourrait être sympa et améliorerai le travail de chacun grâce au savoir faire de scripteur plus chevronnés non?
Chronos séquencés
Une bonne façon de créer un donjon, des effets ou une quête qui paraissait unique est d'utiliser une séquence scrpitée dans le but de créer un évènement qui ne sera pas vu régulièrement. Quelques exemple de ce type de séquences scriptées dans fallout 3 sont la sceène de l'aniversaire au début du jeu et les effet critiques de mort provoqués par les armes à énergie. Sans doute le structure de script la plus commode pour controler ce type de séquence est ce que j'aime appeler "Un chrono séquencé"
La structure de base dun chrono séquencé consiste en deux varaible de control, et une série d'étape conditionnée à l'intérieure d'un block GameMode. L'une de ces variables est une intégrale, et contrôle les "étapes" de la séquence, quant à l'autre variable, c'est une variable de typeFloat, qui contrôle le timing de la séquence.
Parce que le chrono utilisé dans un "chrono séquencé" est de relative courte durée et s'exécute dans un bloc GameMode, il est contrôlé via la fonction GetSecondsPassed. GetSecondsPassed est une fonction qui retourne le temps qui s'est écoulé, en secondes, depuis que le script s'est éxécuté pour la dernière fois. Pour les script d'effet ou les scripts d'objet, il s'agira du temps écoulé depuis la dernière frame, mais pour les scripts de quête cela sera affecté par le temps d'éxécution du script de quête.
Parce que la fonction GetSecondsPassed n'est pas cumulative ((càd que la valeur retournée est réinitialisée à chaque frame, au lieu d'augmenter), une variable de type Float est nécessaire pour stocker en mémoire l'accumulation de toutes ces valeurs retournées dans le but de déterminer le temps passé depuis un évènement particulier. Heureusement, le sode nécessaire pour réaliser cela est simple:
set fTimer to fTimer - GetSecondsPassed
Vous avez sans doute noté que mon chrono est un compte à rebours. Bien qu'un chrono qui compterait le temps qui s'accumule est tout à fait possible, je trouve que la méthode du compte à rebours est plus facile pour visualiser un "chrono séquencé"
Maintenant que nous savons grosso modo comment va fonctionner la partie "chrono" de notre "chrono séquencé", il est temps de regarder comment nous allons contrôler les différentes étapes de notre séquence. Une fois encore le code à utiliser est relativement simple, nous alons utiliser une variable de type intégrale pour stocker en mémoire l'étape actuelle de notre séquence et un groupe de condition pour vérifier la valeur de cette variable. Dans cet exemple, il y a trois étape, commençant par une étape que nous appellerons "stage 0" (la variable désignant l'étape est appelée "iStage") :
if iStage == 0
; Stage 0
elseif iStage == 1
; Stage 1
elseif iStage == 2
; Stage 2
endif
Maintenant, il y a encore une chose dont nous avons besoin pour organiser proprement les étapes de notre "chrono séquencé". Pour le moment, rien dans notre script ne fera changer d'étape. Cela veut dire que, parce que les variables sont automatiquement initialisée à la valeur 0, le "chrono séquencé" restera à l'étape 0 de la séquence éternellement. Pour changer cela, une commande appelée "Set" doit être utilisée pour incrémenter la valeur de notre variable "iStage" :
if iStage == 0
; Stage 0
set iStage to 1
elseif iStage == 1
; Stage 1
set iStage to 2
elseif iStage == 2
; Stage 2
set iStage to 3
endif
Avec le code ci dessus, l'étape est avancée de 1 à chaque frame. Alors que ce comportement n'est pas entièrement nécessaire (vous pouvez imposer d'autres conditions pour incrémenter la variable iStage et donc passer à l'étape suivante) cela est très simple donc je l'utilise pour notre exemple.
Maintenant la prochaine étape pour organiser la structure de notre "chrono séquencé" est la plus cruciale. Nous allons combiner la partie "chrono" et la partie "étape" de notre script. Afin de réaliser cela nous avons besoin d'inclure notre chrono dans les conditions d'étape. Donc notre script continuellement alterner entre décompter le chrono (le faire diminuer dans l'exemple), et exécuter le code pour une étape particulière (celle qui sera valide à ce moment là). Parce que notre chrono décroît, nous devons l'initialiser par une varaiable que nous appellerons 'fTimer" qui aura de ce fait une valeur supérieure à 0. Donc voilà comment nous combinons notre chrono et notre "compteur d'étape" :
if fTimer > 0
set fTimer to fTimer - GetSecondsPassed
elseif iStage == 0
; Stage 0
set iStage to 1
elseif iStage == 1
; Stage 1
set iStage to 2
elseif iStage == 2
; Stage 2
set iStage to 3
endif
Now, in order to utilise our timer, we need to initialise it by setting our timer variable to a value greater than 0. Because the code for each stage runs once the timer has run out, we can reset the timer within all of the stages. For example, this code will introduce a 3 second delay between stage 0 and stage 1, followed by a 1 second delay between stage 1 and stage 2:
Maintenant, afin d'utiliser notre chrono, nous avons besoin de l'initialiser en fixant la valeur de la variable représentant le chrono à une valeur supérieure à 0. Parce que le code pour chacune des étape s'exécute une fois que le chrono s'est écoulé, nous pouvons réinitialiser le chrono à une valeur différente pour chacune des étapes. Par exemple, ce code introduit un délai de 3 secondes entre l'étape 0 et l'étape 1, suivi par un délai d'une seconde entre stage 1 et stage 2.
if fTimer > 0
set fTimer to fTimer - GetSecondsPassed
elseif iStage == 0
; Stage 0
set iStage to 1
set fTimer to 3
elseif iStage == 1
; Stage 1
set iStage to 2
set fTimer to 1
elseif iStage == 2
; Stage 2
set iStage to 3
endif
La structure de base du code est maintenant mise en place, maintenant nous pouvons commencer à ajouter dans notre code ce qui fera quelque chose, pendant la séquence que nous pouvons désormais contrôler. Pour cet exemple, je vais faire un script attaché à un "token" qui, quand il est ajouter dans l'inventaire d'un pnj, l'oblige à jouer l'animation "Explosive Planted" (celle où le pnj se débat quand vous lui avez fourrer une grenade dans les poches pour le faire exploser), suivi dun son beep comme celui que fait une mine quand elle s'active, pour se terminer avec un pnj mourrant dans une explosion :
ScriptName PantsExplodedTokenScript
float fTimer
int iStage
ref rContainer
Begin OnAdd
set rContainer to GetContainer
if rContainer.IsActor
else ; if rContainer.IsActor == 0
RemoveMe
endif
End
Begin GameMode
if fTimer > 0
set fTimer to fTimer - GetSecondsPassed
elseif iStage == 0
if rContainer.GetIsCreature
; Creatures don't have the appropriate animations
elseif rContainer.GetEquipped AnimationRestrictedArmors
rContainer.PlayIdle PanicGrenadePlantPA
else
rContainer.PlayIdle PanicGrenadePlant
endif
set iStage to 1
set fTimer to 3
elseif iStage == 1
rContainer.PlaySound3D WPNMineTick
set iStage to 2
set fTimer to 1
elseif iStage == 2
; Ensure that the explosion kills the actor
rContainer.SetActorValue Health 1
rContainer.PlaceAtMe MineFragExplosion
RemoveMe
endif
End
Ne vous inquiètez pas si vous ne savez pas ce que font les divers ajouts que j'ai fait dans mon scrip. L'important est surtout de comprendre la structure d'un "chrono séquencé".
Quand vous mettez en place un "Chrono séquencé"pour contrôler une séquence scriptée, la première question que vous devez vous poser est : comment les évènement vont il s'enclencher. Si la séquence doit démarrer dès que le script s'exécute, comme avec un script d'effet, alors la première étape de votre séquence doit être le "stage 0". Si ce n'est pas le cas, et si la séquence doit être enclenchée par un évènement extérieur, comme par exemple lorsque une étape de quête est atteinte, alors dans ce cas la première étape doit être le "stage1" et la valeur de votre variable "iStage" doit être modfiée lorsque cet évènement arrive.
Re: TUTO : Les chronos séquencés
Excellent , merci ! Je venais de tomber sur le site de Cipscis et j'avais l'intention de traduire notamment "scripting for beginners" mais je découvre qu'une partie du travail est déjà fait !
As-tu l'intention de traduire d'autres pages consacrées au script ?
As-tu l'intention de traduire d'autres pages consacrées au script ?
"Quel est ce monde où l'on gère les enfants et rassure les marchés ?"
-
- Moddeur aspirant
- Messages : 97
Re: TUTO : Les chronos séquencés
Salut,
Non je n'avais pas vraiment l'intention de traduire le reste à vrai dire. Cette partie m'intéressait et je voulais garder une version française. Bon courage pour la traduction si tu t'y met.
Il faut d'ailleurs que je réédite le topic car il est bourré de fautes d'orthographe et de fautes de frape.
Non je n'avais pas vraiment l'intention de traduire le reste à vrai dire. Cette partie m'intéressait et je voulais garder une version française. Bon courage pour la traduction si tu t'y met.
Il faut d'ailleurs que je réédite le topic car il est bourré de fautes d'orthographe et de fautes de frape.
Re: TUTO : Les chronos séquencés
Faut-il demander une autorisation pour traduire et republier sa page ?
"Quel est ce monde où l'on gère les enfants et rassure les marchés ?"
-
- Moddeur aspirant
- Messages : 97
Re: TUTO : Les chronos séquencés
A mon avis je ne pense pas que a pose problème, si un auteur fait un tuto c'est bien pour que tout le monde puisse le lire donc si son tuto est traduit dans une autre langue c'est encore mieux. Par contre il faut bien laissé l'indication et la référence de son site. Cela dit je ne me suis as vraiment posé la question en fait. Tu peux peut être lui demander.
Re: TUTO : Les chronos séquencés
Fort bien. Merci.
"Quel est ce monde où l'on gère les enfants et rassure les marchés ?"
Re: TUTO : Les chronos séquencés
Une traduction est déjà disponible : http://www.fallout-3.com/forum/showthread.php?t=7672
"Quel est ce monde où l'on gère les enfants et rassure les marchés ?"
-
- Moddeur aspirant
- Messages : 97
Re: TUTO : Les chronos séquencés
Cool.
Au fait j'ai essayé le script du tuto et .... il ne marche qu'à moitié, l'animation de panique ne s'exécute pas(en revanche le pnj meurt bien dans une explosion après un petit son beep)
Au fait j'ai essayé le script du tuto et .... il ne marche qu'à moitié, l'animation de panique ne s'exécute pas(en revanche le pnj meurt bien dans une explosion après un petit son beep)
-
- Moddeur aspirant
- Messages : 97
Re: TUTO : Les chronos séquencés
Ca y est j'ai enfin réussi à faire jouer l'animation de panic avant que le pnj n'explose.
En fait le problème est tout bête : les animations PanicGrenadePlantPA et PanicGrenadePlant qui doivent être jouée sont contenus dans une branche de l'arbre des animations (dans Gameplay, Idleanimation de la barre des menus du GECK) qui prévoit une condition pour que ces animations puissent être jouées par un pnj (Getexplosiveplanted = 1 je crois). J'ai donc fait une copie de cette branche d'animation, renommées les copies de chaque animations, et j'ai enlevé la condition précédemment évoquée pour la remplacer par une autre (en l'espèce : 1 condition vérifiant que le pnj a au moins un exemplaire du token dont se sert le script pour déclencher la séquence).
J'ai ensuite remplacé dans le script les noms des animations à jouer par le nom des animations que je venais de "créer" et voilà une belle panique chez notre pnj lors de l'ajout du token dans son inventaire.
En fait le problème est tout bête : les animations PanicGrenadePlantPA et PanicGrenadePlant qui doivent être jouée sont contenus dans une branche de l'arbre des animations (dans Gameplay, Idleanimation de la barre des menus du GECK) qui prévoit une condition pour que ces animations puissent être jouées par un pnj (Getexplosiveplanted = 1 je crois). J'ai donc fait une copie de cette branche d'animation, renommées les copies de chaque animations, et j'ai enlevé la condition précédemment évoquée pour la remplacer par une autre (en l'espèce : 1 condition vérifiant que le pnj a au moins un exemplaire du token dont se sert le script pour déclencher la séquence).
J'ai ensuite remplacé dans le script les noms des animations à jouer par le nom des animations que je venais de "créer" et voilà une belle panique chez notre pnj lors de l'ajout du token dans son inventaire.
Re: TUTO : Les chronos séquencés
Bien Joué ! Et merci pour l'info. (J'ai fait une version pdf corrigée de ta traduction , je vais rajouter ces quelques lignes)
"Quel est ce monde où l'on gère les enfants et rassure les marchés ?"