Skip to content

Commit

Permalink
Mapgen-spawned NPC camps
Browse files Browse the repository at this point in the history
  • Loading branch information
RenechCDDA committed Apr 29, 2024
1 parent 53d39a9 commit 157858d
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 18 deletions.
1 change: 1 addition & 0 deletions data/json/recipes/basecamps/recipe_groups.json
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
},
{
"id": "faction_base_bare_bones_basecamp_0",
"//": "Hardcoded reference in funaction 'place'(overmap.cpp). Please be mindful if changing the ID.",
"description": "Faction Base Bare Bones Basecamp. Manually add bulletin board to use. No construction. Can be constructed anywhere. Access to crafting recipes using Supplies zone covered furniture and appliances.",
"om_terrains": [ "ANY" ]
}
Expand Down
4 changes: 3 additions & 1 deletion doc/OVERMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ Depending on the subtype, there are further relevant fields:
"overmaps": [
{ "point": [ 0, 0, 0 ], "overmap": "campground_1a_north", "locations": [ "forest_edge" ] },
{ "point": [ 1, 0, 0 ], "overmap": "campground_1b_north" },
{ "point": [ 0, 1, 0 ], "overmap": "campground_2a_north" },
{ "point": [ 0, 1, 0 ], "overmap": "campground_2a_north", "camp": "isherwood_family", "camp_name": "Campground camp" },
{ "point": [ 1, 1, 0 ], "overmap": "campground_2b_north" }
],
"connections": [ { "point": [ 1, -1, 0 ], "terrain": "road", "connection": "local_road", "from": [ 1, 0, 0 ] } ],
Expand All @@ -444,6 +444,8 @@ Depending on the subtype, there are further relevant fields:
| `point` | `[ x, y, z]` of the overmap terrain within the special. |
| `overmap` | Id of the `overmap_terrain` to place at the location. If ommited no overmap_terrain is placed but the point will still be checked for valid locations when deciding if placement is valid. |
| `locations` | List of `overmap_location` ids that this overmap terrain may be placed on. Overrides the specials overall `locations` field. |
| `camp` | Will make a NPC-owned camp spawn here when given a value. The entered value is the ID of the faction that owns this camp. |
| `camp_name` | Name that will be displayed on the overmap for the camp. |

### Connections

Expand Down
25 changes: 12 additions & 13 deletions src/basecamp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,12 @@ void basecamp::add_expansion( const std::string &bldg, const tripoint_abs_omt &n
update_resources( bldg );
}

