Oyez, oyez !

Les résultats du vote sur les meilleurs RPG de tous les temps sont désormais dévoilés dans ce message !

Merci à toutes et à tous pour votre participation !

N'hésitez pas à aller commenter, ajouter des jeux auxquels vous n'auriez pas pensé...

[Script/BG] Enchaînement de scripts (+ modification de l'alignement)

Répondre
Bataff
Zombi
Messages : 47
Enregistré le : ven. 25 oct. 2019, 14:53
Localisation : vers Lyon
Statut : Hors ligne

[Script/BG] Enchaînement de scripts (+ modification de l'alignement)

.

Message par Bataff »

Bonjour

Un sujet de discussion après un petit retour d'expérience sur la gestion des scripts.
Les scripts, on peut en mettre sur les PJ et les PNJ, ainsi que sur les cartes, sans oublier baldur.bcs qui est actif dans toutes les situations.
Le problème est que la programmation dans un script est linéaire : on ne peut pas faire de sous-scripts et il n'y a pas d'actions prévues permettant de passer directement d'un script à un autre, comme on le fait facilement avec les dialogues. Un script qui pourrait n'utiliser qu'une dizaines d'états (ou blocs) peut se retrouver alors à traiter une centaine d'états, ce qui peut aussi ralentir le jeu s'il y en a vraiment trop.

Pour cela, j'ai fini par trouver une méthode qui permet au moins de ne pas surcharger le jeu par d'innombrables états (et je ne serais pas surpris que d'autres la connaissent déjà) :
Je commence par le début (et qui servira d'exemple pour la suite). J'avais eu l'idée d'incorporer les changements d'alignements des PJ de l'équipe plutôt que d'utiliser la réputation lors des issues des dialogues ou diverses actions. Et les triggers et actions à ce sujet sont faibles :

Trigger :

Code : Tout sélectionner

0x400A Alignment(O:Object*,I:Alignment*Align)
Returns true only if the alignment of the specified object matches that in the second parameter.
Action :

Code : Tout sélectionner

159 ChangeAlignment(O:Object*,I:Value*Align)

This action changes the alignment of the target creature to the specified value. Values are from align.ids.
Les possibilités sont faibles car :
- il n'y a rien qui permet de connaître directement l'alignement de tel ou tel PJ. Pour le savoir, il faudrait le "trigger" 9 fois de suite (donc 9 états). Ou alors utiliser les masks.
- L'action ne permet que de fixer un alignement précis. Je n'en ai pas vu qui permettrait de faire progresser l'alignement d'un cran vers Bon par exemple (et de même pour "vers Mauvais" ou "vers Loyal" ou "vers Chaotique".

Après, vouloir incorporer les changements d'alignements est toujours possible en gérant tous les cas. Le problème est que cela va nécessiter des dizaines d'états, voire davantage si on veut le faire pour les 6 PJ du groupe.

Mais il y a moyen, sans que cela surcharge le traitement des états des scripts par le jeu :

Pour faire changer l'alignement d'un cran de tel ou tel PJ ou plusieurs ou tous, le moddeur a besoin de plusieurs valeurs à préciser :
- une pour indiquer l'orientation de l'évolution de l'alignement ("vers Bon", "vers Mauvais","vers Loyal","vers Chaotique"), ce qui peut se traduire par 0,1,2,3 ou 4 (par défaut : 0 : "aucun changement")
- une pour chaque PJ pour indiquer si un changement serait à faire sur son alignement. Donc 0 (rien) ou 1 (alignement à modifier).
Appelons la première variable aligvers et les autres aligp1, aligp2, ... ,aligp6 (pour simplifier la lecture, je ne mettrais pas de préfixe ici). Elles sont toutes globales.

On crée un premier état de script qui va simplement vérifier si aligvers n'est pas égal à 0. Il faut que cet état soit dans un script fonctionnant en permanence. J'ai donc choisi de le mettre à la fin de baldur.bcs par un extend_bottom dans le fichier .tp2 du mod.
Si aligvers est différent de 0, ce script doit ensuite faire démarrer un autre script. Comme je l'ai dit au début, il n'y a pas d'instruction directe pour cela, mais ... on peut rajouter un script qui fonctionne aussi en permanence et qui pourra prendre le relai après que baldur.bcs ait fini son traitement. Pour cela, il suffit d'utiliser l'action ChangeAIScript(S:ScriptFile*,I:Level*Scrlev).
Mais pour quelle créature et dans quelle case ? Cela pourrait être une créature invoquée ou autres, mais il y aurait plus simple : la case Override de Player1. Celle-ci est normalement toujours vide (j'ai testé et vérifié pour pratiquement toutes les classes d'un perso créé au début du jeu).
(Que cette case serait toujours vide est cependant sujet à caution (rien ne dit que quelque-part lors du cours du jeu un autre script n'y serait pas incorporé, par le jeu ou par un autre mod). Jusqu'à preuve du contraire, c'est ce que j'utilise pour le moment -et que je libère après utilisation-)
L'intérêt d'un script mis dans cette case est que ce script sera actif en permanence, tout comme baldur.bcs, et que l'on peut le changer en un autre, puis un autre, à volonté.

On rajoute alors un Override(Player1,ChangeAIScript("aligvers",OVERRIDE)) dans l'état rajouté dans baldur.bcs, ainsi qu'une variable habituelle passant de 0 à 1 pour éviter de ré-enclencher les actions de cet état. Celui-ci a fini son traitement et c'est le script "aligvers.bcs", mis dans la case Override de Player1, qui va démarrer à son tour. La transition est faite.

Ce script "aligvers.bcs" va aiguiller entre quatre scripts possibles selon la valeur de aligvers (1,2,3 ou 4), un état par possibilité. Si aligvers=1 alors le nouveau script sera aligB (B comme Bon), si c'est 2 le nouveau script sera aligM, si c'est 3 le nouveau script sera aligL et si c'est 4 le nouveau script sera aligC. La valeur de aligvers est aussi mise à zéro avant la transition.
Pour passer de ce script à l'un des 4 suivants : La même méthode, on met le nouveau script dans la case Override de player1 par Override(Player1,ChangeAIScript("aligB",OVERRIDE)) (si le script suivant est aligB)

Le script aligB va aiguiller selon le numéro du PJ dans le groupe. Pour chaque PJ, un nouveau script (aligB1,aligB2, ...). Six blocs donc à écrire pour ces six cas possibles et transition à l'un de ces nouveaux scripts par Override(Player1,ChangeAIScript("aligB3",OVERRIDE)) (si aligp1=0 , aligp2=0 et aligp3=1). Mise à zéro du premier aligp1, aligp2,...,aligp6 ,trouvé comme étant égal à 1, avant la transition. J'ai aussi rajouté un état à la fin de aligB qui a comme trigger True() et qui libère la case Override de Player1 par Override(Player1,ChangeAIScript("",OVERRIDE)) (à ce stade, tous les PJ auront été traîtés et ce sera la fin de l'opération)

Le script aligB3 devra ensuite changer l'alignement de Player3 un cran "vers le bon", au cas par cas, suivant les 6 cas possibles de son alignement actuel : Loyal neutre, Neutre strict, Chaotique neutre, Loyal mauvais, Neutre mauvais et Chaotique mauvais (inutile de se soucier des alignements en "bon", on ne pourra pas les rendre "plus bons")
Ce dernier script aligB3 de la chaîne se termine en revenant au précédent aligB par Override(Player1,ChangeAIScript("aligB",OVERRIDE)), pour que aligB traite les changements éventuels des PJ suivants.

Alors, certes, cela fait beaucoup d'états de scripts à écrire juste pour faire changer l'alignement (j'ai compté 176 états dans 29 scripts en tout). Mais, au final, il n'y a qu'un état (celui dans baldur.bcs) qui est laissé actif en permanence. Tous les autres ne sont utilisés uniquement que lorsqu'il y en a besoin. Ceci car la case Override de Player1 est aussi vide avant l'utilisation des scripts que après (comme si ces autres états de scripts étaient rangés dans un placard lorsqu'on ne s'en sert pas).

Je ne mets pas ici tous les scripts que j'ai écrit, il y en a beaucoup trop, surtout après ce long message. L'idée était de montrer cette méthode. Mais peut-être y en a-t-il d'autres voire de meilleures idées ou suggestions/remarques ?

Edit : J'ai oublié de parler d'une valeur de sécurité (pour éviter que la chaîne de scripts soit ré-enclenchée, alors qu'elle ne s'est pas terminée, si le moddeur la ré-utilise tout de suite après).
Le processus de changement d'alignement ne s'enclencherait pas si cette valeur n'est pas 0 (ce que devra vérifier l'état rajouté dans baldur.bcs) et le moddeur qui utilise la procédure devra aussi le vérifier.
L'état rajouté dans baldur.bcs le mettrait ensuite à 1 et à la fin du processus par la chaîne des scripts, au moment où la case Override de Player1 est mise à vide, il sera remis à 0.

Edit2 : J'ai continué à faire des tests plus poussés (plusieurs changements à la suite sur les 6 persos de l'équipe). Ca marche, aucun soucis de ce côté. Par contre, il faut quand même un temps pour que ce système de scripts en arborescence fasse tout.
Le problème est qu'il faut un petit temps (pas grand chose et largement moins qu'une seconde) pour que le nouveau script se mette en route à chaque transition et, si on fait bon nombre de transition, il faut alors attendre un peu.
C'est jouable ceci dit, puisqu'un mod ne va pas faire des changement d'alignements en permanence. Disons qu'il y a une petite gêne.
Aussi je me demande si ce ne serait pas mieux de regrouper l'ensemble des petits scripts utilisant la case override de Player1 en un, deux ou trois scripts seulement, et laisser en l'état le script à un état rajouté dans baldur.bcs et servant de déclencheur.
Bataff
Zombi
Messages : 47
Enregistré le : ven. 25 oct. 2019, 14:53
Localisation : vers Lyon
Statut : Hors ligne
.

Message par Bataff »

Suite à l'Edit2 du message précédent, j'ai ré-organisé les états (et, dans le cas-où, sauvegarder les anciens dans un autre répertoire) et cela marche beaucoup mieux. Un petit temps pour le démarrage puis les actions s'enchaînent les une après les autres rapidement.
Grâce aussi à Continue() qui était inutile dans la première idée mais dont l'emploi est bénéfique pour cette seconde solution, étant donné que les états dans un script sont devenus plus nombreux et que plusieurs états d'un même script seront enclenchés.

Voilà ce qu'il y a en résumé :
- Un script entalibg composé d'un seul état et rajouté à la fin de baldur.bcs par extend_bottom. Il installe le script suivant entalign dans la case Override de Player1.
- Le script entalign composé de 5 états qui installe dans la même case de Player1 l'un des 4 scripts entaligB, entaligM, entaligL et entaligC selon la valeur de entchgtalign (1 pour Bon, 2 pour Mauvais, 3 pour Loyal, 4 pour Chaotique). Le 5ème état est une sécurité si cette valeur n'était pas 1,2,3 ou 4, et mettra dans ce cas un script nul dans la case override de Player1 (=> fin).
- Les 4 scripts entaligB, entaligM, entaligL et entaligC. Ces derniers effectuent les changements éventuels de l'alignement au cas par cas, pour chaque PJ du groupe selon leurs valeurs entchgtalignP1, entchgtalignP2, ..., entchgtalignP1. Pour chacun de ces quatre scripts, j'ai rajouté Continue() à la fin des actions de chaque état (sauf le dernier). A la fin du script, un état demandant à vider la case Override de Player1 (=> fin). En tout, 37 états pour chacun de ces 4 scripts.
- Eventuellement, on pourrait aussi rajouter d'autres scripts après ceux-là pour s'occuper des changements éventuels de certaines classes (paladin, rôdeur, prêtre de Lathandre/Helm/talos,...) compte-tenu des nouveaux alignements obtenus.
- Et la valeur de sécurité activée à 0 ou 1, que j'avais parlé dans l'Edit1 de mon précédent message.

Si je souhaite par exemple que Imoen (Player2) soit un peu plus méchante, il suffit que j'exécute un état de script qui vérifie que la valeur de sécurité est 0, qui met la valeur entchgtalign à 2 et la valeur entchgtalignP2 à 1 (les autres entchgtalignP... des autres PJ sont 0 par défaut). En gros, c'est comme utiliser une fonction mais sans nom.

Edit : Une dernière chose que je viens de me rendre compte, l'état de script dans baldur.bcs peut être enlevé puisque le moddeur doit vérifier que la sécurité est 0 et que cet état ne fait que la remettre à 1 et mettre le premier script dans la case override de Player1.
Dans ce cas, le moddeur devra écrire un état de script qui :
- vérifie que la sécurité est 0.
- met cette sécurité à 1.
- active les variables entchgtalign, entchgtalignP1, entchgtalignP2, ... , entchgtalignP6 selon ses souhaits.
- installe le script entalign dans la case override de Player1
(et là, c'est comme utiliser une fonction avec le nom entalign)

Mieux encore, il peut utiliser directement l'un des quatre scripts entaligB, entaligM, entaligL et entaligC de la même manière et, dans ce cas, il n'aura pas besoin d'activer la variable entchgtalign .

Et pour aller encore plus loin, en rajoutant une activation de la sécurité à 1 au début des actions dans entalign, entaligB, entaligM, entaligL et entaligC, on peut alors éviter au moddeur de la mettre à 1 lui-même.
Répondre

Retourner vers « Scripts »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 1 invité