How to Make a Circular DanganRonpa Courtroom and Some Other Stuff

Get started with the upcoming AAO version 6.

Moderator: EN - Forum Moderators

Post Reply
User avatar
Semper Solus
Posts: 54
Joined: Mon Nov 18, 2013 5:47 am
Gender: Male
Spoken languages: English, עברית, Español
Location: You know, I actually have no idea. I should probably turn off the computer and check.

How to Make a Circular DanganRonpa Courtroom and Some Other Stuff

Post by Semper Solus »

Hi. Semper Solus here.

I'd been working on and off on an Ace Attorney/Danganronpa fan-game since before V3.

Since I'm still not done with the first case (or with graduate school), I decided I'm just going to stop now.
With AAO, that is. Not grad school. Want to make that clear.

This is a tutorial for all the cool stuff I successfully did in the unfinished case, since I don't want my hard work going to waste.
I really hope you understand my writing, because I'm not the best at communicating how to do things. It involves knowing what other people know and what they don't.

Anyway, I'm making my partially finished yet well-done garbage available to everyone. There is no part 1-2, because I wanted to do the interesting part first. Unfortunately, as a result, I have no insight as to how to script the "Deadly Life" section. But I think you'll probably pick up some ideas of how I would have tackled it by reading this guide.

Anyway, moderators, please delete this if I put it in the wrong place.

The Revolving Danganronpa Courtroom

The only real scroll options AAO gives you are "move all the way to the right", "move all the way to the left", and "move to the center". Somehow, we are to turn that into a circular courtroom that can scroll left and right and reach any one of 16 locations.

My workaround: I wrote some Python code that, when run, can generate the Catalysis code for 80 or so places, each of which can be used to simulate 2 or 5 transitions.
Yes, to do this, you will either have to use Catalysis, or mess around with JSON data, neither of which is 100% endorsed by Unas et al.

The code can be found here. Anyone's welcome to use or modify it, but I'd really like if I got a PM when the case is done so I can see what became of it.

The code has 3 methods. "macros" and "objects" make the macros and objects. They are non-negotiable for the courtroom to work.
"frames" makes frames. It's for this thing I was experimenting with to do that thing Danganronpa does where everyone in the courtroom continues making the last emotional pose they made when talking even when the camera isn't directly on them. A more detailed explanation is in the .py file. It causes noticeable lag, and I'm not sure anyone would notice if you didn't do it.

What you do (ie. what I know works):
  1. Download the .py file.
  2. Follow the documentation to change the .py file to your liking
  3. Use a python interpreter (3.3+) like IDLE or command line python3 to run it.
  4. Run each method you want ("macros()", "objects()", "frames()"), and paste the result into the appropriate Catalysis text file. I recommend putting some kind of marker on either side like "//GENERATED STUFF START" and "//GENERATED STUFF END", because there will be a lot of it, and you'll want to skip it in your text editor.
  5. Use the new macros I gave you to bring the courtroom to life!
If all goes well, I should also have a thread in the art forum with my resized and reindexed Danganronpa stuff.

Also, the code for this courtroom is written such that you can have a unique background and foreground for each person. It could be modified to be used for DGS/PLvAA-style multiple-witness trials.
This is left as an exercise.
Like, it's not that hard, but I don't want to do it.

The In-Game Clock

I'm proud of this one.
Now, as I mentioned before, I did this in Catalysis, and that makes this a lot easier, but the circular courtroom is the only thing you really need Catalysis for.

Anyway, there are two kinds of in-game clocks. One is the kind that keeps track of how much time passes. Don't do that one. The other is the kind that moves the clock forward whenever you complete a task in the game. That kind is fair. Your choices matter, but you have all the time you want to think about them. That's the kind I'm going to show you how to implement.

I've decided that, rather than upload a screenshot of the editor to a hosting service that will probably go down by the time you read this, I'm just going to paste my Catalysis script and explain what it means, frame by frame:
Spoiler : "Catalysis" :

Code: Select all

wait, 1
proceed, anchStartChapter


anc, anchClock
wait, 1
variImphours, {VariHours}

wait, 1
condit, anchClockSet
variMinutes > 59, anchFixMinutes
variHours > 23, anchFixHoursMil
!(variHours < 12), anchFixHoursPM

anc, anchFixMinutes
wait, 1
variMinutes, {variMinutes - 60}
variHours, {variHours + 1}

wait, 1
proceed, anchClock

anc, anchFixHoursMil
wait, 1
variHours, {variHours - 24}

wait, 1
condit, anchFixHoursAM
!(variHours < 12), anchFixHoursPM

