Page 1 sur 1

[WeiDU] Définition automatique des variables RGB dans les effets #51 et 52

Posté : sam. 19 sept. 2015, 23:48
par Freddy_Gwendo
Tous ceux qui ont utilisé les effets de coloration avec les effets 51 [Colour: Strong/Dark by RGB] et 52 [Colour: Very Bright by RGB] avec un tp2 ont dû se taper la saisie dans DLTCEP, puis un copie-coller de la variable du paramètre 1 dans leur tp2.

Pour rappel :
IESDP a écrit : Alters the colour of the area specified by the 'Location and Speed' field, to the colour specified by the 'RGB colour' field.

The 'RGB Colour' field is handled as follows:
Second byte = Red (0-255)
Third byte = Green (0-255)
Fourth byte = Blue (0-255)
J'ai voulu automatiser cette procédure en utilisant directement les valeurs RGB dans une fonction.

En utilisant la définition du paramètre 1 [0x0004 - 4 (dword) - Parameter 1], plutôt qu'utiliser la commande WRITE_LONG, je peux décomposer la variable en 4 WRITE_BYTE, dont la première
variable est égale à 0 et les trois suivantes aux variables Red, Green et Blue.

Ce qui me donne :

Code : Tout sélectionner

[color="#00FF00"]DEFINE_PATCH_FUNCTION[/color] ~[color="#EE82EE"]GW_DEF_RGB_COLOR[/color]~
	[color="#00FF00"]INT_VAR	[/color]GW_red	 = 0
		GW_green = 0
		GW_blue	 = 0
	[color="#00FF00"]RET[/color]	GW_color
[color="#0000FF"]BEGIN[/color]

	[color="#FF0000"]SET[/color] GW_color = (256 * GW_red) + (65536 * GW_green) + (16777216 * GW_blue)

[color="#0000FF"]END[/color]
Et ça ne fonctionne pas !

Du coup, j'ai essayé de comprendre pourquoi et j'ai découvert de manière empirique un truc bizarre : c'est la variable blue qui pose problème.
Plus exactement, dès qu'elle est supérieure à 127, elle devient négative : -16777216 * GW_blue.
Problème, la commande

Code : Tout sélectionner

	[color="#FF0000"]SET[/color] GW_blue2 = (0 - GW_blue * 16777216)
me renvoie tout de même une valeur positive.

Alors, j'ai bidouillé un truc qui fonctionne :

Code : Tout sélectionner

DEFINE_PATCH_FUNCTION ~GW_DEF_RGB_COLOR~
	[color="#00FF00"]INT_VAR	[/color]GW_red	 = 0
		GW_green = 0
		GW_blue	 = 0
	[color="#00FF00"]RET[/color]	GW_color
[color="#0000FF"]BEGIN[/color]

	[color="#FF0000"]SET[/color] GW_blue2 = GW_blue * 16777216

	[color="#FF0000"]PATCH_IF[/color] ([color="#EE82EE"]"%GW_blue%"[/color] > 127) [color="#0000FF"]BEGIN[/color]

		[color="#FF0000"]SPRINT[/color] GW_blue2 [color="#FF0000"]EVAL[/color] [color="#EE82EE"]"%GW_blue2%"[/color]

	[color="#0000FF"]END[/color]

	[color="#FF0000"]PATCH_PRINT[/color][color="#EE82EE"] "TEST de CONTROLE de GW_DEF_RGB_COLOR pour blue = %GW_blue%	==>	GW_blue2 = %GW_blue2%"[/color]

	[color="#FF0000"]SET[/color] GW_color = (256 * GW_red) + (65536 * GW_green) + GW_blue2

	[color="#FF0000"]PATCH_PRINT[/color] [color="#EE82EE"]"TEST de CONTROLE GW_DEF_RGB_COLOR - red = %GW_red% - green = %GW_green% - blue = %GW_blue%	==> color = %GW_color%"[/color]

[color="#0000FF"]END[/color]
Que j'ai simplifié en :

