Npc template

From Stardew Modding Wiki
Jump to navigation Jump to search

1.6+ The "Everything You Possibly Need For A Romanceable NPC" List of Templates

Hello! Aviroen here. Below I have constructed a ROMANCEABLE NPC template which is a standalone .json

"What does standalone mean?"

- It means it can be it's own separate json like "NPCNAME.json" or "Dialogue.json" or "MarriageDialogue.json", and must be included in your content.json:

EXAMPLE:

    {
    "Logname": "Include List",
    "Action": "Include",
    "FromFile": "{{FOLDER}}/NPCNAME.json, {{FOLDER}}/Dialogue.json"
    }

"What is all of this

{{ModId}}_

business?"

Internalizing your NPC's name with YOURMOD.UNIQUEID helps keep clarity just incase you have the same name as any other NPC. It makes it so you don't run into complications with dialogues/schedules/etc.

You DO NOT need to remove that part of the code, Content Patcher will automatically replace it with your manifest's UNIQUE ID.

You just HAVE TO REMEMBER that anytime you're referencing your NPC, you need to append it with the {{ModId}}_NPCNAME.

While it is not 100% necessary, if you don't have a very unique name, it's good for compatibility.

Sidenote from Ichor (author of Lacey and Nightshade):

"i find it very helpful in CP to set up a dynamic token with your NPC's internal name, so that writing events (in particular) is less painful. e.g. Lacey is {{ModId}}_Lacey which expands to ichortower.HatMouseLacey_Lacey, so i set up a token that's just {{Lacey}} for events"

  {
   "Changes": [
        {
            "Action": "EditData",   //this is assumed you've already loaded a blank.json into data/characters/[npcname]
            "Target": "Data/Characters",
            "Entries": {
                "{{ModId}}_<NPCNAME>": { //unique id of the npc, must be used when referecing the npc at all
                    "DisplayName": "{{i18n:{{ModId}}_<NPCNAME>}}", //translation capability
                    "BirthSeason": "Fall",
                    "BirthDay": 3,
                    "HomeRegion": "Other", //town / desert / other
                    "Language": "Default", //default or dwarvish
                    "Gender": "Undefined", //male, female, undefined (undefined gets auto-sorted as female)
                    "Age": "Adult", //child, teen, adult changes reactions from stringsfromcsfiles
                    "Manner": "Rude", //polite, neutral, rude changes stringsfromcsfiles
                    "SocialAnxiety": "Shy", //outgoing, neutral, shy changes stringsfromcsfiles
                    "Optimism": "Negative", //positive, neutral, negative changes stringsfromcsfiles
                    "IsDarkSkinned": false, //determines for children
                    "CanBeRomanced": true, //checks to see if a bouquet can be gifted to this npc
                    "LoveInterest": null, //sort of flavor text
                    "Calendar": "HiddenUntilMet", //shows their birthday on the calendar, alwaysshown, hiddenuntilmet, unknownuntilmet, hidden
                    "SocialTab": "HiddenUntilMet", //shows them on the social tab, alwaysshown, hiddenuntilmet, unknownuntilmet, hidden
                    "CanSocialize": null, //boolean, whether this npc can even have a dialogue box with the player [true/false]
                    "CanReceiveGifts": true, //whether this npc is antisocial or not
                    "CanGreetNearbyCharacters": true, //reacts to townspeople when they pass by
                    "CanCommentOnPurchasedShopItems": null, //needs i18n or dialogue strings to react to farmer's purchase if true
                    "CanVisitIsland": null, //game state query-able if npc can visit island randomly
                    "IntroductionsQuest": false, //sets if this npc is included into the intro quest of introducing yourself to everyone
                    "ItemDeliveryQuests": null, //sets if this npc gets put on the bulletin board for randomly generated quests
                    "PerfectionScore": false, //checks if this npc is required for perfection for friendship
                    "EndSlideShow": "TrailingGroup", //shows this npc following behind in perfection cutscene
                    "SpouseAdopts": null, //game state query-able whether this npc will always adopt or not https://stardewvalleywiki.com/Modding:Game_state_queries
                    "SpouseWantsChildren": true, //game state query-able about the npc will want children at all
                    "SpouseGiftJealousy": null, //specific gendered jealousy male-male female-female about this npc whether you gift nonbirthday/quest/festival
                    "SpouseGiftJealousyFriendshipChange": -30, //friendship loss or gain for jealousy gifting of above
                    "SpouseRoom": { //the square in the farmhouse that gets dedicated to this npc
                        "MapAsset": null, //null for vanilla, set to loaded filename for custom npc
                        "MapSourceRect": {
                            "X": 0, //this is if you're wanting to move it to a different spot in the farmhouse
                            "Y": 0,
                            "Width": 6, //the custom spouse tmx width
                            "Height": 9 //custom spouse room tmx height
                        }
                    },
                    "SpousePatio": { //this is the spot outdoors on the farm where the spouse sits if they don't have a schedule for the day
                        "MapAsset": null, //null for vanilla, set to loaded filename for custom npc
                        "MapSourceRect": {
                            "X": 0, //this is for if you want it to be someplace different on the farm
                            "Y": 0,
                            "Width": 4, //this is the width of the plot on the farm
                            "Height": 4 //this is the height of the plot on the farm
                        },
                        "SpriteAnimationFrames": [ //this is the animation that loops when your custom npc is standing on their spousepatio, [frame, miliseconds] REMEMBER! these loop!
                            [ 16, 1500 ]
                        ],
                        "SpriteAnimationPixelOffset": { //this is if your npc is slightly odd shaped, like taller than normal, or shorter than normal
                            "X": 0,
                            "Y": 0
                        }
                    },
                    "SpouseFloors": [], //this is the subset of floors that the npc will plaster in the farmhouse
                    "SpouseWallpapers": [], //this is the subset of wallpapers that the npc will plaster in the farmhouse
                    "DumpsterDiveFriendshipEffect": -5, //whether the npc loses friendship with you if they catch you digging in the trash
                    "DumpsterDiveEmote": null, //the emote above their head when they catch you digging in the trash
                    "FriendsAndFamily": { //whether any other npcs are related
                        "<NPCNAME>": "{{i18n:<RELATIONSHIP>}}", //i18n is the default.json used for translations
                    },
                    "FlowerDanceCanDance": null, //sets if the npc will dance at the flower festival on spring 24
                    "WinterStarGifts": [], //items that this npc can gift during the winter star festival https://stardewvalleywiki.com/Modding:Item_queries#Item_spawn_fields
                    "WinterStarParticipant": null, //whether the npc even participates in winter star, can be game state query-able
                    "UnlockConditions": null, //game state query-able about whether the npc has an unlock condidion before seen
                    "SpawnIfMissing": true, //forcibly spawns the npc if they're stuck
                    "Home": [ //sets the npc's spawn point
                        {
                            "Id": "Default", //the default of where they spawn
                            "Condition": null, //game state query-able condition if they change homes
                            "Location": null, //specific location from data/location
                            "Tile": {
                                "X": 0, //x position where the npc idles
                                "Y": 0 //y position where the npc idles
                            },
                            "Direction": "right" //direction that they face while idling
                        }
                    ],
                    "TextureName": null,
                    "Appearance": null, //new appearance system, highly customizable, see: Outfits.json
                    "MugShotSourceRect": null, //change the position of their headshot in the calendar/map/etc if they're shorter/taller than normal
                    "Size": {
                        "X": 16, //this is for how wide each character sprite is
                        "Y": 32 //this is for how tall each character sprite is
                    },
                    "Breather": true, //whether this places the breathing animation over the npc
                    "BreathChestRect": null, //changeable if you want to enlarge/shrink the breathing animation
                    "BreathChestPosition": null, //changeable if the npc is taller/shorter than normal
                    "Shadow": null, //changeable to visible, offset, or scale / visible is default true whether null or not, offset to offset the shadow, scale to enlarge/shrink
                    "EmoteOffset": { //whether to offset the emote bubble over the npc or not
                        "X": 0,
                        "Y": 0
                    },
                    "ShakePortraits": [], //the index of the portraits/npc to shake during dialogue, will always trigger
                    "KissSpriteIndex": null, //whether this npc has a kissing or hugging sprite, reminder that characters/npc and portraits/npc starts at 0
                    "KissSpriteFacingRight": false, //whether the sprite is facing to the right
                    "HiddenProfileEmoteSound": null, /* https://docs.google.com/spreadsheets/d/1CpDrw23peQiq-C7F2FjYOMePaYe0Rc9BwQsj3h6sjyo/edit?gid=239695361#gid=239695361 for soundbank / hiddenprofile when clicking on their social tab after 4 hearts shows a different animation if changed */
                    "HiddenProfileEmoteDuration": 4000, //how long the animation will run in miliseconds
                    "HiddenProfileEmoteStartFrame": 32, //whichever sprite index the frame is on
                    "HiddenProfileEmoteFrameCount": 2, //how many frames the sprite index will go through, going left to right
                    "HiddenProfileEmoteFrameDuration": 200.0, //how long each frame will last measured in miliseconds
                    "FormerCharacterNames": [], //used for older saves if the npc has changed names and must be globally unique
                    "CustomFields": null //custom fields is used for c# implementation
                }
            }
        }
     ]
 }

