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] Comment fonctionne la commande SetTokenObject ?

Répondre
Sous Nain
Statut : Hors ligne

[SCRIPT] Comment fonctionne la commande SetTokenObject ?

.

Message par Sous Nain »

Après un petit tour sur IESDP, je remarque une action SetTokenObject(S: string, O: Object) qui est censé permettre :

1) de "copier" la valeur du Token spécifié d'un personnage à un autre
2) de "nommer" un personnage qui sera ensuite accessible sous ce nom, ex:

Code : Tout sélectionner

SetTokenObject("MYTARGET", [ENEMY])
Attack("MYTARGET")

La fonction 2) étant celle qui m'intéresse, j'ai essayé de la mettre en application, sans grand succès (ça ne fait rien).

J'avoue aussi ne pas très bien comprendre : est-ce que chaque créature a des valeurs de Token qu'il est possible de modifier, ou est-ce qu'il y a une valeur globale pour chaque token, et que les créatures n'ont qu'une valeur par défaut qui est mise dans la valeur globale dès que la-dite créature est active ?

De même, comment peut marcher le SetTokenObject pour la fonction 2) ?

Donc bref, si quelqu'un s'y connais en Token et plus particulièrement sur cette fonction, et qu'il veut bien me l'expliquer, et bien qu'il le fasse :p

Merci !
Sous Nain
Statut : Hors ligne
.

Message par Sous Nain »

:hop:
Personne pour répondre à ma question ? Allez, une bonne action ^^
Bataff
Zombi
Messages : 47
Enregistré le : ven. 25 oct. 2019, 14:53
Localisation : vers Lyon
Statut : Hors ligne
.

Message par Bataff »

Comme les 'token' sont ce que je suis en train d'utiliser en ce moment, je vais essayer de répondre afin de faire le point sur ce que je comprends, bien que ce topic date de 16 années.

Les actions qui gestionnent les tokens :

Code : Tout sélectionner

 247[B] SetToken(S:Token*,I:STRREF*)[/B] Variants: [BG2/BGEE] [BG1/IWD1/IWD2/PST]

This action sets the specified token to the specified value. Whenever the token is then used within a strref, the current value of the token will be displayed. Values assigned by this action are not saved.

Code : Tout sélectionner

 248 [B]SetTokenObject(S:Token*,O:Object*)[/B] Variants: [BG2/BGEE] [BG1/IWD1/IWD2/PST]

This action sets the token specified by the string parameter (e.g. DAMAGER) to the name of the object specified in the object parameter. Values assigned by this action are not persisted to save games.

Code : Tout sélectionner

[B]SetTokenGlobal(S:GLOBAL*,S:Area*,S:Token*)[/B] Variants: [BG2/BGEE] [BG1/IWD1/IWD2/PST]

This action sets the specified token to the given variable (in the specified scope). The example script will display 100 over the head of the active creature.

IF
  Global("Value","GLOBAL",0)
THEN
  RESPONSE #100
    SetGlobal("Value","GLOBAL",100)
    SetTokenGlobal("Value","GLOBAL","PPOINTS")
    DisplayStringHead(Myself,63037) //63037  is <PPOINTS> for me
END
Si on scrute l'exemple donné, quelqu'un qui a fait un peu de programmation de base en C++ ou Pascal ou ... reconnaîtra un pointeur. Aussi faut-il comprendre la notion de pointeur avant de comprendre ce qu'est un token (ou "jeton" en Français).

Un pointeur ressemble à une variable mais il ne contient pas le contenu de cette dernière. Il contient l'adresse de cette variable. Son intérêt est alors qu'il peut changer de variable (en "pointant" sur la nouvelle), ce qui peut être utile par exemple avec les tableaux. Si on utilisait une variable il faudrait changer son contenu, alors qu'avec un pointeur il suffit de "pointer" sur une autre variable ayant ce nouveau contenu.

C'est comme lorsqu'on entre dans un magasin de vêtements et que l'on souhaite acheter un vêtement précis. le vendeur peut :
- soit aller trouver lui-même ce vêtement puis vous l'apporter (il vous donne le contenu).
- soit vous dire d'aller dans tel rayon à droite ou à gauche (il vous donne le chemin pour accéder au contenu)
Dans le premier cas on est en mode variable et dans le second cas on est dans le mode pointeur. Et dans les deux cas, on pourra avoir ce que l'on recherche.
Par contre, le problème est dans la façon d'utiliser l'un ou l'autre. Un pointeur ne s'utilise pas comme une variable. De plus, un pointeur à un type. Certains pointent sur des entiers, d'autres sur des chaînes de caractères, etc.

