Friday, September 29, 2017

Monday, September 25, 2017

Looking at the 5th Edition SRD - part 2 - Racial Abilities


    Last post I looked at the 5th Edition SRD races in general, this time I want to focus on the abilities themselves.  Just what kind of power level should a racial ability be at?  And what kinds of things should racial abilities do?  There isn't a document anywhere from the developers that will tell us that (at least not that I've found) so let's look at what they wrote and see if we can figure something out.
    I'm going to keep using the 5 action types from before: Exploring, Investigating, Manipulating, Talking, Fighting.
   
  Exploring
Darkvision - Within 60 feet treat dim light as bright or darkness as dim, cannot see color in darkness.
Keen Senses - you are proficient in Perception (Wis).
Halfling Nimbleness - you can move through the space of any creature a size larger than you.
Naturally Stealthy - you can attempt to hide even when you are only obscured by a creature that is at least one size larger than you.

  Investigating
Stonecunning - for all History (Int) checks related to stonework you are automatically proficient and double your proficiency bonus.
Artificer's Lore - for History (Int) checks related to magic items, alchemy or technology double your proficiency bonus.

  Manipulating
Tool Proficiency - gain proficiency with choice of: smith's tools, brewer's supplies or mason's tools.
Fey Ancestory - you have Advantage on saving throws against Charm, and magic can't put you to sleep.
Trance - you don't need to sleep, instead meditating 4 hours (remaining semi-conscious) and gaining all the benifits of sleep.
Cantrip - you know 1 cantrip from the wizard spell list, Int is the controlling attribute.
Lucky - when you roll a natural 1 for an attack roll, ability check or saving throw you can re-roll.
Gnome Cunning - you have Advantage on all Int, Wis and Cha saving throws against magic.
Tinker - gain proficiency with tinker's tools; can spend 1 hour and 10 GP to construct a Tiny clockwork device; device ceases to function after 24 hrs, unless you spend 1 hr to repair it, you can also dismantle it to reclaim the materials.  Max of 3 items at any one time, and three examples are given (toy, fire-starter and music box).
Skill Versatility - gain proficiency in two skills of choice.
Infernal Legacy - you know the Thaumaturgy cantrip; at 3rd level you can cast Hellish Rebuke (at 2nd level) once between long rests; at 5th level you can cast Darkness; Cha is controlling attribute.

  Talking
Extra Language - you can read and write one extra language.
Brave - you have advantage on saving throws against being frightened.
Menacing - gain proficiency in the Intimidation skill.

  Fighting
