Creating a small scene between NPCs
This tutorial will teach you how to create two NPCs, and have them talk to each other and do other actions. It is based off a scene from the modification "Chrono Trigger: Crimson Echoes."
Contents
Temporal Flux Tutorial Disclaimer[edit]
This tutorial involves Temporal Flux. Since these tutorials are not meant to augment your game, you should make a copy of your Chrono Trigger ROM for use with these instructions. This not only backs it up, but will prevent you from unnecessarily changing and overwriting your clean copy, which you probably want to still play time to time, no?
In this tutorial, you will use and learn the basic, following skills and commands:
- Creating an NPC
- Making an NPC face a certain way
- Using NPC animations
- Correctly structuring conversations and actions
- Moving NPCs and making them disappear
- Preventing the party from leaving the scene in progress
- Using a value-to-mem operation once the scene ends
- How to make the scene start two different ways
Getting Started[edit]
As stated above, this tutorial is based off a scene from Crimson Echoes. Specifically, we're going to have Bandeau, the ferryman who appeared at the end of Chrono Trigger, argue with the new Medina elder, a Blue Imp. After a couple animations and appeals, Bandeau will storm out, while the Blue Imp will go to the window to gaze and ponder the turn of events. The tutorial will be divided into two sections; creating the NPCs, and making them interact.
Creating the NPCs[edit]
Firstly, we need to clean up the event code for Medina Elder's House 1F {021}. Several happenings go on here, and we want to eliminate them so that they will not intrude upon our work or unnecessarily complicate it. Delete all Objects after 07. This way, only the String Index and Music (Object 00), and the Player Characters, will be the only ones left.
That might have seemed a little drastic, but now we're ready to make the actual NPCs. Recall that we're going to be using two here -- the Blue Imp, and Bandeau, the ferryman. Let's do Bandeau first. Create a new object (it will appear as Object 0D; don't worry). You'll see Startup / Idle, Activate, and a list of Arbitrary commands. We're only concerned with Startup / Idle at the moment, because this is what tells the game what to do the very moment you enter the room. Let's run through what to do to load him up. Use the 'command' button to make commands that you can edit to specific event functions for this list.
- Object Coordinates - Use this to place him. Coordinates X - 98, Y - 98 (to reference these, open the real Medina Elder's House map, fullsize, and move your mouse. In the lower right corner, digits will tell you the coordinates your mouse is currently hovering on).
- Sprite Drawing - Under command, select Load Sprite. Type is NPC, and the NPC itself is 34 - Villager (Man).
- Facing - This will make him face a certain direction. Under facing, put right.
- Animation - Most NPCs in RPGs have a basic walking animation. Use animation 01, normal.
- Return
- End (these two terminate the Startup commands; the game would glitch otherwise)
Let's review what we should have now.
You can disregard the little [####] tags next to the commands; just make sure the commands are there and in that order. Congratulations! If you write memory and save, there will be a man in the Medina Elder's House. However, he won't do anything or even speak yet; let's keep going. Next, we need to create the Blue Imp. Similar to what you did to create Bandeau, let's make a new object, and give it startup commands.
- Object Coordinates - X - B2, Y - 98 (this will put him across from Bandeau).
- Sprite Drawing - Load Sprite, type: enemy. Use enemy C, which is a Blue Imp. Put Parameter - 8, as this will make the enemy behave like an NPC rather than an actual enemy in battle.
- Facing - Put facing left; he'll look at Bandeau now.
- Return
- End
Okay, let's check it out.
There we have it; Medina Elder's House is now populated by these two. What's the next step? Why, making them speak and behave! Lock in and proceed to the next section.
Scripting NPC Interaction[edit]
Before we go on, let's review exactly what's going to happen. Bandeau and the Elder are going to exchange lines. What does this mean, exactly? Will we have to put a command on Bandeau to say something, then tell the game to switch over to the Elder, who will have a line? Actually, consider this. If the two are standing there, not moving and not voice-animated, could you tell the difference if text spoken by both of them was simply placed under one NPC's file? There'd be no way. Thus, we don't have to waste event space for both NPCs by putting their own lines in their own code. Rather, we can stack all the text on one character's code to conserve space. You'll see what I mean when we begin. Before we continue, however, we need to give our new characters lines. We'll use the strings I typed for Crimson Echoes.
In Temporal Flux 1.7, go to Dialogue (0x384650) in Strings (if 2.0 is out by the time you read this, you can just paste these as you make textbox commands). Replace lines 00-07 with the following:
00 ELDER: I'm sorry Bandeau, but I{line break} can't accept. Please understand.{null} 01 BANDEAU: Eh? But elder, there are {line break} countless Porre merchants waiting{line break} to do business here.{delay 03} Just sign the{line break} agreement, and they'll steam right in.{null} 02 ELDER: ...{delay 03}{line break} Again, no, thank you. Right now, we{line break} don't need to get involved in Zenan{line break} politics. Your ferry service is enough.{null} 03 BANDEAU: Urgh, I don't believe this...{null} 04 BANDEAU: Hey, you guys! What if{line break} riches lay in wait for your town?{line break} For free, I might add? Wouldn't you{line break} take it without a second thought?{null} 05 ELDER: Hey!! It's not for free! If I{line break} sign, we have to promise only to trade{line break} with Por...{delay 03}{instant full break} {null} 06 BANDEAU: Enough! Have it your way!{line break} But don't come crying if ticket prices{line break} take a little hike, heh heh...{null} 07 BANDEAU: ...mm, I'm in trouble now...{delay 02}{instant full break} {null}
Just for kicks, note the {instant full break} and {delay 02} in the last line. That will ensure that after two seconds, the textbox will terminate. Now we're ready to move on. We're going to put all the dialogue under Bandeau's commands; specifically, they're going under the Arbitrary0 heading. We don't need to put anything under Activate, because Bandeau is going to leave the room after the scene and not come back. Placing the commands in Arbitrary0 will also ensure that they are triggered the moment your party members approach Bandeau. Let's run through the events; I'll provide explanations for them.
- Sprite Movement - Command ExploreMode Off. This will make sure that when you approach Bandeau and the scene begins, the party will be frozen in place so it cannot leave while the scene is still running.
- Text - Command, textbox. Make four of these commands, starting with String Index 0 and going up to 3.
- Animation - Animation 9, normal. This will make Bandeau throw up his arms as he makes a retort.
- Text - Command, textbox. String Index 4.
- Animation - Animation 1, normal. This will return Bandeau to his earlier animation, since it's not normal for people to throw up their arms and keep them that way.
- Text - Command, textbox. Do three more of these, using String Indices 5-7.
- Sprite Movement - Move Sprite, X - 7, Y - C, animated false. This will make Bandeau walk to the entrance after he's done arguing. Animated - false ensures that his previous animation doesn't carry over while he's walking (for instance, if a Mystic were sticking his tongue out at you, and you used Move Sprite with Animated - True, he'd float with his tongue out rather than walk).
- Sprite Drawing - Drawing Status, status - hide. This will make Bandeau disappear right after he gets to the room exit, making it seem as if he exited the Elder's House.
- Sprite Movement - Command ExploreMode On. Now the party can move again.
- Return - Good form requests placement of one of these.
This is a good stopping point to review what we've just done. More is in store, but for now, your event should look like this if you followed the above diagram:
We're getting near the end. As promised, we're now going to make the Blue Imp walk over to the window and gaze out. Now, what should we put this under? Startup? Of course not, or he'd do it as soon as you entered the place. Activate? No, we don't want to have to press 'A' to get him to do it. Arbitrary0? Nah, we don't want it happening if you accidentally brush him before you brush Bandeau. Let's put it under Arbitrary1. In fact, Arbitrary 1 through D are slots for putting all sorts of actions that can be triggered. You'll see how it works in a moment. Before we work out the specifics, lets script the actions themselves.
Chrono Trigger NPCs, like the playable characters, don't have to move in rigid, robotic, linear patterns. They can walk diagonally. It is also noteworthy that if you tell them to walk to a certain tile, they won't exactly walk on its center, but will stop walking as soon as they reach it. Remember, we're putting this in Arbitrary 1 of the Blue Imp, not Bandeau, or he'd be the one walking. Keep this in mind as we go over his movements. Here's what to do to get him to walk over there:
- Sprite Movement - Move Sprite X - C, Y - C, animated - false. In fact, all the animateds will be false.
Now, do the same thing four more times, using these coordinates for each Move Sprite command:
- 11, C
- 11, 7
- 13, 6
Now, we need to make him look at the window.
- Facing - Facing Up. Once he gets to the window, he'll look up, or north.
- Return - This just needs to be here.
Okay, now the Imp will walk fine. But how do we make him do this after Bandeau walks out? Simple. We need to put an Object Function command back up in Bandeau's event code. Thus, after he gets the command to walk out, this Object Function command will point to the Blue Imp's Arbitrary1, which will start his own commands to walk. So, before the Return command in Bandeau's Arbitrary0 heading, put this event command.
Object Function - Call Object Function, delay - 0, object - (whatever the Blue Imp's object number is), and Function - Arbitrary1.
Now, the Imp's actions will be triggered. We're almost ready! But we need to do two things to finish the scene. Firstly, the Imp needs to say something after the scene is over. This will go under Activate. Let's give him this line for now (as you did with the earlier stuff, put it in the StringIndex under Strings for this area, line 08).
ELDER: I regret losing his friendship...{line break} but Medina just can't afford this action.{line break} Not yet, anyhow.{null}
You should know how to give NPCs lines now; simply give him a Textbox command, and a Return underneath it.
Secondly, answer me this -- how do we prevent this event from taking place every time the player enters this room? If we leave the event code as it is, every single time the player exits and re-enters the Medina Elder's House, Bandeau and the Blue Imp will be talking again, just like a time loop (TNG: Cause and Effect, anyone?). We don't want this, however; Bandeau is mad, and he's getting out of there. Now, there are two ways to do this; Bitmath or a Value-to-mem operation. Bitmath will be covered in a separate tutorial, so let's use Value-to-mem.
Value-to-mem is simply writing a value to an address in the game. At the event code's request, this value can be checked. For instance, we're going to write something the first time this scene displays, and then put something in the event code that says "Hey, if this value has been written, Bandeau shouldn't be here and other stuff should be different." BitMath is better for this kind of thing, but as stated above, this will be covered elsewhere. Now, firstly, we need to find an address to write to. If you're making a hack, you need to keep track fo this sort of thing. At the moment, we're going to use one used for a Kilwala on Denadoro Mts. Sorry 'lil Kilwala, but we're going to borrow the command that decides whether you give the player a Mid Ether or not. Here's how we do it; I first checked that scene on Denadoro and got this address for value-to-mem operations: 7F00F2. Now, follow the logic:
- Assignment - Value-to-mem, Value - 1, Store to 7F00F2, width one byte. Stick this under Bandeau's Arbitrary0, anywhere you like. This means that when the scene is triggered by touching Bandeau, it writes a value of 1 to this address.
- Comparison - Value-to-mem, Address - 7F00F2, value - 1, width - one byte, operation - ==. This means that if the value written to that address equals 1, certain events can be done. Put this in Bandeau's Startup, underneath Animation 01. Now, keep it highlighted, and press the Command button to make...
- Sprite Drawing - DrawStatus (Hide). This means if 7F00F2 = 1, Bandeau isn't going to be there. This should be under the Comparison event above.
- Return.
- Comparison - Value-to-mem, Address - 7F00F2, value - 1, width - one byte, operation - ==. Like the one above, this will alter events if the scene has already happened. Put this one at the very beginning of the Blue Imp's Startup. Highlight it, press Command to expand beneath it, and put...
- Object Coordinates - X - 10F, Y - 07C. This means if you leave and re-enter, he'll have stopped looking through the window, and will be near the couch.
- Sprite Drawing - Load Sprite, type: enemy. Use enemy C, which is a Blue Imp.
- Return.
- End.
Okay! That's it; the scene is done, and will not happen again if you've already triggered it once. You can go check it out now. The code should look like this, altogether:
Other Scene Options[edit]
While other things like battles and Gates will be covered in other tutorials, there are regardless a couple things we can add to this scene to change it up. Specifically, we're going to do a MoveParty command, and also learn how to make the scene start without having to touch Bandeau. Let's start with the simplest first: MoveParty.
The MoveParty command is what makes Crono and his crew move around when ExploreMode is Off and a scene is in progress. For instance, if a scene existed in which explosions were happening all over the place, you would use the MoveParty command to make Crono dodge them. Since Bandeau is storming out of the Medina Elder's House, let's have Crono dash out of his way and then watch him leave. These events will suffice:
- Sprite Movement - MoveParty, PC1 X coordinate - 7, Y coordinate - 8. You can set other coordinates for the other party members if you desire. Place this right after Bandeau's MoveSprite command.
- Facing - Facing Down. Put this in the Crono (Object 01) Arbitrary01 tag.
- Object Function - Call Object Function, object 01, delay 0, function Arbitrary01. This will make it so that as soon as Crono runs out of the way, he'll look to the door and watch Bandeau leave. Put it right after the MoveParty command above.
Try it out! Watch as Crono gets out of the way. Now that that's taken care of, let's make this entire scene start as soon as Crono enters the room. If you've scanned other location event code, you've probably noticed that there's an Object00 in nearly all cases. In Object00, the Dialogue Index is specified (which dialogue offset that this location draws its strings from), and music is also selected for the area. It's also the most common place for scene startups and stuff that happens as soon as you enter the room. Getting this scene to start immediately is simple; in Object00, Startup / Idle, you...
- Comparison - Value-to-mem, Address - 7F00F2, value - 0, width - one byte, operation - ==. This means if the value of the address we're using is 0 when you walk in, it will go ahead with commands under it. Underneath this comparison, add...
- Object Function - Object 8 (or whatever Bandeau is), Delay 0, Function Arbitrary0.
This will call Bandeau's Arbitrary0 into action as soon as the party enters the room, which effectively starts the scene. Additionally, since the scene writes a value of 1 to address 7F00F2 after it takes place, the Object Function command we use to start it will get passed over since it depends on the value being 0.
I hope you've learned from this tutorial; you can do all sorts of things now. The only limit is your imagination.
From: Modification