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.
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.
- 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.