Events for Everyone

From Stardew Modding Wiki
Jump to navigation Jump to search

This guide attempts to provide a more in-depth explanation to modding events as a reference for both beginners and experts.

Introduction

Written by Thylak and hence references Subway to Stardew a lot in its examples. I like alliteration. I like combinations of commands. And I like coding events more than anything else.

Eventing is a learned skill with a lot of quirks that requires a bit of hands-on experience to get the hang of. Despite an event being made of the combination of commands, most resources tend to focus on explaining one command by itself and don't mention that most commands impact each other. I will try my best to document everything I know so you don't have to fiddle around so much. You will still need to fiddle.

While I will try to provide a thorough walkthrough for everything, I highly recommend checking out other pages like LenneDalben's guide to expand your knowledge. I mostly just wanted a page for all my templates and to infodump about eventing. I am obsessed with coding events and you can be, too!

Preparation / Helpful Links

It isn't necessary to have everything together if you're jumping into eventing, but you will probably find yourself referencing/using these eventually. I will explain more later down the line.

  • Content Patcher. You will need that to make/load your mod. Events can be made entirely with a Content Patcher mod (no need for C#). If you haven't familiarized yourself with Content Patcher, I would recommend reading though the documentation and also look through the files of other mods to familiarize yourself with what a working mod looks like.
  • The Event Data page on the Stardew Wiki for referencing the different commands/preconditions.
  • The event spreadsheet is also helpful for referencing various things such as portraits, spritesheet frames, and audio IDs.
  • Unpack the game's files with StardewXNBHack so you can see the game's files. Helpful for viewing maps and seeing how vanilla events are coded.
  • Tiled to open the .tmx files in the games Maps folder. It helps to figure out which coordinates exactly the camera of your event will focus on and where to place your characters.
  • Debug Mode mod for event testing. This will show which command has an issue if your event gets stuck (which it likely will).
  • Event Changes in 1.6. The Stardew Wiki's Event Data page is still helpful, but isn't up to date with all the new features that 1.6 brought. This includes new preconditions and commands!
  • List of Game State Queries (GSQs). Helpful to reference for event preconditions.
  • SpringObjects tilesheet table. Helpful if you want to use the addObject command. Note: Only valid objects work as of 1.6!

Ideas to Implementation

Ideas

I will assume that you have an idea of what your mod/event consists of. You're making a mod, after all! Personally, I am not a writer and have a very weak imagination so I cannot help you regarding event ideas. You should first organize your ideas into a timeline and think about the requirements needed to trigger your event. The only necessary requirement is location, but time, weather, and heart levels are common preconditions.

If you're making a custom NPC, check the Tips for Heart Events page and LemurKat's guide for pointers on story-telling in the context of heart levels in-game!

Before I start listing out the "rules" of writing events, I will say: you don't have to match vanilla. You're making a mod. Make what you want to see. If what you want to see are events that match vanilla, here are some pointers.

Matching Vanilla

  • Romancable NPCs have events in increments of 2 up until 10 hearts and another heart event when married at 14 hearts. This means they have events for 2, 4, 6, 8, and 10 hearts.
  • Non-romancable NPCs tend to have 1-2 events and no rules for when they happen. Most tend to either have an event or send you mail at 2 and 7 hearts. Again, make what you want to see.
  • If they're datable, 10 hearts and up will be locked behind dating. If you care about others not wanting to date your NPC, the "important" information and climax of their story should be around 8 hearts with +10 hearts focusing more on their relationship with the farmer. 10 heart events with the vanilla spouses tend to revolve around setting up their first kiss with the farmer. Vanilla spouses have marriage events at 14 hearts, but anything between 11-14 hearts is locked behind marriage.
  • For non-romancable NPCS, I have this as my guideline:
    0: Generic or distant. Just usual "customer service" blurbs or "Why are you talking to me?".
    2: Opening up, some general information about your character/what they do.
    4: Kind of friends, a bit more backstory and insight. Can also share interest in the farmer themselves.
    6: Friends, more open. Displays clear relationship development. Willing to tell the farmer almost anything.
    8: Good friends, unlocking the climax of their character. (Angst and loredumps... Where I would personally place bombs like Jas crying about her parents.)
    10: Normal with the power of friendship. Still open but it's just the usual shenanigans. They have their struggles, but they are also doing well with the farmer to support them!
  • The length of vanilla events are usually between 1-3 minutes with most being around 1 minute. Shane's events are on the longer side since his story is "heavier" in content. I am biased as a chronic long event maker, but I think telling a story is more important than worrying about time elapsing in multiplayer without pauses. If you do struggle to make events under 10 minutes like me, just remember to write a disclaimer that your mod is intended for single player and you/your friend might pass out in multiplayer.
  • Long events aren't necessarily bad; boring events can feel longer than they are. To avoid boring events, try to throw in at least one question or farmer interaction to keep the player "active". Of course, the farmer doesn't always need to be present/active in your mod, especially if you're trying to show NPCs having lives outside of their input. In this case, try to keep things interesting whether that be in dialogue or actions. Eventing allows for a lot of "show, not tell" and narration is used sparingly in vanilla.
  • To help with concision, try to focus on cutting down the amount of down time as possible by making commands continuous. For example, if your event starts with the farmer walking into the scene, add a true at the end of the move command (to make something like /move farmer 6 0 1 true/ if you want them to move 6 tiles to the right) so that the next commands can start without the player having to wait for them to walk into place. The farmer walking into the scene isn't really the interesting part of your event. Just get to the interactions and information.
  • Get used to dense walls of text. You can code events as seperate lines as of 1.6, but I would advise against doing that as it could cause more complications down the line. Please merge your events into a block of text like in vanilla before debugging!

Limitations

Before you get too attached to some event ideas, here are a few things to note.

  • The Farm map is heavilly hardcoded and unfriendly for events. This is because the Farm house can be moved and players can place items around where the character will walk into. NPCs also only spawn outside of the farmer's door no matter what coordinates try to spawn them at. You can still use the move command on them to change their positions. For different "spawn" points, I would start the event's viewport at -1000 -1000 to show a black screen and then adjust the camera to where it should be after moveing everyone into place. (My use case for this is adding more NPCs to the side during a pet adoption event.) I would still avoid doing anything too complex on the Farm map because it is just a pain. You can also use positionOffset to warp them where you want them to be, but keep in mind you won't be able to use the move command in the event with that actor.
  • The FarmHouse map is also difficult to work with for the same reasons above. Only the kitchen and spouse room is really "safe" from decorations, so try to keep events to those areas to save yourself the headache if you really, really want to have an event at home.
  • Farmer animations are VERY limited and finicky. Attempting to use the showFrame command for their front-facing sitting sprite will result in them turning into a bowling pin. They can only sit sideways (unless if holding strings clearly meant for riding an animal). If you remember a farmer animation being used in a vanilla event, you should be okay.
  • Most things added with the specificTemporarySprite command (Penny's picnic blanket, Shane passed out on the floor, etc.) are hardcoded and cannot be positioned freely outside of the event they were made for. The only specificTemporarySprite intended for general use is the tiny heart that appears during kiss scenes.
  • PlayerKilled events (rescues from the Mine and waking up in the Hospital) are repeated and difficult to tell a complex story with. They are seperated by Mines/Hospital versions, so you can have 1 per location. Hospital events apply to everywhere outside of the mines. They don't need to take place in the Mine/Hospital, but the target must be for one of those before using changeLocation. The "Spouses React to Player Death" mod swaps out which character appears using When conditions that activate when the player chooses a spouse. Any mod that adds a PlayerKilled event will override all of the Mines/Hospital events, so there will be no randomization between which events show, meaning the player will no longer be saved by Maru or Linus, as well as other modded NPCs. You cannot try to keep track of how many times a player died and make an NPC grow increasingly more worried with alternate events. You cannot set an event to start only after the player died. (I tried.) It is preferred to have your PlayerKilled event locked behind marriage/a When condition for compatibility. Remember to write it with it being repeated in mind!
  • You cannot change the relationship status of the farmer with an NPC in vanilla. If really you want a character to initiate dating/break up, you can use the commands added in the "Dynamic Dialogue Framework" mod after adding it as a dependency. If using it, you would use setDating <NPCName> [true/false].
Emotes

Implementation (General Rules)

It takes a while for a beginner to remember, but here are some rules you should/will eventually know by heart. Don't worry if you don't just yet, I'll remind you in later sections! It just helps to have a quick cheat sheet for reference.

Movement Directions
x/y Coordinate Direction Facing Value Facing Direction
-x Left 0 Up (Backwards)
x Right 1 Right
-y Up (Backwards) 2 Down (Forwards)
y Down (Forwards) 3 Left


@ = Farmer's name. You can also use {{PlayerName)} in cases where @ doesn't work, such as the message command.

#$b# = Dialogue break. A dialogue box can fit around 177 characters before overflowing into the next text box.

-1000 -1000 = These coordinates should be used if you want the screen to be black. The game has special handling to not display anything at these coordinates.

64 15 = Coordinates for the viewport outside of the Farm house.

Content Patcher / Set-Up Templates

Event Starter Template

This is a minimal template for an event at 1 heart with NPCName and the minimum/maximum times as the limit. LocationName should be the name of the map your event starts on. The event ID should be unique to avoid overlaps (unless if you want to replace a vanilla event, in which case you should copy its event ID.) Event IDs are no longer limited to just numbers as of 1.6. Copy and edit as needed.

{
    "Action": "EditData",
    "Target": "Data/Events/LocationName",
    "Entries": {
		"ModId.EventId/f NPCName 250/t 600 2600": "continue/-1000 -1000/farmer 0 0 0 NPCName 1 1 0/skippable/pause 1000/speak NPCName \"Dialogue here.\"/pause 1000/globalFade/viewport -1000 -1000/stopMusic/end",
}
},

Custom Locations

If you are making events in a custom location, you will need to Load a blank JSON file before you can add in your event through EditData . Your blank.json is exactly as it sounds like it what you think it would be: a seperate JSON file with nothing but this:

{
}

Before you target your events to a custom location, first make sure they are accessible and added to Data/Locations like this:

// This is an example on how to add a location, but you'll need to change the name to your map ID and map file name
{
  "LogName": "Load Map Into Assets",
  "Action": "Load",
  "Target": "Maps/Custom_SomeMap", 
  "FromFile": "assets/Maps/Custom_SomeMap.tmx" 
},
{
  "LogName": "Add Map To Locations",
  "Action": "EditData",
  "Target": "Data/Locations",
  "Entries": {
    "Custom_SomeMap": { 
      "DisplayName": "Some Map Name",
      "DefaultArrivalTile": { 
        "X": 1,
        "Y": 23
      },
      "CreateOnLoad": { 
        "MapPath": "Maps/Custom_SomeMap"
      }
},

After all of that, you can make your custom location availible for events by inserting these lines. You can load as many locations as you want onto the same blank.json.

        {
            "LogName": "Custom Locations Events Blank",
            "Action": "Load",
            "Target": "Data/Events/Custom_SomeMap",
            "FromFile": "assets/blank.json"
        },

Eventing Essentials

You don't need preconditions to trigger an event (outside of the location the event is targeted for), but you probably will want them. The Event Data and Migrating to 1.6 pages on the Stardew Wiki are pretty straightforward with documenting the availible preconditions and explaining them, so I won't go too in-depth about every precondition listed. Events are set to be seen and unrepeatable unless if you use the eventSeen <event ID> falsecommand within the event.

Setting Up

If you're confused by the starter template above, here is an explanation. You can also check the Anatomy of an Event page for a more thorough walkthrough with more event preconditions tacked on if that helps.

{
    "Action": "EditData",
    "Target": "Data/Events/LocationName",
    "Entries": {

This adds the event to the game via Content Patcher. Event data is stored by location. Be sure to change LocationName to an actual location that you loaded in! In vanilla, this is usually the name of the .tmx file for your chosen map, save for the FarmHouse variations, which all use FarmHouse. Common beginner mistakes would include targeting Library instead of ArchaeologyHouse or AlexHouse instead of JoshHouse.  Example: If I wanted my event to start at the Railroad, I would change the 3rd line to say Target": "Data/Events/Railroad",

"ModId.EventId/f NPCName 250/t 600 2600": "continue/-1000 -1000/farmer 0 0 0 NPCName 1 1 0/skippable/pause 1000/speak NPCName \"Dialogue here.\"/pause 1000/globalFade/viewport -1000 -1000/stopMusic/end",

Event ID

ModId.EventId = Really just your event ID.

It's good practice to prefix your event name with what you have your mod ID as in your manifest.json (please know how to set up a content pack before going any further). You want this to be unique to keep your mod compatible with other mods. This can be numbers (and was limited to only numbers prior to 1.6) but there are only so many number combinations before everyone overlaps; it was changed because it's a disaster waiting to happen. Please use more than numbers.

Example: one of my event IDs should be something along the lines of Thylak.Submas.SubwaytoStardewEmmet10Heart.

NPC Hearts

f NPCName 250 = Precondition for heart levels. f is for friendship. NPCName should be replaced with the internal name of your NPC

This is straightforward for vanilla, which would simply replace the field with something like Elliott, but custom NPCs may be loaded in as something like {{ModId}}Emmet. (You should make your internal name unique for better compatibility but I didn't know before jumping into making an expansion SORRY. Don't be like me.) I used AdoptableJoltikEmmet as my event-only double in my sample/side mod for Subway to Stardew, but he's just Emmet there.

250 is how many heart points with the specified NPC are required for the event to play; 250 is also the amount of points for 1 heart, so multiply that by how many hearts you want to lock an event behind up to 2500 for 10 hearts and 3500 for 14 hearts.

Example: For a 10 heart event with Emmet I would have something like f Emmet 2500.

Time

t 600 2600 = This indicates the time frame between when the event can be triggered.

A day in Stardew starts at 6:00 AM (600) and ends at 2:00 AM (2600) with an hour being another 100. You can use a military time converter for the most part until you get to the later hours.

Time in Stardew progresses in ticks of 10. Unneccesary zeroes in your time (like 0600) will render your precondition invalid so your event won't start at all; the same applies to numbers higher than 2600 (like 26000).

Both values must be different with the first number being at least 10 less than the second number. If you want an event to start after the farmer sleeps/wakes up, set your target location to FarmHouse and set the time to t 600 610.

Example: I want Emmet to meet me in the morning between 6:00 and 10:00 AM. I would set my time to t 600 1000.

Music

continue= This is where your music selection at the beginning of the event should be.

If set to continue, it simply continues whatever track was playing when you entered an event (so something like spring1 if you came in from outside). Check the event spreadsheet for the music IDs and what track they correspond to! Music can be changed later with the playMusic command.

Example: I want the event to start with the movie theater background music, so I'll set that value to movieTheater.

Viewport

-1000 -1000 = This refers to where your viewport/camera is positioned when you start an event. First number is the x coordinate and the second is the y coordinate. Maps will never have their tiles in the negatives, so using -1000 -1000 as your coordinates will gurantee that your event starts as a black screen. The game also has special handling to not display anything at -1000 -1000 set as the coordinates, so use those if you need a fade to black. I prefer to place my viewport focus 1-2 tiles below where I have my characters so that the dialogue box doesn't cover them. The doorstep of the farm is 64 15.

Example: I want my event to focus on the middle of the train station's bench on the Railroad map. I will set this value to 39 42.

Event Actors

farmer 0 0 0 NPCName 1 1 0= This refers to which characters you use and the coordinates you spawn them in including facing direction. You need three numbers after the character's internal name denoting x, y, and facing values. You can have any amount of characters you want. Even if you don't include the farmer as an active/visible character in your event, you should still spawn them in to prevent any issues. If you want them offscreen, throw them into the void and spawn them like farmer -100 -100 0. You need to spawn everyone used in your event at the start whether or not they're visible at the beginning (unless if using the addTemporaryActor command). You can always spawn them in the negative void and use the warp command to bring them into the scene later. It doesn't matter if they overlap x and y coordinates. You will probably end up opening Tiled to find your coordinates.

Facing Values
Value Direction
0 Up (Backwards)
1 Right
2 Down (Forwards)
3 Left

Example: I want the farmer to start at the station steps while Emmet stands in front of the bench with Ingo offscreen facing left. I would set this to farmer 32 40 1 Emmet 39 41 2 Ingo -100 -100 3.

Event Content

skippable = Adds the skip button to the event. You cannot take away the ability to skip an event later. It is recommended to make all of your event skippable in case of repeat playthroughs. This does not need to be the first command, but it's good to have it appear as early as possible.

pause 1000 = If everything is in place and you don't want to start with your event actors walking into the scene as it fades in, use pause 1000 before a dialogue box command so that it doesn't freeze the event with it partially faded in. Events will automatically fade in from black. The fade lasts 1000 milliseconds.

speak NPCName \"Dialogue here.\"/ = Basic setup for one line of dialogue. Note that dialogue will need to have the "s prefixed with a \ so that it doesn't break the event code. The entirety of the event should be in quotation marks. See the "Making Messages" section for more on the dialogue commands.

pause 1000/globalFade/viewport -1000 -1000/stopMusic/end", = Generic ending with a fade to black. I always end my events with this chunk at the end, only swapping out the end command if I want to use something like end NewDay instead. You need to have an end command of some sort.

// A slightly more filled out example event would look something like this. This event starts at the Railroad before 10:00 AM at 10 hearts with Emmet, includes dialogue, the farmer walking, Ingo yelling off-screen, and ends with the farmer passing out after the event ends.
{
    "Action": "EditData",
    "Target": "Data/Events/Railroad",
    "Entries": {
		"Thylak.Submas.SubwaytoStardewEmmet10Heart/f Emmet 2500/t 600 1000": "movieTheater/39 42/farmer 32 40 1 Emmet 39 41 2 Ingo -100 -100 3/skippable/pause 1000/speak Emmet \"I am Emmet.#$b#I am now saying a second line of dialogue.$1#$b#Yup. What I do. What I say. Always the same.$3\"/move farmer 4 0 1/move farmer 0 1 1/speak Emmet \"Mhm. Let's depart. I am going to make you sleep now. You are now feeling verrrry sleepy.$6\"/speak Ingo \"EMMET, WHAT OPERATIONS ARE YOU CONDUCTING AT THIS HERE STATION?!$3\"/speak Emmet \"Shh. Just a demonstration. Don't worry about it. Now departing.\"/pause 1000/globalFade/viewport -1000 -1000/stopMusic/end NewDay",
}
},

Preconditions

Conversation Topics

The addConversationTopic command creates a new key for daily dialogue, this should be used in the event content- not the preconditions area!

An example from one of my events is /addConversationTopic SubmasIntroduction 7/; this allows me to add introduction dialogue for Ingo and Emmet as well as have other NPCs comment on their arrival after seeing their introduction event. This conversation topic lasts for 7 days just like the vanilla Introduction conversation topic, so the dialogue will only be availible until that time elapses.

  • Conversation topics last 4 days unless specified.
  • Conversation topic dialogue will only be shown once during the time frame. They stack with other conversation topic dialogue and the NPC's usual daily dialogue.
  • You can use conversation topics as a precondition to space out events. This is good if you have a lot of events in the same area and do not want them playing back-to-back.
  • You can use as many conversation topics in a precondition as you want.

To use conversation topics as a precondition, use /A <dialogue ID>/ to have the event not play while the conversation topic duration is active.

In my example, /A SubmasIntroduction/ would make it so that an event doesn't play until the week after seeing the introduction event is over.

In daily dialogue, you would use the conversation topic ID the same way you would as any other key. You can use this key on as many characters as you like. Between two dialogue files in my mod (seperated by character), it looks something like this:

"SubmasIntroduction": "I'm the Subway Boss Ingo, it’s a pleasure to meet you!",

"SubmasIntroduction": "...$3#$b#.....$3#$b#.......$3#$b#I am Emmet. I am a Subway Boss.",

Item Requirements

You can have an event only start if the farmer has a certain item in their bag with i <item ID>. A vanilla example of this being used is Jodi's largemouth bass event. If you want your event to be locked behind more than one item but only requiring one/either of them, you will need to make two seperate events with different preconditions. These events can share an event ID and content, just with different preconditions so that only one will play.

Days of the Week

Prior to 1.6, days of the week were exclusive, meaning that the event would play on the days not mentioned in the preconditions line. For example /d Tue Wed Thu Fri Sat Sun/ would have an event only availible on Monday. 1.6 added a new precondition so you can use DayOfWeek <day>+ to do the opposite; an example of this would be /DayOfWeek Mon+Tue/ for an event to play on both Monday and Tuesday.

Reversing Preconditions

You can add a! before a precondition to denote it doing the opposite of what is the default behavior. For example /!e Thylak.Submas.SubwaytoStardewEmmet10Heart/ would make it so that you can only see an event if you haven't seen an event with the ID Thylak.Submas.SubwaytoStardewEmmet10Heart already.

Common Commands

This is for commands that are helpful but don't require a whole category for explanation. Other commands will be mentioned, so check their categories for more explanation if you're confused.

Pause

The pause command is used to well... add pauses to an event! The number afterwards specifies how many milliseconds the pause takes. Adding pauses between commands can help to debug movements since some commands just don't like being used directly after one another. You'll remember which ones don't like each other eventually. For example, a jump after a move command will cause an NPC to keep walking further than specified, so it should be something like move Emmet 3 0 1/pause 10/jump Emmet instead of move Emmet 3 0 1/jump Emmet.

The minimum amount of milliseconds you can use is 10. This is nearly imperceptible. Here are some common millisecond values:

  • pause 10 = When you need a pause but really don't want to add a pause. Shortest pause possible.
  • pause 50 = Used between multiple positionOffset commands to make actors slide instead of snap into place. Used in vanilla for kisses (Sam).
  • pause 100 = Also used between multiple positionOffset commands to make actors slide instead of snap into place. Used in vanilla for kisses (Sebastian).
  • pause 250 = Map tiles in Stardew are all animated at 1 frame per 250 milliseconds. Good for actions that don't have a lot of "frames", like "animating" with the showFrame or addObject commands.
  • pause 500 = Used in vanilla after most commands including speak, emote, and faceDirection. You don't need to add them, but some may like the slower pacing (I don't).
  • pause 1000 = Used for fade in and fade outs.
  • pause 2500 = The exact amount of time a speech bubble added with the textAboveHead command appears for until it disappears.

Warp

The warp command is used to teleport your actors into the designated x and y coordinates. In your events, it should be formatted like /warp NPCName x y/. Aside from that, here are some things to know.

  • Warps happen almost instantaneously, taking even less time than a faceDirection command. You don't really need to specify true to make it continuous. Keep it to 2 values.
  • Do not specify a facing direction like you would with the move command. This is the most common error with the warp command.
  • It also helps to reset a character so that they do not walk off screen after trying to use the move command after using positionOffset on them. You can warp an actor in place to fix errors.

FaceDirection

The faceDirection command makes your actors face up/down/left/right with the first frame on their spritesheet for the row of the designated direction's walk cycle. In your events, it should be formatted like /faceDirection NPCName 0/with 0 being your desired facing direction value.

  • This command is not continuous. A short pause occurs while your NPC turns.
  • Do not use /move NPCName 0 0 0/ in place of a /faceDirection NPCName 0/ (in all directions) for best compatibility and futureproofing. You can add true after the direction value if the tiny pause bothers you.
  • Using faceDirection may show the second column on your walk cycle instead of the first after a showFrame command. To fix this, use the showFrame command again for the correct frame it should display (first column in the walking sprites for the desired direction) and then use faceDirection normally to restore their breathing animation.
Facing Values
Value Direction
0 Up (Backwards)
1 Right
2 Down (Forwards)
3 Left

ChangeLocation / ChangeToTemporaryMap

The changeLocation command is used to switch maps. There is no limit to how many times you can change locations. In your events, it should be formatted like /changeLocation LocationName/. You can also use changeToTemporaryMap to accomplish the same goal.

  • You can switch locations to maps that aren't loaded into Data/Events. Only the locations you trigger an event in need to be loaded in with a blank.
  • You cannot use event fork in a location not loaded into Data/Events. You will also need to load the event map into Data/Events/Temp before you do.

IgnoreCollisions

The ignoreCollisions command allows actors to walk through tiles on the Buildings layer of a map without issues. In your events, it should look something like /ignoreCollisions NPCName/.

  • An event will freeze if the farmer walks into an invalid location, so I would highly reccommend adding an /ignoreCollisions farmer/ to the start of your event (after skippable). This would allow the event to run while debugging and fixing movements.
  • You can use ignoreCollisions on any and all actors in an event, even those added with addTemporaryActor. Make sure it comes after you spawn in your TemporaryActor first.

Camera

Viewport

Viewport refers to where the camera is positioned with x and y coordinates. I recommend having your event positioned 1-2 tiles below where your characters/main focus is so that it isn't obscured by any dialogue boxes.

  • viewport x y = Snaps the viewport into place. I like to use the fade command before it if I want to fade in. (Ex. /fade/viewport x y/)
  • viewport x y true = Fades into the scene without a pause. I prefer using the fade command instead out of habit.
  • viewport x y true unfreeze = Used in one vanilla event to train the camera on the player in the FarmHouse. At -100 -100 it tells the game to fade in to the scene while ignoring the void and position the camera on the player.
  • viewport x y clamp = Focuses the camera to show no black border. Good for if you want the scene to be somewhere like the edge of Town outside of the BusStop entrance.
  • viewport -100 -100 true unfreeze= Tells the game to fade in to the scene while also ignoring the void and just position the camera on the player.

Pan / Fade

There is almost no difference between all the fade commands. You can use whichever you like. My routine consists of the good old regular fade in the middle of events and a globalFade to end.

To pan the camera, use viewport move <x> <y> <duration>.

  • The x and y coordinates are not by tiles nor pixels. I am not sure as to the exact rules, but I have found that it pans about the length of the dialogue box with a portrait (brought up by the speak command).
  • The duration is determined in milliseconds. To start and match vanilla, use 5000 for every count of 2 in the x/y coordinates.
  • Use small numbers (like 1-2) for your x and y coordinates. A common misconception is that it will pan by tiles/pixels (the wiki is wrong). The camera pans FAR past that. There is very little control over where it can be positioned. You can only use whole numbers.
  • You can pan the camera diagonally.

AmbientLight

The ambientLight command is used to set lighting on temporary maps such as the telescope scenes in Maru's stargazing event. Much like regular maps, the RGB values are subtractive, with 0 0 0 being full brightness.

If you need help visualizing the subtractive numbers to colors, you can play around with the AmbientLight spreadsheet.

Flash / Glow

I haven't played around with this too much because I am sensitive to light and preferred to just use fades to black instead. Though it may not be as immersive, those with light sensitivity might appreciate your events being easier on the eyes (I would). That said, if you still want to use them, here's what I know about the flash/glow commands.

You can use screenFlash to make the screen white and then hold it for a specified number of seconds (must be over 1). Unfortunately, the white will not fade in and the screen will flash instantaneously (be careful). screenFlash 5 will cause a flash to white and hold the screen as white for 5 seconds.

The glow command will fade into a specified RGB color until you use the stopGlowing command. I would use this instead of screenFlash since I'd rather not give myself a headache when exposing myself to flashing lights over and over during debugging.

Movement

Which Command Do I Use?

For making an NPC/the farmer walk, you will find yourself using either the move or advancedMove commands. These both use a combination of x/y and facing directions to make an actor travel across tiles. You cannot make a character walk diagonally with these commands. You must write them moving horizontally/vertically, one direction at a time.

  • move: Most common. Automatically pauses the event until the actor finishes moving the specified amount of tiles unless suffixed with true. You should try to use this until you find that you need an advancedMove.
  • advancedMove: Helpful for multiple directions and more complex movements. Will not pause the event when active. Use if you have multiple characters walk together outside of one straight line. Can be looped. Good if you want something in the background like Emily walking back and forth behind the Saloon's counter. Can force a character to walk even after a positionOffsetunlike the move command.

Move

You must specify x, y, and facing directions each time you use the move command. You can only specify either x or y in a single command, the other must be set to 0.

  • You cannot use the move command after using positionOffset on an actor until you warp them. Not doing so will result in them walking endlessly offscreen and into the void.
  • Adding true after the facing direction will make the next command start while the actor walks. This is good if you want them to walk while playing a dialogue line or walking in/out of the scene. Example: /move Emmet 0 10 2 true/speak Emmet \"I am approaching. While talking.\"/
// In this example, Emmet moves 10 tiles right, 20 tiles forward, 30 tiles left, 40 tiles backwards, and faces forward after he's done walking.
"speak Emmet \"I'm on my way. I'm on my way.\"/move Emmet 10 0 1/move Emmet 0 20 2/move Emmet -30 0 3/move Emmet 0 -40 2/speak Emmet \"I have arrived. I have arrived.\"/end"
Move Directions Guide
x/y Coordinate Direction Facing Value Facing Direction
-x Left 0 Up (Backwards)
x Right 1 Right
-y Up (Backwards) 2 Down (Forwards)
y Down (Forwards) 3 Left

AdvancedMove

Only specify facing direction when at a pause or ending the advancedMove. Do not specify facing direction for every direction walked unless you specify a duration to pause at. In your events, this should be formatted something like /advancedMove NPCName false x y x y x y x y facing milliseconds/.

If you are having issues when debugging, you should use stopAdvancedMoves and warp them onto the tile they should be before continuing before using another movement command on your actor. It is good to get into the habit of using stopAdvancedMoves even if no issues are found.

  •  stopAdvancedMoves applies to all actors and cannot specify only certain actors.
  •   waitForAllStationary will pause the event until all movements are done. You can use this to make advancedMove pause like a regular move without needing to figure out the exact milliseconds for an actual pause.
  • Change false after the NPC's name to true if you want them walking around to loop. This also stops after stopAdvancedMoves.
  • You need to specify seconds and facing at the last movement in the command. If you do not, your command will be invalid. The last number is arbitrary, but I usually leave it as 100.
  • You can add a stop in the middle of the command. This will look something like /advancedMove NPCName false x y x y facing milliseconds x y x y facing milliseconds/ with the second movement having a pause.
  • For reading multiple (two or more) movements, you should look to see two pairs of 0's close to each other otherwise your command will break. No moving in the x direction twice unless specifying a pause. Same for the y direction. Go x then y, or y then x. No x then x or y then y.
  • The up facing direction value in an advancedMove is 4 instead of the usual 0.
// In this example, Emmet moves 10 tiles right, 20 tiles forward, 30 tiles left, 40 tiles backwards, right again before facing backwards for 2500 miliseconds, 20 tiles forward, and 30 tiles left before stopping to face forward for 1500 milliseconds. He repeats this behavior.

"speak Emmet \"Fueled up. Full steam ahead.\"/advancedMove Emmet true 10 0 0 20 -30 0 0 -40 10 0 4 2500 0 20 -30 0 2 1500/speak Emmet \"These tracks go on forever.\"/end"

// This command will continue with little to no pause before bringing up the next command, which in this case is his next spoken line.
AdvancedMove Directions Guide
x/y Coordinate Direction Facing Value Facing Direction
-x Left 4 Up (Backwards)
x Right 1 Right
-y Up (Backwards) 2 Down (Forwards)
y Down (Forwards) 3 Left

Speed

The speed command can be used to make an actor walk faster or slower. It does not affect anything outside of the move or advancedMove commands. It is split between NPCs and the farmer.

  • Default speed in events is 3 for both NPCs and the farmer.
  • Speed is persistent with the farmer. When changing speed, remember to use /speed farmer 3/ when you want them to go back to normal and before you end your event if you haven't already.
  • Speed resets to default with NPCs after every movement command. advancedMove counts as one command. To have consistent speed while using the move command, you need to set the speed each time. Here is an example from one of my events: /speed Emmet 8/move Emmet -2 0 0/speed Emmet 8/move Emmet 0 -5 3/
  • Do not set the speed to 1 with any actor. This will break your event and movements.
  • Lowest speed you can have is 2.
  • Unsure as to if there is a cap on speed, but I wouldn't use anything above 8. It's comically fast. Anything more I think would be too jarring.

Jump

You must specify your actor's name. Jump intensity can be omitted to make the command just /jump NPCName/. Jumps can be adjusted to be lower or higher with a value at the end. The default jumping value is 8. If lowering the jumping intensity, your command should look something like /jump NPCName 3/.

  • Jumps are near-continuous. You can emote while jumping.
  • The jump sound scales with the jumping height. You will not hear a sound effect with jump NPCName 1.
  • You can make an actor jump in a specified direction by using /jump NPCName/move NPCName x y facing/.
  • You can change the distance of the jump with the speed command. This will not change the height of the jump without a movement command.
  • You cannot use jump after a move command. This will cause your actor to walk further than intended. Add a pause if you want them to walk and then jump in place (ex: for a shocked reaction). You can /jump NPCName/move NPCName 3 0 1/ but you cannot /move NPCName 3 0 1/jump NPCName/ .

ShowFrame

The showFrame command is used to display a specific frame on an actor's spritesheet. Check the event spreadsheet for reference on the frame IDs for both vanilla NPCs and the farmer. The farmer spritesheet is much more finicky to work with, many sprites will not work!

  • This command is instantaneous.
  • Removes the breathing animation when active. Use faceDirection if trying to make an NPC turn around/reset if you want a breathing animation. Otherwise, this may be helpful if you're simulating something like photos in Haley's event.
  • NPCs cannot have their sprites flipped unless using a workaround with the animate command.
  • The farmer can have their sprites flipped with this command by either specifying farmer where NPCName usually would be or omitting it. The farmer is selected by default.
  • /showFrame 101/ = The farmer's kissing sprite, facing right as per default.
  • /showFrame farmer 101/ = The farmer's kissing sprite, flipped to face left.
  • The farmer cannot sit facing forwards. Only the farmer's side sitting sprites work as intended. Attempting to use any sitting sprite (besides the one of them holding strings for riding an animal) will turn them into a bowling pin.

Animate

The animate command is primarily used when showFrame doesn't suffice or is too inefficient for its purpose. This is good to use on characters in the background to make a scene feel more lively, such as Lewis and Marnie drinking in the Saloon. Animations can be looped, flipped, and vice versa. There is no limit to the amount of frames you can add, but you shouldn't have to use many.

As per the wiki, it should look something like /animate <actor> <flip> <loop> <frame duration> <frames...>/. The actor is either farmer or an NPC name, flip and loop are true/false values, the frame duration is in milliseconds, and frames are the sprites on the spritesheet starting from 0. I usually start off with my frame duration being set to 250 milliseconds and adjusting it to be faster/slower from there.

  • This command is instantaneous.
  • Unlike showFrame, the farmer must be specified as an actor.
  • You can use this command with only one frame to flip a vanilla NPC's sprite without having to add or edit their spritesheet (preferred for compatibility). For example, if I wanted to make Maru kiss Penny despite all vanilla NPCs only having kiss sprites facing left, I would have something like /showFrame Penny 20/animate Maru true false 250 28/ in my event.
  • To stop an animation and make an NPC move again, I usually use a combination of stopAnimation, showFrame, faceDirection, and warp to "reset" them enough to move without making the event freeze or having the actor walk into the void. You don't have to do all of this if there's no issue, but I got into the habit of doing something like /animate NPCName true false 250 0 1 2 3/speak NPCName \"Event stuff until I want to stop an animation.\"/stopAnimation NPCName/showFrame NPCName 3/faceDirection 2/warp NPCName 2 9/move NPCName 3 0 1/ every time I made an animated NPC move. This is usually not necessary with the farmer.
// Pierre fistfighting, facing right as default, and stopping on the final frame without repeating at 200 milliseconds per frame
/animate Pierre false false 200 21 22 20 21 20 21 20 17 18 20 21 20 21 20 21 22 20 21 17 18 19/

// Pierre fistfighting, flipped to face left, and stopping on the final frame without repeating at 200 milliseconds per frame
/animate Pierre true false 200 21 22 20 21 20 21 20 17 18 20 21 20 21 20 21 22 20 21 17 18 19/

// Pierre fistfighting, flipped to face left, and looping the animation at 200 milliseconds per frame
/animate Pierre true true 200 21 22 20 21 20 21 20 17 18 20 21 20 21 20 21 22 20 21 17 18 19/

// Pierre fistfighting, facing right as default, and looping the animation at 200 milliseconds per frame
/animate Pierre false true 200 21 22 20 21 20 21 20 17 18 20 21 20 21 20 21 22 20 21 17 18 19/

PositionOffset

The positionOffset command is used to shift an actor a specified number of pixels. This is helpful for adjusting placement when a warp onto a specified tile isn't enough; common use cases include making actors sit and kiss. I usually start out with larger numbers such as 20 or 40, adjusting up or down by 10, and then fine-tuning in the 1's.

  • This command is instantaneous. Use pauses if you want your actor to "slide" into place.
  • Diagonal movement is possible. You can specify both x and y values in a single command!
  • You cannot use the move command on an actor until you use warp on them. They will walk into the void and your event will freeze.
  • You can offset the y value to bring an actor backwards or forwards. I usually bring characters forward about 4-7 pixels so they overlay the farmer in a hug and don't clip through chairs.
// Kissing template with Elliott. Adjust as necessary. You will need to add or remove more offset commands depending on NPC size!
/faceDirection Elliott 3/faceDirection farmer 1/pause 100/positionOffset farmer 2 0/pause 100/positionOffset farmer 2 0/pause 100/positionOffset farmer 2 0/pause 100/positionOffset farmer 2 0/positionOffset Elliott -2 0/pause 100/positionOffset farmer 2 0/positionOffset Elliott -2 0/pause 100/positionOffset farmer 2 0/positionOffset Elliott -2 0/pause 100/positionOffset farmer 2 0/positionOffset Elliott -2 0/pause 100/positionOffset farmer 2 0/positionOffset Elliott -2 0/showFrame Elliott 35/showFrame 101/pause 4000/

For more templates using positionOffset, I would check Arknir's Tips for NPC Movement in Events!

Making Messages

Speak

Much like daily dialogue, lines are broken up by #$b# and portrait commands are placed at the end of a line. You do not need to specify the first/neutral portrait as $0. Unlike daily dialogue, you can only use #$b#; using #$e# will break your event as you can't exactly choose between either continuing to speak to an NPC or running off. Events are verrrrry railroaded. You're stuck continuing it.

The quotation marks (") around the line must be prefixed by a \ to make /speak NPCName \"A valid speak command!\"/.

The maximum character count for a text box is around 177 characters, so add a #$b# when you reach around that number if you want cleaner lines and are picky about your sentences not being broken up.

When using tokens (such as @ for the player's name), you should keep your line around 155 characters.

// Example of Emmet saying three lines. First with the neutral/$0 portrait, second with his happy portrait, and third with his unique portrait
"pause 1000/speak Emmet \"I am Emmet. You are @.#$b#I am now saying a second line of dialogue.$1#$b#Yup. What I do. What I say. Always the same.$3\"/end"

Message

This works like the speak command (and a daily dialogue prefixed with %) to display a text box with no dialogue portrait.

@ for the player name does not work in this command; use {{PlayerName}} (with the brackets, capitalization, and everything!) instead.

The text box adjusts in height according to the amount of text you wrote. You can write as much as you want, but make sure you add a break if it ends up overflowing out of the screen.

// Example of the message command
/message \"You are {{PlayerName}}. This is a message command. There is no NPC or portrait associated with this.#$b#You can use line breaks too.\"/
Emotes

TextAboveHead

The textAboveHead command works like the speak and message commands to display a speech bubble above the actor's head.

It's more like a message command in the sense that you have no portraits and need to use {{PlayerName}} instead of @. Many characters do not work and are instead replaced with special characters, such as < turning into a heart.

This displays for 2500 milliseconds and persists unless if you use another textAboveHead command to override what was being said earlier. This isn't too much of an issue since it's not too long and people need time to read, but keep the fact that you will need to for it to disappear in mind. You cannot adjust how long this displays for.

Emote

The emote command displays the squiggly white bubbles with icons that you often see in other events. These appear for about 1500 milliseconds and are not continuous by default.

I like to use these in place of actual pauses between dialogue. You can only use emotes from 4-60 in increments of 4 otherwise your event will loop endlessly. /emote NPC 0/ is not a valid command because emote 0 is not valid. You must use 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, or 60.

Number Emote
0 Nothing. Do not use this. Your event will break.
4 Water drop with a question mark for empty watering can.
8 Question mark
12 Angry / squiggles
16 Exclamation mark
20 Heart
24 Sleepy zzz's
28 Sad / sweat drop
32 Cat mouth smile
36 Angry / X emote
40 Ellipses / pause / dot dot dot
44 No bait
48 Community center bundle?
52 Video game
56 Music note
60 Blushing smile

Questions

Which Command Do I Use?

If you're making a question in an event, there are three commands that you can use to implement them. Usage varies based on how the question affects your event. The maximum amount of options you should have is 10, otherwise they won't all fit on the player's screen.

  • question null = Used when all the player responses have no effect on the rest of the event. Good for if you want a small and inconsequential interaction for fun (ex. saying "Hi!" or "Hello.")
  • quickQuestion = All the player responses can have different effects on the rest of the event. They don't all have to be different, but the option is there. Best if you want friendship and dialogue changes for different responses. There's no limit to how many options you can have.
  • question fork = Only two responses allowed. To be honest, I hate this command. Unless if you're doing something drastic like rejecting Elliott's boat ride at 10 hearts, I wouldn't use this command at all. quickQuestion was added in 1.5 to help questions in events not be so terrible to work with. This is what you had to work with.

Question Null

You can have as many meaningless responses as you want (try to stay under 10 unless if you want it to overflow on a screen). Responses are seperated by a #. It is formatted very similarily to the speak and message commands with the same necessary space before \" enclosing the dialogue with a \"/ at the end. Here is a template:

/pause 10/question null \"Response prompt.#Answer 1 response.#Answer 2 response.#Answer 3 response.\"/pause 10/

Example use of this command from one of my events:

/question null \"I am verrrrry busy.#How long have you been working for? You look tired......#Emmet, don't you think you should take a break?\"/

QuickQuestion

The quickQuestion command switches the format a bit from the usual event format. Once you get used to \\ in place of / alongside (break) as an option divider it will be easy. Here is more explanation on the rules:

  • (break) = Divides routes between answers. Yes, you need to type out (break) as if it were a / or a # , with the word break surrounded by parentheses and everything. I know it looks terrible.
  • \\ = replaces / until the question portion is over. Use / only at the end and when you are ready for the question paths to merge back into the main event. Using it in the middle of your responses will cause your event to stop.
  • You can use most event commands in a quickQuestion. This is the preferred question format for different dialogue options, emotes, movements, and friendship changes. The only commands you can't use within a quickQuestion are more question commands (no quickQuestion within a quickQuestion, no question null, no forks) and the end commands (such as end warpOut or end NewDay). There is no limit to how many commands you use in an option path.
  • You can use the switchEvent command in a quickQuestion to have multiple option paths that lead to more questions the same way you would as a fork while also not being limited to two choices. I would reccommend looking at the mod "A Secret Forest Walk" to see how this can be done!
/pause 10/speak NPCName \"Dialogue here leading up to the question\"/quickQuestion Response prompt, usually says the question.#Answer 1#Answer 2#Answer 3(break)emote NPCName 16\\friendship NPCName 250\\speak NPCName "Answer 1 response.\"\\pause 10(break)emote NPCName 16\\speak NPCName "Answer 2 response.\"\\pause 10(break)emote NPCName 16\\friendship NPCName -250\\speak NPCName \"Answer 3 response.\"\\pause 10/message \"Event continues normally from here, all options merge back\"/pause 10/

Example use of this command from one of my events:

// If selecting the first option, you recieve +30 friendship with Elliott, and Harvey shoos him out of the Hospital mid-thought.
// If selecting the second option, you lose -20 friendship with Elliott, -30 with Ingo and Emmet, and Elliott storms off.

"/speak Elliott \"Have things really gone that badly for them? To such an extent that they faint from exhaustion when trying to achieve their goals?$2#$b#That doesn't seem to be very healthy of them.... What do you think?$7\"/quickQuestion What do you think?#I agree. They seem to be lonely, too...#They'll be fine. Don't bother them.(break)friendship Elliott 30\\textAboveHead Elliott \"Perhaps... I could...\"\\speed Harvey 5\\move Harvey 0 7 2\\emote Harvey 12\\faceDirection farmer 0\\jump farmer 5\\shake Elliott 1000\\emote Elliott 16\\speak Harvey \"You two! Go home, and get some rest already!$5\"\\emote Elliott 28(break)friendship Elliott -20\\friendship Emmet -30\\friendship Ingo -30\\move Elliott 0 0 2\\speak Elliott \"Hmph! Well, okay. If that's what you think, then so be it.$5\"\\emote Elliott 12\\move Elliott 0 3 2\\warp Elliott 100 100/pause 1000/globalFade/viewport 1000 1000/stopMusic/end",

Question Fork

Again, I would only use this command if you really know what you're doing and/or are making drastically different changes with your option paths akin to that of a rejection. Note the different fork being on a seperate line. If using this as a template, make sure you use question fork1 with the 1 and keep the yes/no options in the same order. You will need to make your own fork ID.

{
    "Action": "EditData",
    "Target": "Data/Events/LocationName",
    "Entries": {
		"ModId.EventId/f NPCName 250/t 600 2600": "continue/-1000 -1000/farmer 0 0 0 NPCName 1 1 0/skippable/pause 1000/message \"This is an example of a question fork.\"/question fork1 \"Do you want to proceed with the main event?#Yes#No\"/fork QuestionForkAnswerNo/speak NPCName \"Yippee!!! Thanks for saying yes. Let's go do event stuff!\"/message \"I'm cutting this down for example purposes but the event continues normally from here\"/pause 1000/end",
  "QuestionForkAnswerNo": "emote NPCName 16/speak NPC \"No? Okay. Fine. Be that way.\"/end",
}
},

Example use of this command from Elliott's 10 heart event:

 "43/f Elliott 2500/w sunny/t 700 1300/G !IS_PASSIVE_FESTIVAL_TODAY SquidFest": "ocean/-1000 -1000/farmer 13 16 2 Elliott 13 27 1/specificTemporarySprite elliottBoat/skippable/viewport 17 26 clamp true/speak Elliott \"@... Would you do me the honor of joining me for her maiden voyage?\"/question fork1 \"Get in the boat?#Yes#No\"/fork NoToElliott/globalFade/viewport -1000 -1000/changeToTemporaryMap ElliottSea false/playSound wateringCan/message \"I'm cutting this down for example purposes but the event continues normally from here\"/pause 1000/end",
  "NoToElliott": "emote Elliott 16/pause 800/end dialogue Elliott \"...$a\"",

Temporary Tricks

Some more technical commands used in eventing magic.

ChangeName / ChangePortrait / ChangeSprite

These all require a bit of work in Content Patcher and outside of the event itself. For portrait/sprite changes, you will need to load them in properly before you can use them.

changeName NPCName NewDisplayName = Changes the display name of the actor. This will not change their internal name, so you will need to use the name before the change in the commands to make them move/speak/etc. This is good for use with temporary actors who have not been loaded with a display name. Compatible with i18n translations.

A labelled tilesheet for use in the addBigProp command.

changePortrait NPCName Specification = Changes the portrait for the actor. Must be loaded in as NPCName_Specification. This would be something like Penny_Beach and used in her 10 heart event as /changePortrait Penny Beach/

changeSprite NPCName Specification = Changes the sprite of the actor. The spritesheet must be loaded in as NPCName_Specification. Same as the portrait equivalent of this command.

// Example taken from Maru's hospital event, where she switches into her uniform
"7/f Maru 1000/p Maru": "Hospital_Ambient/-1000 -1000/farmer -10000 -10000 0 Maru 9 15 3 Harvey 7 10 0/skippable/changeSprite Maru Hospital/changePortrait Maru Hospital/showFrame Maru 18/viewport 10 15/pause 4000/speak Maru \"*sigh*... I'm so sick of preparing these samples...$s\"/end"

AddTemporaryActor

Temporary actors are actors that only appear in events and behave like regular NPCs. They do not disappear with removeTemporarySprites. You will need to load a temporary actor's spritesheet seperately from your event before being able to spawn them in, much like a custom NPC.

Portraits are optional, spritesheets are mandatory. Spritesheets can be any size you want; they are not limited to base game size restrictions as long as you have a 4 columns. (I use this to load in all my Pokemon!)

  • Without a disposition or entry in Data/Characters, your actor will be added into your event with its internal name; this is easy to overcome by using the changeName command, so please make a unique internal name. As per the wiki, the addTemporaryActor command is utilized like addTemporaryActor <character> <sprite width> <sprite height> <tile x> <tile y> <facing> [breather] [Character|Animal|Monster] [animal name]. You can see how the secret woods Bear is loaded in for reference.
  • For custom actors and in most cases, you will be loading in a Character regardless of actual species and not need to specify animal name.
  • Breathing is decided via true/false values.
  • Temporary actors behave much like regular NPCs, but may be trickier to move if they are larger than the 16 x 32 pixel size for standard NPCs. They will walk further than specified and warp a bit weirdly compared to standard-sized NPCs, but it isn't too much of an issue. Don't be too picky with them.
// This loads in AdoptableJoltikGalvantula as a non-breathing temporary actor at 33 x 26 pixels and on tile 19 20 facing left before changing her name to display as Galvantula. Note that Galvantula is still commanded with her internal name

"pause 1000/addTemporaryActor AdoptableJoltikGalvantula 33 26 19 20 3 false Character/changeName AdoptableJoltikGalvantula Galvantula/move AdoptableJoltikGalvantula 0 -4 1 true/speak AdoptableJoltikGalvantula \"Gal... (Okay...)\"/end"

AddObject / AddBigProp

Items added through these commands can be removed with the removeTemporarySprites command.

The addObject command broke a bit in 1.6 as it no longer supports non-valid objects on the Maps\springobjects.png tilesheet and swapped out a few items, but its general usage remains the same.

  • Assuming you know what object you want to add, you would use addObject <x> <y> <sprite index> [layer].
  • The x y being the coordinates of the tile you want to spawn the item on, sprite index being the object's ID on the tilesheet, and layer being its numerical order on a map in Tiled (use 1 - 4, I usually just set it to 1.
  • The sparkling effects from sprite indexes 352 - 367 are no longer valid items and will display as an error sign. To animate sparkles, see the temporarySprite command.
  • The tiny green stool at sprite index 312 now displays as a brown single-seat sofa as of 1.6.

The addBigProp command works similarly to the addObject command, but pulls from TileSheets\Craftables.png instead of Maps\springobjects.png. This tilesheet remained largely unchanged. You will need to count from 0 for every item up until you find the sprite index for the prop you want. I made a terrible, terrible table at 4 AM to help you with that. I used /addBigProp 28 22 106/ to add a camera on a tripod to one of my events. I can only confirm that the numbering is accurate up to 106. Have fun.

AddLantern

Items with the addLantern command use an object from the springobjects spritesheet and can be set to emit light.

These cannot be removed even with the removeTemporarySprites command. They will be stuck in your event until the event is over.

  • The sparkling effects from sprite indexes 352 - 367 are no longer valid items and will display as an error sign. To animate sparkles, see the temporarySprite command.
  • A light radius of 0 places the sprite with no light, which may be helpful if you want to use removeTemporarySprites but only want to clear items added with addObject.

TemporarySprite

This command is used for the sprites on Tilesheets/animations.png, such as the various sparkle effects.

In your event, it should be formatted something like /temporarySprite <x> <y> <row in texture starting from 0> <number of frames starting from 1> <speed of frame rate in milliseconds> <flipped> <layer depth (like addObject, so 1, 2, 3, etc)>/. Much like addObject, you should just set your layer value to 1 if you want it to not clip through anything.

The added sprite automatically disappears when the animation finishes.

// I use the icy-blue sprites on row 13 for a "using a Pokeball" effect. This is a 10 frame animation that I usually set to play at 1 frame per 100 milliseconds.
"speak Emmet \"All aboard, Eelektross.\"/temporarySprite x y 13 10 100 false 1/pause 2000/"

Ends

All ending commands can only be used once in an event. They cannot be used in a quickQuestion. These can be used with end as the actual ending command.

End WarpOut

This will end the event and drop the farmer off in the nearest exit for that location. You cannot specify which location uses which exit. For more specification, use this alongside the changeLocation command. For example, one of my events uses /changeLocation FarmHouse/end warpOut/stopMusic/end" to end with the farmer outside on their porch after being walked home at night.

End Dialogue

The end dialogue command can only be used once as it is an ending command. This dialogue will override their daily dialogue for the day, so they will not say anything else to you. This is good for events where you reject an NPC so badly they do not want to talk anymore. (I use it to make Emmet go nonverbal, but vanilla uses it in Elliott's 10 heart event to emphasize how awkward rejection is.)

You cannot specify multiple NPCs to add dialogue for after an event with this command. If you want to do this, use addConversationTopic and implement their lines in the newly made daily dialogue key.

PlayerKilled

You can use minedeath in any event to make the farmer lose items from their bag even in the Hospital's PlayerKilled event. This is helpful if you don't want Harvey to charge you, but still want the lost item penalty. You can also omit both the minedeath and hospitaldeath commands in those events for no lost item penalty. This isn't an ending command. You can use it more than once, but I don't see why you would.

Debugging

Event debugging will require playtesting your event multiple times until it's perfect. To make this easier, you don't have to open and close your game every time you make a change. Here are some commands that will save your life.

Patch Reload

Prefix patch reload before your Mod ID (in your manifest, should be something like AuthorName.ModName) into the SMAPI tab and hit enter. This will refresh your mod and load it in-game after making any changes.

This command makes it so you don't have to restart your game after editing your event. patch reload is not case-sensitive, but your Mod ID is.

Example: I have Subway to Stardew's ID set as Thylak.Submas so I would type patch reload Thylak.Submas into SMAPI.

Debug Ebi

Prefix debug ebi before your event ID into the SMAPI tab and hit enter. This will start your event without having to meet the preconditions to trigger it manually. You can play the event again even if you have already seen it.

You cannot have any menu tabs open or try to debug ebi your way into an event on the same map it is supposed to start at. It will not play properly.

Example: To play the example event ID I used earlier, I would type debug ebi Thylak.Submas.SubwaytoStardewEmmet10Heart into SMAPI.

EventSeen

Prefix eventseen before your event ID into the SMAPI tab, suffix it with false, and hit enter. This will mark the event as unseen to allow you to attempt to trigger the event manually and by meeting all the preconditions needed if you have already triggered it. (You most likely will when debugging, this saves you the hassle of making a new save file!)

Example: To play the example event ID I used earlier, I would type eventseen Thylak.Submas.SubwaytoStardewEmmet10Heart false into SMAPI before trying to enter the Railroad at 10 hearts with Emmet.

Debugging Issues and Solutions

Some issues in event script and how to solve them. Please check LenneDalben's table for more. I will update this as I remember more errors.

Issue Cause Fix
Actor walks further than specified after using a move and jump command. The jump command doesn't like being directly after the move command. Add a pause, faceDirection, or emote to seperate the move from the jump. It should be something like /move NPCName 3 0 1/pause 10/jump NPCName/ .
Question fork 1 only plays the main event no matter which option is selected despite the question fork command being set up correctly. You made an error in the main event's later commands. Double check that all your commands are written out properly. You may have capitalized a command wrong.
Event won't start at all. Your preconditions are wrong and/or your target location is incorrect. Double check your preconditions. You may have set a time frame incorrectly
Emote keeps looping. Your emote is invalid. Check if your emote number is correct.
Dialogue keeps looping after a speak command. Your speak command is invalid. Check that you have a single space after your NPCName, correctly placed slashes, and line breaks/portrait commands inputted correctly.