CUSTOM EVENT GUIDE by Siv Hello! I'm Siv, maker of Siv's Marriage Mod. This guide is meant to help anybody make custom events for their game. If you feel like your favorite character just didn't get enough attention, this is a good way to add content. You can make virtually as many events for an NPC as you wish. This guide will assume you have a basic understanding of how to mod the game's XNB files. If you don't know how to do this, I recommend visiting this thread to find guides. You will also need a source code editor like notepad++. GETTING STARTED In your unpacked Content folder, go to Data\Events. Select the location where your event will trigger. If your location does not have a <location>.yaml file already in the Events folder, you can add one yourself. Simply open one of the .yaml files in the folder and save it as the EXACT name of your location (i.e. "Tent.yaml"). This IS case-sensitive, and you MUST include the .yaml extension. Then, delete everything below the "content: #!Dictionary<String,String>" line. Add the parameters that must be met for your event to trigger. (These parameters are explained in detail below in the blue section.) Add the script for your event. (Explained below.) Pack the .yaml back into an .xnb file, then replace the current .xnb file in your game's content folder (if one already exists). Test the event, then find & fix any errors. EVENT TRIGGERS "7563/f Lewis 1500/z spring/w sunny/e 457/t 1000 1600/n mayorLetter: This is the example trigger I will be using. This is not a real event in the game, but it would trigger under the right circumstances if I added it. "/" is the character used to separate parameters of the trigger. 7563 This is the unique ID of the event. This ID must not be the same as any other event's ID, otherwise when one triggers then you will not be able to trigger the other event with the same ID. For safety, I usually use a long (but not random) string of numbers. f Lewis 1500 This parameter means the event will only trigger when Lewis is at 1500 friendship. One heart is equal to 250 friendship, so you can do the math here. This event will only trigger when Lewis is at 6 hearts. You can replace "Lewis" with any NPC, but it must be spelled correctly and is case-sensitive. z spring Event will only trigger in spring. Can be replaced with "summer", "fall", or "winter". w sunny Event will only trigger when weather is sunny. Can be replaced with "rainy", "windy", or "snowy". e 457 Event will only trigger when you have seen this event ID. Can be replaced with any event's ID (as long as it doesn't match the current event's ID). t 1000 1600 Event will only trigger between 10:00am and 4:00pm. This uses 24 hour time. You can replace either number with whatever you want (usually in between 600 and 2350). n mayorLetter Event will only trigger once you have read the mail "mayorLetter". Go to Content\Data\mail.xnb to find the names of mail, or add your own. See "Mail Events" below for more information on this. OTHER TRIGGERS p Clint Event will only trigger when Clint is present on the map. Can be replaced with any NPC. k 6942 "Kills" an event by ID when this event is triggered, making it so the event won't trigger, ever, even if the requirements are met. You can use this if you want one event or another to activate but not another. Useful for creating branching stories. d Tue Event will only trigger on Tuesday. Can be replaced: Mon, Tue, Wed, Thu, Fri, Sat, Sun. j 10 Event will only trigger on the 10th day of the season. y 2 Event will only trigger in year 2. Can be replaced with any year. m 12000 Event will only trigger when you have 12,000G or more. Can be replaced with any amount. h cat Event will only trigger if your animal preference is set to cat. Can be replaced with dog. *There are more triggers than these, but these are likely the only ones you will need to use. The only trigger that you NEED for your event is an ID - everything else you include or don't is up to you. SCRIPT The script for your event tells the game which actions to perform. Most of them are fairly easy to use and understand, but one typo will make your event freeze and potentially crash your game, so you must be meticulous with your typing and proofreading. Like the trigger parameters, script actions are separated by "/". jaunty/7 9/farmer 6 8 2 Lewis 10 9 3/skippable/pause 500/emote Lewis 8/pause 500/move farmer 0 2 1/move farmer 2 0 0/speak Lewis \"Oh, why hello there, @!#$b#What can I do for you?$h\"/pause 1000/emote farmer 32/pause 2000/globalFade/viewport -1000 -1000/end warpOut" #!String jaunty This is the music that will start playing at the beginning of your event. You can experiment to find which music you want to use. Some of the music names are: jaunty, gusviolin, 50s, poppy, sweet, distantBanjo, and playful. There are others, but as far as I know there is no master list. This makes choosing music very frustrating, so I usually go with whatever I can find that fits. This MUST go first in the script. 7 9 This is the viewport for the event, AKA the tile that will be in the middle of your screen. You can change the viewport at any time AFTER this by using "viewport x y true", or just "viewport x y" if you are placing your viewport off the map. This MUST go after the music name. farmer 6 8 2 Lewis 10 9 3 This adds the named NPCs and farmer (hereafter called "actors") to the event. You can add any actor you want. The format is "Name x y d", where d = direction you want the actor to be facing. This MUST go after the original viewport. skippable Makes the event skippable. This MUST go directly after the actor positions. THE FOLLOWING COMMANDS CAN GO IN ANY ORDER: pause 500 "Pauses" the event for 500 milliseconds (half a second). Just creates some empty space. It's a good way to keep events from feeling too chaotic, like everything happens too fast. This can be as short or as long as you like. emote Lewis 8 Makes the named actor display the named emote. You can find the emotes in Content\TileSheets\emotes.png. They go in multiples of 4, since each emote has 4 frames. You only need to name the first frame, so "emote Lewis 8" makes Lewis display the "?" emote (all 4 frames of it). move farmer 0 2 1/move farmer 2 0 0 Makes the named actor move. The values are "move Name x y d", where d = direction you want the actor to be facing when the movement is done. **The x y values for the move command do NOT make the actor move to an x y position, but rather: they move the specific number of tiles x and y (x being horizontal and y being vertical, but I hope you already knew that). ***The actors CANNOT move on both the x and y axis in ONE MOVE COMMAND. Therefore, you MUST separate all x and y movements like I did above. speak Lewis \"Oh, why hello there, @!$s#$b#What can I do for you?$h\" Makes the named actor speak (NOT the farmer). The format for speech is a little bit weird, and you MUST get it right or it won't work. speak Name MUST be followed by \"Dialogue\" (and / before the next action). #$b# will separate the text into different dialogue boxes. The @ symbol calls the farmer's name. The $s before the #$b# will make Lewis display his sad portrait for that dialogue box. Almost all NPCs have happy and sad portraits. The $h before the last forward slash will make Lewis display his happy portrait for that dialogue box. Using no specific portrait command will make the default portrait appear. $h = happy $s = sad $a = angry If you want to use a specific portrait but don't know how, open their portrait .png, then you can use $1, $2, $3, etc. The portraits start at $0, but you will never have to use $0, since $0 is the default portrait. globalFade/viewport -1000 -1000 This command is used to make the map fade to black. globalFade will make the map fade, then you must immediately follow it with the viewport command to make the viewport go off the map, otherwise after the fade the map will still be visible (don't ask me why). It doesn't have to be -1000 -1000, but that ensures nothing will be visible. end warpOut" #!String This makes the event end, and it will end with the player warping out of whatever map they are on. #!String is the way every content string in the game ends, thus, events must also end with this. Other ending options are... end dialogue Lewis \"Let me know if I can help you with anything.$h\"" #!String Makes the event end. Next time you talk to Lewis, he will say that dialogue. end position 7 9" #!String Makes the event end and the farmer will be standing on that tile. end" #!String Just makes the event end. OTHER SCRIPT ACTIONS warp farmer 10 9 Warps the actor to the specified x y location. They will be facing the same direction as before. This is useful when switching to a new map, or making a character leave or enter your event. When a character is LEAVING your event, you must warp them off the map, like so: warp Emily -30 -30 She'll be safe offscreen if/when you need her again - simply warp her back if you want her. Similarly, if you are having a character enter the event later, especially if they are entering a building, have them start offscreen. Then, write a line like this: playSound doorClose/warp Shane 10 8 Assuming 10, 8 is where the entrance to the map is located, this creates a good illusion of the NPC walking into the building, where in reality they are just getting warped in. faceDirection Lewis 2 Makes actor face whichever direction specified. showFrame Lewis 26 Shows the actor's specified frame on their sprite sheet. Usually used to show special frames specific to certain events (such as an NPC sitting down). I think this will work for the farmer, too, but I have no idea which frame is which for the farmer, since they have 10349023852 frames probably. speed farmer 4 Changes the actor's speed for the NEXT MOVE ONLY. 3 is the default. 4 is a good running speed. playSound dwop Plays the specified sound once. Like music, I don't think there is a master list, so it is ultimately a guessing game. Dwop is the sound it makes when you kiss your spouse. Other sounds include: drumkit, wateringCan, doorClose, and openBox. Good luck finding which ones are which. You'll have to dig through other events to find the names of sounds. shake Lewis 1000 Makes the actor shake for the specified amount of milliseconds. jump farmer Makes the actor jump in the air. textAboveHead Lewis \"Hello!\" Creates a small text bubble above the actor's head with the dialogue in it. I don't think this works for the farmer but I could be wrong. Format is like "speak" command. addQuest 54 Adds the quest by ID to your quests. message \"Display message.\" Displays the specified message. Format is like "speak" command, but it displays a message with no name or actor portrait. animate Lewis true true 200 24 24 24 25 25 25 26 26 26 Animates the current actor. The format is "animate Name t/f t/f speed frames". In this example, 200 is the speed (I think it's milliseconds per frame) and it will animate the frames specified after. I am not sure what the t/f values are specifically, but false false will make it not loop, and true true will make it loop. stopAnimation Lewis Will stop any animation you started for the actor. mail lewisLetter Will send the mail specified the following day. friendship Lewis 250 Adds the specified amount of friendship points. 250 points is one heart. Can also use - to take away an amount, such as "friendship Lewis -250". playMusic poppy Will play the specified music. Uses the same music cues as always. specificTemporarySprite linusCampfire Adds the specific temporary sprite you specify to the scene. I still have not found where these sprites are defined or how the game knows where to place them. Not very useful overall. changeLocation Beach Changes the event's location to the specified map. This map MUST be a game location that already exists. changeToTemporaryMap ElliottSea Changes the event's location to a temporary map. You can create your own temporary maps (follow the format of the maps that already exist) for your events. question fork1 \"Go fishing with Willy?#Yes#No\"/fork noFishing noFishing: "pause 500/speak Willy \"...Oh. Another time, then.\"/pause 500/end warpOut" #!String Forks the event to a sub-event. The sub-event, instead of having a number ID, will have the name you give it, in this case, "noFishing". On a new line, write the name of your sub-event and a colon, then give it a script. You do NOT need to start this script with music, a viewport, and actor positions, as those WILL carry over from the main event. The format is question fork1 \"Question#Answer1#Answer2\"/fork Answer2result. You can change the "fork1" to "fork0" to make it fork from the first option. speak Linus \"$q -1 null#How do you like it?#$r -1 0 event_dinner1#It's delicious!#$r -1 0 event_dinner2#I've had better.\" Creates a question with different answers and unique dialogue responses from the NPC. The format is: \"$q -1 null#Question#$r -1 0 dialoguename1#Response 1#$r -1 0 dialoguename2#Response 2\" It can be a little confusing. I don't use this action much because of that. If you use this command, you MUST find the corresponding NPC's dialogue .yaml and add the responses like this: event_dinner1: "I'm so glad!$h" #!String event_dinner2: "Oh...$s" #!String ambientLight 0 0 0 Creates ambient light on the map. I haven't used it much so I don't know how it works, and I've had problems with it when I have tried to use it in the past. positionOffset farmer 10 0 Offset's the actor's position. I think the numbers refer to pixels, and they are x y. They can also be negative values. Basically, inches the actor away from the center of their tile amount x or y. I haven't used it too much but it can be pretty useful. Mail Events To create an event that begins with the player receiving a letter, complete the following steps: Open Content\Data\mail.yaml and add the letter you want to start your event, such as an invitation for a picnic. Call it whatever you wish. For this example we will call it "mayorLetter". Open Content\Data\Events\Farm.yaml and add the line to add the letter to the mailbox under the desired circumstances. In this example, we want the letter to be delivered when the player has reached 6 hearts with Lewis. "x mayorLetter" will add the letter to the mailbox. The script MUST say "null". This line MUST have its own unique ID that is different from the event we want it to start. "234909/f Lewis 1500/x mayorLetter: "null" #!String Open the .yaml of the map you want your event to occur at. When writing the trigger parameters, make sure to include "n mayorLetter". Thanks for reading my guide! I know it's a little messy/unorganized, so feel free to ask me any questions that aren't answered here. I found most of this information myself by studying other events, and I find that is probably the best way to learn. However, it's frustrating when there are many commands you aren't sure of, so I hope this is helpful for anyone who wants to make custom events for their game (and even share them with others). :^) If you use my guide as a reference and you decide to share your custom events with others (whether on these forums, nexus mods, or anywhere else) I would appreciate a shout-out or even a link back!
A list of quick parts taken from the .exe, such as how to call the name of your spouse, child, or pet. dialogueHappy = "$h"; dialogueSad = "$s"; dialogueUnique = "$u"; dialogueNeutral = "$neutral"; dialogueLove = "$l"; dialogueAngry = "$a"; dialogueEnd = "$e"; dialogueBreak = "$b"; dialogueKill = "$k"; dialogueChance = "$c"; dialogueDependingOnWorldState = "$d"; dialogueQuickResponse = "$y"; dialoguePrerequisite = "$p"; dialogueSingle = "$1"; dialogueQuestion = "$q"; dialogueResponse = "$r"; breakSpecialCharacter = "{"; playerNameSpecialCharacter = "@"; genderDialogueSplitCharacter = "^"; quickResponseDelineator = "*"; randomAdjectiveSpecialCharacter = "%adj"; randomNounSpecialCharacter = "%noun"; randomPlaceSpecialCharacter = "%place"; spouseSpecialCharacter = "%spouse"; randomNameSpecialCharacter = "%name"; firstNameLettersSpecialCharacter = "%firstnameletter"; timeSpecialCharacter = "%time"; bandNameSpecialCharacter = "%band"; bookNameSpecialCharacter = "%book"; rivalSpecialCharacter = "%rival"; petSpecialCharacter = "%pet"; farmNameSpecialCharacter = "%farm"; favoriteThingSpecialCharacter = "%favorite"; eventForkSpecialCharacter = "%fork"; kid1specialCharacter = "%kid1"; kid2SpecialCharacter = "%kid2";
Thank you for writing this wonderful guide! I'm looking to get into end-game modding soon (have to wait for my new laptop to ship first) -- adding some more scenes, quests, NPCs and such that trigger after finishing the community center (would love to extend the game a bit, you know?). But the actual packaging of the game is much different than anything I'm used to. This really just reduces the problem to writing, and maybe a little bit of graphic design. Thanks for being so clear!
There are specific triggers for after the community center is completed. I can add them to the OP, but I don't know much about them yet.
Nice work! You might also want to mention that, to actually change locations, you have to use the warp function right after, and that there's also the question fork0 function (which is basically the same, it only changes which answer triggers the fork). All in all, pretty complete guide. Here's to hoping it'll help people learn how to make events so that we can get even more mods!
Yes, I've been slowly adding details I left out at first, since I was a little lazy with some of the more specific instructions. Technically, if you don't want the actors to move, you don't have to warp them and they'll stay in the same x y locations on the new map lol. :^P
Oh, no worries -- I figure I'll just have the Mayor's "thank you for fixing the community center" letter as a requirement, or look at the file for that letter or the Dark Talisman quest.
I expanded a bit on the "warp" command & how it can be used when making characters enter or exit the event. Also, if you guys are working on custom events and have any questions, feel free to ask! I'm not really an expert on the system, but I've done a lot of staring at the .yaml files, so I'll probably be able to help out with problems.
While tinkering, I came across a few other useful commands: viewport move <X> <Y> <Time> Pans the camera, instead of jumps to a co-ordinate. The X and Y values seem to specify how many pixels the screen moves per milisecond on each axis (and can be positive and negative to indicate direction), while Time is the number of miliseconds the pan takes to execute. It's quite hard to use it precisely, because it works in pixels-per-millisecond, rather than tiles, but it's much prettier than a hard jump. Also, event-time is not paused while the pan is happening, so you might want a pause command with the same time specified so things don't happen while the camera is moving. advancedMove <NPC> <loop> [<x> <y>...] Takes a series of (X,Y) values, in the same manner as the standard move command, and executes them in sequence. However, it also executes them in parallel with the standard event execution, so if you set one NPC moving using advancedMove, and another moving with just move, you can get them moving at the same time. Unlike the move command, which will let you just plow headlong through anything, advancedMove checks for collisions, and will cease moving if the character hits anything. Unfortunately, although there is the capacity for an endBehaviour to trigger, it can only be set when setting up advancedMoves programmatically, meaning there is no way to configure an action to happen at the end of the movement through the Event syntax - you just have to sort of guess when the movement will finish.
It's so cool that this has its own post! I was wondering where the guide was. Thank you! I should try to make one of these one of these days
Does anyone know if there is a trigger for if your spouse has asked you for a baby? I'm planning on creating Harvest Moon styled pregnancy and birth events but I'm struggling on getting a good way of showing the events when it makes sense.
I looked through the yaml dialogues for almost two hours last night looking for that very thing. Didn't find anything in any of them.
Sound list: //PlaySound doorClose archaeo axe boulderCrack coin cut dialogueCharacter dialogueCharacterClose dropItemInWater ghost grunt hammer hoeHit openBox pickUpItem sandyStep seeds shadowpeep shiny4 smallSelect throwDownITem grassyStep stoneStep thudStep eat fishBite toolSwap pullItemFromWater woodyStep bob dwoop explosion crafting detector furnace powerup desolate jaunty starshoot sappypiano musicboxsong 50s ragtime sadpiano fuse echos sampractice heavy honkytonky poppy shimmeringbastion aerobics hitEnemy slime Duggy money toolCharge ow death fireball rabbit woodyHit breathout breathin wind springtown wavy clubloop achievement wedding flute drumkit0 drumkit1 drumkit2 drumkit3 drumkit4 drumkit5 drumkit6 phone thunder rain crickets wand title_night questcomplete cavedrip objectiveComplete backpackIN Crystal Bells Cavern Secret Gnomes Cloth Icicles XOR Near The Planet Core Of Dwarves spring2 spring3 Pink Petals Tropical Jam Ghost Synth Plums Majestic Orange summer2 Cyclops winter3 New Snow croak treethud treecrack axchop leafrustle crystal sweet potterySmash select flameSpellHit flameSpell debuffHit debuffSpell monsterdead clubhit clubswipe openChest rockGolemSpawn rockGolemDie darkCaveLoop bugLevelLoop batFlap batScreech bigDrums clubSmash ocean spring_day_ambient marnieShop toyPiano skeletonStep skeletonDie skeletonHit slimeHit dustMeep throw minecartLoop CloudCountry roadnoise busDoorOpen SettlingIn sipTea shadowDie shadowHit healSound coldSpell tribal Upper_Ambient Frost_Ambient Lava_Ambient yoba warrior slingshot discoverMineral trashcan newArtifact reward newRecord newRecipe Overcast woodsTheme stumpCrack secret1 trainWhistle trainLoop getNewSpecialItem nightTime Meteorite UFO owl dogs scissors Milking Duck sheep killAnimal boulderBreak sell purchaseClick cast SinWave slowReel fastReel tinyWhip button1 FishHit jingle1 fishEscape fishSlap Cowboy_OVERWORLD Cowboy_singing Cowboy_Secret Cowboy_gunshot cowboy_boss cowboy_dead Cowboy_Footstep Cowboy_undead cowboy_powerup cowboy_gunload cowboy_gopher cowboy_explosion cowboy_outlawsong playful AbigailFlute AbigailFluteDuet breezy kindadumbautumn Hospital_Ambient breakingGlass spaceMusic robotSoundEffects robotBLASTOFF pool_ambient cameraNoise keyboardTyping mouseClick elliottPiano tinymusicbox gusviolin whistle event1 tickTock FlowerDance event2 moonlightJellies fallFest christmasTheme junimoMeep1 communityCenter junimoStarSong busDriveOff stairsdown serpentHit serpentDie dogWhining shwip fallDown WizardSong doorCreakReverse cacklingWitch glug harvest rooster dog_pant dog_bark spirits_eve MainTheme jojaOfficeSoundscape grandpas_theme fall_day_ambient summer_day_ambient snowyStep spring1 summer1 summer3 fall3 fall1 fall2 winter2 winter1 libraryTheme cracklingFire babblingBrook heavyEngine spring_night_ambient cricketsAmbient distantBanjo give_gift MarlonsTheme Saloon1 stardrop crit cancel winter_day_ambient Stadium_cheer Stadium_ambient EmilyDance EmilyDream EmilyTheme parrot shaneTheme bigDeSelect bigSelect stoneCrack wateringCan cluck swordswipe slimedead EarthMine FrostMine LavaMine goat cow SpringBirds springsongs Ship boop pig rainsound purchase daggerswipe flybuzzing rockGolemHit parry seagulls clank trashcanlid distantTrain dwop bubbles moneyDial gulp purchaseRepeat dirtyHit fishingRodBend waterSlosh Cowboy_monsterDie Pickup_Coin15 cowboy_monsterhit slosh woodWhack barrelBreak doorCreak doorOpen crow thunder_small cat Sorry for the format.
i just found a program for extracting the sound files from the big cab file down to separate wave files. its a tiny program called "unxwb." i how have a playlist of all of the songs longer than 2 minutes in the game.
I grabbed up the "WaveBankExtractPackV2" from the audio editing thread found here a while back although I haven't tested it since I needed a framework or something.. Stardew ringtones!!
Am I doing something wrong that I just don't realize? I unpacked the original xnb to get the yaml I was going to modify, deleted everything after the content: "#!Dictionary<String,String>" line, made my event, and am now trying to repack the event into and xnb, but when I try to pack it into an xnb file again nothing happens. The xnb file that comes out the other end is the original file, without any of the modifications I added. can anyone explain what is happening?