Howdy, Stranger!

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

Player Inventory

I'm finally ready to start working on my roguelike's inventory system.

With equipment in games, usually each item has multiple purposes, aspects and attributes. I'm not really certain how to go about adding, removing and accessing them all in the player's inventory, or updating the various stats and whatnot when a piece is equipped or unequipped.

Here's one weapon in the game now:
<<set $WepName = "hatchet">>
<<set $Skill = $AxeMaceSkill>>
<<set $WeaponBon = 0>>
<<set $WepWoundMod = 1.5>>
<<set $Parry = Math.floor(($Skill * 0.5) + 3 + $CombatReflexes + $DB)>>
There will almost certainly need to be more variables before the game goes alpha.

I have a basic understanding of arrays. I use one to take three numeric variables, sort them, and then assign the highest value to another variable. Beyond that, I'm no expert.

Didn't want to reinvent the wheel. If someone has some advice or suggestions before I get too deep into this, I'm certainly open to them!

Keep in mind, though, I'm a total newbie. This is my first time ever working with Twine, CSS, or JavaScript and I don't even have a rudimentary understanding of the latter two!

Thanks! :)

Comments

  • I'm not sure how fitted Twine is for a roguelike, but good luck.

    L goes over using JavaScript arrays in this blog post http://www.glorioustrainwrecks.com/node/5034

    For storing information about weapons, you might try JavaScript Objects.
    A quick example:
    <<set $axe = {}>>
    <<set $axe.name = "Axe">>
    <<set $axe.damageRange = [1,5]>>
    Object: <<print $axe>> which you don't use
    Name: <<print $axe.name>>
    Damage: <<print $axe.damageRange>>

    This would allow you to swap in and out weapons with a simple
    <<set $weapon  = $axe>>
  • Wow! JavaScript Objects! I had no idea at all! Thanks a lot! :D

    I'm very glad I asked, now! I'll toy with those.

    My friends and I are really enjoying the current version of it, so a CYOA roguelike is possible! :) It's also something different, so I'm trying hard to make it a good example of one of the first CYOA roguelikes out there. I think my friend's ten-year-old son played it for like two hours straight! XD I left the room and came back, and was like, "Are you still playing Abaddon?" He was like, "Yeah! I'm on level 3!" I didn't have the heart to tell him I didn't bother making more levels after that, because who would go around killing that many monsters at this point?  ;D

    Oh, and I did read L's blog post. It's how I re-discovered arrays, actually. :)

    Thanks again! :)
  • Well, I worked like a madman possessed and completely implemented weapons as objects. I thought it was going to be a Herculean task, but since weapon modifiers get changed in combat to flat values (eg. <<set $Weapon.Damage = $Damage>>), it wasn't all that bad. Most of the combat code stayed the same.

    Just wanted to say thanks again! That really helped a lot! I can''t imagine if I had tried to set weapons (and later armor) up as a series of if statements! XD
  • I'll just add a good luck to you--I've been working on some stuff with RPG dlements myself, and there's something that's a lot of fun about bending Twine to fit an otherwise-already-existing but unrepresented genre. I'd been using a weird series of <<display>> statements to handle inventory myself, but this array stuff sounds so much easier. I'll be excited when yours comes out!
  • My poor little feeble mind has been totally blow away by this whole concept that everything is an object. Once I finished with weapons last night, I looked at my code with new eyes. Why aren't monsters objects? Why isn't the player? Why isn't the healing potion, or for that matter, every single item and piece of equipment an item?

    This new perspective is like night and day.

    Here is a broadsword in my game:
    <<set $Broadsword = {}>>
    <<set $Broadsword.WepName = "broadsword">>
    <<set $Broadsword.Skill = $BroadswordSkill>>
    <<set $Broadsword.WeaponBon = 1>>
    <<set $Broadsword.WepWoundMod = 1.5>>
    To have the player equip the sword, all I do is <<set $Weapon = $Broadsword>>. (In the future, it will be <<set $Player.Weapon = $Broadsword>>.)

    In the combat code, which is beyond voluminous, I had to change a few variables. This isn't actual code in my game, but just as an example, I had to change <<set $Damage = $Damage + $WeaponBon>> to <<set $Damage = $Damage + $Weapon.WeaponBon>>.

    Instead of rolling against $Skill to hit, now the code rolls against $Weapon.Skill.

    Here's another change that's going to happen but hasn't yet.

    Take a look at this line again:
    <<set $Broadsword.Skill = $BroadswordSkill>>
    That's setting the weapon's skill ($Broadsword.Skill) to the player's broadsword skill ($BroadswordSkill).

    However, the player should be an object.

    After I make the player an object called $Player, that line of code ill have to say,
    <<set $Broadsword.Skill = $Player.BroadswordSkill>>
    Pretty cool, eh? :D

    I'd post my game now, but at this point, it will be easy to mistake it for something that's a lot closer to being finished than it really is. It's an entirely playable game with random rooms and monsters and complex combat and treasure and traps and all that. However, it's a pale, bleak shadow of what it will be when completed.

    However, I'll be happy to post large portions of code, basically everything if it will help someone. :)
  • Sharpe wrote:
    This new perspective is like night and day.

    Here is a broadsword in my game:
    <<set $Broadsword = {}>>
    <<set $Broadsword.WepName = "broadsword">>
    <<set $Broadsword.Skill = $BroadswordSkill>>
    <<set $Broadsword.WeaponBon = 1>>
    <<set $Broadsword.WepWoundMod = 1.5>>


    You could make that somewhat more succinct by using an object literal.
    <<set $Broadsword = {
    WepName: "broadsword",
    Skill: $BroadswordSkill,
    WeaponBon: 1,
    WepWoundMod: 1.5
    }>>
  • Sharpe wrote:
    However, I'll be happy to post large portions of code, basically everything if it will help someone. :)

    I'd be interested to see how you're going about generating the map/rooms, actually.
  • Sorry, there's no awesome dungeon-building algorithm. Just random numbers and conditional branches picking room descriptions and door directions and basic variable use. Nothing interesting. I think it gives a pretty cool illusion of a dungeon crawl, though.
  • Well if you've done the legwork and are willing to share I might as well ask. Do you have a script written for detecting duplicate items in an array and sending the duplicates to a quantity property?

    I'd really like to print
    Potion x3
    Instead of
    Potion
    Potion
    Potion
    If you're using a hashmap or something like that, that would be fine. Unless you don't have the functionality. Then I've got my project for tomorrow.
  • What?! Heck no! I just learned what objects were in this thread! ;D

    Sharpe wrote:
    Keep in mind, though, I'm a total newbie. This is my first time ever working with Twine, CSS, or JavaScript and I don't even have a rudimentary understanding of the latter two!


    "Have you written a script," she asks . . .  ::)

    Just kidding, just kidding!  ;D

    But, no, I'm afraid I'm quite new at all this, "all this" being even the very most basic foundations of CSS and JavaScript.

    I usually aways set the number of items when they are received (<<set Item.amount = item.amount + 1>>), so I don't foresee this being an issue for me personally. I do this even for unique items.
  • Hey, we're in the same boat. My history before last week was that I taught myself HTML tags in 2000 when I was only 13 and last year I buckled down and learned basic C++. Enough to make a command line program! Woo!  :P

    But if I may ask, how are you printing out the contents of your inventory? Right now I'm using:
    <<set #inv=[]>>
    To create an array and when I pick up an item I use:
    <<set $inv.push("Potion")>>
    If you're using:
    <<set Potion.amount = Potion.amount + 1>>
    How are you displaying a list of items (inventory screen) without checking for every single variable? I suppose I could do both, but that seems sloppy. Like... do a <<if $inv.indexOf("Potion") gte 1>> to make sure that player has at least 1 and then do a <<$Potion.amount>> for the quantity?

    EDIT: Fixed typos. Ooof, its late. I should get to bed.
  • Yeah, it's 3 a.m. and I just can't do it. Tomorrow. . .

        zzzZZ
    -_-
  • Well, the thing is, in my current game, not all things that need to be objects are objects. So, I haven't ran into the same problem.

    In my attempt to figure out what I will do when I get there, I started working on printing the inventory.

    I ran into a roadblock when trying to put an object into an object inside an object. Or, at least I think that's what I'm trying to do . . .
    <<set $player = []>>
    <<set $player.gold = 10>>
    Gold: <<print $player.gold>>G
    Prints "10."
    <<set $player = {
    gold: 10,
    silver: 25
    }>>
    Gold: <<print $player.gold>>G
    Silver: <<print $player.silver>>S
    Prints "10, 25."
    <<set $player = []>>
    <<set $player.inventory = []>>
    <<set $player.inventory.push("Potion")>>
    <<print $player.inventory>>
    Prints "Potion."
    <<set $player = {
    inventory: [],
    gold: 10,
    silver: 25
    }>>
    <<set $player.inventory.push("Potion")>>
    <<print $player.inventory>>
    Prints "Potion."
    <<set $potion = 5>>
    <<set $player = {
    inventory: [],
    gold: 10,
    silver: 25
    }>>
    <<set $player.inventory.push($potion)>>
    <<print $player.inventory>>
    Prints "5."
    <<set $player = {
    inventory: {
    gold: 10,
    silver: 25,
    potion: 0
    }
    }>>
    <<set $player.inventory.potion = 5>>
    <<print $player.inventory.potion>>
    Prints "5."
    <<set $sword = []>>
    <<set $player = {
    inventory: {
    gold: 10,
    silver: 25,
    potion: 0
    }
    }>>
    <<set $player.inventory.potion = 5>>
    <<print $player.inventory.potion>>
    <<set $player.inventory.push($sword)>>
    bad expression: state.history[0].variables.player.inventory.push is not a function

    So, I'm messing with that right now . . .
  • Sharpe wrote:


    bad expression: state.history[0].variables.player.inventory.push is not a function



    This is a known bug as of right now.
  • Okay, but after I changed to ["push"]() I get a new error (probably because I'm doing something wrong this time! ;D).
    <<set $sword = 1>>
    <<set $player = {
    inventory: {
    gold: 10,
    silver: 25
    }
    }>>
    <<set $player.inventory.potion = 5>>
    <<print $player.inventory.potion>>

    <<set $player.inventory.["push"]($sword)>>
    <<print $player.inventory.sword>>
    bad expression: missing name after . operator
  • Okay, there are two problems here:

    2) You need to write it as $player.inventory["push"], not $player.inventory.["push"]
    1) Plain Objects don't have push() - only Arrays and other things do.

    Try this:
    <<set $sword = "Sword">>
    <<set $player = {
    purse: {
    gold: 10,
    silver: 25
    },
    inventory: [ "potion", "shield", "potion", "potion" ],
    }>>
    <<set $player.inventory.silver = 5>>
    <<print $player.inventory.silver>>
    <<set $player.inventory.push($sword)>>
    Also, don't push() an Array into another Array, unless you really want an Array inside an Array.
  • L wrote:
    1) Plain Objects don't have push() - only Arrays and other things do.

    Perhaps that I don't understand the difference between an array and an object is keeping me from understanding what I'm doing wrong.

    Here's the code again:
    <<set $sword = "Sword">>
    <<set $player = {
    purse: {
    gold: 10,
    silver: 25
    },
    inventory: [ "potion", "shield", "potion", "potion" ],
    }>>
    <<set $player.purse.silver = 5>>
    <<set $player.inventory.push($sword)>>
    <<print $player.inventory>>
    <<print $player.purse.gold>>
    <<print $player.purse.silver>>
    What if $sword was an object?
    <<set $sword = {
    amount: 1
    }>>
    I guess first I should ask if that is an object or an array. As far as I know, it's an object.

    Now that it's an object, it can't be somehow added to $player.purse or $player.inventory?

    I noticed you used "{}" for purse and "[]" for inventory. Is "{}" for an object and "[]" an array? I mean, I see the syntax difference between ["Stuff", "Stuff", 1, 25, "Stuff"] and { stuff: 1, stuff: "yes"}. But, is there more to the difference? Both can hold numbers and strings, but an object can have multiple properties at once?

    I guess that all goes back to the question, "Can an object not hold an object?"

  • JavaScript objects are, pretty much, bags of properties.

    JavaScript arrays are just a special type of object with a little extra syntactical sugar on the side.  There are two parts to that:
    [list type=decimal]
    Has a numeric length property and non-negative integer properties.
    Inherits the Array prototype.

    The former allows you to iterate over the object like an array, and pass it to functions expecting to be able to iterate over it like an array.  The latter gives the object access to all of the "array" methods from the Array prototype.  Objects which meet both criteria are considered arrays.  Object which only meet the former are called array-like objects.  Objects only meeting the latter aren't terribly useful.

    The properties on objects (and arrays) can reference anything a variable can: strings, numbers, objects, arrays, functions, etc.

    When creating literals, {} creates an plain/generic object literal and [] creates an array literal.

    Yes, an object can contain multiple properties.  Yes, an object can contain/reference other objects via its properties.  Your last example shows both of those actually.

    The object referenced by $player, contains the properties purse, which references an object with its own properties (gold and silver), and inventory, which references an array with its own properties (length, 0, 1, 2, 3, and others inherited from the Array prototype).

    You may find JavaScript @ Mozilla Developer Network informative.
  • Thanks so much for that information! I really appreciate it very much. :)

    I screwed up royally when I asked if an object could contain an object because, like you point out, the above code does just that. What I meant to askif I can get it out now that it's 3 a.m. againis can an object held in an object hold an object?

    The question isn't as important as the code example; for two days now, I haven't been able to do this:
    <<set $sword = {
    amount: 1
    }>>

    <<set $player = {
    purse: {
    gold: 10,
    silver: 25
    },
    inventory: [ "potion", "shield", "potion", "potion" ],
    }>>
    <<set $player.purse.silver = 5>>
    <<set $player.inventory["push"]($sword)>>
    Inventory: <<print $player.inventory>>
    How many swords: <<print $player.inventory.sword.amount>>
    At first, I thought it was because of the bug, then, I thought it was because I used ".["push"]" instead of "inventory["push"]."

    Now what am I doing wrong? ;D

    Thanks again!
  • [quote]
    <<print $player.inventory.sword.amount>>
    "sword" is not a property of the array $player.inventory

    Here are the (non-inherited) properties of $player.inventory at that point:

    0: "potion",
    1: "shield",
    2: "potion",
    3: "potion",
    4: { amount: 1 },
    length: 5
    Thus, you have to refer to the sword object (which by now is completely nameless) as $player.inventory[4].amount.
    Of course, that's fairly unreadable, and indicates that you shouldn't be using an array at all if you need to refer to objects by their identity rather than their array location.

    This topic seems to be drifting quite quickly away from Twine-specific minutiae.
  • Yeah, Twine really has awoken a desire to lean JavaScript in me. I'll spend some time in the books. I learned as much CSS I needed in one day; maybe if I spend all day today learning JavaScript, I'll be able to answer my own rudimentary questions! ;D

    Thanks again!


    EDIT: The discussion in this thread is continued here: http://twinery.org/forum/index.php/topic,724.0.html
Sign In or Register to comment.