Aller au contenu


Additem Avec Variables


  • Veuillez vous connecter pour répondre
4 réponses à ce sujet

#1 Snaïpe

Snaïpe

    ...itset tnus otroh nI


Posté 10 septembre 2009 - 19:10

J'ai remarqué que certains débutants étaient bloqués dans leur script sur le fait qu'additem ne prenait pas les variables.

je propose donc ici un petit truc pour ceux qui ne sont pas encore à l'aise avec les scripts ( bien que cela soit extrêmement évident pour ceux qui ont appris un tant soit peu la programmation ; mais bon, il faut bien un début à tout :) )

En effet, à moins de passer par le Morrowind Scripting Extender, puisqu'il y a bien la fonction Xadditem, ID, var_short , où ID est l'ID de l'objet en question et var_short une variable quelconque de type short, il n'y a pas 36 solutions pour ajouter et enlever des objets à un NPC/container : mettre une boucle while ( ou une condition if, si la variable est très grande. )

en pratique ça donne ça :

Begin Mon_Script

short nombreObjets; le nombre d'objets que vous voulez ajouter
short i; ( j'utilise i par pure convention, et par rapidité, vous pouvez mettre ce que vous voulez)

while( i < nombreObjets )

   Additem, ID, 1
   set i to i + 1

endwhile

end

en l'appellant, le script va executer le contenu de la boucle while ( en une frame ), tant que i sera inférieur à nombreObjets.

pour de grandes valeurs, imaginons que le joueur achète une demeure, dont le prix est un nombre aléatoire ( un peu de role play ! ) entre 100 000 et 150 000, le fait de boucler d'aussi grandes valeurs risque de faire geler l'écran ( je rappelle que while s'exécute jusqu'a ce que la condition soit vraie en une Frame.
faire un if simple ne serait pas non plus une bonne idée, car pour d'aussi grandes sommes, le script ajouterai/retirerai au fur et a mesure, et étendu sur un aussi grand laps de temps, ça serait suicidaire ( ça vous rappelle quelque chose, dans vos premiers scripts buggués quand un objet s'ajoutait indéfiniment dans l'inventaire du joueur ? :) )

pour palier à ce problème, il faut utiliser une condition if, doublé d'une boucle while :

Begin Mon_script

short nombreObjets
short nombreParEtape; variable définissant le nombre d'objets a ajouter/retirer par étape
short nombreEtapes; nombre d'étapes
short nombreREstant; nombre d'objets restant ( pour faire l'appoint )

short i
short n; pareil que dans l'exemple 1, mettez ce que vous voulez

if( nombreEtapes == 0 )

   set nombreEtapes to ( nombreObjets / nombreParEtape )

endif

if( n < nombreEtapes )

   while( i < nombreParEtape )

	  Additem, ID, 1
	  set i to i + 1

   endwhile

   set i to 0
   set n to n + 1

else

   set nombreRestant to ( nombreObjets - ( n * nombreParEtape ))

   while( i < nombreRestant )

	  Additem, ID, 1
	  set i to i + 1

   endwhile

   stopscript, Mon_script

endif

end

Il faut renseigner deux valeurs : nombreObjets pour le nombre d'objets a ajouter/retirer et nombreParEtape pout le nombre d'étapes désirées.

le principe est le même que l'exemple 1 : on exécute une boucle qui va ajouter le nombre d'objets demandé (nombreObjets) divisé par le nombre d'étapes (nombreParEtape). le décimal obtenu sera arrondi à l'inferieur, et l'exécution de la boucle recommencera à chaque frame jusqu'a ce que le nombre d'objets ajouté/retiré atteigne approximativement la valeur voulue; puis en dernier, on réalise l'appoint manquant.

par contre, les variables du script dépendent de votre cpu : ne donnez pas à nombreParEtape un nombre trop élevé, a moins de geler chaque frame du jeu... vous pouvez aussi différer l'execution sur un nombre de frames donné ou sur un temps donné.

*on peut aussi mettre un nombre plus grand à Additem / removeitem ( 100, 1000 par exemple ), mais il faudra réaliser l'appoint à la fin, de préférence avec 1

ce script est valable pour ceux qui veulent utiliser des variables et pour ceux qui ne veulent pas :
j'ai remarqué que les fonctions Additem et Removeitem étaient partiellement buggées : a partir d'une certaine valeur ( je pense 65536, à vérifier ), le nombre d'objets ajoutés ou retirés n'est pas le même que la valeur inscrite. en faisant une boucle pour ajouter/retirer des objets, le problème ne se pose plus.

voila, en espérant avoir aidé certains :)

Edit : petite précision ajoutée. (voir * )

Modifié par Snaïpe, 10 septembre 2009 - 19:16.


#2 Kafou

Kafou

    Le canari a bouffé le rominet !


Posté 10 septembre 2009 - 21:27

Ou bien, tu fais le tout en une seule frame en te passant totalement de while sauf sur une très grande valeur, puisque tu peux faire additem avec plus que 1 en paramètre. Le reste tu le fais à coup de if, en divisant la valeur par deux à chaque fois.

Au lieu de diviser sur plusieurs frames, tu divises carrément la complexité du truc. C'est une astuce donnée pourtant à plusieurs endroits :)

while ( nombreObjets - i >= 1024 )
   Additem, ID, 1024
   set i to i + 1024
endwhile

if ( nombreObjets - i >= 512 )
   Additem, ID, 512
   set i to i + 512
