Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Simplest way to do an Inventory in Twine 2?

So, how do you all handle inventories in Twine? I can imagine using (history: ) and just sending the user to passages when they take an item. But then you can't easily remove/re-add items. Do you use the (dataset: ) array? Can you append or concatenate dataset arrays?

Comments

  • P.S. Harlowe
  • I do it via variables. I.e., if someone gets a shield, you can set the variable $shield to true. Then, I use if/else statements to check those variables.

    Datasets might be more efficient (and, yes, you can append to them, etc.), but I always found variables easier to track.

    If you need actual code examples, let us know.
  • Ah. Of course. That is a simple and easy way to do it. I think I just got caught up in trying to do it a more complicated way. Now that I think about it, it was so I could print out a player's inventory in one go instead of a bunch of statements to check for everything the player could have. But really, it's not a bad idea to keep a passage with all list of all your variables anyway, so...
  • edited May 2015
    ... and the nice thing about variables is they have some flexibility. Like you could set $matches to 6, and then $matches = $matches-1 anytime a player uses one.
  • edited May 2015
    You can do a basic inventory via the (dataset:) macro.

    I've used a combination of the dataset and count macros and the contains operator. Did what I needed at the time. Might be something you could use as well.

    From @L's Twine 2.0 Harlowe Guide

    (dataset:) This macro produces a Javascript Set, which is a more limited form of array that does not have numeric properties - you can only query whether it contains a value using contains or is in. It can be used for simplifying (if:) statements - instead of writing (if: $a is "sword" or $a is "axe" or $a is "dagger") dozens of times, you can write (set: $weapons to (dataset: "sword", "axe", "dagger")) and then simply write (if: $a is in $weapons).

    contains: This operator is used to check if a string or some text contains another substring. For instance, "Red" contains "R" evaluates to true. (It can also be used with arrays to check for inclusion: (array: 1,4,5) contains 4 evaluates to true.)

    (count:): This macro takes an array and a value, and returns the number of times the value appears within the array. (count: $a, "Egg") returns the number of times the string "Egg" is a value in $a. It's like the contains operator, but it produces a number rather than just true or false.

  • @rayotus

    I found this, I think on glorious trainwreck... but it works great:
    <<set $inv = ["Dagger", "Shield", "Potion"] >>
    <<if $inv.length is 0>>You have nothing.
    <<else>>
    Your inventory contains:
    <<print $inv.join("\n")>>
    <<endif>>
    
    
    You decide to [[drop your potion]]
    
    ―> (new room)
    
    <<script>>
    // Removes an element from an array.
    // String value: the value to search and remove.
    // return: an array with the removed element; false otherwise.
    Array.prototype.remove = function(value) {
    var idx = this.indexOf(value);
    if (idx != -1) {
    return this.splice(idx, 1); // The second parameter is the number of elements to remove.
    }
    return false;
    }
    <</script>>
    
    It breaks on the ground and just in front of you, and you see....
    
    <<set $inv.remove('Potion')>>
    Your inventory now only contains:
    <<print $inv.join("\n")>>
    

    If I miscredited it, let me know... but I think I saw it there.

    —Sage.
  • It works great for SugarCube, probably doesn't work for Harlowe.
  • @AvaJarvis
    Missed that, above, thanks.
  • The following is a Harlowe version of @Sage's post:

    1. Place the following in your story's Story Javascript area:
    // Removes an element from an array.
    // String value: the value to search and remove.
    // return: an array with the removed element; false otherwise.
    Array.prototype.remove = function(value) {
    	var idx = this.indexOf(value);
    	if (idx != -1) {
    		// The second parameter is the number of elements to remove.
    		return this.splice(idx, 1); 
    	}
    	return false;
    };
    
    2. Copy the following In your start passage:
    (set: $inv to (array: "Dagger", "Shield", "Potion"))
    (if: $inv.length is 0)[You have nothing.]
    (else:)[Your inventory contains:
    (print: $inv.join("\n"))
    ]
    
    You decide to [[drop your potion]]
    
    3. Create a new passage titled drop your potion and copy the following into it:
    It breaks on the ground and just in front of you, and you see....
    
    (set: $dummy to $inv.remove("Potion"))
    Your inventory now only contains:
    (print: $inv.join("\n"))
    
    4. Dance around with your hands in the air like you just don't care...
  • But I wanted to dance around… :(
Sign In or Register to comment.