Code : Tout sélectionner

[color="#00FF00"]DEFINE_PATCH_FUNCTION[/color] ~[color="#EE82EE"]GW_DEF_RGB_COLOR[/color]~
	[color="#00FF00"]INT_VAR	[/color]GW_red	 = 0
		GW_green = 0
		GW_blue	 = 0
	[color="#00FF00"]RET[/color]	GW_color
[color="#0000FF"]BEGIN[/color]

	[color="#FF0000"]SET[/color] GW_blue2 = GW_blue * 16777216

	[color="#FF0000"]SPRINT[/color] GW_blue2 [color="#FF0000"]EVAL[/color] [color="#EE82EE"]"%GW_blue2%"[/color]

	[color="#FF0000"]SET[/color] GW_color = (256 * GW_red) + (65536 * GW_green) + GW_blue2

	[color="#FF0000"]PATCH_PRINT[/color] [color="#EE82EE"]"TEST de CONTROLE de GW_DEF_RGB_COLOR - red = %GW_red% - green = %GW_green% - blue = %GW_blue%	==> color = %GW_color%"[/color]

[color="#0000FF"]END[/color]
Puis je lance :

Code : Tout sélectionner

[color="#0000FF"]LPF[/color] ~[color="#EE82EE"]ADD_CRE_EFFECT[/color]~ [color="#00FF00"]INT_VAR[/color] opcode = 51 target = 1 duration = 9 parameter1 = GW_color [color="#0000FF"]END[/color]
Et ma créature bénéficie de l'effet de recoloration ! ^^

Le but du jeu étant d'utiliser un tableau de recoloration (opcode, red, green, blue, location => color) appelé si nécessaire par la créature. Une fois mes couleurs définies, si je veux un golem bleu électrique par exemple, je n'ai plus qu'à utiliser la variable color = electric_blue. Idem pour les autres créatures ou les autres couleurs.

Bref, ça marche très bien, mais comme j'ai horreur de ne pas comprendre, si l'un de vous a une explication, je suis preneur. ]8 [Colour: Change by RGB][/URL], 9 [Colour: Glow Pulse] et 50 [Colour: Glow by RGB (Brief)], et notamment pour définir le paramètre 2 :
IESDP a écrit : Location and speed :

The 'Location' field is handled as follows:
First byte = Location
Third byte = Speed (0-255)

A speed of 0 does not pulsate. A speed of 1 is fastest, and a speed of 255 is slowest.

Posté : dim. 20 sept. 2015, 11:17
par Isaya
Le problème vient du fait que la couleur bleue occupe l'octet poids fort du mot de 32 bits. Le codage des entiers utilise le bit de poids en tant que bit de signe lorsqu'un entier représente un nombre signé. De fait la plage des nombres en valeur absolue est deux fois plus faible lorsqu'on considère que c'est signé (2^32 - 1, soit 2147483647). Pour trouver le code associé à une valeur négative, le langage fait l'opération 2^32 - valeur absolue de la valeur. Quand tu fais l'opération 0 - valeur négative, tu fais sans doute l'opération inverse (ça dépend du langage dans lequel WeiDU est écrit), ce qui t'amène à trouver une valeur positive probablement inférieure à 2147483647.

Le gros problème avec WeiDU est qu'on ne peut pas choisir si les nombres que l'on manipule sont signés ou non. Je n'ai trouvé aucune indication dans la documentation sur le fait que les variables de type entier sont signées ou non. La seule référence à cette question se trouve dans les fonctions READ_LONG / READ_SLONG, où la question du signé est traitée, en laissant d'ailleurs supposer que par défaut c'est non signé (peut être pour des raisons historiques, la fonction version SLONG a été ajoutée tardivement).

Néanmoins le fait que tu aies obtenu une valeur négative laisse supposer que, par défaut, les opérations sont faites avec des nombres signés. Et, vu le contournement que tu as trouvé, SPRINT ou EVAL considère au contraire que les valeurs sont non signées. Malheureusement il n'y a aucune trace d'une telle information dans la documentation. Si tu veux des certitudes, il te faudra interroger Wisp sur le forum WeiDU.