endif

if ( nombreObjets - i >= 256 )
   Additem, ID, 256
   set i to i + 256
endif

if ( nombreObjets - i >= 128 )
   Additem, ID, 128
   set i to i + 128
endif

if ( nombreObjets - i >= 64 )
   Additem, ID, 64
   set i to i + 64
endif

if ( nombreObjets - i >= 32 )
   Additem, ID, 32
   set i to i + 32
endif

if ( nombreObjets - i >= 16 )
   Additem, ID, 16
   set i to i + 16
endif

if ( nombreObjets - i >= 8 )
   Additem, ID, 8
   set i to i + 8
endif

if ( nombreObjets - i >= 4 )
   Additem, ID, 4
   set i to i + 4
endif

if ( nombreObjets - i >= 2 )
   Additem, ID, 2
   set i to i + 2
endif

if ( nombreObjets - i >= 1 )
   Additem, ID, 1
   set i to i + 1
endif

J'ai mis 1024 comme limite mais on peut mettre plus ou moins selon l'ordre de grandeur de nombreObjets.
You look like you need a monkey!

Attention : perfectionniste paresseux.

#3 Snaïpe

Snaïpe

    ...itset tnus otroh nI


Posté 11 septembre 2009 - 06:18

Voir le messageKafou, le 10.09.2009 à 22:26, dit :

Ou bien, tu fais le tout en une seule frame en te passant totalement de while sauf sur une très grande valeur, puisque tu peux faire additem avec plus que 1 en paramètre. Le reste tu le fais à coup de if, en divisant la valeur par deux à chaque fois.

Au lieu de diviser sur plusieurs frames, tu divises carrément la complexité du truc. C'est une astuce donnée pourtant à plusieurs endroits :)

le seul hic pour cette méthode ( et puisque je suis en train de l'expérimenter sur de très grandes valeurs ), c'est que par exemple, si je veux enlever 1 243 562 PO au joueur, puis ensuite 32 PO à cause d'une taxe sur un produit, les ordres de grandeur que tu proposes ne pourraient pas fonctionner... ( enfin si, mais il faudrait ajouter des conditions pour vérifier si le bout de script est bien dans l'ordre de grandeur )

Edit : je viens d'y penser, on pourrait aussi tenter de déterminer la valeur à diviser suivant nombreObjets, à creuser

mais pour un script simple, avec un ordre de grandeur de nombreObjets réduit, en effet, ton script serait plus utile. :)

et comme je l'ai dit plus haut, ce n'est qu'un script d'exemple, on peut adapter en mettant la valeur que l'on veut à additem ( 10, 100, 1000, 65, 93, etc ) :)

Modifié par Snaïpe, 11 septembre 2009 - 16:16.


#4 Kafou

Kafou

    Le canari a bouffé le rominet !


Posté 11 septembre 2009 - 09:51

Voir le messageSnaïpe, le 11.09.2009 à 07:17, dit :

le seul hic pour cette méthode ( et puisque je suis en train de l'expérimenter sur de très grandes valeurs ), c'est que par exemple, si je veux enlever 1 243 562 PO au joueur, puis ensuite 32 PO à cause d'une taxe sur un produit, les ordres de grandeur que tu proposes ne pourraient pas fonctionner... ( enfin si, mais il faudrait ajouter des conditions pour vérifier si le bout de script est bien dans l'ordre de grandeur )
Et pourquoi donc ????
Tu peux mettre 2048, 4096 etc. en début de script, je n'ai fait que donner un exemple pas trop long.
Et dans tous les cas, ça marche (c'est juste un peu plus long si la première boucle est faite sur une petite valeur).

Le sens de mon message c'est qu'un seul while est nécessaire, sur une valeur aussi grande que possible. Le reste, c'est que de la division par deux. Dans l'idéal il y aurait 31 if successifs et pas de while et ça marcherait aussi bien, mais d'après ce que tu dis additem ne fonctionne plus passé 65536.

Et ce n'est pas une question d'utilité mais d'efficacité.
You look like you need a monkey!

Attention : perfectionniste paresseux.

#5 Snaïpe

Snaïpe

    ...itset tnus otroh nI


Posté 11 septembre 2009 - 16:15

Voir le messageKafou, le 11.09.2009 à 10:50, dit :

Et pourquoi donc ????
Tu peux mettre 2048, 4096 etc. en début de script, je n'ai fait que donner un exemple pas trop long.
Et dans tous les cas, ça marche (c'est juste un peu plus long si la première boucle est faite sur une petite valeur).

Le sens de mon message c'est qu'un seul while est nécessaire, sur une valeur aussi grande que possible. Le reste, c'est que de la division par deux. Dans l'idéal il y aurait 31 if successifs et pas de while et ça marcherait aussi bien, mais d'après ce que tu dis additem ne fonctionne plus passé 65536.

Et ce n'est pas une question d'utilité mais d'efficacité.

oups, mea culpa, je n'ai pas saisi la subtilité du script tout de suite. :)

effectivement, le temps est bien réduit, donc à défaut de la mienne, c'est ta technique la meilleure pour les grands traitements d'objets.

pour ce qui est de la limite de 65536, ce n'est qu'un supposition, je n'ai pas encore testé ( j'ai remarqué que ça bugguait à une valeur d'environ 70000; à vérifier donc )




0 utilisateur(s) li(sen)t ce sujet

0 membre(s), 0 invité(s), 0 utilisateur(s) anonyme(s)