void basecamp::define_camp( const tripoint_abs_omt &p, const std::string_view camp_type )
void basecamp::define_camp( const tripoint_abs_omt &p, const std::string_view camp_type,
bool player_founded )
{
query_new_name( true );
if( player_founded ) {
query_new_name( true );
}
omt_pos = p;
const oter_id &omt_ref = overmap_buffer.ter( omt_pos );
// purging the regions guarantees all entries will start with faction_base_
Expand All @@ -205,9 +208,11 @@ void basecamp::define_camp( const tripoint_abs_omt &p, const std::string_view ca
e.pos = omt_pos;
expansions[base_camps::base_dir] = e;
const std::string direction = oter_get_rotation_string( omt_ref );
const oter_id bcid( direction.empty() ? "faction_base_camp_0" : "faction_base_camp_new_0" +
direction );
overmap_buffer.ter_set( omt_pos, bcid );
if( player_founded ) {
const oter_id bcid( direction.empty() ? "faction_base_camp_0" : "faction_base_camp_new_0" +
direction );
overmap_buffer.ter_set( omt_pos, bcid );
}
update_provides( base_camps::faction_encode_abs( e, 0 ),
expansions[base_camps::base_dir] );
} else {
Expand Down Expand Up @@ -808,14 +813,8 @@ void basecamp::unload_camp_map()

void basecamp::set_owner( faction_id new_owner )
{
for( const std::pair<faction_id, faction> fac : g->faction_manager_ptr->all() ) {
if( fac.first == new_owner ) {
owner = new_owner;
return;
}
}
//Fallthrough, id must be invalid
debugmsg( "Could not find matching faction for new owner's faction_id!" );
// Absolutely no safety checks, factions don't exist until you've encountered them but we sometimes set the owner before that
owner = new_owner;
}

faction_id basecamp::get_owner()
Expand Down
3 changes: 2 additions & 1 deletion src/basecamp.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,8 @@ class basecamp
void add_expansion( const std::string &terrain, const tripoint_abs_omt &new_pos );
void add_expansion( const std::string &bldg, const tripoint_abs_omt &new_pos,
const point &dir );
void define_camp( const tripoint_abs_omt &p, std::string_view camp_type );
void define_camp( const tripoint_abs_omt &p, std::string_view camp_type,
bool player_founded = true );

std::string expansion_tab( const point &dir ) const;
// check whether the point is the part of camp
Expand Down
7 changes: 5 additions & 2 deletions src/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6754,12 +6754,15 @@ basecamp map::hoist_submap_camp( const tripoint &p )
return pcamp ? *pcamp : basecamp();
}

void map::add_camp( const tripoint_abs_omt &omt_pos, const std::string &name )
void map::add_camp( const tripoint_abs_omt &omt_pos, const std::string &name, bool need_validate )
{
basecamp temp_camp = basecamp( name, omt_pos );
overmap_buffer.add_camp( temp_camp );
get_player_character().camps.insert( omt_pos );
g->validate_camps();
// Mapgen-spawned camps never need or want to validate, since they'll always be on newly generated OMTs
if( need_validate ) {
g->validate_camps();
}
}

void map::update_submaps_with_active_items()
Expand Down
2 changes: 1 addition & 1 deletion src/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -1712,7 +1712,7 @@ class map
computer *add_computer( const tripoint &p, const std::string &name, int security );

// Camps
void add_camp( const tripoint_abs_omt &omt_pos, const std::string &name );
void add_camp( const tripoint_abs_omt &omt_pos, const std::string &name, bool need_validate = true );
void remove_submap_camp( const tripoint & );
basecamp hoist_submap_camp( const tripoint &p );
bool point_within_camp( const tripoint &point_check ) const;
Expand Down
2 changes: 2 additions & 0 deletions src/omdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,8 @@ struct overmap_special_terrain : overmap_special_locations {
const std::set<std::string> & );
oter_str_id terrain;
std::set<std::string> flags;
std::optional<faction_id> camp_owner;
std::string camp_name;

void deserialize( const JsonObject &om );
};
Expand Down
29 changes: 29 additions & 0 deletions src/overmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1102,6 +1102,8 @@ void overmap_special_terrain::deserialize( const JsonObject &om )
{
om.read( "point", p );
om.read( "overmap", terrain );
om.read( "camp", camp_owner );
om.read( "camp_name", camp_name );
om.read( "flags", flags );
om.read( "locations", locations );
}
Expand Down Expand Up @@ -1312,6 +1314,18 @@ struct fixed_overmap_special_data : overmap_special_data {
points.insert( pos );
}

if( elem.camp_owner.has_value() ) {
if( !elem.camp_owner.value().is_valid() ) {
debugmsg( "In %s, camp at %s has invalid owner %s", context, pos.to_string(),
elem.camp_owner.value().c_str() );
}
if( elem.camp_name.empty() ) {
debugmsg( "In %s, camp was defined but missing a camp_name.", context );
}
} else if( !elem.camp_name.empty() ) {
debugmsg( "In %s, camp_name defined but no owner. Invalid name is discarded.", context );
}

if( elem.locations.empty() ) {
debugmsg( "In %s, no location is defined for point %s or the "
"overall special.", context, pos.to_string() );
Expand Down Expand Up @@ -1418,6 +1432,21 @@ struct fixed_overmap_special_data : overmap_special_data {
result.omts_used.push_back( location );
const oter_id tid = elem.terrain->get_rotated( dir );
om.ter_set( location, tid );
if( elem.camp_owner.has_value() ) {
// This always results in z=0, but pos() doesn't return z-level information...
tripoint_abs_omt camp_loc = {project_combine( om.pos(), location.xy() ), 0};
get_map().add_camp( camp_loc, "faction_camp", false );
std::optional<basecamp *> bcp = overmap_buffer.find_camp( camp_loc.xy() );
if( !bcp ) {
debugmsg( "Camp placement during special generation failed at %s", camp_loc.to_string() );
} else {
basecamp *temp_camp = *bcp;
temp_camp->set_owner( elem.camp_owner.value() );
temp_camp->set_name( elem.camp_name );
// FIXME? Camp types are raw strings! Not ideal.
temp_camp->define_camp( camp_loc, "faction_base_bare_bones_basecamp_0", false );
}
}
if( blob ) {
for( int x = -2; x <= 2; x++ ) {
for( int y = -2; y <= 2; y++ ) {
Expand Down

0 comments on commit 157858d

Please sign in to comment.