Revoir fondamentalement le système de gestion aléatoire des trésors dans NWN ?

Répondre
Partager Rechercher
Je ne sais pas ce que vous en pensez mais le système de gestion aléatoire de trésors de NWN me parait... nullissime. A croire que le gars de Bioware chargé de concevoir ce système avait trop fait de Diablo tard le soir avant de développer son script. Notez que je n'ai rien contre les joueurs de Diablo (j'en étais un occasionnellement) mais lorsqu'un programmeur bossant sur un jeu qui a officiellement un gameplay différent des Diablo-Like se laisse influencer de la sorte, là on peut se dire qu'il y a un gros problème. Certains diront peut-être "Voilà encore un exigent qui grogne après Bioware. S'il est pas content, qu'il fasse mieux lui-même". Mais la grosse différence, c'est que je ne grogne pas après Bioware parce qu'ils n'ont pas fait assez bien... mais parce qu'ils ont fait moins bien que par le passé (c'est fort tout de même ) !

ça parait un peu obscur ? je développe...
Dans NWN, nous avons un système de gestion aléatoire des trésors basé UNIQUEMENT sur le niveau du personnage. Lorsqu'on a un tonneau en ville qui donne 10 po lorsqu'un PJ de niv.1 l'ouvre, un PJ de niv.18 qui passe une demi-heure plus tard et ouvre le même tonneau peut se retrouver avec une armure en peau de dragon rouge (oui le Harnois (+5) qui réduit de 50% les dégâts contre le feu... Le pire c'est que ceci est une expérience vécue, lors d'une tentative de jouer en multijoueurs sur la campagne officielle )

Là où on comprend encore moins comment raisonne Bioware c'est lorsqu'on commence à se pencher sur la façon dont fonctionnait la génération aléatoire de trésors sous... Baldur's Gate II ! Celle-ci était ô combien plus simple et ô combien plus réaliste. Si l'on pouvait adapter ce système à NWN, je pense que l'équilibre du jeu pourrait y gagner beaucoup !

Mais cela fait intervenir une grosse question : Est-il possible sous NWN, d'aller chercher des données sélectionnées de manière aléatoire dans un tableau situé dans un fichier 2DA ?

Certains fichiers 2DA de Baldur's Gate II (et il en était de même pour Icewind Dale) géraient la génération aléatoire d'objets. Le principe était le suivant : A la mort d'une créature (toujours dans BG2), un script (car cela ne pouvait être rien d'autre qu'un script à mon avis) choisissait aléatoirement un type d'objets parmi les suivants : "Equipement", "Magique", "Parchemin", "Trésor". Une fois ce type d'objet sélectionné, il allait sélectionner un objet au hasard dans le fichier 2DA correspondant. Ces derniers avaient pour nom "RNDEQUIP.2DA", "RNDMAGIC.2DA", "RNDSCROL.2DA" et "RNDTREAS.2DA". Ces quatres fichiers contenaient, sous forme de tableaux, la quasi-totalité des TAGs des objets du jeu (ceux n'y figurant pas étant bien évidemment les objets uniques, qui eux étaient placés à un endroit bien précis ). Dans certains emplacements des tableaux il n'y avait pas de TAG mais un nombre. Cela représentait en fait le nombre de pièces d'or générés.

