It looks like you're new here. If you want to get involved, click one of these buttons!
<<set $foo = {}>>
Now, the variable $foo is an object. Who cares, right? <<set $foo= {
property1: "bar",
property2: 894,
property3: $baz,
}>>
More interested now? <<set $player = {
name: "Jane",
age: 21,
height: 63,
weight: 100,
hair: "Blonde",
eyes: "Blue",
}>>
That's a lot more well organized and legible than seven different variables. <<set $player.hair = "Brown">>
To print the player's new hair color, we would do:
<<print $player.hair>>
That would print "Brown" without the quotes. Hello, <<print $player.name>>!
What color would you like to dye your hair?
[[Blonde][$player.hair = "Blonde"]]
[[Brown][$player.hair = "Brown"]]
[[Black][$player.hair = "Black"]]
[[Red][$player.hair = "Red"]]
Another thing one can do, cutting out several lines of code in some cases, is set one object to be another. <<set $gun = {
name: "S&W .38",
maxAmmo: 6,
ammo: 6,
caliber: 38,
damage: 10,
}>>
Let's say the player finds a new gun, an M1911. Here's how it would compare:
<<set $colt45 = {
name: "Colt .45",
maxAmmo: 8,
ammo: 8,
caliber: 45,
damage: 20,
}>>
Now, here's the easy part. Let's say the player is out of ammo in his revolver and finds the M1911 on a table. The player takes it. Here's how we could replace all the code in the $gun object quickly and easily:
<<set $gun = $colt45>>
You might say every time the player fires a shot, a bullet is used. You could do that like this:
<<set $gun.ammo = $gun.ammo - 1>>
or
<<set $gun.ammo -= 1>>
Those do the exact same thing, the second way is just more concise. <<if $gun.ammo gt 0>>
<<set $gun.ammo -= 1>>
Bang! You fire a shot!
<<else>>
You pull the trigger, but hear only a click. You're out of rounds!
<<endif>>
Attached is an example of the material above.
Comments
I'm working up to doing one on lists and how and why to use them next. It should be about as helpful as this one, I think. A lot of Twine users don't realize how important and helpful lists are. Actuallly, the loops guide I wrote isn't real impressive without knowing how to use lists.
After that, I'll combine the three guides I've writtenloops, objects, and listsinto one and write one more guide; it will be the Big One. It will be about putting objects into lists and sorting/interacting with them, especially with loops (so you can see why I had to write the other three guides first). At that point, your Twine game will look a bit like a "real" computer program.
These tutorials will accelerate the learning process, good work!
I've run into a snag though. I'm trying to set it up so clicking the link "Fire gun" automatically removes one bullet from chosen weapon AND calculates remaining health of the one being hit. The bullet-removal works beautifully, but I cannot figure out the formula to make the setter link do the damage.
I assumed it would simply be something like but apparently not. It refuses to update the healthdisplay.
Here are the two passages that I am building the test in:
First, I've made an inventory passage containing all my stuff, like so: and then there's the actual passage shown on screen for the player. The top paragraph is all just debug stuff, where I slowly figure out the correct formulas for stuff and check if it works. The thing I can't get to work right now is the link where I shoot myself (yeah, I know :P Just for testing). TLDR; my question is simply what the correct formula for this would be when it goes in a setter-link, and whether I can use a setter link to set more than one variable at the same time - remove a bullet AND inflict damage.
The first is that you are reseting the player object each time. You click the link, the hgits get taken off the player object, and you go to the start page. First thing that happens there is that the inventory passage is called in, and player object reset to 100 hits.
The easy way around that is to break start into two passages. The first passage calls in ventory, then you go to a play page, and you keep looping around that page.
The second problem is it screws up if you do not pick armour and weapon before shooting. You need some default values.
I did wonder if a better way to set up the objects is in a script:
// weapons<br />$sw38 = {name:"S&W .38", maxAmmo:6, ammo:6, damage:10,};<br />$colt45 = {name:"Colt .45", maxAmmo:8, ammo:8, damage:22,};<br /><br />// armor<br />$kevlar = {name:"Kevlar Vest", rating:7,};<br />$trenchcoat = {name:"Trenchcoat", rating:3,};<br /><br />// player<br />$player = {name:"Player", maxHealth: 100, health: 100,};
For some reason that does not work. I would be curious why not (I would guess it has to do with scope).
Without testing (or reading any other replies as I'm in a hurry), that doesn't look like it will work the way you want it to work. You don't want damage to increase as the armor value gets higher, I doubt.
Try this: Though that's not how I would handle the whole thing at all.
Also, you're going back to Start. Are you certain you're not re-initializing your objects? Your setter-link probably changes the values, then you go back to Start and set them to the default value again.
@Pixie (and Sharpe): So I'm resetting everything by going to the start page? That might just be it...though the "current ammo in gun" thing updates perfectly, so I assumed health would as well. But you're probably right - I shall attempt to split the start page up and only visit it once when beginning the game. Thanks!
@Sharpe: That looks more correct indeed. My original math is baaad, shall try your formula instead.
If you got a better way to handle something like this though, I'd be more than interested in hearing it. I'm making all of this up as I go, so smarter approaches are always welcome. Just...you know...keep it on a level I can follow.
Actually they do exactly the same thing!
Here is what I would do. Have a start page that calls inventory to set stuff up, and have a second page, say called "Play", where you pick up guns, shoot, etc.
The inventory page could look like this (with everything inside one <<set>> macro):
<<set //initialise everything<br /><br />//weapons<br />$sw38 = {name:"S&W .38", maxAmmo:6, ammo:6, damage:10,};<br />$colt45 = {name:"Colt .45", maxAmmo:8, ammo:8, damage:22,};<br /><br /><br />//armour<br />$kevlar = {name:"Kevlar Vest", rating:7,};<br />$trenchcoat = {name:"Trenchcoat", rating:3,};<br />$none = {name:"No armour", rating:0,};<br />$armor = $none<br /><br />//player<br />$player = {name:"Player", maxHealth: 100, health: 100,}<br />>>
However, the important changes are to have a "no armour" armour, and to set $armor to that, so you know $armor.rating always has a value.
Then I would put this inside a script passage:
window.shootmyself = function(p, g, a) {<br /> d = g.damage - a.rating;<br /> if (d < 1) d = 1;<br /> p.health -= d;<br /> g.ammo--;<br />};
What this does is define a function called "shootmyself", that will take three parameters; player, gun and armour. It works out the damage, to a minimum of 1 (you might prefer 0), and takes that off the player health, and also reduces the ammo by one.
just to explain that last but one line, I have not seen anyone mention this, but a quick way to increase a value by 1 is like this:
value++;
And to reduce it by 1 like this:
value--;
The link in your game passage then looks like this:
[[Shoot|Play][shootmyself($player, $gun, $armor)]]
Set by reference turns $gun into a pointer to the $colt45 structure - and any changes made to $gun would be permanently made to $colt45 - so if later on I did $gun = $pistol, then $gun = $colt45 because they'd picked up another, supposedly fully loaded colt, my new colt .45 would only have as many bullets left as the original (because after doing $gun = $golt45, $gun.bullets -= 1 is the same as $colt45.bullets -= 1).
To get around this we need some sort of clone function - but I don't know enough about twine and javascript to work out which of the many alternatives (http://stackoverflow.com/questions/728360/most-elegant-way-to-clone-a-javascript-object) would be the best - or how to import such a function into twine.
For something like $gun you could set up a specific copy macro: In the wield passage: ...then remember only to work with the $player.gun values (although you could <<set $gun to $player.gun>> to get a shortcut to them.
Although the wiki references a parameter function, which might be able to make something like <<wield $colt45>> work - all the examples of adding macros seem to imply that your need to use javascript - are they pre 1.4.1 or is the parameter function there to support javascript macros?
Not trying to be mean, but you still have not downloaded and reviewed my (super crappy) Twine 23 challenge game as I twice advised you to do. So, I'm going to have to stop answering your questions now.
While I would advise against recommending total beginners to write JS scripts for Twine (especially in place of things that are easily handled by Twine code), that's a really good example of a simple JS function for use in Twine. Much better example than the one I wrote that sorts objects by properties. Awesome!
I need to do a beginner's guide to JS for Twine one of these days.
I personally would not do that. Just me, but for a number of reasons, I would keep the equipment (and just about all other) objects separate from the $player object. I feel you and I've done it that way before, but I'm no longer of that same opinion.
Also, to address the other issue you mentioned, sometimes I'll just do: Then, if I want to go back to the previous $foo, I just do: I should add that to the example program. Of course, I don't do that for inventories where you'll want to swap between several items, but that works for a number of other things.
For inventories, I use lists/arrays, and that's getting into another area best left for another thread. I'd like to keep this as close to using objects as we can manage.
Is that not what you want to happen though? If the player drops the colt, and then picks it up again, it should have the same number of bullets in it. Now, if you are writing a game where rooms are generated at random (rogue-like style), then yes, you might want to clone objects to go in each room, but otherwise, I would not.
There's also no need to go looking for a clone function, as the headers already include one, clone() (e.g. <<set $gun = clone($colt45)>>).
Honestly though, if you're going to get into creating new instances of items a lot, I'd make a simple constructor for the item, rather than cloning new instances of base objects all the time.
@Pixie: Hooray! You're describing pretty much exactly what I did after yesterday's last round of answers, and that works brilliantly. And adding a $noArmor and a $noGun solved alot of problems indeed.
@Mykael:
Hmmmmm...so far my guns seem to be fully loaded every time I switch to a new one, so I don't think the problem you're talking about has happened to me yet. Though, as Pixie points out, I'd actually like the guns to "remember" the number of bullets in it regardless of weapon-swapping - I've just ignored that particular problem till I got the guns to work in the first place.
I shall definitely refer to this when and if it occurs though - never hurts to be prepared. Thanks!
Okay, that's fine. No need to play it or review it (it's terrible). It's just an RPG combat system.
[I'm not strictly a newbie...
I remember back to when http://gimcrackd.com/etc/src/ didn't redirect to twinery.org and Twee and Twine were experimental tools for story generation. I don't think that macros and full Javascript features were really pushed back then - it all seemed like it was only designed for interactive branching stories and not a lot else.
At some point I went off chasing the new-fangled Inform7 because it was so full of features it just had to be great, good and the best.
Now I'm back here instead :-X
As a seasoned programmer, I like what I see under the skin of Twine - I still use 'classic' Tiddlywiki all the time because it's still such a great concept.]
Really looking forward to regenerating an existing wiki-based game in a totally new way with Twine!
Once again, thanks for all the useful info! Didn't intend to hijack the thread!
One of the most useful thing with this is having them as args[] in SugarCube widgets.
Here's an example :
Start:
<<set $player = {
str: 5,
dex: 5,
health: 3,
}>>
<<set $enemy = {
str: 5,
dex: 5,
health: 3,
}>>
So you get a character and an enemy with 3 stats. Let`s say that the rule to loose health in a combat is to have a dexterity inferior to opponents str.
Combat :
<<widget "loosingHealth">>
<<if $args[0].dex < args$[1].str>>
<<set $args[0].health -=1>>
<<endif>>
<<if $args[1].dex < args$[0].str>>
<<set $args[1].health -=1>>
<</widget>>
Now you can call your widget without sending every variables, you can send the object and everything will follow.
<<loosingHealth $player $enemy>>
Now, you can create an unlimited number of characters and send them in that widget.
Can you explain Constructors?
A book I liked about java-script related design patterns is Learning JavaScript Design Patterns
As to explaining constructors. So far you've probably seen things like this: (using the colt45 example from before) In most cases, there's absolutely no reason to have instances of these objects lying around. It's often better to simply have some sort of construction function that returns new instances of the object (an actual constructor or a factory, whatever).
A very basic constructor example: You could easily make that more generic as well. For instance, you could have a Gun constructor which would take some number of arguments that determined what type of gun object it would yield.
I suggested that book if they are interested in learning about patterns only because a) it targets java-script and b) its on-line.
If you know of a better one for beginners then please link it so I can add it to my list.
The ones I normally use (GoF and a Java related one) either a) are C / Java based, or b) cost money.
Have you found an answer or figured out your double-pane question in the other thread?
For example, I'm making Snowpiercer parody game where you have to move up a train a fight people in train cars. Each train car has a "power" that represents your chance of beating it. That's $thiscar.power. However, when I try to access it in a script using I get "undefined" back. Is there a different way I'm supposed to be doing this?
I'll have to rummage through this forum to pick up all the tips I can once I'm integrating everything together.