Dwarven Resiliance - you have Advantage on saving throws against poison and resistance to poison damage.
Dwarven Combat Training - you are proficient with: battleaxe, handaxe, light hammer, warhammer.
Dwarven Toughness - +1 hit point per level.
Elf Weapon Training - you are proficient with: shortsword, longsword, shorbow, longbow.
Breath Weapon - is either a 30' line of 15' cone; does elemental damage; enemies save at 8 +Con +Proficiency Bonus; 2d6 damage (half on successful save) increasing at 6th, 11th and 16th levels; after used cannot use again until a short or long rest.
Damage Resistance - gain resistance to one elemental type.
Relentless Endurance - whenever you drop to 0 hp but are not killed, can instead drop to 1 hp; cannot use again until after a long rest.
Savage Attacks - when you roll a melee critical you can add one extra weapon's damage die.
Hellish Resistance - you have resistance to fire damage.


    Okay, having listed all the racial abilities (just 27 of them, not a bad sized pool but not great accounting for repeats) I've got a few observations.  Let's look at the general abilities...

  • Skill Proficiency - Keen Senses and Menacing both give you proficiency with one skill.  But Skill Versatility gives you 2 skills (so, would it essentially be 2 "uses" or "abilities" from a balance standpoint?)
  • Double Proficiency Bonus - Stonecunning and Artificer's Lore both double your proficiency bonus with one aspect of a single skill; and grant you proficiency (Artificer's Lore doesn't specify this, but it seems logical to include it).
  • Tool Proficiency - the Dwarven Tool Proficiency and Tinker both give a tool proficiency.  Though Tinker then gives you special things you can make with that proficiency.  Is that an ability or just defining a specific tool's effect in the race section and not with the other equipment?  I'm thinking it's defining the tools in the wrong place (though that does mean that only Gnomes know how to use them, which seems a little odd, logically speaking).
  • Weapon Proficiency - Dwarven Combat Training and Elf Weapon Training both give you proficiency with 4 weapons. (a useless ability if you become a Fighter, since there are no "exotic weapons" like in earlier D&D games.  Still, this adds quite a bonus to non-fighting classes, since there is no "attack bonus progression" for different classes, everybody just either adds Proficiency or doesn't (so an Elf Wizard at the same level as a Fighter is just as skilled with a longbow, except for their Dex mods).
  • Language Proficiency - Extra Language gives you a bonus language, and really you need some kind of secret or ancient languages gives that everybody speaks Common (I don't know, language just seems like a weird part of the game, like it doesn't really matter at all, yet it's mentioned all over the place - maybe it's just me).
  • Saving Throw Advantage - Brave gives you advantage on saves vs fear.  But then Dwarven Resiliance gives you adv to save vs poison and also resistance to poison; and Gnome Cunning gives you adv to Int/Wis/Cha saves vs magic only.  Exactly what scale is appropriate?  Is Dwarven Resistance again the equivalent of 2 abilities (1 for the save adv and 1 for the damage resist)?  Gnome Cunning only applies to non-physical magic effects - is that the equivalent of 1, or 2 or 3 abilities?  Exactly how broadly applicable should a save advantage be?  I really wish the designers had dropped at least a few hints on this one.  Oh yeah, I forgot about Fey Ancestry, which gives a bonus to only one type of magic, charms (the 'cannot be magically put to sleep' seems like  it should really be part of another ability, Trance).
  • Damage Resistance - the Dragonborn's Damage Resistance and Hellish Resistance both let you resist one type of elemental damage.
  • Bonus Spell - Cantrip gives you a spell (cantrips don't use a spell slot or have to be prepared); but then Infernal Legacy gives you a cantrip and two real spells at higher levels -- again, from a balancing standpoint, was that one ability meant to be the equivalent of 2 or 3 abilities then?  Is it really useful enough to count as 2 or 3 abilities? (which is why I ask, if one ability is meant to be the equivalent power of several, then it has to be useful enough to justify that)
  • Environmental Alteration - There are 3 types of light: bright, dim and darkness.  The Darkvision ability improves the ambient light by one level (darkness becomes dim, dim become bright).  This could be extrapolated for other environmental effects.  Say that there is Comfortable, Hot (take some skill/roll penalty) and Blazing (take damage/minute) to define temperatures, a theoretical Heat Tolerance ability, patterned off Darkvision, could treat Blazing environments as Hot, and Hot environments as Comfortable.
  • Bonus Hit Points - Dwarven Toughness gives you +1hp/lvl.  That's a clear benchmark :)
  • Alter Rules - Halfling Nimbleness and Naturally Stealthy both alter the normal rules somehow.  Nimbleness let's you move through occupied spaces, normally forbidden, and Stealthy increases the circumstances when you can attempt a stealth check.  It would really be nice to have some more of an idea what kinds of rules tweaks would be considered appropriate for a racial ability.  And I wonder if Nimbleness shouldn't be part of the Small size? (heck even Stealthy - both seem like they come from you being small and hard to stop or see/keep track of ?)
  • Alter Rolls - Lucky, Relentless Endurance and Savage Attacks all change how you roll dice.  Lucky doesn't have any limits on it, it says you can re-roll every 1 - which again makes me wonder if it was meant to be "worth" 2 or more abilities (since that's pretty handy, granted only a 5% chance on a d20, but a 1 is an auto-fail).  Endurance let's you keep going (and fighting, risky as that would be) but only once between long rests (8hr sleep or very light activity), pretty handy too.  And Savage adds one more die of damage on a critical, which is again about a 5% chance (and basically triples damage instead of doubling it).
  • Bonus Weapon - Breath Weapon actually gives a bonus innate weapon.  It does have the bonuses of being able to hit multiple targets, does decent damage (2-12 or 1-6 on save, compared to a 1-8 sword) and does elemental damage.  It's drawbacks are that it takes a save, and is only usable between rests (and even a "short" rest is 1 hour, a not-inconsiderable length).  That's actually not a terrible template for considering what kinds of special attacks might be appropriate.
  • General Change - Trance let's you sleep in half the time, which is not bad, but you have to wonder just what all it's meant to do?  If the rest of the party is still sleeping, then can you use the time to craft?  Read?  What sort of bonus is this supposed to be?  It takes some creative thinking to make this really useful.  Also, even though it isn't listed as an ability, Dwarves can move at their speed even in heavy armor, which is another bonus.

    Looking at the action groups, the majority of abilities are for Manipulating or Fighting (at 9 each), followed by Exploring (4), Talking (3) and Investigating (2).
    In all, there are enough fairly clear kinds of bonuses to make it feel like you can define what sort of power a racial ability should have.  And then there are enough edge-cases and exceptions that make you wonder.  Overall it's not too bad.  I would like to have a more even spread of options, again there seems to be a lot of fighting or working with stuff, but not as much for the other action types.  Of course, that raises the (very important) question of "how many abilities should a race have?"  Which is hard to choose.  The thing is, if a race only has Fighting abilities, then it's predisposed to only fight.  Which sounds great, if a player wants to make a strong fighter then that type of race reinforces that play-style.  But, it reduces the available story options, since that character is useless for anything else, thus every adventure has to focus on fighting (yeah, yeah, there's the whole party and spotlight-sharing that complicates that, but still, you get my point).  Now, I'll tip my hat to the designers that these races are pretty well-balanced overall to avoid that.  Even the stereotypically-fighter-focued Half-Orc has a Talking ability (with the auto-proficiency in Intimidation).  Oddly, the Dragonborn is the only race (at a glance) that is purely one play-style (as their only 2 abilities are both Fighting, and they have the fewest number of abilities of all the races - which means Dragonborn really need to get overhauled).
    Taking a detailed look at these races has given me a feel for some things I like (and a few I dislike), but the game is made up of a lot of components, so let's move on.  I was going to follow the PDF, but I'm changing my mind - next I want to look at Backgrounds.
   

Friday, September 22, 2017

Open2 Engine: Bookworm - part 1 - Project Outline

    The Open2 Engine is going to be several "programs" that together can create and play Interactive narratives and Role-Playing Games.  The first one I'm going to start working on is "Bookworm."
    Bookworm is simple enough, it is designed to display and create documents.  That doesn't sound very exciting, because it isn't.  It is, however, the foundation for a lot of more advanced programs/ options.  To open a document you need to be able to open a file from the user's computer, to edit or create it you need to be able to organize all that data and write it to the user's computer.  To read it you need to show and hide text.  All of which also needs to be done in a program like, say, Twine - where you load and save the stories you're working on, and then show and hide the document as the reader plays the story.  So while Bookworm is not going to earn me any "cred" as a game developer, it's going to have a lot of code that I'm going to be using for the more interesting programs I work on down the road.
    There are 5 main things Bookworm needs to be able to do:
  • Load
  • Display
  • Annotate
  • Edit/Create
  • Save

Load
    The first thing a book reader needs to do is load a book to read, right?  So how do we load a file from the user's computer?  Well, i actually fond a really cool blog called "This Could Be Better" (I love his blog's name too) that has a post here with some working code to load and save text files.  The system I'm planning has 3 steps:
    First, save the document as HTML, using <div>s and IDs around the content, but not as a full webpage (so no <head> or <body> tags).
    Second, load the file using the code from the site above (which uses the HTML <input type="file"> element, and then creates a hidden link to that file).
    Third, append the contents of that file into a <div> or other holder element.
    I've actually got some code that mostly works for this, just a few bugs to iron out and it'll be ready to rock - super huge thanks to the blogger above (didn't see his/her name anywhere on the site) for giving me most of the code I needed.

Display
    Once we've loaded the document, we need to display it.  This is really, really easy.  I'm going to use the code I posted before to show and hide text.  The only trick is getting the click handlers to see the added text (usually the function that adds the handlers runs when the document loads, so it doesn't "see" the file after it's loaded).  I think I can fix that.
    I'd also like to have a Table of Contents, Index, and let the user create bookmarks of their own, all of which is going to complicate things - but should be fairly do-able.

Annotate
    Besides just showing the document, I want the reader to be able to make notes.  I'm thinking of 2 levels of notes, for the whole document (that would always be visible) and for each specific passage (that would only show up when that passage was displayed, naturally).  This is slightly tricky, but not too hard, the simple way is to add some <textarea>s to hold the plain text notes.  Ideally I'd like "rich text" notes that could be in different colors and fonts, and even to apply a "highlighter-effect" to color the document text.  For a rich text editor I'm going to have to find somebody else's code (that's a concept over my head right now) so I think that'll be a feature for down the road.  I'm not sure how to do the highlighter, I don't want to change the original document.  That one is a very far down the road possibility.

Edit/Create
    Besides reading existing files, I also want to be able to create new ones, using the right format so they'll display correctly (since I'm using the "data-goto" attribute for links, which lines up to the "id" attribute of the text to show - so those two attributes need to line up, which can be tricky when you have 400 of them - in something like an Interactive Narrative story).  I have some ideas for HTML forms in a jQuery-ui Accordion wrapper that I think will work, but there's a lot to track and figure out for this one.

Save
    Lastly, you need to save all this information.  That means I need a separate file (I want to keep the original un-touched) with all the notes and stuff, or to create a whole new file.  That's actually kind of tricky.  The documents are going to be plain HTML, but the notes and such will likely need to be saved in another format.  Right now I'm looking at JavaScript Object Notation (or JSON) which is really easy for JavaScript to natively read/write.

    It doesn't seem like much, but it's going to be enough to keep me busy for a while.  I did a quick mock-up that is surprisingly workable, and depressingly buggy :)  Still, it looks like something I can do, and it's all code that I'm sure will be re-used in other projects down the line.
    So that's the overview, next week I'll start posting my code and you can see what it looks like.  Until then!



Wednesday, September 20, 2017

Monday, September 18, 2017

Looking at the 5th Edition SRD - part 1 - Races

    With all these OGL games to draw from, let's take a look at one of them.  The 5th Edition SRD, based on the latest version of Dungeons and Dragons, is a fairly simple set of rules - so let's peek at how it's constructed.  I'm going to go along with the PDF, which does not have the greatest layout.

Races
    So let's look at the provided races:

Dwarf 
+2 Con
Medium, 25' speed (not reduced by heavy armor)
Exploring- Darkvision
Investigating- Stonecunning
Manipulation- Tool Proficiency
Talking-
Fighting- Dwarven Resilience, Dwarven Combat Training

    Hill Dwarf (sub-race)
    +1 Wis
    Fighting- Dwarven Toughness


Elf
+2 Dex
Medium, 30' speed
Exploring- Darkvision, Keen Senses
Investigating-
Manipulation- Trance
Talking- Fey Ancestry
Fighting-

    High Elf (sub-race)
    +1 Int   
    Manipulating- Cantrip
    Talking- Extra Language
    Fighting- Elf Weapon Training


 Halfling
 +2 Dex
Small, 25' speed
Exploring- Halfling Nimbleness
Investigating-
Manipulation- Lucky
Talking- Brave
Fighting-

    Lightfoot (sub-race)
    +1 Cha
    Exploring- Naturally Stealthy


 Human
 +1 to all Attributes
Medium, 30' speed
Exploring-
Investigating-
Manipulation-
Talking-
Fighting-


 Dragonborn
 +2 Str, +1 Cha
 Medium, 30' speed
Exploring-
Investigating-
Manipulation-
Talking-
Fighting- Breath Weapon, Damage Resistance


 Gnome
 +2 Int
 Small, 25' speed
Exploring- Darkvision
Investigating-
Manipulation- Gnome Cunning
Talking-
Fighting-

    Rock Gnome (sub-race)
    +1 Con
    Investigating- Artificer's Lore
    Manipulating- Tinkering


 Half-Elf
 +2 Cha; +1 to two other scores of choice
 Medium, 30' speed
Exploring- Darkvision
Investigating-
Manipulation- Skill Versatility
Talking- Fey Ancestery
Fighting-


 Half-Orc
 +2 Str, +1 Con
 Medium, 30' speed
Exploring- Darkvision
Investigating-
Manipulation-
Talking- Menacing
Fighting- Relentless Endurance, Savage Attacks


 Tiefling
 +2 Cha, +1 Int
 Medium, 30' speed
Exploring- Darkvision
Investigating-
Manipulation- Infernal Legacy
Talking-
Fighting- Hellish Resistance


 Some other random notes:
  • Everyone is literate (usually speaking multiple languages), which does feel kind of odd for a quasi-medieval setting.
  • I hate how they count movement by the foot- it's so unreal that you might as well just admit it's for a battle-map and say 5 or 6 squares.
  • There is no background or setting information whatsoever in the PDF, which was meant to encourage people to create their own setting, but still makes it weird to read.
  • Is there any way at all that Age really matters?
  • Alignment is pretty useless, in general and in this specific edition - and applying it to a whole race is questionable (granted, it gives a "stereotype" to play off of, but I question the real usefulness of that).

    So, looking over everything we have a few conventions, and a few things strike me:

+3 to attributes - with 2 from the race and 1 from the sub-race (or all from race if it doesn't have any subs); except for Half-Elves who get an extra attribute point, and Humans who get 3 extra points.  This is weird, since humans get a +1 to every attribute, that means Dwarves are only 1 point tougher, Elves 1 point faster, and so on.  That just seems off somehow.  Not that it's a huge mechanical issue, while Humans get twice as many attribute points they have no other abilities at all compared to the other races (which, honestly, also feels kind of weird).

Darkvision is fairly common - 6 races have Darkvision while 3 don't.  I'm not really fond of this.  The trade-off of carrying a torch in a cave (let's you see but makes you easier to be seen) is a tactical problem (or really just a headache, until you can magick darkvision for everybody), but making Darkvision so common almost seems like it's punishing those without it.  It seems like Elves, Half-Elves and Half-Orcs (maybe) should have the older editions' "Low-Light Vision" instead of full-blown Darkvision.

Why not make Half-Elves and Half-Orcs sub-races of Humans? - yeah, the mechanics is a bit weird, you have to over-write the Human's default abilities, but it would just make more sense if these were somehow sub-races (and it would be great if you could keep the same pattern for all the races - I don't know, I just hate when a game establishes a pattern and then starts throwing around exceptions - it's an issue of mine ;).

Number of abilities:
Dwarf- 7 (I'm counting the speed thing as an ability),
Elf- 7,
Halfling- 4,
Human- 1 (the extra attribute points are an ability),
Dragonborn- 2,
Gnome- 4,
Half-Elf- 4 (the extra attribute is an ability),
Half-Orc- 4,
Tiefling- 3
    Comparing abilities in absolute terms is tricky, just because Dwarves have 7 abilities to Humans' 1 doesn't take into account how generally useful those abilities will be.  Still, by the quantity (regardless of quality) it seems like Dwarves and Elves are a little high and Humans and the Dragonborn a bit on the low side.

Ability Spread:
    Okay, I've been using a system first created by a friend of mine, The Homeless Nerd (rest in peace buddy), that divides all actions into 5 general categories: Exploring is everything dealing with the environment (movement/navigation, perception/stealth, bypassing locks and traps); Investigating covers the ability to gain extra information or deal with missing information; Manipulating covers interacting with objects (and people as objects, like healing); Talking deals with interpersonal issues (not being seen is Exploring, wearing a disguise is Talking); and Fighting covers hurting other people (demolitions or sabotage is Manipulating).  While this is a bit simplistic, it actually covers a pretty good amount of options and groups some things logically together.
    So, looked at from the perspective I just outlined, how many of the 5 categories get covered by each race?
Dwarf- 4,
Elf- 4,
Halfling- 3,
Human- 5 (since attributes are tied to skills, in essence all skills/action types are also raised),
Dragonborn- 1,
Gnome- 3,
Half-Elf- 3,
Half-Orc- 3,
Tiefling-3
    In all there's a nice spread, except for the Dragonborn (which, combined with their lower number of absolute abilities makes me think they're a little under-powered; their breath weapon is not that damaging and is only usable once between rests, the resistance is the only really all-around good ability; and I'm surprised they didn't get darkvision too (not that I think that would be a good thing :))


     Overall, I think it's a pretty solid system.  I like the conventions, and dislike the races that don't conform to them.  I am reminded of something by The Angry GM about separating Race and Culture - which I think would be a fantastic addition to this system (modified for the different game rules of course).  I do want to tweak the Humans and Dragonborn: though I'm not entirely sure how at the moment.  I'm also weighing the specifics of the different abilities, so while I like these rules overall I'm sure that I'm going to change them to at least some degree.
     Which is one of the things I've been turning over in my mind.  At first I was just going to copy-and-paste the SRD and start implementing in via JavaScript, but on reflection I don't think I want to go that route.  I'm going to actually make a setting and tweak the rules to my own desires.  While this makes my end product a little less useful to other people who want to use the RAW (Rules As Written), well, that's too bad (and it shouldn't be impossible to fork the code to make a more standards-compliant version, I think).



Longwelwind's Adventures - a cool new story format for Twine

    I first came across this via Twitter, and it's so cool I have to pass it on here.  This is a very cool story format for Twine, it has a great old-school CRPG vibe.  I am totally jealous of the author :)



    Find it here: https://longwelwind.github.io/adventures/



Friday, September 15, 2017

The Open2 Engine - part 7 - Dream The Impossible Dream

    Okay, so the last week has laid a lot of groundwork for my Open2 Engine project.  Time to look way, way down the road at where I want to go with all of this.
    I've always liked to take the long view, and so what exactly do I want the "Open2 Engine" to be when it's all said and done?  Well, that's actually a pretty crazy thing, because I want it to be something that - at the moment - I can't do/ create.  I actually see the Open2 System as comprising several parts...
  1. Rulebooks - these are all the OGL resources, and the games of my own that I make from them.
  2. Worlds - while having a generic game gives you some flexibility to adapt it to your own world, having a specific world also really helps to make the game come to life.  I want to create a few settings/ game worlds and also provide them free/openly (under a Creative Commons license I'm thinking).
  3. Modules - I also want to make some adventures and campaigns; in an ideal world that were system-neutral, you could take the story itself and add whatever specific Rulebook you wanted to it (that is hard though because mechanics do drive story to some degree).
  4. Engines - this is the biggest part, the "Engines" are how the reader/ user interacts with all this stuff, and there are several I want to make...
    • Bookworm is a simple reading app, basically the ability to show and hide text I did in yesterday's post.
    • PChelper is a reader that also has code to create and play characters.
    • GMhelper is a reader that also helps GMs create and run adventures.
    • Listener is a parser-based Interactive Narrative editor and player.
    • Weaver is a hypertext-based IN editor and player; basically Twine.
    • VizTalk is a visual novel-based IN editor and player.
    • HCDcrawler is a game interface for an RPG inspired by the SSI "Gold Box" AD&D games like Pool of Radiance and Curse of the Azure Bonds.
   Is that an overly-ambitious goal?  Yeah, it sure is.  I don't care though.  I'll figure it out one piece at a time.  It's also going to be very tricky to structure, I want this to be very flexible, something that you can mix and match - which means I'm going to have to carefully structure my code and data in a way that will allow that to happen.
    So, from here I'm going to shift from looking at the project in general to examining each specific component and how it will relate to the others.  Also, I've been posting every day for about a week now, which has left me a little tired :)  So on Monday I'm going to take a look at the 5e SRD - how the game is structured, how that structure compares to other OGL games, and an "under the hood" "deep dive" into building off that structure to create a game of my own.
    Until then, I hope you have a good weekend!


Thursday, September 14, 2017

The Open2 Engine - part 6 - Twine-like Text



    Now I'm going to pull together some of the things I've been talking about in my whirlwind series. And, if I can get it to work, I'm going to do so in this very post.

    So my first sample project is going to show and hide text like Twine does. There's a thing called Lorem ipsum, it's placeholder text, and I found some cool alternate ones on-line that I'm going to use to fill in my example passages below.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis tincidunt dapibus posuere. Nam dapibus, ante eget fermentum accumsan, ex orci facilisis purus, dignissim pretium nisi quam at erat. In faucibus purus sit amet sodales lobortis. Ut ullamcorper mollis dolor, non dictum justo venenatis ac. Nulla eu rhoncus neque, vel finibus urna. Integer vitae est tortor. Vivamus pellentesque vel diam volutpat mattis. Quisque aliquet turpis vel lectus blandit, ut elementum risus laoreet. Aliquam erat volutpat. Nulla facilisi. Praesent gravida tellus in ligula hendrerit feugiat. Fusce sodales porta nisi, eget vulputate enim. Aenean at rutrum tellus. Phasellus tincidunt lacus a augue suscipit, et pharetra eros suscipit. Integer nulla enim, porttitor in luctus sed, vestibulum quis lorem.
Next Passage
You're all clear, kid. Let's blow this thing and go home!Ye-ha! I can't get involved! I've got work to do! It's not that I like the Empire, I hate it, but there's nothing I can do about it right now. It's such a long way from here. The Force is strong with this one. I have you now.Don't be too proud of this technological terror you've constructed. The ability to destroy a planet is insignificant next to the power of the Force. Hey, Luke! May the Force be with you. Look, I can take you as far as Anchorhead. You can get a transport there to Mos Eisley or wherever you're going. I want to come with you to Alderaan. There's nothing for me here now. I want to learn the ways of the Force and be a Jedi, like my father before me.Leave that to me. Send a distress signal, and inform the Senate that all on board were killed. Escape is not his plan. I must face him, alone. I care. So, what do you think of her, Han? I care. So, what do you think of her, Han? Dantooine. They're on Dantooine. I find your lack of faith disturbing.
Next Passage
Knights of Ni, we are but simple travelers who seek the enchanter who lives beyond these woods. I don't want to talk to you no more, you empty-headed animal food trough water! I fart in your general direction! Your mother was a hamster and your father smelt of elderberries! Now leave before I am forced to taunt you a second time! Shut up! Will you shut up?! Oh, ow! Well, how'd you become king, then? Camelot! Shut up! But you are dressed as one… Burn her anyway! I dunno. Must be a king. And the hat. She's a witch! A newt? Found them? In Mercia?! The coconut's tropical! You don't vote for kings. I have to push the pram a lot.
Next Passage
Smooth as an android's bottom, eh, Data? Mr. Crusher, ready a collision course with the Borg ship. You did exactly what you had to do. You considered all your options, you tried every alternative and then you made the hard choice. Our neural pathways have become accustomed to your sensory input patterns. You're going to be an interesting companion, Mr. Data. They were just sucked into space. A lot of things can change in twelve years, Admiral. That might've been one of the shortest assignments in the history of Starfleet. Wait a minute - you've been declared dead. You can't give orders around here. I think you've let your personal feelings cloud your judgement. Captain, why are we out here chasing comets? Some days you get the bear, and some days the bear gets you. Is it my imagination, or have tempers become a little frayed on the ship lately? Maybe we better talk out here; the observation lounge has turned into a swamp. Well, that's certainly good to know. When has justice ever been as simple as a rule book? Talk about going nowhere fast. Fate. It protects fools, little children, and ships named "Enterprise." I'll be sure to note that in my log. Yesterday I did not know how to eat gagh. I'll alert the crew. Why don't we just give everybody a promotion and call it a night - 'Commander'? Travel time to the nearest starbase? Computer, lights up! Mr. Worf, you sound like a man who's asking his friend if he can start dating his sister.
Next Passage
Th’art nesh thee nay lad soft lad wacken thi sen up t’foot o’ our stairs. Nay lad where’s tha bin. Th’art nesh thee a pint ‘o mild any rooad t’foot o’ our stairs. Where there’s muck there’s brass t’foot o’ our stairs ah’ll gi’ thee a thick ear. Ah’ll learn thi tintintin tell thi summat for nowt soft lad mardy bum. Chuffin’ nora ah’ll box thi ears soft lad ee by gum tell thi summat for nowt ah’ll gi’ thee a thick ear. Bobbar nay lad. Breadcake soft southern pansy wacken thi sen up. Be reet where’s tha bin mardy bum mardy bum. Tell thi summat for nowt where there’s muck there’s brass shu’ thi gob. Dahn t’coil oil. That’s champion ey up will ‘e ‘eckerslike shurrup by ‘eck. Eeh. Shu’ thi gob face like a slapped arse god’s own county soft lad th’art nesh thee tha daft apeth.

The End




    Let's look at the code that makes this work...
    First, we need to set up the page.  In this case I'm using a bunch of HTML <div> tags to separate each passage.  I need to be able to pick out each one to show or hide, so I'm giving each an ID attribute.  They are all going to have some light blue text, for this example, so I'm giving them a class of "example" - and they are all going to start hidden, except for the first one, so I'm giving them another class of "passage" - which looks like this...

<div class="example" id="1"></div>
<div class="example passage" id="2"></div>
<div class="example passage" id="3"></div>

    The CSS to make the text color and hide the passages looks like this...

.example {color: LightSteelBlue;}
.passage {display: none;}

    Now I need the links, the way to change the passages.  I'm using a plain anchor link, with a target of "#" as a placeholder, and I'm adding a special attribute.  HTML 5 let's you make up your own attributes starting with "data-".  I'm going to add a "data-goto" attribute to each link, and the attribute's value is going to be the ID of the passage to show.  Adding some placeholder text and the links makes my HTML look like this:

<div class="example" id="1">
    Sample Text
    <a href="#" data-goto="2">Next Passage</a>
</div>

<div class="example passage" id="2">
    Sample Text
    <a href="#" data-goto="2">Next Passage</a> </div>

<div class="example passage" id="3">
    Sample Text
    <a href="#" data-goto="2">Next Passage</a> </div>

    Now, I need to use some JavaScript to make the links show and hide the passages.
    I'm going to use jQuery to get the anchor links.  Thing is, what if I didn't know how many links there were going to be?  And what if I wanted some regular links and some links that changed passages?  What if I wanted to use buttons or images along with anchor links?  Well, then I should set my code to look for anything that had the "data-goto" attribute, whatever element that is, and ignoring all others...

$('[data-goto]')

Okay, that will add this to just the elements I want.  Now, I need to set a "click handler" - a function to run when the user clicks on the link/whatever...

.on('click', function (event) {

Now for the function itself.  I want to do two things, hide the current passage and show the next one.  Hiding the current passage is easy, I'm going to get the parent <div> of the link (that's the <div></div> that's around the link), I'll get that in two steps.  First I need to select the link that's been clicked on.  The event handler passed along the event itself as a parameter, that set something called "this".  "This" is a context, a reference to the calling object (it's really complicated, which is why I didn't mention it before - just roll with it).  By selecting "this" I can then use the jQuery method of .parent() to get a parent of the link, in this case the <div>.  Lastly I can use another method .hide() to hide that div.  Yeah, it's complicated to describe it, but it's actually pretty simple - and it's just one line of code...

    $(this).parent('div').hide();

With the current passage hidden, I just need to show the next one.  I'm going to have to select the next passage, which I'm doing by using the same number in the "data-goto" attribute of the link and the "id" attribute of the passage.  To select an ID with jQuery you add a hash, "#", so I'm going to make a string with the hash and number.  Then, I'll make the selection with that string and use the method .show() to show the new passage...

    let sGoto = "#" + $(this).attr('data-goto');
    $(sGoto).show();

Finally, I'm using return false to stop the default behavior of the anchor link.  I didn't do this in a separate page I created, but when I copied the code onto Blogger I had the links do weird things, so this just tells Blogger to ignore my special links...

return false;
});

And there you go, you now have a way to show and hide passages just like Twine!

    I did want to add another little project, a tiny Parser game, but my code is not liking me today - so that'll be an upcoming update :)


Wednesday, September 13, 2017

The Open2 Engine - part 5 - Whirlwind JavaScript

    Okay, with HMTL we made a document, CSS made that document pretty, now with JavaScript we can make that document act and react.  So let's do another Flash-fast tour, hold on to your hats...

Variables
    Okay, let's start with variables - how we store data.  If our program is going to do something, odds are it's going to need to remember information.  A variable is just that, a place to put some data.  Creating a variable is usually with "var" like this...

var variableName = "data";

    Now, the "variableName" is an example of "Camel Case" which is the JavaScript convention of naming everything with a lower-case word, and adding capitalized words after to create a descriptive name.  You could name a variable anything beginning with '$', '_', or a letter - after which you can use the same and numbers (so can't start with a number, can use it later though).
    Variables come in different types, and the one I made above is a "string" - a series of numbers/letters/symbols, like a sentence.  Since a string is created by using quotes, if you want quotes in the string itself you've got to mix them...

var htmlElement = 'myElement attribute="value" something';

or you have to "escape" them with the backslash...

var htmlElement = "myElement attribute=\"value\" something";

Notice that I've put a semicolon at the end of each line, the semicolon is used to tell JavaScript where the end of a command is at (like how a period shows the end of a sentence).

    Instead of making a string, I could make a number, like so...

var myNumber = 10;

However, JavaScript is a "loosely typed" language, which means a variable can be just about anything.  That will occasionally make life interesting when a variable is not what you think it is.       
    Here's an example, let's add two numbers together...

var A = 1;
var B = 1;
var C = A + B;
console.log(C);
>2

Okay, the "console" is a hidden developer tool (you can access it from a browser or your programming IDE, you can't see it with just a text editor).  I'll use the ">" at the start if a line to show what the console would output (if you were running this and not reading it :).  So in our example above we get just what we expect, we set two variables, each is equal to the number 1, and we add them together to get the number 2.
    But what if we accidentally put some quotes around one of our variables?  Like this...

var A = "1";
var B = 1;
var C = A + B;
console.log(C);
>11

Huh?  Well, by putting the quotes around the first variable we turned it into a string instead of a number, and addition on a string becomes "concatenation" (or, combining the contents of two strings into one)...

var A = "this";
var B = "WORD";
var C = A + B;
console.log(C);
>thisWORD

    Because JavaScript doesn't track variables too closely, I like to do it myself (this number/string thing has bit me on the rump before) so I can remember what something is.  Camel Case is not very descriptive to me, I prefer something called "Hungarian Notation" where you prefix every variable name with the type of data that variable is supposed to hold.
    So, the way I would write a string is to start with the letter "s" (for string)...

var sFirstName = "Bob";
var sAddress = "123 Lane";

    Most numbers I've had to track were whole numbers, or integers, so they start with "i"...

var iLocationsDiscovered = 0;
var iHitPoints = 20;

    There's not really a right or wrong way, it depends on your audience.  If you're programming as a part of a team, you should use whatever naming convention the team uses (duh).  Since I'm writing this by myself (and I'm old and crotchety) I'm going to use my own style of naming (which you should know since you're going to have to read it :).

    In my projects so far, pretty much the first thing I've done is start declaring the variables I'm going to need.  But, while strings and numbers are nice, they are pretty much just one piece of information per variable, what if we wanted to store several bits of data in one place?


Arrays
    Think of a backpack.  It's a single object, but it can contain multiple items within itself.  That's basically an Array.  We define an array with brackets, and separate the items within by commas...

var aBackpack = [rock, knife, apple];

So how do we find something in the array?  By using it's "index", which is a number - starting with zero! - that points to the array's contents...

console.log(aBackpack[0]);
>rock

console.log(aBackpack[1]);
>knife

console.log(aBackpack[2]);
>apple


We can also make an empty array and then define the contents like variables...

var aBackpack = [];
var aBackpack[0] = "rock";
var aBackpack[1] = "knife";
var aBackpack[2] = "apple";

Arrays also have "methods", special commands we can call to interact with the array.  One is "push" which adds an item to the end of the array.  "Pop" will delete the last item, and "length" will say how many items are in the array...

var aBackpack = [rock, knife, apple];
console.log(aBackpack.length);
>3

aBackpack.push(potion);
console.log(aBackpack);
console.log(aBackpack.length);
>rock, knife, apple, potion
>4
 
aBackpack.pop;
console.log(aBackpack);
>rock, knife, apple


    Arrays can hold any kind of data, strings, numbers, even other arrays!  Arrays can also hold objects...


Objects
    Like an array, an Object is a way to group several variables together.  Objects are made with curly braces "{ }" and hold key: value pairs...

oPlayer= {
    Name: "Bob",
    Class: "Fighter",
    Strength: 10,
    hitPoints: 20,
    Backpack: [rock, knife, apple]
};

These are all "properties" and can be accessed with "dot notation" or the objectName.propertyName...

console.log(oPlayer.Name);
>Bob

console.log(oPlayer.Backpack[1]);
>knife

    We can also give objects "methods" or commands that they can carry out, and we can add a property or method by defining the object with it...

oPlayer.Punch = function () {
    console.log("pow!")
};

oPlayer.Punch();
>pow!

    Objects are a great way to keep information together, but let's look at how to actually act on that information with functions...


Functions
    Data just sits there, to act on it we need functions.  Declaring a new function looks like...

function functionName (parameters) { commands };

Let's make a hypothetical "Attack Turn" function, we'll have a monster attack a character (which will be a nice complex example).  Virtually every function is going to act on some variables, so let's think about the ones we need.  We're going to need a monster and a player, so we'll make them 2 objects.  Each is going to need a chance to hit, which we'll turn around and say is a % chance "to be hit" (you'll see).  Each is also going to need the damage they do, and the health they have.  That should do for a bare-minimum example.  So here are my two objects...

oPlayer = {
    ToBeHit: 40;
    Health: 20;
    Damage: 5;
};

oMonster = {
    ToBeHit: 60;
    Health: 10;
    Damage: 10;
};

I'm giving my player lower odds of being hit, but the monster does more damage (just because, it's an example :).
    Now, the first things we need to create our function is a name and the parameters.  "Parameters" are just variables we're going to pass to the function for it to work on.  In this case, I'm going to pass two parameters, the attacker and the defender.  So I've got this...

function fAttackTurn (attacker, defender) { };

Okay, now we need the code, the commands of what the function should do.  There are some functions that JavaScript has created for us, one of them is "Math.random" which we can use to get a random number.  So we're going to get the chance to hit needed, then a random number between 1 and 100, compare the two, and if the random number is lower than or equal to the chance to hit, we'll do the attacker's damage to the defender's health.  This should show us a lot of what functions can do.
    First, inside the function let's make a variable for the attack roll (our random number)...

function fAttackTurn (attacker, defender) {
    var iAttackRoll;
};

Well, that makes an "undefined" variable, one that has no value (not even zero).  Let's make it equal to the JavaScript function for our 1-100 number (which is, well, complicated)...

function fAttackTurn (attacker, defender) {
    var iAttackRoll = Math.floor(Math.random () * 100) + 1;
};

Yeah, it's a bit complicated, functions can get that way.  Anyways, that will give us a random number between 1 and 100.  So let's compare that number to the defender's odds of being hit and see if it's less than or equal to (a hit) or greater than (a miss)...

function fAttackTurn (attacker, defender) {
    var iAttackRoll = Math.floor(Math.random () * 100) + 1;
    if ( iAttackRoll <= defender.ToBeHit){

    } else {

    }
};

Well, what do we want to do?  Either way let's do the console.log of what we got, and if we do hit then we want to subtract the attacker's damage from the defender's health...

function fAttackTurn (attacker, defender) {
    var iAttackRoll = Math.floor(Math.random () * 100) + 1;
    if ( iAttackRoll <= defender.ToBeHit){
       console.log("You hit!")
       defender.Health = defender.Health - attacker.Damage
    } else {
       console.log("You missed!")
    }
};

Okay, let's stop and look at how we'd "call" this function, or run it.  We'll have the monster attack the character...

fAttackTurn (oMonster, oPlayer)

To have the player attack the monster, we reverse the parameters...

fAttackTurn (oPlayer, oMonster)

    Okay, so let's stop and look at some of that function in more detail.


Decisions and Loops
    One of the things our "Attack Turn" function had to do was make a decision - it had to decide if the attack roll was higher than the defender's defense.  To do that we used an "if" statement

if ( iAttackRoll <= defender.ToBeHit)

If has a lot of ways to compare things (and thus, it's a pretty common way to make decisions)...

if ( this > that )  - greater than
if ( this >= that )  - greater than or equal
if ( this < that )  - less than
if ( this <= that )  - less than or equal

To compare if two things are equal is a little tricky, one way is like this...

if ( this == that)

One equal sign "sets" a variable to a value, 2 equal signs "compares" two variables/values.  The catch is that 'number as a string' problem at the beginning of the post.  Let's make 2 numbers and compare them...

var A = 1
var B = 1
if ( A == B ) {
    console.log ("true!")
}
>true!

Now, let's make one of those a string instead of a number...

var A = "1"
var B = 1
if ( A == B ) {
    console.log ("true!")
}
>true!

Well, that's still true even though one variable is a string and the other is a number.  We might not want that, we might want to only compare numbers to numbers or strings to strings.  That takes three equal signs, and while the code in the "if" will run if that's true, let's add the "else" to run code if it's false...

var A = "1"
var B = 1
if ( A = = = B ) {
    console.log ("true!")
} else {
    console.log("false!")
}
>false!

I spaced out the equals signs to show there are 3 of them, called "strict equality".

    "If" is the most common way to make a decision, but sometimes we need to "loop" or go through a series of values and check each one.  Let's say we want to look in the player's backpack and see if they have a knife.  The most common loop is "for"...

for ( counter ; comparison ; operation ) {
    do something
}

So, first we create a counter, which is a variable almost always called "i", and we set a starting value...

for ( i = 0 ; comparison ; operation ) {
    do something
}

Next we compare where we are (with our counter) to where we want to be (or the end of the loop, which in this case is the length of the player's backpack)...

for ( i = 0 ; i < backpack.length ; operation ) {
    do something
}

Why not go until i <= backpack.length?  Because the loop is always going to run the first time, so we want to stop before the length or else we'd run one time too many.
    Lastly, we need to increase our counter (otherwise we won't go forward) which is usually with the "increment" operator, which takes a variable and adds 1 to it...

for ( i = 0 ; i < backpack.length ; i++ ) {
    do something
}

And then we'd add the code to see if the backpack item we were looking at was the one we wanted.  Which I'll leave as an exercise for the reader :).


Manipulating The DOM
    Okay, I need to wrap this up because I've been typing for a few hours now!
    So far we've just looked at JavaScript itself, how do we get our JavaScript to interact with the webpage?  Well, we use the DOM, or Document Object Model.  Basically, JavaScript itself gives us a few functions to access parts of the page.
    There are 3 main functions we can use to select something on the page.  If we want to get a tag (like <p> or <div>) we'd use...

document.getElementsByTagName("p")
document.getElementsByTagName("div")

    If we want to get an element by it's class (let's say the class is "yellowtext"), we'd use...

document.getElementsByClassName("yellowtext")

    And to get an element by it's ID..

document.getElementById("id")

     We can also change the content of an element with...

element.innerHTML = new html content

    I'm actually not going to go into this in any detail, while you can access elements from JavaScript I really prefer to use a JavaScript library called jQuery which is a lot easier to use (and type) - I'll go into jQuery when I start using it on the project.


Events
    Last thing to mention, and again it's time to wrap this up - we can also listen for "events" something that the user does.  So we can listen for a "click" event and do something when the user clicks on a button, or a "mouseover" event for when the user moves the mouse over an element.  Again this is something that can be done in JavaScript, but I'm going to use jQuery for - and I'll be able to give you some concrete examples once the project gets rolling.


    Wow, that was a lot - and even though I always say I've only scratched the surface, in this case that's an understatement!  There is so very much more of JavaScript to cover - which is why it's usually discussed in something the size of a book!

    This finishes the last of my 'whirlwind' tours, next post we're going to actually make something using HTML, CSS and JavaScript.  As I've mentioned before, my recommended starting point to learn more is the w3schools site.
    Until tomorrow!



Tuesday, September 12, 2017

The Open2 Engine - part 4 - Whirlwind CSS

    Yesterday I gave a dazzlingly-brief overview of HTML, today I'm going to do the same for CSS.  While HTML is about defining the elements on a page, CSS is about how to show those elements.  So let's jump right in...

    First, how do we tell the page where to find the CSS?  Well, there are 3 ways.  First there is "in-line" where we define the CSS in the HTML page right at the element that we're styling.  You might have noticed that yesterday when I was styling the <div> and <spans>...


In the code on the left you can see the attribute "style" in the <div> and <span> elements.  That's the in-line styling.  But we can also put the styling at the top of the page, in the <head> section.  If we do that, though, we need some way to tell the style what elements to style.  So, we can add a "selector" saying what elements to apply the style to.  In this case, we'll add the blue border to every <div> tag and the red border to every <span> tag...


The third way we can add styling is perhaps the most common, we'll link to an external file.  We first create the link by adding a line to the <head> section pointing to our stylesheet file (which is usually "default.css" or something similar).  Then, in the stylesheet we'll change styling by element to styling by class, which looks like .className (a period and then the name)...
 


If we want to style by an ID, we write it this way: #IDname (the hash, or pound sign, then name)...



    Okay, so that's a quick look at where to put styles and how to select the elements to style, so what all can we do with CSS?  Well, we've looked at the "border" property - the quick version of it takes the size of the border (which I'm giving in "pixels" (px)), then the style of the border (a solid line so far), and then the color of the border.  Let's look at a few more borders...


    Besides styling around an element with a border, we can also style an element itself...



    Another really big thing we use CSS for is positioning.  Getting everything exactly where you want it is tricky, because you have no idea what device the user is on, a 32" desktop monitor or a 5" phone?  Is the browser taking up the whole window or, like me in these examples, is the browser only filling up half the screen?  Browsers try to dynamically grow and shrink elements to fit in the best way possible - using CSS we can force elements to be positioned a certain way.
    Let's start be forcing how big something should be...



    The boxes look weird all lined up vertically, let's arrange them horizontally by using the property float: left...


    The little 50px red box is too small for the text in it, so let's set the overflow: hidden property to hide the excess (we could also set overflow: scroll if we wanted to add scrollbars, but those would look weird on such a small element)...


    I've been hard-coding sizes with pixels, we could also set the size as a percentage of the screen...


    We set the "padding" to put empty space between the contents and the element...


    And setting a "margin" will put empty space between the element and other elements...


    We can also define where an element should appear relative to another element or the screen itself.  Here is a <div> with a black background and some red, blue and green <div>s within it.  This is how they look with no positioning at all...


    Here they are with the float: right for the red box and float:left for the green and blue...


    Now I'm going to set clear: left for the blue box, which will move it down ("clearing" any elements from being on it's left side)...


    The position property describes where to place things on the screen.  Setting position: absolute will let you give a distance from the container (from the top and left sides here) to display each element at...


    While we defined our own classes for the elements, CSS also has "pseudo-classes" that describe how an element is interacted with.  Here I'm adding the pseudo-class :hover so that when the mouse hovers over the red box it will turn white...

 


    Okay, again I am only giving the quickest introduction to CSS here, something to hopefully let you start imagining how you can position and style the elements of your pages.  For a far better description of CSS, and a great reference, visit the w3schools.
    One more whirlwind tomorrow when I'll go over JavaScript.  Then, on Thursday I'll pull it all together and show you how to make a Twine-like display using all three.  Until then!