Concernant l'autre cas d'utilisation que tu envisages, le champ qui te préoccupe est sur les 3ème octet et non le quatrième comme ici le code du bleu. Tu multiplieras par 65536 pour calculer la valeur globale et par conséquent il ne devrait pas entraîner un passage du nombre reconstitué dans le monde négatif.


Alternative possible : calculer ta valeur sur 24 bits puis décaler de 8 vers la droite

Code : Tout sélectionner

SET GW_color = ((GW_red) + (256 * GW_green) + (65536 * GW_blue)) BLSL 8
Du coup, pas d'impact sur le bit de signe dans le calcul, le décalage à gauche décalera les 24 bits sans y toucher et introduira des 0 dans les 8 bits de poids faible.
En principe... reste à savoir si c'est le SET ou la gestion du = qui introduisent la bascule dans le monde négatif car dans ce cas, ma suggestion n'aura aucun effet.

Posté : dim. 20 sept. 2015, 12:12
par Freddy_Gwendo
Un grand merci ! ^^
Isaya a écrit : Alternative possible : calculer ta valeur sur 24 bits puis décaler de 8 vers la droite

Code : Tout sélectionner

SET GW_color = ((GW_red) + (256 * GW_green) + (65536 * GW_blue)) BLSL 8
Du coup, pas d'impact sur le bit de signe dans le calcul, le décalage à gauche décalera les 24 bits sans y toucher et introduira des 0 dans les 8 bits de poids faible.
En principe... reste à savoir si c'est le SET ou la gestion du = qui introduisent la bascule dans le monde négatif car dans ce cas, ma suggestion n'aura aucun effet.
J'ai fait le test avec la fonction suivante :

Code : Tout sélectionner

DEFINE_PATCH_FUNCTION ~GW_DEF_RGB_COLOR~
	INT_VAR	GW_red	 = 0
			GW_green = 0
			GW_blue	 = 0
	RET		GW_color
BEGIN
	SET GW_blue2 = GW_blue * 16777216

	SPRINT GW_blue2 EVAL "%GW_blue2%"

	PATCH_PRINT "blue = %GW_blue%	==>	GW_blue2 = %GW_blue2%"
	SET GW_color = (256 * GW_red) + (65536 * GW_green) + GW_blue2

	SET GW_color_Isaya = ((GW_red) + (256 * GW_green) + (65536 * GW_blue)) BLSL 8
	SET GW_color_Isaya2 = ((GW_red) + (256 * GW_green) + (65536 * GW_blue)) << 8

	PATCH_PRINT "red = %GW_red% - green = %GW_green% - blue = %GW_blue%	==> color = %GW_color% / GW_color_Isaya = %GW_color_Isaya% - %GW_color_Isaya2%"

END
Résultats :

Code : Tout sélectionner

LPF ~GW_DEF_RGB_COLOR~ INT_VAR GW_red = 238 GW_green = 205 GW_blue = 180 RET GW_color END	// -1261572608

	blue = 180	==>	GW_blue2 = -1275068416

	red = 238 - green = 205 - blue = 180	==> color = -1261572608 / GW_color_Isaya = -1261572608 - -1261572608


LPF ~GW_DEF_RGB_COLOR~ INT_VAR GW_red = 4 GW_green = 7 GW_blue = 7 RET GW_color END		// 117900288

	blue = 7	==>	GW_blue2 = 117440512

	red = 4 - green = 7 - blue = 7	==> color = 117900288 / GW_color_Isaya = 117900288 - 117900288


LPF ~GW_DEF_RGB_COLOR~ INT_VAR GW_red = 8 GW_green = 5 GW_blue = 5 RET GW_color END		// 84215808

	blue = 5	==>	GW_blue2 = 83886080

	red = 8 - green = 5 - blue = 5	==> color = 84215808 / GW_color_Isaya = 84215808 - 84215808


