Skip to content

Commit

Permalink
Basecamp recipes can specify parameters and om_terrain_match_type (Cl…
Browse files Browse the repository at this point in the history
…everRaven#72642)

* Pointers and defaults are confuse

* Overkill overloads

* Less stoopid

* multimap -> map of value sets

* ANY handling and astyle

* Underp only being allowed one om_terrain

* om_terrain_match_type usage

* Documentation + starting parameter docs I forgot to add
  • Loading branch information
Procyonae authored Apr 9, 2024
1 parent 5d295aa commit 1b5c1bf
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 153 deletions.
150 changes: 30 additions & 120 deletions data/json/recipes/basecamps/recipe_groups.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,8 @@
"field",
"rural_road",
"dirt_road_farm_parking",
"farmland_straight",
"farmland_turn",
"farmland_turn_inside",
"farmland_U",
"hayfield_straight",
"hayfield_turnL",
"hayfield_turnR",
"hayfield_end"
{ "om_terrain": "farmland", "om_terrain_match_type": "PREFIX" },
{ "om_terrain": "hayfield", "om_terrain_match_type": "PREFIX" }
]
},
{
Expand All @@ -28,14 +22,8 @@
"field",
"rural_road",
"dirt_road_farm_parking",
"farmland_straight",
"farmland_turn",
"farmland_turn_inside",
"farmland_U",
"hayfield_straight",
"hayfield_turnL",
"hayfield_turnR",
"hayfield_end"
{ "om_terrain": "farmland", "om_terrain_match_type": "PREFIX" },
{ "om_terrain": "hayfield", "om_terrain_match_type": "PREFIX" }
]
},
{ "id": "faction_base_firestation_0", "description": "Firestation Base", "om_terrains": [ "fire_station" ] },
Expand Down Expand Up @@ -140,14 +128,8 @@
"field",
"rural_road",
"dirt_road_farm_parking",
"farmland_straight",
"farmland_turn",
"farmland_turn_inside",
"farmland_U",
"hayfield_straight",
"hayfield_turnL",
"hayfield_turnR",
"hayfield_end"
{ "om_terrain": "farmland", "om_terrain_match_type": "PREFIX" },
{ "om_terrain": "hayfield", "om_terrain_match_type": "PREFIX" }
]
},
{
Expand All @@ -157,14 +139,8 @@
"field",
"rural_road",
"dirt_road_farm_parking",
"farmland_straight",
"farmland_turn",
"farmland_turn_inside",
"farmland_U",
"hayfield_straight",
"hayfield_turnL",
"hayfield_turnR",
"hayfield_end"
{ "om_terrain": "farmland", "om_terrain_match_type": "PREFIX" },
{ "om_terrain": "hayfield", "om_terrain_match_type": "PREFIX" }
]
},
{
Expand All @@ -174,14 +150,8 @@
"field",
"rural_road",
"dirt_road_farm_parking",
"farmland_straight",
"farmland_turn",
"farmland_turn_inside",
"farmland_U",
"hayfield_straight",
"hayfield_turnL",
"hayfield_turnR",
"hayfield_end"
{ "om_terrain": "farmland", "om_terrain_match_type": "PREFIX" },
{ "om_terrain": "hayfield", "om_terrain_match_type": "PREFIX" }
]
},
{
Expand All @@ -191,14 +161,8 @@
"field",
"rural_road",
"dirt_road_farm_parking",
"farmland_straight",
"farmland_turn",
"farmland_turn_inside",
"farmland_U",
"hayfield_straight",
"hayfield_turnL",
"hayfield_turnR",
"hayfield_end"
{ "om_terrain": "farmland", "om_terrain_match_type": "PREFIX" },
{ "om_terrain": "hayfield", "om_terrain_match_type": "PREFIX" }
]
},
{
Expand All @@ -208,14 +172,8 @@
"field",
"rural_road",
"dirt_road_farm_parking",
"farmland_straight",
"farmland_turn",
"farmland_turn_inside",
"farmland_U",
"hayfield_straight",
"hayfield_turnL",
"hayfield_turnR",
"hayfield_end"
{ "om_terrain": "farmland", "om_terrain_match_type": "PREFIX" },
{ "om_terrain": "hayfield", "om_terrain_match_type": "PREFIX" }
]
},
{
Expand All @@ -225,14 +183,8 @@
"field",
"rural_road",
"dirt_road_farm_parking",
"farmland_straight",
"farmland_turn",
"farmland_turn_inside",
"farmland_U",
"hayfield_straight",
"hayfield_turnL",
"hayfield_turnR",
"hayfield_end"
{ "om_terrain": "farmland", "om_terrain_match_type": "PREFIX" },
{ "om_terrain": "hayfield", "om_terrain_match_type": "PREFIX" }
]
},
{
Expand All @@ -242,14 +194,8 @@
"field",
"rural_road",
"dirt_road_farm_parking",
"farmland_straight",
"farmland_turn",
"farmland_turn_inside",
"farmland_U",
"hayfield_straight",
"hayfield_turnL",
"hayfield_turnR",
"hayfield_end"
{ "om_terrain": "farmland", "om_terrain_match_type": "PREFIX" },
{ "om_terrain": "hayfield", "om_terrain_match_type": "PREFIX" }
]
},
{
Expand All @@ -259,14 +205,8 @@
"field",
"rural_road",
"dirt_road_farm_parking",
"farmland_straight",
"farmland_turn",
"farmland_turn_inside",
"farmland_U",
"hayfield_straight",
"hayfield_turnL",
"hayfield_turnR",
"hayfield_end"
{ "om_terrain": "farmland", "om_terrain_match_type": "PREFIX" },
{ "om_terrain": "hayfield", "om_terrain_match_type": "PREFIX" }
]
},
{
Expand All @@ -276,14 +216,8 @@
"field",
"rural_road",
"dirt_road_farm_parking",
"farmland_straight",
"farmland_turn",
"farmland_turn_inside",
"farmland_U",
"hayfield_straight",
"hayfield_turnL",
"hayfield_turnR",
"hayfield_end"
{ "om_terrain": "farmland", "om_terrain_match_type": "PREFIX" },
{ "om_terrain": "hayfield", "om_terrain_match_type": "PREFIX" }
]
},
{
Expand All @@ -293,14 +227,8 @@
"field",
"rural_road",
"dirt_road_farm_parking",
"farmland_straight",
"farmland_turn",
"farmland_turn_inside",
"farmland_U",
"hayfield_straight",
"hayfield_turnL",
"hayfield_turnR",
"hayfield_end"
{ "om_terrain": "farmland", "om_terrain_match_type": "PREFIX" },
{ "om_terrain": "hayfield", "om_terrain_match_type": "PREFIX" }
]
},
{
Expand All @@ -310,14 +238,8 @@
"field",
"rural_road",
"dirt_road_farm_parking",
"farmland_straight",
"farmland_turn",
"farmland_turn_inside",
"farmland_U",
"hayfield_straight",
"hayfield_turnL",
"hayfield_turnR",
"hayfield_end"
{ "om_terrain": "farmland", "om_terrain_match_type": "PREFIX" },
{ "om_terrain": "hayfield", "om_terrain_match_type": "PREFIX" }
]
},
{
Expand All @@ -327,14 +249,8 @@
"field",
"rural_road",
"dirt_road_farm_parking",
"farmland_straight",
"farmland_turn",
"farmland_turn_inside",
"farmland_U",
"hayfield_straight",
"hayfield_turnL",
"hayfield_turnR",
"hayfield_end"
{ "om_terrain": "farmland", "om_terrain_match_type": "PREFIX" },
{ "om_terrain": "hayfield", "om_terrain_match_type": "PREFIX" }
]
},
{
Expand All @@ -344,14 +260,8 @@
"field",
"rural_road",
"dirt_road_farm_parking",
"farmland_straight",
"farmland_turn",
"farmland_turn_inside",
"farmland_U",
"hayfield_straight",
"hayfield_turnL",
"hayfield_turnR",
"hayfield_end"
{ "om_terrain": "farmland", "om_terrain_match_type": "PREFIX" },
{ "om_terrain": "hayfield", "om_terrain_match_type": "PREFIX" }
]
},
{
Expand Down
52 changes: 48 additions & 4 deletions doc/BASECAMP.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,6 @@ the needs must be autocalculated.
## Recipe groups
Recipe groups serve two purposes: they indicate what recipes can produced by the camp after an upgrade mission is completed, and they indicate what upgrade paths are available and where camps can be placed.

### Upgrade Paths and Expansions
There are two special recipe groups, `"all_faction_base_types"` and `"all_faction_base_expansions"`. They both look like this:
```json
{
Expand All @@ -232,11 +231,56 @@ There are two special recipe groups, `"all_faction_base_types"` and `"all_factio
},
```

Each entry in the `"recipes"` array must be a dictionary with the `"id"`, `"description"`, and `"om_terrains"` fields. `"id"` is the recipe `"id"` of the recipe that starts that basecamp or basecamp expansion upgrade path, and has to conform to the pattern `"faction_base_X_0"`, where X distinguishes the entry from the others, with the prefix and suffix required by the code. `"description"` is a short name of the basecamp or basecamp expansion. `"om_terrains"` is a list of overmap terrain ids which can be used as the basis for the basecamp or basecamp expansion.
### Upgrade Paths and Expansions

All recipes that start an upgrade path or expansion should have a blueprint requirement that can never be met, such as `"not_an_upgrade"`, to prevent them from showing up as available upgrades.
Additionally, if you want to add an expansion, you must create an OMT with the same `id` as the expansion's `id`.
If the player attempts to start a basecamp on an overmap terrain that has two or more valid basecamp expansion paths, they will allowed to choose which path to start.

Each entry in the `"recipes"` array must be a dictionary with the `"id"`, `"description"`, and `"om_terrains"` fields.

---- Field ---- | --------------------------------------------------------------------------------------------------------- Description --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
`"id"` | Id of the recipe that starts that basecamp or basecamp expansion upgrade path, and has to conform to the pattern `"faction_base_X_0"`, where X distinguishes the entry from the others, with the prefix and suffix required by the code. |
`"description"` | The name shown in-game for the basecamp or basecamp expansion. |
`"om_terrains"` | An array of overmap terrain ids which can be used as the basis for the basecamp or basecamp expansion. Individual entries can either be a string or an object containing `"om_terrain"` for the overmap terrain id, along with at least one of `"parameters"` and `"om_terrain_match_type"` (see [JSON_INFO.md](JSON_INFO.md#Starting-locations)) |


#### Examples

Camp that can be made anywhere

```json
{
"id": "faction_base_barebones_0",
"description": "Barebones Camp",
"om_terrains": [ "ANY" ]
},
```

Camp that can be placed on any overmap terrain starting `farmland_` or `hayfield_` or that match `"farmland"` or `"hayfield"` exactly

```json
{
"id": "faction_base_farmer_0",
"description": "Farmer Camp",
"om_terrains": [
{ "om_terrain": "farmland", "om_terrain_match_type": "PREFIX" },
{ "om_terrain": "hayfield", "om_terrain_match_type": "PREFIX" }
]
},
```

All recipes that start an upgrade path or expansion should have a blueprint requirement that can never be met, such as `"not_an_upgrade"`, to prevent them from showing up as available upgrades. Additionally, if you want to add an expansion, you must create an OMT with the same `id` as the expansion's `id`.
Camp that can only be placed on `"omt_that_varies_in_shape"` if the parameter `"shape"` is set to either `"circle"` or `"circle_alt"` (but not say `"rectangle"` that would want different map updates)

If the player attempts to start a basecamp on an overmap terrain that has two or more valid basecamp expansion paths, she will allowed to choose which path to start.
```json
{
"id": "faction_base_circle_0",
"description": "Farmer Camp",
"om_terrains": [
{ "om_terrain": "omt_that_varies_in_shape", "parameters": { "shape": [ "circle", "circle_alt" ] }
]
},
```

## Sample basecamp upgrade path

Expand Down
34 changes: 30 additions & 4 deletions doc/JSON_INFO.md
Original file line number Diff line number Diff line change
Expand Up @@ -5846,10 +5846,11 @@ String here contains the id of an overmap terrain type (see overmap_terrain.json

If it is an object - it has following attributes:

Identifier | Description
--- | ---
`om_terrain` | ID of overmap terrain which will be selected as the target. Mandatory.
`om_terrain_match_type`| Matching rule to use with `om_terrain`. Defaults to TYPE. Details are below.
Identifier | Description |
---------------------- | --------------------------------------------------------------------------------------- |
`om_terrain` | ID of overmap terrain which will be selected as the target. Mandatory. |
`om_terrain_match_type`| Optional. Matching rule to use with `om_terrain`. Defaults to TYPE. Details are below. |
`parameters` | Optional. Parameter key/value pairs to set. Details are below. |


`om_terrain_match_type` defaults to TYPE if unspecified, and has the following possible values:
Expand All @@ -5874,6 +5875,31 @@ If it is an object - it has following attributes:
id, but may occur at the beginning, end, or middle and does not have any rules
about underscore delimiting.

`parameters` is an object containing one or more keys to set to a specific value provided, say to pick a safe variant of a map.
The keys and values must be valid for the overmap terrains in question.
This can also be used with 0 weight values to provide unique starting map variations that don't spawn normally.

### Examples

Any overmap terrain that is either `"shelter"` or begins with `shelter_`

```json
{
"om_terrain": "shelter",
"om_terrain_match_type": "PREFIX"
}
```

Any overmap terrain that is either `"mansion"` or begins with `mansion_`, and forces the parameter `mansion_variant` to be set to `haunted_scenario_only`

```json
{
"om_terrain": "mansion",
"om_terrain_match_type": "PREFIX",
"parameters": { "mansion_variant": "haunted_scenario_only" }
}
```

## `city_sizes`
(array of two integers)

Expand Down
6 changes: 4 additions & 2 deletions src/condition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -974,7 +974,8 @@ conditional_t::func f_at_om_location( const JsonObject &jo, std::string_view mem
// TODO: legacy check to be removed once primitive field camp OMTs have been purged
return omt_str.find( "faction_base_camp" ) != std::string::npos;
} else if( location_value == "FACTION_CAMP_START" ) {
return !recipe_group::get_recipes_by_id( "all_faction_base_types", omt_str ).empty();
const std::optional<mapgen_arguments> *maybe_args = overmap_buffer.mapgen_args( omt_pos );
return !recipe_group::get_recipes_by_id( "all_faction_base_types", omt_ter, maybe_args ).empty();
} else {
return oter_no_dir( omt_ter ) == location_value;
}
Expand All @@ -991,6 +992,7 @@ conditional_t::func f_near_om_location( const JsonObject &jo, std::string_view m
for( const tripoint_abs_omt &curr_pos : points_in_radius( omt_pos,
range.evaluate( d ) ) ) {
const oter_id &omt_ter = overmap_buffer.ter( curr_pos );
const std::optional<mapgen_arguments> *maybe_args = overmap_buffer.mapgen_args( omt_pos );
const std::string &omt_str = omt_ter.id().str();
std::string location_value = location.evaluate( d );

Expand All @@ -1004,7 +1006,7 @@ conditional_t::func f_near_om_location( const JsonObject &jo, std::string_view m
return true;
}
} else if( location_value == "FACTION_CAMP_START" &&
!recipe_group::get_recipes_by_id( "all_faction_base_types", omt_str ).empty() ) {
!recipe_group::get_recipes_by_id( "all_faction_base_types", omt_ter, maybe_args ).empty() ) {
return true;
} else {
if( oter_no_dir( omt_ter ) == location_value ) {
Expand Down
Loading

0 comments on commit 1b5c1bf

Please sign in to comment.