Si on reprend les trois actions ci-dessus, on comprend que SetToken(S:Token*,I:STRREF*) permet d'assigner un token à une adresse indexée sur une chaîne de caractères (strref). Le "I" de "I:STRREF*" est simplement le numéro de la chaîne de caractères , et dans ce cas le token est un pointeur sur une chaîne de caractères. Ce que ne peut pas faire SetTokenGlobal(S:GLOBAL*,S:Area*,S:Token*) car cette action-là assigne un token sur une variable de type entier.
Quant à SetTokenObject(S:Token*,O:Object*), celui-là je ne l'ai jamais utilisé. De ce que je comprends dans la description est qu'il assigne le token, écrit sous la forme d'une chaîne de caractères donc à mettre entre "", au nom de l'objet (ou plutôt à la variable de l'objet contenant ce nom). Donc à priori, cela concerne les token de type chaîne de caractères, comme la première des trois actions.

Si on est dans BG2/BG2EE, un token peut être très utile dans les strref car en fait, lorsqu'on écrit des phrases indexées dans un fichier .tra et que l'on y incorpore par exemple un <CHARNAME> dans une phrase, et bien on utilise un token. CHARNAME est un token et il y en a plein d'autres (https://gibberlings3.github.io/iesdp/appendices/token_lists/bg2tokens.htm -et cette liste n'est pas exhaustive, il y en a encore d'autres comme NEXTLEVEL-)
Et grâce à la 1ère des trois actions précédentes, SetToken(S:Token*,I:STRREF*), on peut créer ses propres token -ici de type chaînes de caractères-.
Par exemple, si on écrit dans le fichier .tra ces deux lignes :
@1 = ~un gâteau~
@10 = ~Imoen est en train de manger <JETON>.~
Et que dans un script on crée un token pointant sur @1 : SetToken("JETON",@1)
Alors la phrase affichée (dans un dialogue, ou dans un script en utilisant DisplayStringHead par exemple) sera : "Imoen est en train de manger un gâteau.
Si plus tard, on veut montrer que Imoen a changé son menu et décide de manger une pomme, il suffira de rajouter @2 = ~une pomme~ dans le fichier .tra et pointer JETON sur @2 : SetToken("JETON",@2)

Je termine sur l'analyse de l'exemple de Sous Nain pour essayer de comprendre pourquoi il ne marche pas :

Code : Tout sélectionner

SetTokenObject("MYTARGET", [ENEMY])
Attack("MYTARGET")
La 1ère ligne assigne le token MYTARGET au nom de l'objet [ENNEMY].
La seconde ligne utilise l'action Attack sur le token "MYTARGET".
Si cela ne marche pas, peut-être est-ce parce-que l'action Attack s'attend à avoir comme paramètre un objet -ou son nom qui le référence- et non un token sur le nom d'un objet ? La question que l'on pourrait se poser dans ce cas est comment utiliser un token contenant la variable au lieu de la variable elle-même ? (si c'est possible, la réponse pourrait être très utile sur l'utilisation de bon nombre d'actions)

Edit : Si ce n'est pas possible, ce que voulait faire Sous Nain sera possible en n'utilisant pas de token . Simplement ceci : Attack([ENNEMY])

Autre chose, j'ai lu la phrase au haut de la page en lien plus haut un peu rapidement. Les autres token référencés (donc comme NEXTLEVEL) ne seraient "pas fiables dans des circonstances générales".

Edit2 : Ah, y a peut-être une solution (mais comme je viens juste de la voir et donc que je ne l'ai pas testée, je n'en fais pas un nouveau message).
Sur cette page §13 : https://www.pocketplane.net/tutorials/simscript.html#EssTokens (tutoriel de SimDingO)
You can also use tokens for targetting, with SetTokenObject.
If you use the action SetTokenObject("TARGET",Myself), you can then use [TARGET] as an object in subsequent blocks/scripts.

Bear in mind that tokens are not stored in the savegame; therefore, for them to be used, they must be reinitialized every time the game is loaded.
Si j'ai bien compris, cela voudrait dire qu'il faudrait écrire Attack([MYTARGET]) à la place de Attack("MYTARGET"), si on utilise un token.

Edit3 Après plusieurs essais de SetTokenObject mais dans d'autres contextes, l'hypothèse que j'ai émise dans l'édit2 ne tient pas, on peut bien mettre le token entre "". Cette action ne fait que pointer sur le nom de l'objet mentionné (note : pas la deathvar, le nom). Par contre, je me demande si le problème ne vient pas du fait que [ENNEMY] peut désigner tous les ennemies présents alors qu'un token ne peut être assigné qu'à une seule variable.

Sinon, un problème de mon côté en essayant d'utiliser SetTokenGlobal, comme dans l'exemple donné dans IESDP (cf description plus haut). Le programme me donne un 0 au dessus de la tête au lieu de la valeur voulue (100 dans l'exemple). Dans le fichier .tra, j'ai mis ~<jeton>~ dans la strref et vérifié par NI que le flag Hastoken est activé. En résumé, au niveau des affichages, ça marche avec les chaînes de caractères mais pas avec les nombres entiers.

Autre soucis avec les strref : Si j'écris dans le .tra : @600 = ~<jeton1><jeton2><jeton3>~ il m'affiche les phrases pointées par <jeton1> et <jeton3> mais pas celle de <jeton2>. J'obtiens quelque-chose comme ça : Phrase1<jeton2>Phrase3
Par contre, si je sépare les trois par un espace ou autre chose, ça marche.

Edit4 Bon, pour SetTokenGlobal, je viens de faire d'autres tests pour voir si le problème vient seulement de l'affichage (0 au lieu de la valeur contenue dans la variable pointée). Et le problème est que le token pointe sur une variable dont le contenu est 0 (je l'ai vu en écrivant un état de script vérifiant si le token donne 0 puis affichant alors une phrase quelconque).
Peut-être que cela pourrait lié à mon type d'installation, bien que basique (BG1+TOSC+BG2+TOB+BG2FixPack+BGT+GUI+mod de test), aucune idée pour le moment.

Edit5 Toujours pour SetTokenGlobal, pour contourner le problème, j'ai eu l'idée de rajouter une valeur (50) à "JETON" avec IncrementGlobal. JETON ne pointe alors plus sur une variable contenant 0 mais bien 50. Si bien que si on rajoutait la valeur mentionnée dans SetTokenGlobal à la place de 50, le problème serait alors "un peu plus" résolu.
Par contre, lorsqu'on l'affiche il met toujours 0 au dessus de la tête.
(dans le .tra : j'ai mis @... = ~<JETON>~ , les trois flags connus -texte,son,token- étant activés).

Edit6 (le dernier) Pour aller plus loin, j'ai pointé JETON sur une autre variable : Il donne encore 50.
Et si je reprends la précédente : 50 encore.
Bien que les token ne sont pas sauvegardés lorsqu'on sauvegarde une partie, je l'ai fait quand même. Et dans NI, j'ai vu ... JETON dans la liste des variables (avec comme valeur 50).
C'est comme si un token de type "variable entière" était assimilée à une variable entière proprement dite, et non un vrai token.
Bref (ou du moins dans mon cas), l'action SetTokenGlobal est beuguée.

Edit6 (suite et fin ...)
Hmm, cela pourrait être dû à l'utilisation de IncrementGlobal qui aurait créé une variable JETON ...
Quoiqu'il en soit, cette action ne marche pas pour moi (alors que dans d'autres posts ou tutos externes, elle fonctionnerait, même en LOCALS). Peut-être est-ce dû à l'un des mods BG2FixPack, BGT ou GUI, je ne sais pas ...
De plus, en ce qui concerne les Token-"Chaîne de caractères", j'ai remarqué que si le token est utilisé en dehors de la créature qui l'a créé par son script, notamment par le script d'une carte, il met du temps à s'actualiser et il faut alors utiliser un wait() avant. Et de même si on crée le token par le script d'une carte. Il s'actualise cependant rapidement si c'est le script de la "créature créatrice" qui l'utilise.

Et, sinon, grâce à SetToken, j'ai pu contourner le problème de SetTokenGlobal, en composant plusieurs scripts enchaînés permettant de traduire la valeur numérique d'une variable en une chaîne de caractères. Ca marche mais le hic est qu'il faut trois ou quatre secondes à chaque utilisation compte-tenu du nombre énorme des états de scripts.

Et sur ce ... je m'arrête là :noflood:
Bataff
Zombi
Messages : 47
Enregistré le : ven. 25 oct. 2019, 14:53
Localisation : vers Lyon
Statut : Hors ligne
.

Message par Bataff »

Ca y est, j'ai compris d'où vient le problème de SetTokenGlobal : Il marche parfaitement à condition d'écrire "GLOBAL" en majuscules (alors que cela n'est pas forcément nécessaire avec SetGlobal).

Par exemple, ce script fonctionne correctement :

Code : Tout sélectionner

IF
  See([PC])
  NumTimesTalkedTo(0)
THEN
  RESPONSE #100
    SetGlobal("valeur","Global",255)
    SetTokenGlobal("valeur","GLOBAL","TESTER")
    DisplayStringHead(myself,~<TESTER>~)
    Dialogue([PC])
END
Mais si on met "Global" ou "global" à la place de "GLOBAL", on verra 0 à la place de 255 au dessus de la tête du PNJ ...
Avatar du membre
Freddy_Gwendo
Adepte de Grondemarteau
Orbe ancien
Messages : 5877
Enregistré le : sam. 23 avr. 2011, 00:26
Localisation : Égaré dans un vortex entre Féérune et le Royaume de Diamant Éternel
Statut : Hors ligne
.

Message par Freddy_Gwendo »

Je conseille toujours aux débutants moddeurs de respecter la casse, notamment des actions et des variables. WeiDU étant ce qu'il est, il se comporte bizarrement et, même s'il accepte parfois certains mots clés en minuscules, respecter la casse définie dans IESDP permet souvent d'éviter ce genre de mésaventures. ;)

Et désolé de ne pas avoir participé plus tôt, j'étais passé complètement à côté de ton topic, pourtant intéressant parce que j'ai développé pour les versions EE une bibliothèque qui me permet de rendre certains tokens sensibles à la casse ou au sexe. J'avoue que je ne me suis pas encore lancé dans le code pour les versions classiques, de peur que ce ne soit malheureuxement pas possible, du moins sans y passer des semaines. :$
CARPE DIEM...Co-modérateur de La Forge et de La Chambre des Scribes
Moddeur qui s'arrache les cheveux...
Bataff
Zombi
Messages : 47
Enregistré le : ven. 25 oct. 2019, 14:53
Localisation : vers Lyon
Statut : Hors ligne
.

Message par Bataff »

Freddy : Merci pour ton avis :)

Ben, je crois que ma manie de vouloir écrire essentiellement en minuscules m'aura donné une leçon :dash1: (mais rien de grave, et on apprend aussi plein de choses en cherchant à droite à gauche)

Sinon, je ne pense pas que ce soit dû à WeiDU car si on regarde dans le fichier compilé .bcs par Weidu, les strings parmi les trois arguments de SetGlobal() ou SetTokenGlobal(), sont passés en respectant correctement les minuscules/majuscules, concaténés ou non :

Code : Tout sélectionner

 Pour la ligne SetGlobal("valeur","Global",255) :

30OB
0 0 0 0 0 0 0 0 0 0 0 0 ""OB
OB
0 0 0 0 0 0 0 0 0 0 0 0 ""OB
OB
0 0 0 0 0 0 0 0 0 0 0 0 ""OB
255 0 0 0 0"Globalvaleur" "" AC

Code : Tout sélectionner

Pour la ligne SetTokenGlobal("valeur","GLOBAL","TESTER") :

335OB
0 0 0 0 0 0 0 0 0 0 0 0 ""OB
OB
0 0 0 0 0 0 0 0 0 0 0 0 ""OB
OB
0 0 0 0 0 0 0 0 0 0 0 0 ""OB
0 0 0 0 0"GLOBALvaleur" "TESTER" AC
Et comme c'est le jeu qui se base sur ce qui est compilé, ce doit donc logiquement être lui qui fait une différence sur le traitement des minuscules/majuscules selon telle ou telle action. Du moins c'est mon avis.
Répondre

Retourner vers « Scripts »

Qui est en ligne

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