Dev Blog – Switches 3

Text-only post today, sorry ’bout it!

I promised a follow-up post on Switches in Vidar. First, I talked about how the key to Switches is that one event can toggle another’s self-switches. Then I talked about how I use a modified Event Spawn script to dynamically place all of the puzzle parts at the start of a new game, and told you that I do the same for Switches.

Here’s the dilemma; placing things like barrels and wolves is easy, they always do the exact same thing. That means that all of the logic is self-contained in the event, and Event Spawn just copy/pastes it accordingly. Switches are not only puzzle-dependent, they’re option-dependent. One option in a specific puzzle slot might use a Switch to open a door, while another rotates an arrow. So I had to make a system where the logic inside a Switch is always the same, and it knows exactly which function to call.

An event knows its own Event ID. And an event can always get the current Map ID through the command editor. And an Event ID is unique per map, which means that every single event in the game has a unique combination of Map ID and Event ID. And now, we’re in business.

So when I spawn a Switch, I take a few extra steps. I have a hash called $chosenSwitches which maps [mapid, event id] to a Switch object. Once I’ve spawned the switch, I know all of that information:

new_event = EventSpawn.spawn_event_map(34, switch.map, switch.graphic, x, y, true, 0)
switch.id = new_event.id
$game_self_switches[[puzzle.map, switch.id, "B"]] = true if switch.dark == true 
$chosenSwitches.merge!([switch.map, switch.id] => switch)

The first line creates the Switch event, and a reference to it. The second line takes that event’s id and stores it in the Switch object. The third is unique to the Dark Cave biome – if the Switch is supposed to be “dark” (that is, invisible unless a light is on nearby), then turn self-switch “B” on for that event. The last adds our mapping to the $chosenSwitches hash.

Practically speaking, our event is now mapped to an object, which opens up a world of possibilities. Each Switch can have a function .call, which is unique to that Switch. When building the option, I can set each function by hand, but the logic inside each switch is the same:

mapid = $game_variables[1]
eventid = @event_id
switch = $chosenSwitches[mapid, eventid]
switch.call

This is the general gist of things – there’s a little bit more (that has to do with saving $chosenSwitches, and why it’s impossible with this set up) – but I’ll save that for another time!

Friday Script Or Not – Fomar’s Skill Master / Learn By Doing

If you want to get the most out of RPG Maker, learn Ruby. In the meantime, lots of talented scripters have done the work for you. Every Friday, The Iron Shoe features a fun script and goes into detail about how to use it. It also covers a little bit of Ruby each time so you can make even more out of the script.

Everyone loves to make their RPG stand out just a little bit, and one amazing way to do that is with a unique skill system. Today I want to talk about one option – a learn-by-doing system where you increase your skill ability based on the number of times you’ve used it! This is a Friday Script post, and we’ll delve into Fomar’s awesome and succinct Skill Mater scriptBut first, we’re going to do it all without scripts. In fact, you can make this system with events alone.

Skill System By Events

There are a few basic components we need to create in the database. The first is, for every skill that can be leveled, we need a variable corresponding to each actor that can use it. Based on your game design, this could be a lot of variables! You’ll need one final variable that the ID of the caster. Make a note of which one that is (here, 16)

Multiple actors could have access to the same skill - or not! Whatever you want!

Multiple actors could have access to the same skill – or not! Whatever you want!

The second is to build the skills, as many levels of them as we want. So, if we want “Spin Attack I”, “Spin Attack II”, and “Spin Attack III,” we make each skill with higher damage amounts, higher MP costs, etc.

Learn By Doing

Skills can do more than one thing. Just use the ; to separate lines of code.

Note that in my damage formula box, I have a normal damage formula, followed by:

; $game_variables[16] = a.id

Variable 16 is my Caster ID variable. What I’m asking the damage formula box to do is first deal damage, then set the variable to who is casting. We’ll use this in the next step. It’s important that every skill that you want to level has this little line after it’s damage formula. You can copy and paste it – it’s the same variable, same everything for every skill.

