Tuesday, December 13, 2016

Dec 13 2016 Devlog: Cracking the code

Tonight I'm going back to the usual tone I've set lately, and delve into some of the programming issues I've been wrestling with. It comes with a surprising revelation: I'm actually sort of okay at this thing it seems.

I still feel like a hack when assembling things, but tonight was one of those nights where I made a plan, followed it through, then came up with a better way to do it immediately after. So I'm going to be talking about that.

Tonight's project was supposed to be a relatively simple task, programming-wise: Implement a Divination check at the start of the day. It's something I've been meaning to do, but just kept putting off until now, since I have the time and we're nearing the end of the first major milestone.

While conferring with my writer, it occurred that I also needed a way to handle another event that could occasionally crop up: receiving letters at the start of the day. Now, that doesn't sound very hard, but there's a twist: Some of these letters are invitations to meet, and accepting them should, logically, lock you in to that event during the appropriate time slot - turning it into a mandatory event that eats up a period of time you could use for improving your skills instead.

Inserting a quick check to see if an event triggers during the start of the day is a simple matter, so the divination check was literally a five minute job - just tell it to point to an event that checks to see if the appropriate message should appear on a given day, then back to where it left off to continue executing the rest of the start-of-day code. Not a big problem. The issue came in though when I realized this simple solution wouldn't exactly work for the letters as well. I mean, it could, but... why settle for something less?

So I reconsidered my approach. Instead of having the letter event trigger immediately after the divination check, I thought about how I could use the loading order of the day planner to my advantage. Instead of forcing it to load all kinds of values or defaults on a given day, I could theoretically get it to load up the appropriate default information, and then modify only what was absolutely necessary.

Seemed very simple at the time. The way my modified DSE framework operates is thus: At the start of the day, it checks to determine what the day of the week is, and based on this it loads up the set of default events - in this case, it performs the following operations:


  1. Determines whether it is an "event day" or not (any day that does not have mandatory classes to attend)
  2. Determines what the day of the week is
  3. Loads the appropriate defaults in based on the previous two steps
  4. Calls up the Day Planner, based on whether this is an Event Day or not
  5. User inputs their schedule for the day, based on what selections they have available (two periods on a class day, four periods on any other)
  6. Executes the events based on the selections made in all previous steps, selected from a list set in the event scheduler.
Now, typically this is a much simpler operation: all of the choices given by the default are blank, giving the user total control. In my case, that's not an acceptable solution, so alterations were made. But at this point, I have six different Day Planner defaults that can be called - one for each of the five days where the player goes to class (for each class is different), and one for any other day that has no defaults.

While this works, things get complicated real fast once you accept an invitation from a character to meet with them. There's no universal template that can be made for this, so how the heck do we solve this issue?

The solution is pretty simple: Insert a new step between 3 and 4. Let's call it step 3.5. The things this step does is fairly straightforward:

  1. Checks to see if this is a day the player gets a letter. If not, it goes right to step 4 listed above.
  2. If the player does receive an invitation, it then executes a little event right there detailing the contents of the letter, and asks a very simple question: Do you attend, or not?
  3. Assuming the player says yes, it then modifies the default day schedule accordingly. Otherwise, it returns to step 4 detailed above.
  4. It then sets a flag indicating that the player has elected to accept the invitation, thus locking in that event at that time and location. This flag will later be removed once the scene executes, and again at the end of the day (more on that later).
  5. It calls up the Day Planner, but this time modified to reflect the new changes. Instead of creating templates for every conceivable combination (which is a nightmare), we can load one of two planners depending on whether or not we are in an Event Day or not.
  6. Lastly, once the Day Planner choices have been locked in, it jumps straight to step six detailed above, like it normally would.
Now, there is one problem I can already see cropping up with this: If you only have one flag determining an event which can play out across multiple characters, it's possible to accidentally trip an event that you shouldn't, which would also have the unintended consequence of allowing you to skip the event that you were supposed to see.

Fortunately this is an easy fix: Just make one flag for each character, problem solved. But because of this setup, there's a really neat feature that I was pondering about implementing long before I started coding this scene, and as luck would have it, this setup easily allows for:

A 'maybe' option.

Maybe you aren't sure if you want to show up there or not. Could be you want to mull it over - take a look at your stats and ask yourself whether it's worth it to skip out on a character event for some sweet sweet skill points. All you have to do in this case is show up at the right place, at the right time. In this case, a different Day Planner is loaded - the default one. But since the flag should already be set (as you've received the invitation), you can still trigger the scene normally so long as that flag is set in place.

This is why it's important to make sure that at the end of the day these flags are removed. Regardless of whether it was already removed or not, forcibly removing them at the end of every day solves the issue of any accidents occurring. And thankfully, event dependencies will should prevent other unintended events from that same character occurring that rely on that same flag.

Now why is this such a big deal for me, that I was able to come up with this solution? Because frankly I have very little idea how the Day Planner code actually works. I mean, I have some general ideas, but this is the first time I've been able to deviate so heavily from the core framework, and make it work in my favor.

To me, that's a huge victory worth celebrating. A couple hours of work, and suddenly I've opened the doors to a new realm of possible depths that we can explore later on down the road.

All in all, I'd call that a good day's work.

No comments:

Post a Comment