anc, anchFixHoursAM
wait, 1
variAmpm, AM
variImphours, {hours}

wait, 1
proceed, anchClockSet

anc, anchFixHoursPM
wait, 1
condit, anchFixHoursMisc
variHours=12, anchFixHoursNoon

wait, 1
proceed, anchClockSet

anc, anchFixHoursMisc
wait, 1
variAmpm, PM
variImphours, {hours-12}

wait, 1
proceed, anchClockSet

anc, anchFixHoursNoon
wait, 1
variAmpm, PM
variImphours, {hours}

wait, 1
proceed, anchClockSet

anc, anchClockSet
wait, 1
variTime, {(variMinutes > 9) & variImphours.'\:'.variMinutes.' '.variAmpm | variImphours.'\:0'.variMinutes.' '.variAmpm }

wait, 1
proceed, {variClockReturn}


Oookay. Yes, this looks like gibberish. Even to me.

First, I have to explain something about the syntax.
"anc" means "anchor". It's a way of referring to the number of the frame, since in Catalysis we don't know what the frame number is until after the script is compiled.
"varDef" means "define the following variables".
And that's why I precede my variables with "vari" and my anchors with "anch": so my text autocomplete can find all my variables and anchors in one place, but that place doesn't contain "anc" or "varDef".

Oh, and "wait, 1" just means "wait for 1 millisecond", or in other words, "do this so quickly nobody notices". Every frame has this, because nobody wants to see the game update variables the player doesn't even get to see.

What you do:

Assume you have those frames in your game as they are.

Now, say it WAS 11:00 AM, but something happens in-game, and you want to increment variMinutes by 60 (you have to go swimming, and you just ate).

Just make 2 frames:
  1. In this one, you set variClockReturn to the frame ID of the frame after the second one, and set variMinutes to {variMinutes + 60}.
  2. In this one, you proceed to whichever frame anchClock is.
Now, let's walk through what happens:
Spoiler : walkthrough :
First, it sets variImpHours to 11. (Imp stands for imperial. The output will be in imperial time rather than military, like the series does.)

Next, it evaluates some conditions (in order). The first one is true--variMinutes is greater than 59; we just raised it by 60--so we go to a new frame that does nothing but reduce variMinutes by 60 and raise variHours by 1.
Then we go back to start.

Okay, now variImpHours is 12, but variMinutes is less than 59. The first two conditions are false and the third (is variHours greater than or equal to 12?) is true.

We get bounced around, and discover that variAmpm is "PM".
Then that really long string concatenation thingy just assigns 12:00 PM to variTime, and makes sure there's that extra zero in there.
And Hey Presto! You can use variTime whenever you want to print out the in-game time in your game!
Free Time

Maaan, I was ambitious for this.
The code was easy. Took practically no time at all. But writing all that dialogue was something I dreaded even when I enjoyed working on this.

However, if you really hate yourselves that much, here is how you do it:
You need one variable for "number of total times talked to people" and one for each person for "number of total times talked to this person".

You have one fork to choose "which person to talk to" based on user input, and another to choose "which time it is that you're talking to this person" based on that second variable.

The first variable is for "skills", two of which I actually programmed in. One divides the damage you take by a certain amount, and one multiplies the health you get back by a certain amount.
I had some other plans in the works, like saving the correct evidence piece's name as a variable, and using some string functions to provide hints. But, "Of all the words of tongue and pen", etc.


I did some other stuff, too.
For instance, in the Daily Life section, I created a "date" variable, so I could completely automate the green "date and time" intro screen. Plus, since this was a Danganronpa trial, I could automate the nighttime and morning announcements, and even segue into different Monokuma Theaters depending on the date.

Speaking of, those curtains are sprites, and the Monokuma puppet is a two-part background object.

Also, you may notice that there are scenes in the Daily Life phase where there is a lot of scrolling back and forth between people as they talk. That's something Danganronpa does, so I thought it'd be a cute little touch. It's very easy to implement. Just get a background that's 2 or 3 times as wide as the screen. (This isn't as hard as you think if you're already ripping from a visual novel.)

There is also a strategy I use for managing locations. Each location is only used once, but at the start of the Intro, there's a fork that checks event flags and sends you to different areas of the intro. After the intro is over, it uses "Proceed to the following frame" to go to the last frame of the Intro, which reveals the Intro again (so you can use it next time).
If there are no events that aren't ready to happen at that location, the fork will send you straight to the end of the intro. Yay. It's surprisingly economical.

That's pretty much all of it. Feel free to PM me with questions. I'm never on this forum anymore, but PMs will get directed and redirected until they eventually reach whatever service I'm currently using.
Post Reply