Third, we make a common event for each skill that’s going to be leveled. One for Spin Attack level, one for Fireball, etc. In each one, we’ll need to take yet another variable that represents which actor cast the spell, and based on that, increment the correct variable. We’ll also need to ask if that variable is above a certain threshold – if it is, our actor should learn the new, powerful level of the skill! (and take away the weaker one if you’d like).

You'll need one for every chain level of skill, and nesting options for each actor that could use that skill.

You’ll need one for every chain level of skill, and nesting options for each actor that could use that skill.

Let’s walk through the logic of this common event. We have a series of conditional branches which ask “who is the casting actor?” If it’s 1, then increase the skill variable assigned to that actor by 1. If that brings us to 50 or above, ask if Eric’s already learned the next step. If he has, do nothing. If he hasn’t, teach it to him.

And finally, in each of our skills, we need to set the casting actor variable, and call our leveling common event.

Remember to make sure you've already set the caster ID!

Remember to make sure you’ve already set the caster ID!

It’s pretty easy logic, but is extremely tedious. We need potentially dozens of variables, numerous common events. To simplify, we can use Fomar’s script. Download and install it, and open it up. All of our work happens in that script.

Skill System By Script

From above, we still need to keep all of the different skills. So our skill table in the database will be quite long. But we don’t need the variables and we don’t need the common events.

Look for this area in Fomar’s script:

When you get here, delete the example SKILL[3] line. Otherwise you'll end up with something wonky.

When you get here, delete the example SKILL[3] line. Otherwise you’ll end up with something wonky.

There, we’ll add all of our leveling skill scripts. We do it like this:

SKILLS[original] = [new, uses, replace]

We’ll replace the terms original, new, and uses with numbers. And we’ll replace ‘replace’ with true or false. Specifically:

  • “Original” is the id of the skill being used. So for our Fire I, it’s 9
  • “New” is the id of the next level skill. Fire II’s id is 10
  • “Uses” is how many uses it takes to get from the original skill to the new skill. Choose what you’d like.
  • “Replace” is either true or false – if it’s true, the new skill replaces the old; if false, the new skill is added to the list without altering the old.

We list each skill that has the possibility to “evolve” so-to-speak, and separate them with new lines. Something like this:

Using # in our code means anything we type after on that line has absolutely no impact. It's called a "comment," and I use it here to keep track of what each line is doing. Make sure to keep your games organized!

Using # in our code means anything we type after on that line has absolutely no impact. It’s called a “comment,” and I use it here to keep track of what each line is doing. Make sure to keep your games organized!

Beginner Challenge

Sometimes, it’s nice to have branching paths in our skill tree. We also occasionally let players keep a set of earlier skills because, while they do less damage, they cost less, and the strategy inherent in that decision is more interesting than just always blasting away with the highest level fireball. Using Fomar’s script, how can we make our Fire I spell teach you Fire II after 25 uses, but also teach you Fire All after 50 uses (encouraging you to use Fire I even after you get the upgrade)?

Advanced Challenge

There are two classes an actor can be – Witch and Spellsword. Both can cast Fire, and Fire upgrades to Fire II and Fire III. But the Spellsword takes twice as many uses as the Witch does. Using events, how can we achieve this?

We’ll discuss answers in a few weeks!

Dev Blog – Random Generator 3

In the latest build of Vidar (posted on Monday – go download it!) I finally threw the switch on the Random Generator. It’s alive! A few weeks ago, I talked about how, using a tile swapper, I’m able to place things like rocks, holes, and direction arrows based on what’s encoded in any given puzzle’s chosen option.

But there is more to life than lifeless rocks. We need things to interact with, and that requires not a tile, but an event. So I needed an event spawner. There are some great event spawners out there – some which make temporary events, some permanent. But what they all have in common is that they spawn the event on the map you’re currently on. It can pull from a different map, but not to a different one.

After playing around with those, it was clear the game wouldn’t work. Particularly once you get to the Dark Cave, there are so many events being spawned per map that when you enter each, there’s a noticeable pause where the game is unresponsive. Also, from a structural standpoint, I didn’t like not knowing the event IDs of a puzzle until you’ve reached that room – I want to know everything in your particular save file right off the bat.

