J’ai un souci de transport d’objet… Pour mon jeu en cours, j’ai voulu ajouter un sac à dos pour que le joueur transporte ses objets. Rien de bien compliqué initialement, un container transparent dans l’inventaire. J’ai modifié la routine « take » pour que l’objet soit placé dans le sac plutôt que dans l’inventaire.
Mais pas de bol, ça fait planter toutes les actions de gestion d’objet (poser, lancer, mettre…) car l’objet n’étant pas « parent(player) » la routine « take » est appelée en premier, et du coup boucle infinie… J’ai modifié les subs en question, mais il en reste plein qui sont sources de bug, et j’ai pas envie de reprendre 50% des subs des librairies pour ajouter un sac à dos…
Tout d’abord, pourquoi le joueur a besoin d’un sac à dos ? Il est limité dans le nombre d’objets qu’il peut transporter ? Et donc tout ce qu’il prend en trop est mis dans le sac ?
Si c’est le cas, je sais qu’I7 possède un type de conteneur (le player’s holdall, ou fourre-tout en français) pour gérer automatiquement ça. Je suppose qu’il y aun équivalent en I6 ?
Dans ta routine « take » modifiée, tu as du code pour mettre un objet dans le sac « automatiquement », c’est ça ? (genre « move obj to sacados » ?) Alors n’exécute ce code que si, au tout début de Take, l’objet est dans un lieu autre que le sac à dos. Du genre
if (parent(obj) ~= sacados) { move obj to sacados; return true;} else { comportement usuel}
Si l’objet n’est pas dans le sac à dos, il y sera ; si il y est déjà, ça fera le truc normal, i.e. le mettre dans le joueur.
En fait il faut sans doute aussi rajouter un test pour « prendre un objet que le joueur a déjà en main » :
if (parent(obj) ~= sacados or player) { move obj to sacados; return;} else {comportement normal}
Je crois ?
EDIT: Ah mais y’a le cas où y’a un objet dans un objet dans le sac à dos… Donc ça serait peut-être mieux d’utiliser IndirectlyContains(player, obj), qui renvoie true si l’objet est dans un truc qui est dans un truc qui… qui est dans le joueur ; donc si c’est faux, le joueur l’a vraiment pas et tu le mets dans le sac à dos, si c’est vrai, le joueur l’a et voudrait l’avoir dans les mains (donc dans le player). Si tu vois ce que je veux dire…
Ah et @Natrium: non, pas de player’s holdall en I6 - ça a l’air pratique pourtant !
Une petite recherche Google et hop ! Selon l’IFWiki, il fut utiliser la constante SACK_OBJECT pour définir un objet en tant que sac, ce que le DM4 confirme :
[code]Object sacados « sac à dos »
with description « Un gros sac sur lequel est peint un sourire. »,
name ‹ sac ›, ‹ dos › , article ‹ votre ›,
has container open openable clothing;
Constant SACK_OBJECT = sacados;[/code]
Par contre, je ne sais pas comment on peut faire pour avoir plusieurs sacs dans le même jeu. Il faudrait voir comment I7 fait.
Après, pas sûr que cette solution correspond à ce que tu veux, Yoruk. Tout dépend de si le joueur à une capacité limitée. Si le sac a une autre utilité (par exemple pour y mettre automatiquement seulement certains types d’objets), alors il faudra utiliser la solution de Mule.
Et en plus, j’aurai appris un truc d’Inform 6 à maître Mule hollandaise !
Ouais carrément, j’en tombe de ma chaise ! Chapeau
Donc, selon l’IFWiki si c’est un SACK_OBJECT tous les objets seront mis dans le sac ; en pratique (ligne 1511 de verblibm) si l’objet a l’attribut « light » ou « worn » il sera pas mis dans le sac (c’est pour éviter de mettre des torches enflammées dans le sac j’imagine). Ca me semble donc être exactement ce que tu veux (et donc si tu veux pas qu’un objet soit mis automatiquement dans le sac tu fais « before [; Take: move self to player; rtrue; ], » au cas par cas).
Bon je viens de tenter la méthode la plus simple, celle du SACK_OBJECT. Pas de bol, ça ne fonctionne pas… Je prends le sac à dos, puis un autre objet, mais il n’est pas placé à l’intérieur…
Ah, il faut peut-être bidouiller la constante MAX_CARRIED aussi (genre le jeu ne fait pas de la place en mettant les choses dans le sac à dos tant que le joueur peut porter des trucs). Je sais plus quelle est la valeur par défaut, mais tu peux mettre 2 parce que le joueur a deux mains Je sais pas ce qui se passe quand tu mets 0, mais je pense que c’est pas une bonne solution (tu veux que le joueur puisse prendre des trucs du sac dans ses mains). Donc je dirais « Constant MAX_CARRIED = 2; » au début de ton code…
Il faut effectivement mettre un MAX_CARRIED (j’ai testé à 2, ça semble bien) sinon cela ne fonctionne pas correctement.
Le souci que j’ai est que comment gérer la prise d’un objet dans mon code ? J’utilise très régulièrement des move objet to player, et du coup l’objet est placé dans le premier niveau d’inventaire. A voir en tests si je peux faire mieux.
Par contre, une action sur un objet type montrer à / poser semble ne pas fonctionner correctement si l’objet est dans le sac. Les essais sont en cours; je poste un exemple bientôt.
Je pense avoir trouvé la solution, du moins une façon de procéder. Il faut, avant d’utiliser un objet situé dans le sac, le prendre à nouveau de façon à le remonter au premier niveau d’inventaire. L’objet fonctionne alors de façon classique.
Histoire de rendre le truc plus réaliste, j’ai modifié la routine TakeSub (et elle uniquement) afin d’ajouter un petit message:
[code][ TakeSub;
if (parent( noun) == SacADos) {move noun to player ; print "Vous sortez ", (the) noun , " du sac.^"; rtrue ; }
if (onotheld_mode == 0 || noun notin player )
if (AttemptToTakeObject(noun)) rtrue;
if (AfterRoutines() == 1) rtrue;
notheld_mode = onotheld_mode;
if (notheld_mode == 1 || keep_silent == 1) rtrue;
L__M(##Take, 1);
];[/code]
Ce qui donne :
J’ai pensé à un truc « Vous prenez l’objet en main » mais bof bof… Un truc a faire serait de dire « L’objet est dans votre sac, allez le chercher » plutôt que « vous n’avez pas ça. » qui est un peu « faux ».
J’ai ajouté une note explicative dans mon jeu pour expliquer cela. Une fois que l’on a saisi la subtilité, ça va tout seul.