Saturday 8 March 2014

Handling an inventory

Here is a set of macros that will make an inventory easy. Just dump this into a script passage, and be sure to call <<initInv>> right at the start.

window.getInv = function() {
  return state.history[0].variables.inventory;
}

macros.initInv = {
  handler: function(place, macroName, params, parser) {
    state.history[0].variables.inventory = [];
  },
};

macros.addToInv = {
  handler: function(place, macroName, params, parser) {
    if (params.length == 0) {
      throwError(place, "<<" + macroName + ">>: no parameters given");
      return;
    }
    if (state.history[0].variables.inventory.indexOf(params[0]) == -1) {
      state.history[0].variables.inventory.push(params[0]);
    }
  },
};

macros.removeFromInv = {
  handler: function(place, macroName, params, parser) {
    if (params.length == 0) {
      throwError(place, "<<" + macroName + ">>: no parameters given");
      return;
    }
    var index = state.history[0].variables.inventory.indexOf(params[0]);
    if (index != -1) {
      state.history[0].variables.inventory.splice(index, 1);
    }
  },
};

macros.inv = {
  handler: function(place, macroName, params, parser) {
    if (state.history[0].variables.inventory.length == 0) {
      new Wikifier(place, 'nothing');
    } else {
      new Wikifier(place, state.history[0].variables.inventory.join(', '));
    }
  },
};

macros.emptyInv = {
  handler: function(place, macroName, params, parser) {
    state.history[0].variables.inventory = []
  },
};


Here is a single page that shows it in action.

First we set up the inventory.<<initInv>>

Then we can use it:
You have <<inv>>.
You pick up a rake.<<addToInv rake>>
You have <<inv>>.
You pick up a spoon.<<addToInv spoon>>
<<if isInInv('spoon')>>You have a spoon<<else>>You don't have a spoon<<endif>>
You have <<inv>>.
You drop the rake.<<removeFromInv rake>>
You have <<inv>>.
You drop the rake again.<<removeFromInv rake>>
You have <<inv>>.
You pick up the spoon again.<<addToInv spoon>>
You have <<inv>>.
You drop nothing (error).<<removeFromInv>>
You have <<inv>>.
You pick up a hat.<<addToInv hat>>
You have <<inv>>.
You drop everything.<<emptyInv>>
<<if isInInv('spoon')>>You have a spoon<<else>>You don't have a spoon<<endif>>
You have <<inv>>.


Note that you can only add and remove one item from the inventory at a time, and you can only have one of anything in the inventory at a time. Also note that this stores strings not objects (if you do not know what that means, it probably does not matter).

Use the getInv function to get a list of objects in the inventory, and isInInv to test if an object is in the inventory.

If you use Sugarcube, you will need to modify the code so that every state.history[0].variables becomes state.active.variables.

10 comments:

  1. Here's the code for SugarCube:

    window.getInv = function() {
    return state.active.variables.inventory;
    }

    macros.initInv = {
    handler: function(place, macroName, params, parser) {
    state.active.variables.inventory = [];
    },
    };

    macros.addToInv = {
    handler: function(place, macroName, params, parser) {
    if (params.length == 0) {
    throwError(place, "<<" + macroName + ">>: no parameters given");
    return;
    }
    if (state.active.variables.inventory.indexOf(params[0]) == -1) {
    state.active.variables.inventory.push(params[0]);
    }
    },
    };

    macros.removeFromInv = {
    handler: function(place, macroName, params, parser) {
    if (params.length == 0) {
    throwError(place, "<<" + macroName + ">>: no parameters given");
    return;
    }
    var index = state.active.variables.inventory.indexOf(params[0]);
    if (index != -1) {
    state.active.variables.inventory.splice(index, 1);
    }
    },
    };

    macros.inv = {
    handler: function(place, macroName, params, parser) {
    if (state.active.variables.inventory.length == 0) {
    new Wikifier(place, 'nothing');
    } else {
    new Wikifier(place, state.active.variables.inventory.join(', '));
    }
    },
    };

    macros.emptyInv = {
    handler: function(place, macroName, params, parser) {
    state.active.variables.inventory = []
    },
    };

    Still trying to work this code out to work with my stuff :\

    ReplyDelete
  2. Though, your if statements don't work for macros in my Twine game in SugarCube for some reason, if you could offer any help, that would be great.

    ReplyDelete
  3. Can anyone provide the macros.isInInv code? I have all else working, but don't see the isInInv function.

    Thans

    ReplyDelete
  4. Can anyone provide the macros.isInInv code? I have all else working, but don't see the isInInv function.

    Thans

    ReplyDelete
  5. Hi, I need some help!

    I basically want to code it so that in a passage I pick up something, and when the message comes up saying "You picked up the note" and next to it a "Go Back" to original passage where the item was originally...I want the option to pick up the note to be gone now in the original passage, for it to recognize that it was already picked up instead of always being available. This is all I have so far from code samples:

    <> There is a note here. [[Pick up the note.]] <>

    Would really appreciate any help!

    ReplyDelete
  6. Hello! I was wondering, since Twine has since expanded and there is now Harlowe, ho would this transfer over into Harlowe code? I'm having a hard time trying to set up the inventory for my story.

    ReplyDelete
    Replies
    1. Sugarcube 2 is better than harlowe in almost every way but if you really want this: http://gersande.com/blog/designing-inventories-in-twine-2-with-the-built-in-harlowe-macros/

      Delete
  7. Odd question... could this be used to contain variables? I'm trying to wrangle and inventory weight system as well as stat changes for each Item equipped (both hands and armour). Using Sugercane with Twine 1.4.2

    ReplyDelete
  8. Twine version 2.1.3 / Sugarcube 2.18.0

    When using this. At start up, I receive:
    Error [StoryInit]: macro <> does not exist.

    I have the following:

    StoryInit:
    <>
    <>
    <>
    <>
    <>
    <>
    <>
    <>
    <>
    <>
    <>

    StoryCaption:
    Inventory:<>
    Closet Inventory:<>


    Inventory Background:
    window.getInv = function() {
    return state.active.variables.inventory;
    }

    macros.initInv = {
    handler: function(place, macroName, params, parser) {
    state.active.variables.inventory = [];
    },
    };

    macros.addToInv = {
    handler: function(place, macroName, params, parser) {
    if (params.length == 0) {
    throwError(place, "<<" + macroName + ">>: no parameters given");
    return;
    }
    if (state.active.variables.inventory.indexOf(params[0]) == -1) {
    state.active.variables.inventory.push(params[0]);
    }
    },
    };

    macros.removeFromInv = {
    handler: function(place, macroName, params, parser) {
    if (params.length == 0) {
    throwError(place, "<<" + macroName + ">>: no parameters given");
    return;
    }
    var index = state.active.variables.inventory.indexOf(params[0]);
    if (index != -1) {
    state.active.variables.inventory.splice(index, 1);
    }
    },
    };

    macros.inv = {
    handler: function(place, macroName, params, parser) {
    if (state.active.variables.inventory.length == 0) {
    new Wikifier(place, 'nothing');
    } else {
    new Wikifier(place, state.active.variables.inventory.join(', '));
    }
    },
    };

    macros.emptyInv = {
    handler: function(place, macroName, params, parser) {
    state.active.variables.inventory = []
    },
    };

    ReplyDelete