Pillars, torches, doors, mirrors, barrels - there are so many events just in this one screenshot that loading them when you enter would break immersion.

Pillars, torches, doors, mirrors, barrels – there are so many events just in this one screenshot that loading them when you enter would break immersion.

So I built my own, using Eshra’s Spawn Event Script as a starting point. It does mostly the same thing, except it opens up the destination map, adds the new event data, and closes it.  I’ve got one “source” map per biome – that is, there’s a Dark Cave map that the player will never see. On it are things like torches, lanterns, wolves, barrels, mirrors – all of the events that will show up in Dark Cave puzzles. A puzzle option knows (i) what map it’s on and (ii) what its “source” map is. From there, it’s a simple matter of copy/pasting events where they should go.

What’s more, I can do this exactly once – when you start a new game. Before you even reach the tutorial, the game runs through every puzzle, chooses an option, does the tile swaps, and now spawns the events on the correct map. This takes some time, which means I need a loading screen in the beginning. But once that’s done, it’s done.

Incidentally, the lantern on the wall is two separate event spawns. One is the flickering lantern, the other is invisible, right below it on the wall, so that your short little self can interact with the lantern.

Incidentally, the lantern on the wall is two separate event spawns. One is the flickering lantern, the other is invisible, right below it on the wall, so that your short little self can interact with the lantern.

This handles a lot of easy events right off the bat. Barrels in the Dark Cave refill your lantern oil. They don’t reference anything else in the puzzle, they don’t do different things that are context dependent. They just call a single common event that plays a little sound, displays a little text, and changes a variable. So I made that barrel once:

This is way easier than having a bunch of barrels in the map that we're going to just set with something like Event Position.

This is way easier than having a bunch of barrels in the map that we’re going to just set with something like Event Position. Which is exactly how Vidar 0.0.1 worked.

Every dark cave option has as an attribute “barrels”, which itself is a list of coordinates. When an option is chosen, I go through those coordinates and spawn duplicates of that barrel at all of the coordinates. Et voila.

This also helps for one-off things like quest items, which might appear all over the place but will always do exactly one thing. I also use the system to spawn switches, but I’m still saving that mess of a post for another day!

Iteration 2

Dev blog? But it’s Friday! What’s going on? I’ll level with you – Friday script posts take me about 5 times longer to make than the other posts. And that doesn’t even include the time spent looking for amazing RPDR gifs. I have to the learn the script, come up with challenging new uses for it, poke at the edges, implement it. I’ve cut corners by featuring scripts I’m using in Vidar, but running out of those.

Never fear, the Friday script feature will be back, but it will be less frequent than…well every week.

So today, even though it’s Friday, I wanted to write about recent iterations to the Ice Cave! After playthrough, it was clear that getting the waypoint was absolutely critical. Without it, it could take 5 of the player’s 10 minutes just to reach the next puzzle. And the waypoint was tied to an incredibly challenging quest from Bernadett, which involved going back and forth across the Ice Cave several times.

But if Bernadett died in the first few days, the player was penalized so heavily that the rest of the game became impossible. While the point of varied quests was to change the way you play the game, I never want you to feel like “oh, so-and-so died, I have to restart.” And our favorite judgmental nun was absolutely in that position. Based on this, I’ve decided to add multiple ways to “teleport” throughout the caves. A minimum of three, so that the player has some way of rapidly advancing to the puzzle they need to tackle next.

1) Waypoints are staying in. Each area has a waypoint that can be unlocked by completing a certain quest, and that waypoint gives the player direct-from-town access to a room in the middle of each biome (chosen randomly, of course).

2) The Ice Cave waypoint is now the reward for completing Borbalo’s quest. His quest is slightly easier than Bernadett’s – asking you only to visit each of the graves, rather than returning ghosts to them. Borbalo’s former quest reward – the journal – is now given to you at the start of every game.

3) Campfires. A new addition to the Ice Cave are randomly placed Campfires. Doing a quick, easy, and early quest for Dani allows you access to Campfires.

The location and number of campfires is random, but there are at least three in the Ice Cave.

The location and number of campfires is random, but there are at least three in the Ice Cave.