Si l'objet sélectionné par le script était de type "Trésor" (donc situé dans le fichier "RNDTREAS.2DA"), en fonction des conditions environnementales dans lesquelles le script s'effectuait (dans quel type de lieu, si le script se déclenchait à l'ouverture d'un coffre ou lors de la mort d'une créature, etc...), un degré de valeur lui était attribué : "Pauvre" (POOR), "Moyen" (AVERAGE), "Abondant" (WELL_OFF), "Généreux" (WEALTHY) ou "Riche" (RICH). Cela déterminait la ligne du tableau sur laquelle devait être sélectionné le TAG de l'objet aléatoire. Ensuite, un jet de D20 virtuel était simulé et le résultat indiquait la colonne du TAG de l'objet choisi aléatoirement.

Le principe était le même pour les objets de type "Equipement", "Magique" et "Parchemin" même si les degrés de valeur existant différaient :
- Pour le type "Equipement", on avait juste les degrés de valeur "1er" (1st), "2e" (2nd) et "3e" (3rd).
- Pour le type "Parchemin", c'était les mêmes degrés de valeur que pour le type "Equipement".
- Pour le type "Magique", on avait juste les degrés de valeur "Faible" (LOW) et "Puissant" (HIGH).

Pour avoir des exemples concrets j'ai transposé le contenu des fichiers RNDEQUIP.2DA", "RNDMAGIC.2DA", "RNDSCROL.2DA" et "RNDTREAS.2DA" de BG2 sur des pages webs aux adresses suivantes :
http://solaufein.free.fr/telechargem...DTREAS-2da.htm
http://solaufein.free.fr/telechargem...DEQUIP-2da.htm
http://solaufein.free.fr/telechargem...DSCROL-2da.htm
http://solaufein.free.fr/telechargem...DMAGIC-2da.htm

Ma réflexion était donc la suivante, vu que sur ce point BG2 et NWN utilisent le même type de fichiers (en l'occurence les fichiers 2DA), qu'est ce qui empêcherait (dans NWN) qu'un script fasse appel à des données contenues dans des fichiers 2DA ? La logique voudrait que cela soit également faisable sous NWN. Si oui, cela serait nettement plus simple que de devoir faire un méga-script-de-la-mort-qui-tue pour la génération aléatoire de trésors.
Cela aurait en plus les avantage suivants :
- Consommation de beaucoup moins de ressources système qu'un énorme script indigeste.
- Modification en toute simplicité par un utilisateur lambda, qui n'a pas besoin de s'y connaitre en script, et qui sera sur de pas faire de bêtises en modifiant un morceau du script qui ne fallait pas
La fonction Get2DAString() est, selon bioware, tres lente. Je ne suis pas sure que la mettre dans un script qui est appelé a chaque fois qu'une creature meure soit une bonne idée... Moi j'avais eut l'idée de mettre tout ca dans une BDD style nwnx, mais le temps et l'envie m'ont manqué.
__________________
..::Heavenlynet le net paradisiaque ::..
http://gw.heaven-ly.net/images/stories/divers/sigfg042.gif
Pour résumer en fait mon gros message, voici succintement les questions principales que je me pose :

Est-il possible sous NWN, d'aller chercher, au moyen d'un script, des données sélectionnées de manière aléatoire dans un tableau situé dans un fichier 2DA ?

Si oui, quelle(s) commande(s) utiliser dans le script pour aller chercher des données dans un fichier 2da ? Pour récupérer un script dans un autre script, c'est la fonction "include" mais ne serait-ce pas différent pour intégrer des données en provenance d'un fichier 2da ?
Complètement d'accord
Le principe d'utiliser des 2DAs est effectivement bien plus logique qu'un énorme script (qui faisait dans le millier de ligne je crois ) pour gérer ça.
Bien que le gain de ressource soit quasiment nul, voir même inverse (Get2DAString est une fonction assez "lente", enfin dans ce cas aucune différence ne sera perceptible), le gain en lisibilité et en ergonomie est considérable.

Cela dit, avant la 1.30, impossible de lire dans les 2DAs par script. Ca aurait été possible de coder en dur (dans l'exe) le système de génération de loot, mais après, impossible à modifier
(bon bien sûr on aurait pu aussi avoir Get2DAString dès le départ, mais bon ... )
D'autre part, je suis quasiment sûr que SoU utilise un système de genre, qui d'autre part sera customisable en jeu par les MJs. J'ai pas encore reçu ma tite boîte (et oui je m'y prends tard pour commander la VO ) donc si tu veux je te donnerais plus de détails à ce moment là. Cela dit, d'autres personnes l'ont déja sous la main, donc ça serait sympa de nous dire un peu comment que ça marche

En tout cas, je trouve l'idée très bonne. Et puisqu'on a déjà le fonctionnement (les 2DAs ne sont pas vraiment réutilisables :/), la tâche s'en trouve considérablement réduite.
Donc si jamais t'a besoin d'un peu d'aide, je suis assez dispo en ce moment

EDIT @ Rhyghar : Get2DAString est assez lente puisqu'elle va lire sur le disque dur. Cela dit, à chaque fois qu'un script est exécuté, il est aussi lu sur le disque (sauf dans le cas des scripts cachés en mémoire). Lire une seule entrée prend une fraction de seconde; lire une vingtaine d'entrées dans une boucle for ou while peut ralentir un tantinet, mais ça reste raisonnable. Dans ce cas donc, je ne pense pas que ce soit un souci, d'autant plus qu'utiliser la BDD sera clairement moins pratique que les 2DAs
mm, je vois pas où est le pb avec un gros script, qui en fait ne serait qu'en gros un jet de dés, puis aller chercher ce qui y correspond dans un switch.
Il existe des fonctions pour aller à la pêche dans les 2DA, enfin, il existeras, il me semble.
Mais faire appel à cette fonction c'est une perte de temps nan ? puisqu'on peut déjà tous les mettres dans des variables, dans l'include :/

du genre

Code PHP:

string RDNMAGIC001 "resref_de_l_item";
string RDNMAGIC002 "resref_de_l_item";
string RDNMAGIC003 "resref_de_l_item";
string RDNMAGIC004 "resref_de_l_item";
string RDNMAGIC005 "resref_de_l_item";
etc
on a alors qu'a faire un truc du style :
Code PHP:

#include "include_ave_les_resref"
string rdn_resref;
switch(
d20())
{
case 
rdn_resref RDNMAGIC001; break;
case 
rdn_resref RDNMAGIC002; break;
case 
rdn_resref RDNMAGIC003; break;
case 
rdn_resref RDNMAGIC004; break;
etc.

Et là on a vraiment tous les moyens pour faire autant de sélections aleatoires qu'on veut, voir y mettre un brin de mal chance

Et pour mettre des sélection de "contexte", les POOR et autre RICH et WEALTHY, ba tu fais un plus gros switch, dans lequel tu met les autres, genre :

Code PHP:

int POOR 1;
int RICH 2;

int nContext = ;//ba ce qu'on veut, faut voir comment c'est choisi
switch(nContext)
{
case 
POOR :
   {
      
string rdn_resref;
      switch(
d20())
         {
         case 
rdn_resref RDNMAGIC001; break;
         case 
rdn_resref RDNMAGIC002; break;
         case 
rdn_resref RDNMAGIC003; break;
         case 
rdn_resref RDNMAGIC004; break;
         
etc.
         }
   }
 break;
case 
RICH :    
{
      
string rdn_resref;
      switch(
d20())
         {
         case 
rdn_resref RDNMAGIC005; break;
         case 
rdn_resref RDNMAGIC006; break;
         case 
rdn_resref RDNMAGIC007; break;
         case 
rdn_resref RDNMAGIC008; break;
         
etc.
         }
   }
break;

Après tout est affair de rédaction, dans les variables, pour les rendres plus parlantes, ou que sais je

Et ca à l'air de devenir gargantuesque, mais pas tant que ca, un switch n'execute que la ligne qui lui est passé en argumùent (dsl si je m'exprime mal, j'y connais pas grd chose ^_^) enfin me semble, ce qui est sensé le différencié de


if()
else if()
etc.

Donc celon moi (avis personnel fondé sur ce que g cru comprendre)
a part que y a BCP de variables de déclarées . . .

rq : l'ideal je suppose serait la possibilité de variables . . . euh, mince c comment déjà, dynamiques ? enfin, de faire un truc du style : je pêhe un nombre i, et je récupère la

string BASE_i;

mais c pas possible dans le nwscript . . . si ?


Enfin c'est sur que aller à la pêche dans les 2DA rendrait le tout plus concit . . . mais plus rapide ? je sais pas . . .

note à moi même : éviter de s'étendre sur des trucs simple
@ Reyan : effectivement tout faire en NWscript est très possible, mais en plus de manquer d'ergonomie (obligation de recompiler les scripts, sauver le mod etc., alors que les modifications sur le 2DA prennent effet immédiatement), les choses s'enveniment rapidement lorsqu'on souhaite inclure beaucoup d'items.
J'ai sous les yeux le script de Bio qui gère les trésors (nw_o2_coninclude), et crois moi, c'est pas beau à voir : 4500 lignes, dont 3000 au moins consacrées à des switch...

Bref, je (re)vote pour les 2DAs
Voui, c'est le TRES GROS argument qui me fait aussi aller en faveur des fichiers 2da : Le script de Bioware sur la génération aléatoire des objets fait 93 pages sous Word (dixit un de mes collègues ). Autant dire que même si tu épures le code à fond, et que tu veux mettre un paquet d'objets aléatoires... Si le script fait plus de 2 pages, ça a plutôt tendance à me refroidir .

Par ailleurs, si entre le script de 93 pages et la fonction permettant de récupérer des infos dans un fichier 2da il n'y a pas de grosses différences de consommation de ressources, je préfère opter pour les 2DA même si c'est un peu plus lent : Dans le cadre d'Eauprofonde, on a pas l'intention de faire un module persistant hébergeant 64 voir 96 joueurs simultanément. Le maximum sera toujours d'une vingtaine de joueurs à la fois, donc on peut se permettre quelques écarts, si cela simplifie ensuite la mise à jour de la liste des trésors (ça aussi c'est un truc qui me tiendrait à coeur : que la liste soit facilement évolutive... Et au sein d'un fichier 2da, difficile de faire plus simple ).
Pour ta proposition Taern, je vais voir avec mes collègues et s'ils sont d'accord (il n'y a pas de raison qu'ils refusent mais bon ) et que tu es d'accord, ben on veut bien "t'engager" pour faire le système de scripts pour la génération aléatoire des trésors (système qu'on mettra ensuite à la disposition de la communauté, bien entendu ).
SoU utilise un autre systeme :
des coffres sont posé dans une zone inaccessible du module. on rempli chaque type de coffre avec les items que l'on souhaite voir apparaitre. Lors de l'ouverture d'un coffre du meme type par un PJ, un item est piqué dans les coffres modèles et créé dans le coffre ouvert par le PJ.

Exemple:
* je pose dans ma zone incassessible un tonneau.
* je remplis ce tonneau avec des items quelconques.

*je pose un autre tonneau du meme type dans une zone accessible par mon PJ.
*lors de l'ouverture du tonneau, un item sera créé a partir de ce qu'il y avait dans le tonneau de la zone inacessible.


Je simplifie là mais c'est la maniere dont fonctionne les tresors de SoU. (Ca doit etre transposable pour nous, pauvre possesseurs de version 1.29, mais là encore, c'est tellement plus simple d'attendre les scripts deja tout fait).

Toujours est il que moi, j'aime pas trop les 2DA (faut dire que j'ai été vaccinée au lag avec les ecritures sur les fichiers)
__________________
..::Heavenlynet le net paradisiaque ::..
http://gw.heaven-ly.net/images/stories/divers/sigfg042.gif
exellent, j'y aurais jamais pensé
sauf que : si on fait ca, ca seras des script, des "GetObjetByTag" etc.
et bon moi m'en fiche g pas de module perso, mais y parait que ca lourd . . . alors si on peut passer par un systeme un peu plus "light", avec moins d'appels à des fonction lourdes, ba ca seras pas plus mal si ?

Autre remarque, pour la lourdeur sur le script, si els switch sont gargantuesque, c'est qu'on est obligé de mettre un possibilité pour chaque variable, donc un cas par resref . . .
si on avait que deux ou trois variables ? avec tous les resref dedans ?

je m'explique : j'avais ca dans un script pour une conversation aleatoire, une string avec toutes les éventuels répliques dedans, et une fonction qui découpait la string et choisissait une des répliques aléatoirement, c'est là :

https://forums.jeuxonline.info/showthread.php?t=180908


Donc avec grand max 10 string je pense, vu la longueur des resref, et moins sans doute en considérant que finalement il n'y a pas grd chose qui varie d'un resref à l'autre, on doit pouvoir tout mettre sans pour autant dépasser la limite de 500 caractères et des brouettes par string . . . . non ?
c toujours pas assez lisible ?
bon, après c'est sur faut compiler . . . non non, les 2DA g rien contre
c juste que je vois pas une utlité si énorme . . . probablement parce que je gère pas de module
Merci pour l'info C'est astucieux effectivement.
L'écriture sur le disque est effectivement assez lente, mais la lecture est normalement beaucoup plus rapide. J'avais fais un test avec la BDD de Bioware (pour donner une idée) : à l'écriture, 500 entrées bloquaient le jeu pendant 15~20 secondes; à l'écriture en une demi-seconde c'était joué. Et je n'ai pas un DD SCSI 20000 tours minutes

Solaufein, faire les scripts me gêne pas du tout, c'est plutôt le terme "engager" qui coince
Normalement ça devrais pas demander trop de temps (un à trois jour je dirais, à vue de nez comme ça au pif ), mais moi dans une semaine et demi je reprend les cours Après ça, je vais être beaucoup moins dispo. Donc si on s'y mets vite, ça sera fait, mais après bye bye Aurora
Répondre

Connectés sur ce fil

 
1 connecté (0 membre et 1 invité) Afficher la liste détaillée des connectés