LPF ~GW_DEF_RGB_COLOR~ INT_VAR GW_red = 7 GW_green = 7 GW_blue = 4 RET GW_color END		// 67569408

	blue = 4	==>	GW_blue2 = 67108864

	red = 7 - green = 7 - blue = 4	==> color = 67569408 / GW_color_Isaya = 67569408 - 67569408


LPF ~GW_DEF_RGB_COLOR~ INT_VAR GW_red = 10 GW_green = 245 GW_blue = 245 RET GW_color END	// -168490496

	blue = 245	==>	GW_blue2 = -184549376

	red = 10 - green = 245 - blue = 245	==> color = -168490496 / GW_color_Isaya = -168490496 - -168490496


LPF ~GW_DEF_RGB_COLOR~ INT_VAR GW_red = 20 GW_green = 8 GW_blue = 0 RET GW_color END		// 529408

	blue = 0	==>	GW_blue2 = 0

	red = 20 - green = 8 - blue = 0	==> color = 529408 / GW_color_Isaya = 529408 - 529408


LPF ~GW_DEF_RGB_COLOR~ INT_VAR GW_red = 255 GW_green = 0 GW_blue = 0 RET GW_color END		// 65280

	blue = 0	==>	GW_blue2 = 0

	red = 255 - green = 0 - blue = 0	==> color = 65280 / GW_color_Isaya = 65280 - 65280

Ça fonctionne parfaitement, et surtout c'est beaucoup plus clair ! ;)

Le gros problème avec WeiDU est qu'on ne peut pas choisir si les nombres que l'on manipule sont signés ou non. Je n'ai trouvé aucune indication dans la documentation sur le fait que les variables de type entier sont signées ou non. La seule référence à cette question se trouve dans les fonctions READ_LONG / READ_SLONG, où la question du signé est traitée, en laissant d'ailleurs supposer que par défaut c'est non signé (peut être pour des raisons historiques, la fonction version SLONG a été ajoutée tardivement).

Néanmoins le fait que tu aies obtenu une valeur négative laisse supposer que, par défaut, les opérations sont faites avec des nombres signés. Et, vu le contournement que tu as trouvé, SPRINT ou EVAL considère au contraire que les valeurs sont non signées. Malheureusement il n'y a aucune trace d'une telle information dans la documentation. Si tu veux des certitudes, il te faudra interroger Wisp sur le forum WeiDU.
Pour tout t'avouer, je me sens moyennement me lancer dans une telle discussion technique avec Wisp sur un sujet que je ne maîtrise pas du tout. :whistle3:
C'est juste un petit miracle que je me sois rappelé l'astuce du SPRINT EVAL que j'ai utilisée pour lire des fichiers 2da et jongler entre des noms de variables textes et entières ayant la même dénomination.
Concernant l'autre cas d'utilisation que tu envisages, le champ qui te préoccupe est sur les 3ème octet et non le quatrième comme ici le code du bleu. Tu multiplieras par 65536 pour calculer la valeur globale et par conséquent il ne devrait pas entraîner un passage du nombre reconstitué dans le monde négatif.
Là, je ne me faisais pas trop de soucis car tous mes tests sur la valeur green (la troisième) fonctionnaient. ;)

Mais au moins je comprend mieux ce que j'ai codé et ça va me permettre de revoir mon codage de la valeur des kits et peut-être la simplifier. :)

Puis je me replonge dans la procédure de copie de la structure d'un fichier bam dans un autre. Mais ça, c'est pas gagné... :$

Posté : lun. 19 oct. 2015, 14:32
par Freddy_Gwendo
Dans un souci de simplification, j'ai trouvé une méthode beaucoup plus simple ce weekend :

Pour le code RGB :

Code : Tout sélectionner

SET GW_color_RGB = (GW_red << 8) + (GW_green << 16) + (GW_blue << 24)

Pour les variables "pulse" (qui combinent emplacement et vitesse) :

Code : Tout sélectionner

SET GW_pulse = (GW_location) + (GW_speed << 16)