Skip to content

Campgrounds

Campgrounds.Framework.Models.Data.CampgroundData

A campground is a destination the player can travel to. It defines where the player and their guest arrive, how long the trip takes, what size tents fit and how the site is presented in the camp list menu.

content.json (abridged)
{
  "Id": "{{ModId}}_RiverClearing",
  "Description": "A quiet bend in the river, sheltered by old willows.",
  "PreviewTexturePath": "Mods/{{ModId}}/RiverClearingPreview",
  "PreviewTextureScale": 4.0,

  "PlayerSpawnTile": { "X": 12, "Y": 18 },
  "GuestSpawnTile": { "X": 14, "Y": 18 },
  "MaxTentTileSize": { "Width": 4, "Height": 3 },

  "TravelScreenText": "You follow the river north until the road runs out.",
  "RequireVehicle": false,
  "TravelTimeInHours": 1,
  "ForceForageRefreshOnVisit": true,

  "UnlockCondition": "PLAYER_HAS_MAIL Current riverAccess",
  "UnlockHint": "The old logging road might go somewhere.",
  "HideUntilUnlocked": false
}

Properties

Identity and presentation

Property Type Default Description
Id required string Unique identifier. Must be the name of a game location you register (see below). Doubles as the Content Patcher entry key and is what campgrounds_startcamp and VillagerData.LikedCampgrounds take. Matched case-insensitively.
Description optional string Flavour text describing the site, shown in the camp list menu.
PreviewTexturePath optional string (default preview) Asset name of the preview image shown when browsing campgrounds. If omitted, the framework's Data/PeacefulEnd.Campgrounds/Campgrounds/Textures/Default_Preview is used.
PreviewTextureScale optional float 4.0 Scale the preview is drawn at. 4.0 matches the game's usual pixel scale. Use 2.0 for a preview drawn at double resolution.

A campground's Id is a location name: you must add the location yourself

Unlike the other content types, a campground isn't self-contained. The framework travels the player to the site by calling the game's getLocationFromName with your Id, so the Id has to match a real, loaded GameLocation (one you register through vanilla Data/Locations, with its own map).

A CampgroundData whose Id doesn't resolve to a location will sit in the menu and then fail to travel anywhere.

The campground's display name (shown in menus and travel messages) comes from that location's DisplayName in Data/Locations, not from anything on CampgroundData.

Spawning

Property Type Default Description
PlayerSpawnTile required Vector2 Tile the player arrives on.
GuestSpawnTile required Vector2 Tile an invited villager arrives on.
MaxTentTileSize optional SizeModel Largest tent footprint the site accepts, in tiles. Omit for no limit.

Both spawn tiles are required even though they're nullable in the model. Validation rejects the campground if either is missing.

Travel

Property Type Default Description
TravelScreenText optional string Text shown on the travel transition screen while the player is on their way.
RequireVehicle optional bool false If true, the player can only travel here once the garage car is repaired.
TravelTimeInHours optional int 0 In-game hours the journey consumes. Must be 015.
ForceForageRefreshOnVisit optional bool false If true, forage on the map is cleared and respawned each morning.

TravelTimeInHours is capped below 16

Validation rejects anything greater or equal to 16. 0 means instant travel.

The hours are applied by advancing the clock. The camp list menu won't let the player travel if arrival would land at or after midnight. Plan the number against when you expect players to set out.

RequireVehicle gates on the garage car

When true, the camp list menu blocks travel to this site until the player has repaired Clem's garage car. Until then, selecting the site shows a "vehicle required" message instead of traveling.

The menu also shows a "requires vehicle" info line for the site, drawn in red while the car is still unrepaired, so the player can see the requirement before they try.

What ForceForageRefreshOnVisit actually does

Each morning, the framework removes every forage object on the campground map, resets its spawn counter and runs the game's normal object-spawn pass again. The effect is a site whose forage is freshly rolled every day rather than accumulating or persisting.

Leave it false for a site where forage should behave like anywhere else in the world. Set it true for a "wild" site you want to feel freshly grown on each trip. It only touches objects the game considers forage, so items placed items and terrain features are untouched.

Dialogue overrides

Property Type Default Description
DialogueOverrides optional List<VisitorDialogueOverride> empty list Replaces the standard VillagerData dialogue for matching NPCs at this campground specifically.

This is how you give a site its own character. If Abigail says something particular whenever she's brought to specific campsite, it goes here rather than in her VillagerData.

{
  "DialogueOverrides": [
    {
      "Id": "Abigail",
      "DialogueDayOfOverride": [
        "The river's is nice here. I love it.",
        "Something something, dialogue."
      ],
      "DialogueDayAfterOverride": [
        "I slept so peacefully with the sound of the river!"
      ]
    }
  ]
}

Unlocking

UnlockCondition, UnlockHint and HideUntilUnlocked behave identically across all unlockable content (see Unlockable content).


VisitorDialogueOverride

Campgrounds.Framework.Models.Data.Visitors.VisitorDialogueOverride

Property Type Default Description
Id required string The NPC's internal name (Abigail, Sebastian), not their display name. Matched case-insensitively.
DialogueDayOfOverride optional List<string> empty list Replaces the day-of dialogue, liked, neutral and disliked alike.
DialogueDayAfterOverride optional List<string> empty list Replaces the day-after dialogue, liked, neutral and disliked alike.

How overriding works

An override only takes effect when its list is non-empty. Concretely:

  • If DialogueDayOfOverride has entries, it replaces LikedDialogueDayOf, NeutralDialogueDayOf and DislikedDialogueDayOf from the NPC's VillagerData.
  • If it's empty or omitted, the VillagerData dialogue is used as normal.
  • The same rule applies independently to DialogueDayAfterOverride.

Overrides are not sentiment-aware

You cannot override only the disliked day-of line. The override collapses all three sentiments into one list, so whatever you write here is said whether the villager loved the trip or hated it.

You can override day-of without touching day-after and vice versa. Supplying only DialogueDayOfOverride leaves the day-after dialogue entirely to VillagerData.


Validation rules

The framework rejects a CampgroundData when:

Condition Message
Id is missing or empty Missing the "Id" property!
PlayerSpawnTile is missing Missing the "PlayerSpawnTile" property!
GuestSpawnTile is missing Missing the "GuestSpawnTile" property!
TravelTimeInHours < 0 The "TravelTimeInHours" can't be negative!
TravelTimeInHours >= 16 The "TravelTimeInHours" can't be greater than 16!
MaxTentTileSize is invalid Invalid MaxTentTileSize given!

Note

Description, PreviewTexturePath and TravelScreenText are not validated. A campground with no preview image loads fine and falls back to the framework's default preview.


Tent fitting

When the player picks a tent for this site, the framework compares the tent's footprint in the chosen direction against MaxTentTileSize. A tent is rejected if either dimension exceeds the limit:

tentSize = tent.GetTileSize(direction)
reject if tentSize.Width > MaxTentTileSize.Width
reject if tentSize.Height > MaxTentTileSize.Height

Two consequences to plan around:

  • The check is per direction. A 4×2 tent facing north may be 2×4 facing east. With a MaxTentTileSize of 3×3, that tent fits in neither direction. With 4×4 it fits in both. A limit of 4×2 would let it face north but not east.
  • Omitting MaxTentTileSize means no limit. Any tent fits, including one large enough to overhang your map's clearing. If your site is tight, set the limit.