Continuing on, if you were following Tutorial: Making a Custom NPC

Dialogue!

NOTE: NOT ALL OF THESE ARE NECESSARY.

https://stardewvalleywiki.com/Modding:Migrate_to_Stardew_Valley_1.6#Dialogue_changes (Current as of August 26, 2024)

{
    "Changes": [
        {
            "Action": "EditData",
            "Target": "Characters/Dialogue/{{ModId}}_<NPCNAME>",
            "Entries": {
                //green rain
                "GreenRain": "{{i18n or straight dialogue}}",
                "GreenRainFinished": "{{i18n or straight dialogue}}",
                //movie
                "MovieInvitation": "{{i18n or straight dialogue}}",
                "RejectMovieTicket_AlreadyInvitedBySomeoneElse": "{{i18n or straight dialogue}}",
                "RejectMovieTicket_AlreadyWatchedThisWeek": "{{i18n or straight dialogue}}",
                "RejectMovieTicket_Divorced": "{{i18n or straight dialogue}}",
                "RejectMovieTicket_DontWantToSeeThatMovie": "{{i18n or straight dialogue}}",
                "RejectMovieTicket": "{{i18n or straight dialogue}}",
                //dating
                "breakUp": "{{i18n or straight dialogue}}",
                "dating_EdelweissSeung_memory_oneyear": "{{i18n or straight dialogue}}",
                "RejectBouquet_NotDatable": "{{i18n or straight dialogue}}",
                "RejectBouquet_NpcAlreadyMarried": "{{i18n or straight dialogue}}",
                "RejectBouquet_VeryLowHearts": "{{i18n or straight dialogue}}",
                "RejectBouquet_LowHearts": "{{i18n or straight dialogue}}",
                "RejectBouquet": "{{i18n or straight dialogue}}",
                //marriage
                "SpouseFarmhouseClutter": "{{i18n or straight dialogue}}",
                "Spouse_MonstersInHouse": "{{i18n or straight dialogue}}",
                "SpouseStardrop": "{{i18n or straight dialogue}}",
                "RejectMermaidPendant_NeedHouseUpgrade": "{{i18n or straight dialogue}}",
                "RejectMermaidPendant_NotDatable": "{{i18n or straight dialogue}}",
                "RejectMermaidPendant_NpcWithSomeoneElse": "{{i18n or straight dialogue}}",
                "RejectMermaidPendant_PlayerWithSomeoneElse": "{{i18n or straight dialogue}}",
                "RejectMermaidPendant_Under8Hearts": "{{i18n or straight dialogue}}",
                "RejectMermaidPendant_Under10Hearts": "{{i18n or straight dialogue}}",
                "RejectMermaidPendant_Under10Hearts_AskedAgain": "{{i18n or straight dialogue}}",
                "RejectMermaidPendant": "{{i18n or straight dialogue}}",
                //divorced
                "divorced": "{{i18n or straight dialogue}}",
                "RejectGift_Divorced": "{{i18n or straight dialogue}}",
                "RejectMermaidPendant_Divorced": "{{i18n or straight dialogue}}",
                "RejectBouquet_Divorced": "{{i18n or straight dialogue}}",
                "WipedMemory": "{{i18n or straight dialogue}}",
                //island
                "Resort": "{{i18n or straight dialogue}}",
                "Resort_Bar": "{{i18n or straight dialogue}}",
                "Resort_Chair": "{{i18n or straight dialogue}}",
                "Resort_Dance": "{{i18n or straight dialogue}}",
                "Resort_Entering": "{{i18n or straight dialogue}}",
                "Resort_Leaving": "{{i18n or straight dialogue}}",
                "Resort_Shore": "{{i18n or straight dialogue}}",
                "Resort_Towel": "{{i18n or straight dialogue}}",
                "Resort_Umbrella": "{{i18n or straight dialogue}}",
                "Resort_Wander": "{{i18n or straight dialogue}}",
                //birthday
                "AcceptBirthdayGift_Negative": "{{i18n or straight dialogue}}",
                "AcceptBirthdayGift_Positive": "{{i18n or straight dialogue}}",
                "AcceptBirthdayGift": "{{i18n or straight dialogue}}",
                //dating proposal
                "AcceptBouquet": "{{i18n or straight dialogue}}",
                //trashcan
                "DumpsterDiveComment": "{{i18n or straight dialogue}}",
                //slingshot
                "HitBySlingshot": "{{i18n or straight dialogue}}",

                ////////////////////////////////////////////////seasonals
                //spring
                "spring_Mon": "{{i18n or straight dialogue}}",
                "spring_Tue": "{{i18n or straight dialogue}}",
                "spring_Wed": "{{i18n or straight dialogue}}",
                "spring_Thu": "{{i18n or straight dialogue}}",
                "spring_Fri": "{{i18n or straight dialogue}}",
                "spring_Sat": "{{i18n or straight dialogue}}",
                "spring_Sun": "{{i18n or straight dialogue}}",
                //flower festival
                "FlowerDance_Accept_Spouse": "{{i18n or straight dialogue}}",
                "FlowerDance_Accept": "{{i18n or straight dialogue}}",
                "FlowerDance_Decline": "{{i18n or straight dialogue}}",
                //summer
                "summer_Mon": "{{i18n or straight dialogue}}",
                "summer_Tue": "{{i18n or straight dialogue}}",
                "summer_Wed": "{{i18n or straight dialogue}}",
                "summer_Thu": "{{i18n or straight dialogue}}",
                "summer_Fri": "{{i18n or straight dialogue}}",
                "summer_Sat": "{{i18n or straight dialogue}}",
                "summer_Sun": "{{i18n or straight dialogue}}",
                //fall
                "fall_Mon": "{{i18n or straight dialogue}}",
                "fall_Tue": "{{i18n or straight dialogue}}",
                "fall_Wed": "{{i18n or straight dialogue}}",
                "fall_Thu": "{{i18n or straight dialogue}}",
                "fall_Fri": "{{i18n or straight dialogue}}",
                "fall_Sat": "{{i18n or straight dialogue}}",
                "fall_Sun": "{{i18n or straight dialogue}}",
                //fair
                "Fair_Judging": "{{i18n or straight dialogue}}",
                "Fair_Judged_PlayerLost_PurpleShorts": "{{i18n or straight dialogue}}",
                "Fair_Judged_PlayerLost_Skipped": "{{i18n or straight dialogue}}",
                "Fair_Judged_PlayerLost": "{{i18n or straight dialogue}}",
                "Fair_Judged_PlayerWon": "{{i18n or straight dialogue}}",
                "Fair_Judged": "{{i18n or straight dialogue}}",
                //winter
                "winter_Mon": "{{i18n or straight dialogue}}",
                "winter_Tue": "{{i18n or straight dialogue}}",
                "winter_Wed": "{{i18n or straight dialogue}}",
                "winter_Thu": "{{i18n or straight dialogue}}",
                "winter_Fri": "{{i18n or straight dialogue}}",
                "winter_Sat": "{{i18n or straight dialogue}}",
                "winter_Sun": "{{i18n or straight dialogue}}",
                //winter star
                "WinterStar_GiveGift_Before_Spouse": "{{i18n or straight dialogue}}",
                "WinterStar_GiveGift_Before": "{{i18n or straight dialogue}}",
                "WinterStar_GiveGift_After_Spouse": "{{i18n or straight dialogue}}",
                "WinterStar_GiveGift_After": "{{i18n or straight dialogue}}",
                "WinterStar_ReceiveGift": "{{i18n or straight dialogue}}",

                //////////////////////////////////////////////////accept gifts example
                "AcceptGift_(O)96": "{{i18n or straight dialogue}}",
            }
        }
        {
            "LogName": "Summit Dialogue",
            "Action": "EditData",
            "Target": "Data/ExtraDialogue",
            "Entries": {
                "SummitEvent_Dialogue3_{{ModId}}_<NPCNAME>": "{{i18n or straight dialogue}}",
            }
        }
    ]
}