Dani’s quest is designed such that about 95% of games will complete it. In exchange, Campfires give the player a trade-off. A player can use a Campfire to immediately end the day and start the next day still in the cave. This means that the player can keep solving puzzles without being forced to awake back in Vidar. But the Beast waits for no man – someone will still die. And if you needed that person to complete a quest, you’re SOL.

4) Ghost running. Bernadett’s quest reward has been upgraded to allow for quick transfers between the graves in the Ice Cave. This is by far the most flexible of the three ways to move about the Ice Cave, and is a strong reward for a difficult quest.

The other biomes are getting a similar facelift. The upshot of this is, more quests. Way more quests. When Vidar started, there were 24 quests planned, full stop. Now we’re at 34, and I expect we’ll be up to 50 by the time the beta is ready. I’m thrilled that the solution to this problem was more game diversity, because that’s what Vidar is all about.

Dev Blog – Switches 1

I thought it worthwhile to do a series on how Switches are handled in Vidar. In this series, when I use the capitalized-S Switches, I’m not talking about those numbered global booleans that you can access in the trigger editors. I’m talking about things you interact with that you expect to do something, like these:

To make matters more confusing, these are called "Switches" in the RTP Character Sheets.

To make matters more confusing, these are called “Switches” in the RTP Character Sheets.

I’ll use the lowercase-s switch to refer to the boolean that you set. Any basic dungeon will end up having a Switch like the one above that opens a door. And it’s easy to have an event page for your Switch look like this:

This is typically accompanied by a page 2, which has as its condition, "Open Door 1"

This is typically accompanied by a page 2, which has as its condition, “Open Door 1”

And then your door would have 2 pages; one where the door is closed, one where it’s open and the conditional is that “Open Door 1” switch. And then you’ll use another switch in another Switch for “Open Door 2,” and another for “Open Door 3…”

This is a bad habit. Stop doing it.

What you’re doing is creating global booleans that only get used once. Not only are you cluttering your list of switches, there’s a strong chance you could accidentally call it with something else, a chance that something gets moved or deleted. Once you have more than 10 doors, you’ve got a headache. These switches are really good for massive plot-moving periods in your game, because they’re an easily referenced marker – use switches for things like “Cave Boss Defeated” or “Fire Summon Available.” Don’t use them for Switches and Doors.

Vidar in particular can’t use switches like this. Why?

  1. There are hundreds of possible doors in Vidar, making tracking them tedious
  2. Which doors are actually spawned at the beginning of the game are chosen randomly, making tracking them really tedious

Plus, it’s bad practice. There’s a much better way. For the second page of your door, instead of using a global switch, use a self-switch. Something like this:

Now your door isn't dependent on some switch in your list that you might accidentally click; it's dependent on its own self-switch.

Now your door isn’t dependent on some switch in your list that you might accidentally click; it’s dependent on its own self-switch.

As it turns out, your Switch can tell the door to turn on its own self-switch. Just use this:

$game_self_switches[[mapid, eventid, "A"]] = true

So instead of using one of those global switches, our Switch page would just look like this:

Since we're not using a global switch, we need to trigger 2 self-switches; the door and the Switch itself.

Since we’re not using a global switch, we need to trigger 2 self-switches; the door and the Switch itself.

Why is this so desirable? Because it’s flexible. We can replace all of those variables dynamically. We can run this thing through a for loop. We can have dynamic control over every door.

So, for example, if we have a room with a puzzle that has 100 doors, we could do something like:

100.times {|i| $game_self_switches[[5,i,"A"]]= $game_self_switches[[5,i,"A"]]? false : true}

which would “toggle” all 100 doors – open all closed ones, close all open ones. With one line of code, and not 100  event calls, nested in if-then statements. And without 100 different switches in our global switch list, which we have to navigate for months to come. Even if you’re not going to do something in-depth, you can easily clean up your game using this method instead of one-off global booleans.

This is the starting point for Switches in Vidar. There’s obviously a lot more – Switches do different things depending on the puzzle they’re in, and having them know what function to call is its own can of worms, but we’ll save that for another day.