We trudge along!

Marriage Dialogue!

{
    "Changes": [
        {
            "LogName": "Engaged Dialogue",
            "Action": "EditData",
            "Target": "data/EngagementDialogue",
            "Entries": {
                "{{ModId}}_<NPCNAME>0": "{{i18n or straight dialogue}}",
                "{{ModId}}_<NPCNAME>1": "{{i18n or straight dialogue}}"
            }
        },
        {
            "LogName": "Marriage Dialogue - Base",
            "Action": "EditData",
            "Target": "Characters/Dialogue/MarriageDialogue{{ModId}}_<NPCNAME>",
            "Entries": {
                "Spring_{{ModId}}_<NPCNAME>": "{{i18n or straight dialogue}}",
                "Summer_{{ModId}}_<NPCNAME>": "{{i18n or straight dialogue}}",
                "Fall_{{ModId}}_<NPCNAME>": "{{i18n or straight dialogue}}",
                "Winter_{{ModId}}_<NPCNAME>": "{{i18n or straight dialogue}}",
                "patio_{{ModId}}_<NPCNAME>": "{{i18n or straight dialogue}}",
                "Rainy_Day_0": "{{i18n or straight dialogue}}",
                "Rainy_Day_1": "{{i18n or straight dialogue}}",
                "Rainy_Day_2": "{{i18n or straight dialogue}}",
                "Rainy_Day_3": "{{i18n or straight dialogue}}",
                "Rainy_Day_4": "{{i18n or straight dialogue}}",
                "Rainy_Day_5": "{{i18n or straight dialogue}}",
                "Indoor_Day_0": "{{i18n or straight dialogue}}",
                "Indoor_Day_1": "{{i18n or straight dialogue}}",
                "Indoor_Day_2": "{{i18n or straight dialogue}}",
                "Indoor_Day_3": "{{i18n or straight dialogue}}",
                "Indoor_Day_4": "{{i18n or straight dialogue}}",
                "Indoor_Day_5": "{{i18n or straight dialogue}}",
                "Rainy_Night_0": "{{i18n or straight dialogue}}",
                "Rainy_Night_1": "{{i18n or straight dialogue}}",
                "Rainy_Night_2": "{{i18n or straight dialogue}}",
                "Rainy_Night_3": "{{i18n or straight dialogue}}",
                "Rainy_Night_4": "{{i18n or straight dialogue}}",
                "Rainy_Night_5": "{{i18n or straight dialogue}}",
                "Indoor_Night_0": "{{i18n or straight dialogue}}",
                "Indoor_Night_1": "{{i18n or straight dialogue}}",
                "Indoor_Night_2": "{{i18n or straight dialogue}}",
                "Indoor_Night_3": "{{i18n or straight dialogue}}",
                "Indoor_Night_4": "{{i18n or straight dialogue}}",
                "Indoor_Night_5": "{{i18n or straight dialogue}}",
                "funLeave_{{ModId}}_<NPCNAME>": "{{i18n or straight dialogue}}",
                "funReturn_{{ModId}}_<NPCNAME>": "{{i18n or straight dialogue}}",
                "Outdoor_{{ModId}}_<NPCNAME>": "{{i18n or straight dialogue}}",
                "Outdoor_0": "{{i18n or straight dialogue}}",
                "Outdoor_1": "{{i18n or straight dialogue}}",
                "Outdoor_2": "{{i18n or straight dialogue}}",
                "Outdoor_3": "{{i18n or straight dialogue}}",
                "Outdoor_4": "{{i18n or straight dialogue}}",
                "spouseRoom_{{ModId}}_<NPCNAME>": "{{i18n or straight dialogue}}",
                "OneKid_0": "{{i18n or straight dialogue}}",
                "OneKid_1": "{{i18n or straight dialogue}}",
                "OneKid_2": "{{i18n or straight dialogue}}",
                "OneKid_3": "{{i18n or straight dialogue}}",
                "OneKid_4": "{{i18n or straight dialogue}}",
                "TwoKids_0": "{{i18n or straight dialogue}}",
                "TwoKids_1": "{{i18n or straight dialogue}}",
                "TwoKids_2": "{{i18n or straight dialogue}}",
                "TwoKids_3": "{{i18n or straight dialogue}}",
                "TwoKids_4": "{{i18n or straight dialogue}}",
                "Good_0": "{{i18n or straight dialogue}}",
                "Good_1": "{{i18n or straight dialogue}}",
                "Good_2": "{{i18n or straight dialogue}}",
                "Good_3": "{{i18n or straight dialogue}}",
                "Good_4": "{{i18n or straight dialogue}}",
                "Good_5": "{{i18n or straight dialogue}}",
                "Good_6": "{{i18n or straight dialogue}}",
                "Good_7": "{{i18n or straight dialogue}}",
                "Good_8": "{{i18n or straight dialogue}}",
                "Good_9": "{{i18n or straight dialogue}}",
                "Neutral_0": "{{i18n or straight dialogue}}",
                "Neutral_1": "{{i18n or straight dialogue}}",
                "Neutral_2": "{{i18n or straight dialogue}}",
                "Neutral_3": "{{i18n or straight dialogue}}",
                "Neutral_4": "{{i18n or straight dialogue}}",
                "Neutral_5": "{{i18n or straight dialogue}}",
                "Neutral_6": "{{i18n or straight dialogue}}",
                "Neutral_7": "{{i18n or straight dialogue}}",
                "Neutral_8": "{{i18n or straight dialogue}}",
                "Neutral_9": "{{i18n or straight dialogue}}",
                "Bad_0": "{{i18n or straight dialogue}}",
                "Bad_1": "{{i18n or straight dialogue}}",
                "Bad_2": "{{i18n or straight dialogue}}",
                "Bad_3": "{{i18n or straight dialogue}}",
                "Bad_4": "{{i18n or straight dialogue}}",
                "Bad_5": "{{i18n or straight dialogue}}",
                "Bad_6": "{{i18n or straight dialogue}}",
                "Bad_7": "{{i18n or straight dialogue}}",
                "Bad_8": "{{i18n or straight dialogue}}",
                "Bad_9": "{{i18n or straight dialogue}}",
            }
        }
    ]
}