From 53d39a984deeed0b5d80039b29060d82796fe7b9 Mon Sep 17 00:00:00 2001 From: RenechCDDA <84619419+RenechCDDA@users.noreply.github.com> Date: Sun, 28 Apr 2024 20:05:50 -0400 Subject: [PATCH 01/21] Revert https://github.com/CleverRaven/Cataclysm-DDA/pull/72296 --- src/character.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/character.cpp b/src/character.cpp index 6c06c2c4abbad..46680e3be5346 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -4985,9 +4985,7 @@ float Character::activity_level() const bool Character::needs_food() const { - // Before the mechanism for non-player faction NPCs to obtain food is set up, it is unreasonable to require them to consume food. - return ( !get_option( "NO_NPC_FOOD" ) && get_faction() == get_avatar().get_faction() ) || - !is_npc(); + return !( is_npc() && get_option( "NO_NPC_FOOD" ) ); } void Character::update_needs( int rate_multiplier ) From 13cb9dd65ddd6924607984b292207d92e9eeb544 Mon Sep 17 00:00:00 2001 From: RenechCDDA <84619419+RenechCDDA@users.noreply.github.com> Date: Sun, 28 Apr 2024 22:39:31 -0400 Subject: [PATCH 02/21] Mapgen-spawned NPC camps --- .../json/recipes/basecamps/recipe_groups.json | 1 + doc/OVERMAP.md | 4 ++- src/basecamp.cpp | 25 ++++++++-------- src/basecamp.h | 3 +- src/map.cpp | 7 +++-- src/map.h | 2 +- src/omdata.h | 2 ++ src/overmap.cpp | 29 +++++++++++++++++++ 8 files changed, 55 insertions(+), 18 deletions(-) diff --git a/data/json/recipes/basecamps/recipe_groups.json b/data/json/recipes/basecamps/recipe_groups.json index 6a45004645072..a1a995f491fa2 100644 --- a/data/json/recipes/basecamps/recipe_groups.json +++ b/data/json/recipes/basecamps/recipe_groups.json @@ -111,6 +111,7 @@ }, { "id": "faction_base_bare_bones_basecamp_0", + "//": "Hardcoded reference in function '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" ] } diff --git a/doc/OVERMAP.md b/doc/OVERMAP.md index fe06ff2f74eb4..d8c4162ac3531 100644 --- a/doc/OVERMAP.md +++ b/doc/OVERMAP.md @@ -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 ] } ], @@ -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 diff --git a/src/basecamp.cpp b/src/basecamp.cpp index 46f9e55169b58..8d1b067f72cdb 100644 --- a/src/basecamp.cpp +++ b/src/basecamp.cpp @@ -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_ @@ -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 { @@ -808,14 +813,8 @@ void basecamp::unload_camp_map() void basecamp::set_owner( faction_id new_owner ) { - for( const std::pair 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() diff --git a/src/basecamp.h b/src/basecamp.h index 8584101fbc429..7c1a638f3e818 100644 --- a/src/basecamp.h +++ b/src/basecamp.h @@ -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 diff --git a/src/map.cpp b/src/map.cpp index 4803ed2411103..4a6c7ccf7a491 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -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() diff --git a/src/map.h b/src/map.h index e72bf4317550c..36f752acd32a6 100644 --- a/src/map.h +++ b/src/map.h @@ -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; diff --git a/src/omdata.h b/src/omdata.h index 5fde4ee375a00..93edb935c8ccc 100644 --- a/src/omdata.h +++ b/src/omdata.h @@ -499,6 +499,8 @@ struct overmap_special_terrain : overmap_special_locations { const std::set & ); oter_str_id terrain; std::set flags; + std::optional camp_owner; + std::string camp_name; void deserialize( const JsonObject &om ); }; diff --git a/src/overmap.cpp b/src/overmap.cpp index 70d02cae1bb82..cdfe5dd82dd78 100644 --- a/src/overmap.cpp +++ b/src/overmap.cpp @@ -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 ); } @@ -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() ); @@ -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 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++ ) { From 0b1ef78bf989e7e1e09ced0f722702406a00178e Mon Sep 17 00:00:00 2001 From: RenechCDDA <84619419+RenechCDDA@users.noreply.github.com> Date: Mon, 29 Apr 2024 00:32:50 -0400 Subject: [PATCH 03/21] No bulletin boards or faction display Fix abandoning camps (remove them from player known list) --- src/faction.cpp | 4 ++++ src/faction_camp.cpp | 5 ++++- src/iexamine.cpp | 5 +++++ src/overmap.cpp | 2 +- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/faction.cpp b/src/faction.cpp index 7a8e691efc2d6..d3e8bf9cccdcb 100644 --- a/src/faction.cpp +++ b/src/faction.cpp @@ -1052,6 +1052,10 @@ void faction_manager::display() const continue; } basecamp *temp_camp = *p; + if( temp_camp->get_owner() != player_character.get_faction()->id ) { + // Don't display NPC camps as ours + continue; + } camps.push_back( temp_camp ); } lore.clear(); diff --git a/src/faction_camp.cpp b/src/faction_camp.cpp index 7ba4af54041c3..2d2b457121ec2 100644 --- a/src/faction_camp.cpp +++ b/src/faction_camp.cpp @@ -2169,6 +2169,10 @@ void basecamp::abandon_camp() for( npc_ptr &guy : get_npcs_assigned() ) { talk_function::stop_guard( *guy ); } + // We must send this message early, before the name is erased. + add_msg( m_info, _( "You abandon %s." ), name ); + std::set &known_camps = get_player_character().camps; + known_camps.erase( omt_pos ); overmap_buffer.remove_camp( *this ); map &here = get_map(); const tripoint sm_pos = omt_to_sm_copy( omt_pos.raw() ); @@ -2176,7 +2180,6 @@ void basecamp::abandon_camp() // We cannot use bb_pos here, because bb_pos may be {0,0,0} if you haven't examined the bulletin board on camp ever. // here.remove_submap_camp( here.getlocal( bb_pos ) ); here.remove_submap_camp( here.getlocal( ms_pos ) ); - add_msg( m_info, _( "You abandon %s." ), name ); } void basecamp::scan_pseudo_items() diff --git a/src/iexamine.cpp b/src/iexamine.cpp index 67df7f0c45400..8c78473b912bb 100644 --- a/src/iexamine.cpp +++ b/src/iexamine.cpp @@ -1977,6 +1977,11 @@ void iexamine::bulletin_board( Character &you, const tripoint &examp ) std::optional bcp = overmap_buffer.find_camp( omt ); if( bcp ) { basecamp *temp_camp = *bcp; + if( temp_camp->get_owner() != get_avatar().get_faction()->id ) { + you.add_msg_if_player( _( "You don't run this camp, the board is useless to you." ) ); + return; + } + temp_camp->validate_bb_pos( here.getabs( examp ) ); temp_camp->validate_assignees(); temp_camp->validate_sort_points(); diff --git a/src/overmap.cpp b/src/overmap.cpp index cdfe5dd82dd78..7339ca0a63dde 100644 --- a/src/overmap.cpp +++ b/src/overmap.cpp @@ -1323,7 +1323,7 @@ struct fixed_overmap_special_data : overmap_special_data { 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 ); + debugmsg( "In %s, camp_name defined but no owner. Invalid name is discarded.", context ); } if( elem.locations.empty() ) { From 82d89ed7ab8aa632881a5fb21c373d045fe2cbce Mon Sep 17 00:00:00 2001 From: RenechCDDA <84619419+RenechCDDA@users.noreply.github.com> Date: Thu, 9 May 2024 06:08:27 -0400 Subject: [PATCH 04/21] Normalize camp access based on faction relationship --- src/basecamp.cpp | 13 +++++++++++++ src/basecamp.h | 1 + src/faction_camp.cpp | 4 ++++ src/iexamine.cpp | 2 +- src/npcmove.cpp | 3 +++ 5 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/basecamp.cpp b/src/basecamp.cpp index 8d1b067f72cdb..72b29570cb05b 100644 --- a/src/basecamp.cpp +++ b/src/basecamp.cpp @@ -324,6 +324,19 @@ bool basecamp::has_water() const return has_provides( "water_well" ) || has_provides( "fbmh_well_north" ); } +bool basecamp::allowed_access_by( Character &guy ) const +{ + // The owner can always access their own camp. + if( fac() == guy.get_faction() ) { + return true; + } + // Sharing stuff also means sharing access. + if( fac()->has_relationship( guy.get_faction()->id, npc_factions::share_my_stuff ) ) { + return true; + } + return false; +} + std::vector basecamp::available_upgrades( const point &dir ) { std::vector ret_data; diff --git a/src/basecamp.h b/src/basecamp.h index 7c1a638f3e818..e372c31e04c40 100644 --- a/src/basecamp.h +++ b/src/basecamp.h @@ -271,6 +271,7 @@ class basecamp /// Changes the faction opinion for you by @ref change, returns opinion int camp_morale( int change = 0 ) const; + bool allowed_access_by( Character &guy ) const; // recipes, gathering, and craft support functions // from a direction std::map recipe_deck( const point &dir ) const; diff --git a/src/faction_camp.cpp b/src/faction_camp.cpp index 2d2b457121ec2..69ea7fc06d633 100644 --- a/src/faction_camp.cpp +++ b/src/faction_camp.cpp @@ -5585,6 +5585,10 @@ void basecamp::feed_workers( const std::vector bcp = overmap_buffer.find_camp( omt ); if( bcp ) { basecamp *temp_camp = *bcp; - if( temp_camp->get_owner() != get_avatar().get_faction()->id ) { + if( !temp_camp->allowed_access_by( you ) ) { you.add_msg_if_player( _( "You don't run this camp, the board is useless to you." ) ); return; } diff --git a/src/npcmove.cpp b/src/npcmove.cpp index 1de7c8cb454d9..4c566a7288c70 100644 --- a/src/npcmove.cpp +++ b/src/npcmove.cpp @@ -4538,6 +4538,9 @@ bool npc::consume_food_from_camp() return false; } basecamp *bcp = *potential_bc; + if( !bcp->allowed_access_by( *this ) ) { + return false; + } if( get_thirst() > 40 && bcp->has_water() ) { complain_about( "camp_water_thanks", 1_hours, chat_snippets().snip_camp_water_thanks.translated(), false ); From 30f09f6c52f3cd7fda727a3a9947481e461d7807 Mon Sep 17 00:00:00 2001 From: RenechCDDA <84619419+RenechCDDA@users.noreply.github.com> Date: Thu, 9 May 2024 06:21:35 -0400 Subject: [PATCH 05/21] Allow all NPCs to eat out of camp that they can access --- src/npcmove.cpp | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/src/npcmove.cpp b/src/npcmove.cpp index 4c566a7288c70..720846ad721b9 100644 --- a/src/npcmove.cpp +++ b/src/npcmove.cpp @@ -4521,9 +4521,6 @@ static float rate_food( const item &it, int want_nutr, int want_quench ) bool npc::consume_food_from_camp() { - if( !is_player_ally() ) { - return false; - } Character &player_character = get_player_character(); std::optional potential_bc; for( const tripoint_abs_omt &camp_pos : player_character.camps ) { @@ -4548,7 +4545,6 @@ bool npc::consume_food_from_camp() set_thirst( 0 ); return true; } - faction *yours = player_character.get_faction(); int current_kcals = get_stored_kcal() + stomach.get_calories() + guts.get_calories(); int kcal_threshold = get_healthy_kcal() * 19 / 20; @@ -4557,30 +4553,10 @@ bool npc::consume_food_from_camp() // but also don't try to eat a week's worth of food in one sitting int desired_kcals = std::min( static_cast( base_metabolic_rate ), std::max( 0, kcal_threshold + 100 - current_kcals ) ); - int kcals_to_eat = std::min( desired_kcals, yours->food_supply.kcal() ); + int kcals_to_eat = std::min( desired_kcals, bcp->get_owner()->food_supply.kcal() ); if( kcals_to_eat > 0 ) { - // We need food and there's some available, so let's eat it - complain_about( "camp_food_thanks", 1_hours, - chat_snippets().snip_camp_food_thanks.translated(), false ); - - // Make a fake food object here to feed the NPC with, since camp calories are abstracted away - - // Fill up the stomach to "full" (half of capacity) but no further, to avoid NPCs vomiting - // or becoming engorged - units::volume filling_vol = std::max( 0_ml, stomach.capacity( *this ) / 2 - stomach.contains() ); - - // Returns the actual amount of calories and vitamins taken from the camp's larder. - nutrients nutr = bcp->camp_food_supply( -kcals_to_eat ); - - stomach.ingest( food_summary{ - 0_ml, - filling_vol, - nutr - } ); - // Ensure our hunger is satisfied so we don't try to eat again immediately. - // update_stomach() usually takes care of that but it's only called once every 10 seconds for NPCs - set_hunger( -1 ); + bcp->feed_workers( *this, bcp->camp_food_supply( -kcals_to_eat ) ); return true; } else { From 9d6f2bfa8933d06c8da43c8522a0740c3bd28c28 Mon Sep 17 00:00:00 2001 From: RenechCDDA <84619419+RenechCDDA@users.noreply.github.com> Date: Thu, 9 May 2024 06:54:07 -0400 Subject: [PATCH 06/21] Add camps to vanilla factions --- data/json/npcs/factions.json | 10 ++- data/json/overmap/overmap_special/alien.json | 2 +- data/json/overmap/overmap_special/campus.json | 7 +- .../overmap/overmap_special/specials.json | 66 +++++++++++++++---- 4 files changed, 68 insertions(+), 17 deletions(-) diff --git a/data/json/npcs/factions.json b/data/json/npcs/factions.json index ea8dd99498fa3..9af12407b5a10 100644 --- a/data/json/npcs/factions.json +++ b/data/json/npcs/factions.json @@ -91,7 +91,8 @@ "known_by_u": false, "size": 70, "power": 100, - "fac_food_supply": { "calories": 115200, "vitamins": { } }, + "//": "No food supply, they eat off of robofac's", + "fac_food_supply": { "calories": 0, "vitamins": { } }, "wealth": 75000, "currency": "RobofacCoin", "relations": { @@ -117,6 +118,7 @@ "known_by_u": false, "size": 100, "power": 100, + "//": "FIXME: No camp! One character spawns at the refugee center but can't eat out of their stores", "fac_food_supply": { "calories": 201600, "vitamins": { } }, "wealth": 100000000, "relations": { @@ -241,7 +243,8 @@ "known_by_u": false, "size": 5, "power": 0, - "fac_food_supply": { "calories": 1152, "vitamins": { } }, + "//": "No camp, on purpose! These guys will literally starve.", + "fac_food_supply": { "calories": 0, "vitamins": { } }, "wealth": 100, "relations": { "lobby_beggars": { @@ -361,6 +364,7 @@ "known_by_u": false, "size": 100, "power": 100, + "//": "No camp, on purpose! The pilgrim group should probably be full marloss, and not need to eat?", "fac_food_supply": { "calories": 172800, "vitamins": { } }, "wealth": 25000, "relations": { @@ -534,6 +538,7 @@ "size": 7, "power": 10, "currency": "signed_chit", + "//": "FOUR camps.", "fac_food_supply": { "calories": 115200, "vitamins": { } }, "wealth": 75000, "relations": { @@ -781,6 +786,7 @@ "known_by_u": false, "size": 3, "power": 3, + "//": "FIXME: Currently no camps! Spawns via % chance in a bit of nested mapgen, then moves to an existing lighthouse (with no way to know which lighthouse during mapgen!). Will probably need some dynamic camp placement to support.", "fac_food_supply": { "calories": 100, "vitamins": { } }, "wealth": 20000, "relations": { diff --git a/data/json/overmap/overmap_special/alien.json b/data/json/overmap/overmap_special/alien.json index 4433a138a3518..073e18bfc7bdc 100644 --- a/data/json/overmap/overmap_special/alien.json +++ b/data/json/overmap/overmap_special/alien.json @@ -57,7 +57,7 @@ { "point": [ 2, 1, 1 ], "overmap": "exodii_base_x2y1z1_north" }, { "point": [ 3, 1, 1 ], "overmap": "exodii_base_x3y1z1_north" }, { "point": [ 0, 2, 1 ], "overmap": "exodii_base_x0y2z1_north" }, - { "point": [ 1, 2, 1 ], "overmap": "exodii_base_x1y2z1_north" }, + { "point": [ 1, 2, 1 ], "overmap": "exodii_base_x1y2z1_north", "camp": "exodii", "camp_name": "Exodii" }, { "point": [ 2, 2, 1 ], "overmap": "exodii_base_x2y2z1_north" }, { "point": [ 3, 2, 1 ], "overmap": "exodii_base_x3y2z1_north" }, { "point": [ 0, 3, 1 ], "overmap": "exodii_base_x0y3z1_north" }, diff --git a/data/json/overmap/overmap_special/campus.json b/data/json/overmap/overmap_special/campus.json index a66a32bd7486f..3abdeb3a8557a 100644 --- a/data/json/overmap/overmap_special/campus.json +++ b/data/json/overmap/overmap_special/campus.json @@ -63,7 +63,12 @@ { "point": [ 10, 6, 3 ], "overmap": "campus_commons_1_2_3_north" }, { "point": [ 9, 7, 3 ], "overmap": "campus_commons_0_3_3_north" }, { "point": [ 10, 7, 3 ], "overmap": "campus_commons_1_3_3_north" }, - { "point": [ 12, 10, 0 ], "overmap": "campus_media_0_0_0_north" }, + { + "point": [ 12, 10, 0 ], + "overmap": "campus_media_0_0_0_north", + "camp": "the_great_library", + "camp_name": "The Great Library" + }, { "point": [ 12, 11, 0 ], "overmap": "campus_media_0_1_0_north" }, { "point": [ 13, 10, 0 ], "overmap": "campus_media_1_0_0_north" }, { "point": [ 13, 11, 0 ], "overmap": "campus_media_1_1_0_north" }, diff --git a/data/json/overmap/overmap_special/specials.json b/data/json/overmap/overmap_special/specials.json index 37276203a0c9a..31d566646f151 100644 --- a/data/json/overmap/overmap_special/specials.json +++ b/data/json/overmap/overmap_special/specials.json @@ -443,7 +443,7 @@ { "point": [ 0, 1, 0 ], "overmap": "hive_edge_01_north" }, { "point": [ 0, 2, 0 ], "overmap": "hive_edge_02_north" }, { "point": [ 1, 0, 0 ], "overmap": "hive_edge_10_north" }, - { "point": [ 1, 1, 0 ], "overmap": "hive_north" }, + { "point": [ 1, 1, 0 ], "overmap": "hive_north", "camp": "apis_hive", "camp_name": "???" }, { "point": [ 1, 2, 0 ], "overmap": "hive_edge_12_north" }, { "point": [ 2, 0, 0 ], "overmap": "hive_edge_20_north" }, { "point": [ 2, 1, 0 ], "overmap": "hive_edge_21_north" }, @@ -716,7 +716,7 @@ "type": "overmap_special", "id": "Cabin_Lapin", "overmaps": [ - { "point": [ 0, 0, 0 ], "overmap": "cabin_lapin_north" }, + { "point": [ 0, 0, 0 ], "overmap": "cabin_lapin_north", "camp": "lapin", "camp_name": "Lapin" }, { "point": [ 0, 0, 1 ], "overmap": "cabin_roof_lapin_north" }, { "point": [ 1, 1, 0 ], "overmap": "field_graboid" } ], @@ -1339,7 +1339,7 @@ { "point": [ 2, 0, 0 ], "overmap": "prison_island_1_3_north" }, { "point": [ 3, 0, 0 ], "overmap": "prison_island_1_4_north" }, { "point": [ 4, 0, 0 ], "overmap": "prison_island_1_5_north" }, - { "point": [ 0, 1, 0 ], "overmap": "prison_island_1_6_north" }, + { "point": [ 0, 1, 0 ], "overmap": "prison_island_1_6_north", "camp": "prisoners", "camp_name": "Holdouts" }, { "point": [ 1, 1, 0 ], "overmap": "prison_island_1_7_north" }, { "point": [ 2, 1, 0 ], "overmap": "prison_island_1_8_north" }, { "point": [ 3, 1, 0 ], "overmap": "prison_island_1_9_north" }, @@ -2080,7 +2080,12 @@ { "point": [ 9, 6, 0 ], "overmap": "evac_center_10_north" }, { "point": [ 5, 7, 0 ], "overmap": "evac_center_11_north" }, { "point": [ 6, 7, 0 ], "overmap": "evac_center_12_north" }, - { "point": [ 7, 7, 0 ], "overmap": "evac_center_13_north" }, + { + "point": [ 7, 7, 0 ], + "overmap": "evac_center_13_north", + "camp": "free_merchants", + "camp_name": "Refugee Center" + }, { "point": [ 8, 7, 0 ], "overmap": "evac_center_14_north" }, { "point": [ 9, 7, 0 ], "overmap": "evac_center_15_north" }, { "point": [ 5, 8, 0 ], "overmap": "evac_center_16_north" }, @@ -2436,7 +2441,12 @@ { "point": [ -2, 4, 0 ], "overmap": "godco_6_north" }, { "point": [ -3, 4, 0 ], "overmap": "forest_thick" }, { "point": [ -4, 4, 0 ], "overmap": "forest_thick" }, - { "point": [ -1, 4, 0 ], "overmap": "godco_5_north" }, + { + "point": [ -1, 4, 0 ], + "overmap": "godco_5_north", + "camp": "gods_community", + "camp_name": "New England Church Retreat" + }, { "point": [ 0, 4, 0 ], "overmap": "godco_4_north" }, { "point": [ 1, 4, 0 ], "overmap": "forest_thick" }, { "point": [ 2, 4, 0 ], "overmap": "forest_thick" }, @@ -2680,7 +2690,7 @@ { "point": [ 1, 7, 1 ], "overmap": "ranch_camp_65_roof_north" }, { "point": [ 2, 7, 0 ], "overmap": "ranch_camp_66_north" }, { "point": [ 2, 7, 1 ], "overmap": "ranch_camp_66_roof_north" }, - { "point": [ 3, 7, 0 ], "overmap": "ranch_camp_67_north" }, + { "point": [ 3, 7, 0 ], "overmap": "ranch_camp_67_north", "camp": "tacoma_commune", "camp_name": "Tacoma" }, { "point": [ 3, 7, 1 ], "overmap": "ranch_camp_67_roof_north" }, { "point": [ 4, 7, 0 ], "overmap": "ranch_camp_68_north" }, { "point": [ 4, 7, 1 ], "overmap": "ranch_camp_68_roof_north" }, @@ -3583,7 +3593,12 @@ { "point": [ 2, -1, 0 ], "overmap": "robofachq_surface_road2_north" }, { "point": [ 3, -1, 0 ], "overmap": "robofachq_surface_road3_north" }, { "point": [ 0, 0, 0 ], "overmap": "robofachq_surface_parking_north" }, - { "point": [ 1, 0, 0 ], "overmap": "robofachq_surface_entrance_north" }, + { + "point": [ 1, 0, 0 ], + "overmap": "robofachq_surface_entrance_north", + "camp": "robofac", + "camp_name": "Hub 01" + }, { "point": [ 2, 0, 0 ], "overmap": "robofachq_surface_car_entrance_north" }, { "point": [ 3, 0, 0 ], "overmap": "robofachq_surface_a3_north" }, { "point": [ 0, 1, 0 ], "overmap": "robofachq_surface_b0_north" }, @@ -3685,7 +3700,12 @@ "id": "isolated_road", "overmaps": [ { "point": [ 0, 0, 0 ], "overmap": "isolated_road_field_0" }, - { "point": [ 1, 0, 0 ], "overmap": "isolated_house_farm_gunsmith" }, + { + "point": [ 1, 0, 0 ], + "overmap": "isolated_house_farm_gunsmith", + "camp": "isolated_artisans", + "camp_name": "Cody & Jay" + }, { "point": [ 0, 1, 0 ], "overmap": "isolated_house_farm_blacksmith" }, { "point": [ 1, 0, 1 ], "overmap": "isolated_house_farm_roof_gunsmith" }, { "point": [ 0, 1, 1 ], "overmap": "isolated_house_farm_roof_blacksmith" }, @@ -5468,7 +5488,7 @@ { "point": [ 1, 4, 0 ], "overmap": "special_forest" }, { "point": [ 2, 4, 0 ], "overmap": "special_forest_thick" }, { "point": [ 3, 4, 0 ], "overmap": "special_forest" }, - { "point": [ 4, 4, 0 ], "overmap": "cabin_isherwood_north" }, + { "point": [ 4, 4, 0 ], "overmap": "cabin_isherwood_north", "camp": "isherwood_family", "camp_name": "Cabin" }, { "point": [ 4, 4, 1 ], "overmap": "cabin_lake_roof_north" }, { "point": [ 5, 4, 0 ], "overmap": "special_forest" }, { "point": [ 6, 4, 0 ], "overmap": "special_forest" }, @@ -5603,7 +5623,12 @@ { "point": [ 14, 8, 0 ], "overmap": "special_field" }, { "point": [ 15, 8, 0 ], "overmap": "special_field" }, { "point": [ 16, 8, 0 ], "overmap": "horse_farm_isherwood_5_north" }, - { "point": [ 17, 8, 0 ], "overmap": "horse_farm_isherwood_6_north" }, + { + "point": [ 17, 8, 0 ], + "overmap": "horse_farm_isherwood_6_north", + "camp": "isherwood_family", + "camp_name": "Isherwood Stables" + }, { "point": [ 18, 8, 0 ], "overmap": "horse_farm_isherwood_7_north" }, { "point": [ 18, 8, 1 ], "overmap": "horse_farm_isherwood_7_hayloft_north" }, { "point": [ 18, 8, 2 ], "overmap": "horse_farm_isherwood_7_roof_north" }, @@ -5905,7 +5930,12 @@ { "point": [ 10, 18, 0 ], "overmap": "farm_isherwood_3_north" }, { "point": [ 10, 18, 2 ], "overmap": "farm_isherwood_3_roof_north" }, { "point": [ 10, 18, 1 ], "overmap": "farm_isherwood_3_hayloft_north" }, - { "point": [ 11, 18, 0 ], "overmap": "farm_isherwood_2_north" }, + { + "point": [ 11, 18, 0 ], + "overmap": "farm_isherwood_2_north", + "camp": "isherwood_family", + "camp_name": "Isherwood Outcropping" + }, { "point": [ 11, 18, -1 ], "overmap": "farm_isherwood_2_cellar_north" }, { "point": [ 11, 18, 1 ], "overmap": "farm_isherwood_2_roof_north" }, { "point": [ 12, 18, 0 ], "overmap": "farm_isherwood_1_north" }, @@ -6045,7 +6075,12 @@ { "point": [ 23, 22, 0 ], "overmap": "rural_road_ns" }, { "point": [ 24, 22, 0 ], "overmap": "smokehouse_north" }, { "point": [ 24, 22, 1 ], "overmap": "smokehouse_roof_north" }, - { "point": [ 25, 22, 0 ], "overmap": "dairy_farm_isherwood_SW_north" }, + { + "point": [ 25, 22, 0 ], + "overmap": "dairy_farm_isherwood_SW_north", + "camp": "isherwood_family", + "camp_name": "Isherwood Farms" + }, { "point": [ 25, 22, 1 ], "overmap": "dairy_farm_isherwood_SW_roof_north" }, { "point": [ 26, 22, 0 ], "overmap": "dairy_farm_isherwood_SE_north" }, { "point": [ 26, 22, 1 ], "overmap": "dairy_farm_isherwood_SE_roof_north" }, @@ -7041,7 +7076,12 @@ "id": "bunker shop", "overmaps": [ { "point": [ 0, 0, 0 ], "overmap": "bunker_shop_g_south" }, - { "point": [ 0, 0, -1 ], "overmap": "bunker_shop_b_south" } + { + "point": [ 0, 0, -1 ], + "overmap": "bunker_shop_b_south", + "camp": "wasteland_scavengers", + "camp_name": "Merchant" + } ], "connections": [ { "point": [ 0, -1, 0 ], "terrain": "road", "existing": true, "connection": "local_road", "from": [ 0, 0, 0 ] } ], "locations": [ "field", "forest_without_trail" ], From 5653001dde361b40036fc0f5f201339a41e9cf78 Mon Sep 17 00:00:00 2001 From: RenechCDDA <84619419+RenechCDDA@users.noreply.github.com> Date: Thu, 9 May 2024 22:52:33 -0400 Subject: [PATCH 07/21] Camps for in-repo mods --- data/mods/Aftershock/maps/overmap_specials.json | 9 +++++++-- data/mods/Aftershock/npcs/factions.json | 6 ++++-- data/mods/DinoMod/NPC/NC_BO_BARONYX.json | 1 + data/mods/Magiclysm/worldgen/forge_of_wonders.json | 2 +- .../Magiclysm/worldgen/multitile_city_buildings.json | 2 +- data/mods/Magiclysm/worldgen/overmap_specials.json | 7 ++++++- 6 files changed, 20 insertions(+), 7 deletions(-) diff --git a/data/mods/Aftershock/maps/overmap_specials.json b/data/mods/Aftershock/maps/overmap_specials.json index 676a88294b56f..53104ef79c460 100644 --- a/data/mods/Aftershock/maps/overmap_specials.json +++ b/data/mods/Aftershock/maps/overmap_specials.json @@ -2,7 +2,7 @@ { "type": "overmap_special", "id": "prepnet_orchard", - "overmaps": [ { "point": [ 0, 0, 0 ], "overmap": "prepnet_orchard_north" } ], + "overmaps": [ { "point": [ 0, 0, 0 ], "overmap": "prepnet_orchard_north", "camp": "Prepnet_Phyle", "camp_name": "PrepNet" } ], "connections": [ { "point": [ 0, -1, 0 ], "terrain": "road" } ], "locations": [ "land" ], "city_distance": [ 5, -1 ], @@ -189,7 +189,12 @@ "overmaps": [ { "point": [ 0, -1, -9 ], "overmap": "augustmoon_docking_arm_north" }, { "point": [ -1, 0, -9 ], "overmap": "augustmoon_bar_north" }, - { "point": [ 0, 0, -9 ], "overmap": "augustmoon_main_concourse1_north" }, + { + "point": [ 0, 0, -9 ], + "overmap": "augustmoon_main_concourse1_north", + "camp": "UICA", + "camp_name": "Port Augustmoon" + }, { "point": [ 1, 0, -9 ], "overmap": "augustmoon_solar_array1_north" }, { "point": [ 0, 1, -9 ], "overmap": "augustmoon_main_concourse2_north" }, { "point": [ 1, 1, -9 ], "overmap": "augustmoon_solar_array2_north" }, diff --git a/data/mods/Aftershock/npcs/factions.json b/data/mods/Aftershock/npcs/factions.json index 2e9d84f8e8fa5..0cfcb82dae5c0 100644 --- a/data/mods/Aftershock/npcs/factions.json +++ b/data/mods/Aftershock/npcs/factions.json @@ -172,7 +172,8 @@ "size": 100, "power": 100, "currency": "", - "fac_food_supply": { "calories": 115200, "vitamins": { } }, + "//": "Doesn't actually have NPCs, so no camp or food supply is necessary.", + "fac_food_supply": { "calories": 0, "vitamins": { } }, "wealth": 75000, "relations": { "free_merchants": { @@ -252,7 +253,8 @@ "known_by_u": false, "size": 15, "power": 20, - "fac_food_supply": { "calories": 1200, "vitamins": { } }, + "//": "Doesn't actually have *spawned* NPCs, so no camp or food supply is necessary.", + "fac_food_supply": { "calories": 0, "vitamins": { } }, "wealth": 7500, "relations": { "free_merchants": { diff --git a/data/mods/DinoMod/NPC/NC_BO_BARONYX.json b/data/mods/DinoMod/NPC/NC_BO_BARONYX.json index b4fbdfd569b6f..d6a4d99eb9a03 100644 --- a/data/mods/DinoMod/NPC/NC_BO_BARONYX.json +++ b/data/mods/DinoMod/NPC/NC_BO_BARONYX.json @@ -286,6 +286,7 @@ "size": 25, "power": 20, "currency": "icon", + "//": "Fixme: Not placed as a special, so can't put a camp down for them!", "fac_food_supply": { "calories": 87500, "vitamins": { } }, "wealth": 82500, "relations": { diff --git a/data/mods/Magiclysm/worldgen/forge_of_wonders.json b/data/mods/Magiclysm/worldgen/forge_of_wonders.json index 0171b0ff8f05c..dc2e024232581 100644 --- a/data/mods/Magiclysm/worldgen/forge_of_wonders.json +++ b/data/mods/Magiclysm/worldgen/forge_of_wonders.json @@ -184,7 +184,7 @@ { "point": [ 0, 0, 1 ], "overmap": "forge_1A_roof_north" }, { "point": [ 1, 0, 0 ], "overmap": "forge_2A_north" }, { "point": [ 1, 0, 1 ], "overmap": "forge_2A_roof_north" }, - { "point": [ 2, 0, 0 ], "overmap": "forge_3A_north" }, + { "point": [ 2, 0, 0 ], "overmap": "forge_3A_north", "camp": "forge_lords", "camp_name": "Forge of Wonders" }, { "point": [ 2, 0, 1 ], "overmap": "forge_3A_roof_north" }, { "point": [ 3, 0, 0 ], "overmap": "forge_4A_north" }, { "point": [ 3, 0, 1 ], "overmap": "forge_4A_roof_north" }, diff --git a/data/mods/Magiclysm/worldgen/multitile_city_buildings.json b/data/mods/Magiclysm/worldgen/multitile_city_buildings.json index 3767a55c23ed3..059167bfc9f1c 100644 --- a/data/mods/Magiclysm/worldgen/multitile_city_buildings.json +++ b/data/mods/Magiclysm/worldgen/multitile_city_buildings.json @@ -4,7 +4,7 @@ "id": "magic_shop", "locations": [ "land" ], "overmaps": [ - { "point": [ 0, 0, 0 ], "overmap": "magic_shop_north" }, + { "point": [ 0, 0, 0 ], "overmap": "magic_shop_north", "camp": "healers_grey", "camp_name": "Healer's respite" }, { "point": [ 0, 0, 1 ], "overmap": "magic_shop_2ndfloor_north" }, { "point": [ 0, 0, 2 ], "overmap": "magic_shop_roof_north" } ] diff --git a/data/mods/Magiclysm/worldgen/overmap_specials.json b/data/mods/Magiclysm/worldgen/overmap_specials.json index ae280b6e80806..5b5fa0698f54f 100644 --- a/data/mods/Magiclysm/worldgen/overmap_specials.json +++ b/data/mods/Magiclysm/worldgen/overmap_specials.json @@ -101,7 +101,12 @@ { "point": [ 3, 3, 0 ], "overmap": "lake_retreat_ground_north" }, { "point": [ 3, 3, 1 ], "overmap": "lake_retreat_z1_north" }, { "point": [ 3, 3, 2 ], "overmap": "lake_retreat_z2_north" }, - { "point": [ 3, 3, 3 ], "overmap": "lake_retreat_z3_north" }, + { + "point": [ 3, 3, 3 ], + "overmap": "lake_retreat_z3_north", + "camp": "wizards_ancient", + "camp_name": "Old Wizard" + }, { "point": [ 3, 3, 4 ], "overmap": "lake_retreat_z4_north" }, { "point": [ 4, 3, 0 ], "overmap": "forest" }, { "point": [ 5, 3, 0 ], "overmap": "lake_shore" }, From 52884dafaef039bb16fd6467fbf088e5f7f7cb9c Mon Sep 17 00:00:00 2001 From: RenechCDDA <84619419+RenechCDDA@users.noreply.github.com> Date: Thu, 9 May 2024 23:32:55 -0400 Subject: [PATCH 08/21] Give all our factions reasonable food stores --- data/json/npcs/factions.json | 43 ++++++++++++++---------- data/mods/Aftershock/npcs/factions.json | 6 ++-- data/mods/DinoMod/NPC/NC_BO_BARONYX.json | 3 +- data/mods/Magiclysm/npc/factions.json | 9 +++-- 4 files changed, 38 insertions(+), 23 deletions(-) diff --git a/data/json/npcs/factions.json b/data/json/npcs/factions.json index 9af12407b5a10..943bf19cae6d0 100644 --- a/data/json/npcs/factions.json +++ b/data/json/npcs/factions.json @@ -60,7 +60,9 @@ "known_by_u": false, "size": 100, "power": 100, - "fac_food_supply": { "calories": 115200, "vitamins": { "iron": 800, "calcium": 800, "vitC": 600 } }, + "//": "90 days worth of food for 10 people, at 3000kcal/day and full RDA of iron/calcium/vitC", + "//2": "Expect to see these values a lot.", + "fac_food_supply": { "calories": 2700000000, "vitamins": { "iron": 86400, "calcium": 86400, "vitC": 86400 } }, "wealth": 100000000, "currency": "RobofacCoin", "price_rules": [ { "group": "NC_ROBOFAC_gear", "markup": 2 } ], @@ -119,7 +121,7 @@ "size": 100, "power": 100, "//": "FIXME: No camp! One character spawns at the refugee center but can't eat out of their stores", - "fac_food_supply": { "calories": 201600, "vitamins": { } }, + "fac_food_supply": { "calories": 2700000000, "vitamins": { "iron": 86400, "calcium": 86400, "vitC": 86400 } }, "wealth": 100000000, "relations": { "old_guard": { @@ -157,7 +159,9 @@ "known_by_u": false, "size": 100, "power": 100, - "fac_food_supply": { "calories": 115200, "vitamins": { } }, + "//": "(only) 30 days worth of food for 100 people, at 3000kcal/day and full RDA of iron/calcium/vitC", + "//2": "Their canonical starvation is not yet implemented.", + "fac_food_supply": { "calories": 9000000000, "vitamins": { "iron": 288000, "calcium": 288000, "vitC": 288000 } }, "wealth": 75000000, "currency": "FMCNote", "price_rules": [ @@ -304,7 +308,7 @@ "known_by_u": false, "size": 100, "power": 100, - "fac_food_supply": { "calories": 115200, "vitamins": { } }, + "fac_food_supply": { "calories": 2700000000, "vitamins": { "iron": 86400, "calcium": 86400, "vitC": 86400 } }, "wealth": 10000000, "currency": "FMCNote", "price_rules": [ { "item": "money_strap_FMCNote", "fixed_adj": 0 }, { "item": "money_bundle_FMCNote", "fixed_adj": 0 } ], @@ -334,7 +338,8 @@ "known_by_u": false, "size": 2, "power": 5, - "fac_food_supply": { "calories": 4000, "vitamins": { } }, + "//": "180 days worth of food for 2 people, at 3000kcal/day and full RDA of iron/calcium/vitC", + "fac_food_supply": { "calories": 1080000000, "vitamins": { "iron": 34560, "calcium": 34560, "vitC": 34560 } }, "wealth": 100000, "currency": "FMCNote", "price_rules": [ { "item": "money_strap_FMCNote", "fixed_adj": 0 }, { "item": "money_bundle_FMCNote", "fixed_adj": 0 } ], @@ -365,7 +370,7 @@ "size": 100, "power": 100, "//": "No camp, on purpose! The pilgrim group should probably be full marloss, and not need to eat?", - "fac_food_supply": { "calories": 172800, "vitamins": { } }, + "fac_food_supply": { "calories": 0, "vitamins": { } }, "wealth": 25000, "relations": { "marloss": { @@ -408,9 +413,10 @@ "likes_u": 0, "respects_u": 0, "known_by_u": false, - "size": 100, + "size": 1, "power": 100, - "fac_food_supply": { "calories": 172800, "vitamins": { } }, + "//": "90 days worth of food for 1 person, at 3000kcal/day and full RDA of iron/calcium/vitC", + "fac_food_supply": { "calories": 270000000, "vitamins": { "iron": 8640, "calcium": 8640, "vitC": 8640 } }, "wealth": 2500000, "relations": { "lobby_beggars": { "knows your voice": true }, @@ -434,7 +440,7 @@ "known_by_u": false, "size": 100, "power": 100, - "fac_food_supply": { "calories": 230400, "vitamins": { } }, + "fac_food_supply": { "calories": 2700000000, "vitamins": { "iron": 86400, "calcium": 86400, "vitC": 86400 } }, "wealth": 45000000, "relations": { "hells_raiders": { @@ -510,7 +516,8 @@ "known_by_u": false, "size": 1, "power": 10, - "fac_food_supply": { "calories": 2304, "vitamins": { } }, + "//": "90 days worth of food for 1 person, at 3000kcal/day and full RDA of iron/calcium/vitC", + "fac_food_supply": { "calories": 270000000, "vitamins": { "iron": 8640, "calcium": 8640, "vitC": 8640 } }, "wealth": 0, "relations": { "apis_hive": { @@ -539,7 +546,7 @@ "power": 10, "currency": "signed_chit", "//": "FOUR camps.", - "fac_food_supply": { "calories": 115200, "vitamins": { } }, + "fac_food_supply": { "calories": 2700000000, "vitamins": { "iron": 86400, "calcium": 86400, "vitC": 86400 } }, "wealth": 75000, "relations": { "free_merchants": { @@ -612,7 +619,7 @@ "size": 25, "power": 20, "currency": "icon", - "fac_food_supply": { "calories": 87500, "vitamins": { } }, + "fac_food_supply": { "calories": 2700000000, "vitamins": { "iron": 86400, "calcium": 86400, "vitC": 86400 } }, "wealth": 82500, "relations": { "gods_community": { @@ -704,7 +711,8 @@ "size": 1, "power": 1, "currency": "fur", - "fac_food_supply": { "calories": 87500, "vitamins": { } }, + "//": "90 days worth of food for 1 person, at 3000kcal/day and full RDA of iron/calcium/vitC", + "fac_food_supply": { "calories": 270000000, "vitamins": { "iron": 8640, "calcium": 8640, "vitC": 8640 } }, "wealth": 82500, "relations": { "free_merchants": { @@ -787,7 +795,7 @@ "size": 3, "power": 3, "//": "FIXME: Currently no camps! Spawns via % chance in a bit of nested mapgen, then moves to an existing lighthouse (with no way to know which lighthouse during mapgen!). Will probably need some dynamic camp placement to support.", - "fac_food_supply": { "calories": 100, "vitamins": { } }, + "fac_food_supply": { "calories": 2700000000, "vitamins": { "iron": 86400, "calcium": 86400, "vitC": 86400 } }, "wealth": 20000, "relations": { "free_merchants": { "knows your voice": true }, @@ -806,7 +814,8 @@ "known_by_u": true, "size": 100, "power": 100, - "fac_food_supply": { "calories": 230400, "vitamins": { } }, + "//": "7 days worth of food for 10 people, at 3000kcal/day and *half* RDA of iron/calcium/vitC", + "fac_food_supply": { "calories": 210000000, "vitamins": { "iron": 3360, "calcium": 3360, "vitC": 3360 } }, "wealth": 45000000, "relations": { "hells_raiders": { @@ -838,7 +847,7 @@ "mon_faction": "exodii", "size": 100, "power": 100, - "fac_food_supply": { "calories": 115200, "vitamins": { } }, + "fac_food_supply": { "calories": 2700000000, "vitamins": { "iron": 86400, "calcium": 86400, "vitC": 86400 } }, "wealth": 75000000, "price_rules": [ { "group": "games_board_all", "premium": 2.5 } ], "relations": { @@ -921,7 +930,7 @@ "known_by_u": false, "size": 100, "power": 100, - "fac_food_supply": { "calories": 115200, "vitamins": { } }, + "fac_food_supply": { "calories": 2700000000, "vitamins": { "iron": 86400, "calcium": 86400, "vitC": 86400 } }, "wealth": 25000000, "currency": "FlatCoin", "price_rules": [ diff --git a/data/mods/Aftershock/npcs/factions.json b/data/mods/Aftershock/npcs/factions.json index 0cfcb82dae5c0..d74423b3b860d 100644 --- a/data/mods/Aftershock/npcs/factions.json +++ b/data/mods/Aftershock/npcs/factions.json @@ -10,7 +10,8 @@ "size": 15, "power": 20, "currency": "crypto_coin", - "fac_food_supply": { "calories": 115200, "vitamins": { } }, + "//": "90 days worth of food for 1 person, at 3000kcal/day and full RDA of iron/calcium/vitC", + "fac_food_supply": { "calories": 270000000, "vitamins": { "iron": 8640, "calcium": 8640, "vitC": 8640 } }, "wealth": 75000, "relations": { "free_merchants": { @@ -91,7 +92,8 @@ { "item": "UICA_1000d", "fixed_adj": 0 }, { "item": "UICA_10000d", "fixed_adj": 0 } ], - "fac_food_supply": { "calories": 115200, "vitamins": { } }, + "//": "90 days worth of food for 10 people, at 3000kcal/day and full RDA of iron/calcium/vitC", + "fac_food_supply": { "calories": 2700000000, "vitamins": { "iron": 86400, "calcium": 86400, "vitC": 86400 } }, "wealth": 75000, "relations": { "free_merchants": { diff --git a/data/mods/DinoMod/NPC/NC_BO_BARONYX.json b/data/mods/DinoMod/NPC/NC_BO_BARONYX.json index d6a4d99eb9a03..9d837d80d5c62 100644 --- a/data/mods/DinoMod/NPC/NC_BO_BARONYX.json +++ b/data/mods/DinoMod/NPC/NC_BO_BARONYX.json @@ -287,7 +287,8 @@ "power": 20, "currency": "icon", "//": "Fixme: Not placed as a special, so can't put a camp down for them!", - "fac_food_supply": { "calories": 87500, "vitamins": { } }, + "//2": "90 days worth of food for 10 people, at 3000kcal/day and full RDA of iron/calcium/vitC", + "fac_food_supply": { "calories": 2700000000, "vitamins": { "iron": 86400, "calcium": 86400, "vitC": 86400 } }, "wealth": 82500, "relations": { "free_merchants": { diff --git a/data/mods/Magiclysm/npc/factions.json b/data/mods/Magiclysm/npc/factions.json index 1965000672f1a..f799a8d4495aa 100644 --- a/data/mods/Magiclysm/npc/factions.json +++ b/data/mods/Magiclysm/npc/factions.json @@ -8,7 +8,8 @@ "known_by_u": false, "size": 5, "power": 100, - "fac_food_supply": { "calories": 115200, "vitamins": { } }, + "//": "90 days worth of food for 1 person, at 3000kcal/day and full RDA of iron/calcium/vitC", + "fac_food_supply": { "calories": 270000000, "vitamins": { "iron": 8640, "calcium": 8640, "vitC": 8640 } }, "wealth": 100000, "currency": "embued_coin", "relations": { @@ -69,7 +70,8 @@ "known_by_u": false, "size": 50, "power": 50, - "fac_food_supply": { "calories": 11520, "vitamins": { } }, + "//": "90 days worth of food for 1 person, at 3000kcal/day and full RDA of iron/calcium/vitC", + "fac_food_supply": { "calories": 270000000, "vitamins": { "iron": 8640, "calcium": 8640, "vitC": 8640 } }, "wealth": 1000, "relations": { "lobby_beggars": { @@ -130,7 +132,8 @@ "known_by_u": false, "size": 5, "power": 100, - "fac_food_supply": { "calories": 115200, "vitamins": { } }, + "//": "90 days worth of food for 10 people, at 3000kcal/day and full RDA of iron/calcium/vitC", + "fac_food_supply": { "calories": 2700000000, "vitamins": { "iron": 86400, "calcium": 86400, "vitC": 86400 } }, "wealth": 75000000, "currency": "denarius", "relations": { From 08679de4ca8597a45cb547c2a37492f83912087f Mon Sep 17 00:00:00 2001 From: RenechCDDA <84619419+RenechCDDA@users.noreply.github.com> Date: Fri, 10 May 2024 00:10:47 -0400 Subject: [PATCH 09/21] Handle infinite food for most NPC factions --- data/json/npcs/factions.json | 1 + doc/FACTIONS.md | 7 +++++-- src/faction.cpp | 1 + src/faction.h | 1 + src/faction_camp.cpp | 8 +++++--- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/data/json/npcs/factions.json b/data/json/npcs/factions.json index 943bf19cae6d0..8c46cfb463fe4 100644 --- a/data/json/npcs/factions.json +++ b/data/json/npcs/factions.json @@ -9,6 +9,7 @@ "size": 1, "power": 100, "fac_food_supply": { "calories": 0, "vitamins": { } }, + "consumes_food": true, "wealth": 0, "relations": { "your_followers": { diff --git a/doc/FACTIONS.md b/doc/FACTIONS.md index 4f83adae3128b..89fe2d48939fc 100644 --- a/doc/FACTIONS.md +++ b/doc/FACTIONS.md @@ -14,6 +14,7 @@ An NPC faction looks like this: "size": 100, "power": 100, "fac_food_supply": { "calories": 115200, "vitamins": { "iron": 800, "calcium": 800, "vitC": 600 } }, + "consumes_food": true, "lone_wolf_faction": true, "wealth": 75000000, "currency": "FMCNote", @@ -66,8 +67,10 @@ Field | Meaning `"known_by_u"` | boolean, whether the player has met members of the faction. Can be changed in play. Unknown factions will not be displayed in the faction menu. `"size"` | integer, an approximate count of the members of the faction. Has no effect in play currently. `"power"` | integer, an approximation of the faction's power. Has no effect in play currently. -`"fac_food_supply"` | integer, the number of calories (not kilocalories!) available to the faction. Has no effect in play currently. -`"vitamins"` | array, *units* of vitamins available to this faction. This is not the same as RDA, see [the vitamins doc](VITAMIN.md) for more details. Has no effect in play currently. +`"fac_food_supply"` | object, mandatory. The overall food supply of the faction, including the `calories` and `vitamins`. +`"calories"` | integer, the number of calories (not kilocalories!) available to the faction. +`"vitamins"` | array, *units* of vitamins available to this faction. This is not the same as RDA, see [the vitamins doc](VITAMIN.md) for more details. +`"consumes_food"` | bool, optional, defaults to false. Controls whether characters eating from the fac_food_supply actually removes food from it. Note that eating is controlled by the external optional "NO_NPC_FOOD". consumes_food only controls whether the eaten food is removed from storage (whether the amount of food available goes down!) `"wealth"` | integer, number of post-apocalyptic currency in cents that that faction has to purchase stuff. Serves as an upper limit on the amount of items restocked by a NPC of this faction with a defined shopkeeper_item_group (see NPCs.md) `"currency"` | string, the item `"id"` of the faction's preferred currency. Faction shopkeeps will trade faction current at 100% value, for both selling and buying. `"price_rules"` | array, allows defining `premium`, `markup`, `price` and/or `fixed_adj` for an `item`/`category`/`group`.

`premium` is a price multiplier that applies to both sides.
`markup` is only used when an NPC is selling to the avatar and defaults to `1`.
`price` replaces the item's `price_postapoc`.
`fixed_adj` is used instead of adjustment based on social skill and intelligence stat and can be used to define secondary currencies.

Lower entries override higher ones. For conditionals, the avatar is used as alpha and the evaluating npc as beta diff --git a/src/faction.cpp b/src/faction.cpp index d3e8bf9cccdcb..ebe431d5be72e 100644 --- a/src/faction.cpp +++ b/src/faction.cpp @@ -132,6 +132,7 @@ faction_template::faction_template( const JsonObject &jsobj ) , wealth( jsobj.get_int( "wealth" ) ) { jsobj.get_member( "description" ).read( desc ); + optional( jsobj, false, "consumes_food", consumes_food, false ); optional( jsobj, false, "price_rules", price_rules, faction_price_rules_reader {} ); jsobj.read( "fac_food_supply", food_supply, true ); if( jsobj.has_string( "currency" ) ) { diff --git a/src/faction.h b/src/faction.h index 464918d46b379..bc732c56ce450 100644 --- a/src/faction.h +++ b/src/faction.h @@ -114,6 +114,7 @@ class faction_template int size; // How big is our sphere of influence? int power; // General measure of our power nutrients food_supply; //Total nutritional value held + bool consumes_food; //Whether this faction actually draws down the food_supply when eating from it int wealth; //Total trade currency bool lone_wolf_faction; // is this a faction for just one person? itype_id currency; // id of the faction currency diff --git a/src/faction_camp.cpp b/src/faction_camp.cpp index 69ea7fc06d633..fdedc5c30d419 100644 --- a/src/faction_camp.cpp +++ b/src/faction_camp.cpp @@ -5534,7 +5534,7 @@ nutrients basecamp::camp_food_supply( nutrients &change ) double percent_consumed = std::abs( static_cast( change.calories ) ) / fac()->food_supply.calories; consumed = fac()->food_supply; - if( std::abs( change.calories ) > fac()->food_supply.calories ) { + if( std::abs( change.calories ) > fac()->food_supply.calories && fac()->consumes_food ) { //Whoops, we don't have enough food. Empty the larder! No crumb shall go un-eaten! fac()->food_supply += change; faction *yours = get_player_character().get_faction(); @@ -5547,8 +5547,10 @@ nutrients basecamp::camp_food_supply( nutrients &change ) return consumed; } consumed *= percent_consumed; - // Subtraction since we use the absolute value of change's calories to get the percent - fac()->food_supply -= consumed; + if( fac()->consumes_food ) { + // Subtraction since we use the absolute value of change's calories to get the percent + fac()->food_supply -= consumed; + } return consumed; } fac()->food_supply += change; From c989f1a5991e76f174a547b24976e8187ec59e90 Mon Sep 17 00:00:00 2001 From: RenechCDDA <84619419+RenechCDDA@users.noreply.github.com> Date: Fri, 10 May 2024 02:10:07 -0400 Subject: [PATCH 10/21] NPC camps use a special camp type which always provides water --- .../json/recipes/basecamps/recipe_groups.json | 1 - .../recipes/basecamps/special_hardcoded.json | 40 +++++++++++++++++++ src/basecamp.cpp | 1 + src/overmap.cpp | 2 +- 4 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 data/json/recipes/basecamps/special_hardcoded.json diff --git a/data/json/recipes/basecamps/recipe_groups.json b/data/json/recipes/basecamps/recipe_groups.json index a1a995f491fa2..6a45004645072 100644 --- a/data/json/recipes/basecamps/recipe_groups.json +++ b/data/json/recipes/basecamps/recipe_groups.json @@ -111,7 +111,6 @@ }, { "id": "faction_base_bare_bones_basecamp_0", - "//": "Hardcoded reference in function '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" ] } diff --git a/data/json/recipes/basecamps/special_hardcoded.json b/data/json/recipes/basecamps/special_hardcoded.json new file mode 100644 index 0000000000000..97e08f4462953 --- /dev/null +++ b/data/json/recipes/basecamps/special_hardcoded.json @@ -0,0 +1,40 @@ +[ + { + "//": "This file contains a special NPC-only basecamp whch doesn't place anything, equivalent to the barebones camp. It is placed during mapgen, and should not show up as a valid player option in regular gameplay. The entire purpose is to provide 'water_well' so NPCs don't dehydrate to death.", + "type": "recipe", + "activity_level": "NO_EXERCISE", + "result": "faction_base_bare_bones_NPC_camp_0", + "description": "NPC-only. If you see this it's a bug", + "category": "CC_BUILDING", + "subcategory": "CSC_BUILDING_BASES", + "skill_used": "fabrication", + "autolearn": false, + "never_learn": true, + "time": "1 h", + "construction_blueprint": "fbbb", + "blueprint_provides": [ + { "id": "gathering" }, + { "id": "fbbb_crafting_recipes_basic" }, + { "id": "fbbb_crafting_recipes_cooking" }, + { "id": "fbbb_crafting_recipes_crafting" }, + { "id": "fbbb_crafting_recipes_custom" }, + { "id": "fbbb" }, + { "id": "firewood" }, + { "id": "foraging" }, + { "id": "sorting" }, + { "id": "logging" }, + { "id": "trapping" }, + { "id": "hunting" }, + { "id": "kitchen" }, + { "id": "relaying" }, + { "id": "walls" }, + { "id": "recruiting" }, + { "id": "scouting" }, + { "id": "water_well" }, + { "id": "patrolling" } + ], + "blueprint_requires": [ { "id": "not_an_upgrade" } ], + "blueprint_name": "NPC-only. If you see this it's a bug", + "check_blueprint_needs": false + } +] diff --git a/src/basecamp.cpp b/src/basecamp.cpp index 72b29570cb05b..8527bba1f8e26 100644 --- a/src/basecamp.cpp +++ b/src/basecamp.cpp @@ -447,6 +447,7 @@ void basecamp::update_resources( const std::string &bldg ) void basecamp::update_provides( const std::string &bldg, expansion_data &e_data ) { if( !recipe_id( bldg ).is_valid() ) { + debugmsg( "Invalid basecamp recipe %s", bldg ); return; } diff --git a/src/overmap.cpp b/src/overmap.cpp index 7339ca0a63dde..aa67aa4ca42d4 100644 --- a/src/overmap.cpp +++ b/src/overmap.cpp @@ -1444,7 +1444,7 @@ struct fixed_overmap_special_data : overmap_special_data { 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 ); + temp_camp->define_camp( camp_loc, "faction_base_bare_bones_NPC_camp_0", false ); } } if( blob ) { From 7d171400de2274ccda421e1875d86466b821eb5a Mon Sep 17 00:00:00 2001 From: RenechCDDA <84619419+RenechCDDA@users.noreply.github.com> Date: Fri, 10 May 2024 02:50:43 -0400 Subject: [PATCH 11/21] Some factions share water access --- data/json/npcs/factions.json | 2 ++ doc/FACTIONS.md | 9 ++++----- src/basecamp.cpp | 7 ++++++- src/basecamp.h | 2 +- src/faction.h | 2 ++ src/npcmove.cpp | 12 ++++++------ 6 files changed, 21 insertions(+), 13 deletions(-) diff --git a/data/json/npcs/factions.json b/data/json/npcs/factions.json index 8c46cfb463fe4..d992b10f4913a 100644 --- a/data/json/npcs/factions.json +++ b/data/json/npcs/factions.json @@ -77,6 +77,7 @@ "defends your space": true, "knows your voice": true }, + "robofac_auxiliaries": { "share my stuff": true }, "marloss": { "kill on sight": true } }, "epilogues": [ @@ -208,6 +209,7 @@ "kill on sight": false, "watch your back": true, "share my stuff": false, + "share public goods": true, "guard your stuff": true, "lets you in": false, "defends your space": false, diff --git a/doc/FACTIONS.md b/doc/FACTIONS.md index 89fe2d48939fc..29b78ddade7cf 100644 --- a/doc/FACTIONS.md +++ b/doc/FACTIONS.md @@ -104,10 +104,9 @@ Flag | Meaning ---------------------- | -- `"kill on sight"` | Members of the acting faction are always hostile to members of the object faction. `"watch your back"` | Members of the acting faction will treat attacks on members of the object faction as attacks on themselves. -`"share my stuff"` | Members of the acting faction will not object if members of the object faction take items owned by the acting faction. +`"share my stuff"` | Members of the acting faction will not object if members of the object faction take items owned by the acting faction. Camps of the acting faction will allow members of the object faction to eat from their food stores (including water access). +`"share public goods"` | Camps of the acting faction will allow members of the object faction to drink from camp water wells. Irrelevant if the relationship already allows "share my stuff". `"guard your stuff"` | Members of the acting faction will object if someone takes items owned by the object faction. -`"lets you in"` | Members of the acting faction will not object if a member of the object faction enters territory controlled by the acting faction. -`"defends your space"` | Members of the acting faction will become hostile if someone enters territory controlled by the object faction. +`"lets you in"` | Members of the acting faction will not object if a member of the object faction enters territory controlled by the acting faction. No current gameplay effect. +`"defends your space"` | Members of the acting faction will become hostile if someone enters territory controlled by the object faction. No current gameplay effect. `"knows your voice"` | Members of the acting faction will not comment on speech by members of the object faction. - -So far, only `"kill on sight"`, `"knows your voice"`, and `"watch your back"` have been implemented. diff --git a/src/basecamp.cpp b/src/basecamp.cpp index 8527bba1f8e26..ea22c5a216c1d 100644 --- a/src/basecamp.cpp +++ b/src/basecamp.cpp @@ -324,7 +324,7 @@ bool basecamp::has_water() const return has_provides( "water_well" ) || has_provides( "fbmh_well_north" ); } -bool basecamp::allowed_access_by( Character &guy ) const +bool basecamp::allowed_access_by( Character &guy, bool water_request ) const { // The owner can always access their own camp. if( fac() == guy.get_faction() ) { @@ -334,6 +334,11 @@ bool basecamp::allowed_access_by( Character &guy ) const if( fac()->has_relationship( guy.get_faction()->id, npc_factions::share_my_stuff ) ) { return true; } + // Some factions will share access to infinite water sources, but not food + if( water_request && + fac()->has_relationship( guy.get_faction()->id, npc_factions::share_public_goods ) ) { + return true; + } return false; } diff --git a/src/basecamp.h b/src/basecamp.h index e372c31e04c40..8822a5c5b65e1 100644 --- a/src/basecamp.h +++ b/src/basecamp.h @@ -271,7 +271,7 @@ class basecamp /// Changes the faction opinion for you by @ref change, returns opinion int camp_morale( int change = 0 ) const; - bool allowed_access_by( Character &guy ) const; + bool allowed_access_by( Character &guy, bool water_request = false ) const; // recipes, gathering, and craft support functions // from a direction std::map recipe_deck( const point &dir ) const; diff --git a/src/faction.h b/src/faction.h index bc732c56ce450..5d99dbd5d4350 100644 --- a/src/faction.h +++ b/src/faction.h @@ -50,6 +50,7 @@ enum relationship : int { kill_on_sight, watch_your_back, share_my_stuff, + share_public_goods, guard_your_stuff, lets_you_in, defend_your_space, @@ -62,6 +63,7 @@ const std::unordered_map relation_strs = { { { "kill on sight", kill_on_sight }, { "watch your back", watch_your_back }, { "share my stuff", share_my_stuff }, + { "share public goods", share_public_goods }, { "guard your stuff", guard_your_stuff }, { "lets you in", lets_you_in }, { "defends your space", defend_your_space }, diff --git a/src/npcmove.cpp b/src/npcmove.cpp index 720846ad721b9..1668d234bf046 100644 --- a/src/npcmove.cpp +++ b/src/npcmove.cpp @@ -4535,10 +4535,9 @@ bool npc::consume_food_from_camp() return false; } basecamp *bcp = *potential_bc; - if( !bcp->allowed_access_by( *this ) ) { - return false; - } - if( get_thirst() > 40 && bcp->has_water() ) { + + // Handle water + if( get_thirst() > 40 && bcp->has_water() && bcp->allowed_access_by( *this, true ) ) { complain_about( "camp_water_thanks", 1_hours, chat_snippets().snip_camp_water_thanks.translated(), false ); // TODO: Stop skipping the stomach for this, actually put the water in there. @@ -4546,9 +4545,10 @@ bool npc::consume_food_from_camp() return true; } + // Handle food int current_kcals = get_stored_kcal() + stomach.get_calories() + guts.get_calories(); int kcal_threshold = get_healthy_kcal() * 19 / 20; - if( get_hunger() > 0 && current_kcals < kcal_threshold ) { + if( get_hunger() > 0 && current_kcals < kcal_threshold && bcp->allowed_access_by( *this ) ) { // Try to eat a bit more than the bare minimum so that we're not eating every 5 minutes // but also don't try to eat a week's worth of food in one sitting int desired_kcals = std::min( static_cast( base_metabolic_rate ), std::max( 0, @@ -4581,7 +4581,7 @@ bool npc::consume_food() const std::vector inv_food = cache_get_items_with( "is_food", &item::is_food ); if( inv_food.empty() ) { - if( !is_player_ally() ) { + if( !needs_food() ) { // TODO: Remove this and let player "exploit" hungry NPCs set_hunger( 0 ); set_thirst( 0 ); From 081357ee4b95e9839f765375e108cbd97c2575c6 Mon Sep 17 00:00:00 2001 From: RenechCDDA <84619419+RenechCDDA@users.noreply.github.com> Date: Fri, 10 May 2024 03:07:55 -0400 Subject: [PATCH 12/21] Can't send NPCs to NPC camps you've never seen before --- src/npctalk_funcs.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/npctalk_funcs.cpp b/src/npctalk_funcs.cpp index f2662bf2a8d1d..f07464cff6d53 100644 --- a/src/npctalk_funcs.cpp +++ b/src/npctalk_funcs.cpp @@ -358,6 +358,9 @@ void talk_function::goto_location( npc &p ) if( elem == p.global_omt_location() ) { continue; } + if( !overmap_buffer.seen( elem ) ) { + continue; + } std::optional camp = overmap_buffer.find_camp( elem.xy() ); if( !camp ) { continue; From d9fdcea79715205fe4926be5387cf8084280729a Mon Sep 17 00:00:00 2001 From: RenechCDDA <84619419+RenechCDDA@users.noreply.github.com> Date: Fri, 10 May 2024 03:21:09 -0400 Subject: [PATCH 13/21] Prevent NPCs from infinitely looping when starved and eating from camp --- src/faction_camp.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/faction_camp.cpp b/src/faction_camp.cpp index fdedc5c30d419..1d129b0bcf0af 100644 --- a/src/faction_camp.cpp +++ b/src/faction_camp.cpp @@ -5600,6 +5600,7 @@ void basecamp::feed_workers( const std::vector Date: Fri, 10 May 2024 06:46:02 -0400 Subject: [PATCH 14/21] Camp migrations for previously placed specials --- .../camp_placement.json | 77 +++++++++++++++++++ .../recipes/basecamps/special_hardcoded.json | 1 + .../Aftershock/migration/camp_placement.json | 13 ++++ .../Magiclysm/obsolete/camp_placement.json | 18 +++++ src/init.cpp | 1 + src/overmap.cpp | 46 +++++++++++ src/overmap.h | 4 + src/savegame.cpp | 7 ++ 8 files changed, 167 insertions(+) create mode 100644 data/json/obsoletion_and_migration_0.I/camp_placement.json create mode 100644 data/mods/Aftershock/migration/camp_placement.json create mode 100644 data/mods/Magiclysm/obsolete/camp_placement.json diff --git a/data/json/obsoletion_and_migration_0.I/camp_placement.json b/data/json/obsoletion_and_migration_0.I/camp_placement.json new file mode 100644 index 0000000000000..3edf7d6904b6f --- /dev/null +++ b/data/json/obsoletion_and_migration_0.I/camp_placement.json @@ -0,0 +1,77 @@ +[ + { + "type": "camp_migration", + "id": "refugee_center_camp_migration", + "camp_migrations": { "name": "Refugee Center", "overmap_terrain": "evac_center_13", "faction": "free_merchants" } + }, + { + "type": "camp_migration", + "id": "exodii_camp_migration", + "camp_migrations": { "name": "Exodii", "overmap_terrain": "exodii_base_x1y2z1", "faction": "exodii" } + }, + { + "type": "camp_migration", + "id": "apis_hive_camp_migration", + "camp_migrations": { "name": "???", "overmap_terrain": "hive", "faction": "apis_hive" } + }, + { + "type": "camp_migration", + "id": "lapin_camp_migration", + "camp_migrations": { "name": "Lapin", "overmap_terrain": "cabin_lapin", "faction": "lapin" } + }, + { + "type": "camp_migration", + "id": "prisoner_camp_migration", + "camp_migrations": { "name": "Holdouts", "overmap_terrain": "prison_island_1_6", "faction": "prisoners" } + }, + { + "type": "camp_migration", + "id": "godco_camp_migration", + "camp_migrations": { "name": "New England Church Retreat", "overmap_terrain": "godco_5", "faction": "gods_community" } + }, + { + "type": "camp_migration", + "id": "tacoma_camp_migration", + "camp_migrations": { "name": "Tacoma", "overmap_terrain": "ranch_camp_67", "faction": "tacoma_commune" } + }, + { + "type": "camp_migration", + "id": "hub_camp_migration", + "camp_migrations": { "name": "Hub 01", "overmap_terrain": "robofachq_surface_entrance", "faction": "robofac" } + }, + { + "type": "camp_migration", + "id": "tacoma_camp_migration", + "camp_migrations": { "name": "Cody & Jay", "overmap_terrain": "isolated_house_farm_gunsmith", "faction": "isolated_artisans" } + }, + { + "type": "camp_migration", + "id": "isherwood_camp_migration_1", + "camp_migrations": { "name": "Cabin", "overmap_terrain": "cabin_isherwood", "faction": "isherwood_family" } + }, + { + "type": "camp_migration", + "id": "isherwood_camp_migration_2", + "camp_migrations": { "name": "Isherwood Stables", "overmap_terrain": "horse_farm_isherwood_6", "faction": "isherwood_family" } + }, + { + "type": "camp_migration", + "id": "isherwood_camp_migration_3", + "camp_migrations": { "name": "Isherwood Outcropping", "overmap_terrain": "farm_isherwood_2", "faction": "isherwood_family" } + }, + { + "type": "camp_migration", + "id": "isherwood_camp_migration_4", + "camp_migrations": { "name": "Isherwood Farms", "overmap_terrain": "dairy_farm_isherwood_SW", "faction": "isherwood_family" } + }, + { + "type": "camp_migration", + "id": "tacoma_camp_migration", + "camp_migrations": { "name": "Merchant", "overmap_terrain": "bunker_shop_b", "faction": "wasteland_scavengers" } + }, + { + "type": "camp_migration", + "id": "tacoma_camp_migration", + "camp_migrations": { "name": "The Great Library", "overmap_terrain": "campus_media_0_0_0", "faction": "the_great_library" } + } +] diff --git a/data/json/recipes/basecamps/special_hardcoded.json b/data/json/recipes/basecamps/special_hardcoded.json index 97e08f4462953..e97158eccfa84 100644 --- a/data/json/recipes/basecamps/special_hardcoded.json +++ b/data/json/recipes/basecamps/special_hardcoded.json @@ -1,6 +1,7 @@ [ { "//": "This file contains a special NPC-only basecamp whch doesn't place anything, equivalent to the barebones camp. It is placed during mapgen, and should not show up as a valid player option in regular gameplay. The entire purpose is to provide 'water_well' so NPCs don't dehydrate to death.", + "//2": "Has hardcoded references in place (overmap.cpp) and overmap::migrate_camps.", "type": "recipe", "activity_level": "NO_EXERCISE", "result": "faction_base_bare_bones_NPC_camp_0", diff --git a/data/mods/Aftershock/migration/camp_placement.json b/data/mods/Aftershock/migration/camp_placement.json new file mode 100644 index 0000000000000..00fcf891e3bac --- /dev/null +++ b/data/mods/Aftershock/migration/camp_placement.json @@ -0,0 +1,13 @@ +[ + { + "//": "Remove all entries after 0.I", + "type": "camp_migration", + "id": "PrepNet_camp_migration", + "camp_migrations": { "name": "PrepNet", "overmap_terrain": "prepnet_orchard", "faction": "Prepnet_Phyle" } + }, + { + "type": "camp_migration", + "id": "augustmoon_camp_migration", + "camp_migrations": { "name": "Port Augustmoon", "overmap_terrain": "augustmoon_main_concourse1", "faction": "UICA" } + } +] diff --git a/data/mods/Magiclysm/obsolete/camp_placement.json b/data/mods/Magiclysm/obsolete/camp_placement.json new file mode 100644 index 0000000000000..4caddcf863451 --- /dev/null +++ b/data/mods/Magiclysm/obsolete/camp_placement.json @@ -0,0 +1,18 @@ +[ + { + "//": "Remove all entries after 0.I", + "type": "camp_migration", + "id": "Forge_Wonders_camp_migration", + "camp_migrations": { "name": "Forge of Wonders", "overmap_terrain": "forge_3A", "faction": "forge_lords" } + }, + { + "type": "camp_migration", + "id": "augustmoon_camp_migration", + "camp_migrations": { "name": "Healer's respite", "overmap_terrain": "magic_shop", "faction": "healers_grey" } + }, + { + "type": "camp_migration", + "id": "augustmoon_camp_migration", + "camp_migrations": { "name": "Old Wizard", "overmap_terrain": "lake_retreat_z3", "faction": "wizards_ancient" } + } +] diff --git a/src/init.cpp b/src/init.cpp index a50437e9a717f..82167f20fa619 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -409,6 +409,7 @@ void DynamicDataLoader::initialize() add( "climbing_aid", &climbing_aid::load_climbing_aid ); add( "effect_type", &load_effect_type ); add( "oter_id_migration", &overmap::load_oter_id_migration ); + add( "camp_migration", &overmap::load_oter_id_camp_migration ); add( "overmap_terrain", &overmap_terrains::load ); add( "construction_category", &construction_categories::load ); add( "construction_group", &construction_groups::load ); diff --git a/src/overmap.cpp b/src/overmap.cpp index aa67aa4ca42d4..ebde29d6e8e2c 100644 --- a/src/overmap.cpp +++ b/src/overmap.cpp @@ -3971,6 +3971,7 @@ void overmap::clear_connections_out() } static std::map oter_id_migrations; +static std::map> camp_map; void overmap::load_oter_id_migration( const JsonObject &jo ) { @@ -3979,11 +3980,34 @@ void overmap::load_oter_id_migration( const JsonObject &jo ) } } +void overmap::load_oter_id_camp_migration( const JsonObject &jo ) +{ + std::string name; + oter_type_str_id oter; + faction_id owner; + jo.read( "id", name ); // Dummy read to suppress error, FIXME + JsonObject jsobj = jo.get_object( "camp_migrations" ); + jsobj.read( "name", name ); + jsobj.read( "overmap_terrain", oter ); + jsobj.read( "faction", owner ); + camp_map.emplace( oter, std::pair( name, owner ) ); +} + +void overmap::reset_oter_id_camp_migrations() +{ + camp_map.clear(); +} + void overmap::reset_oter_id_migrations() { oter_id_migrations.clear(); } +bool overmap::oter_id_should_have_camp( const oter_type_str_id oter ) +{ + return camp_map.count( oter ) > 0; +} + bool overmap::is_oter_id_obsolete( const std::string &oterid ) { return oter_id_migrations.count( oterid ) > 0; @@ -4006,6 +4030,28 @@ void overmap::migrate_oter_ids( const std::unordered_map &points ) +{ + for( const tripoint_abs_omt &point : points ) { + std::optional bcp = overmap_buffer.find_camp( point.xy() ); + if( bcp ) { + continue; // Already a camp nearby, can't put down another one + } + get_map().add_camp( point, "faction_camp", false ); + bcp = overmap_buffer.find_camp( point.xy() ); + if( !bcp ) { + debugmsg( "Camp placement failed during migration?!" ); + continue; + } + basecamp *temp_camp = *bcp; + const oter_type_str_id &keyvalue = ter( project_remain + ( point ).remainder_tripoint )->get_type_id(); + temp_camp->set_owner( camp_map[keyvalue].second ); + temp_camp->set_name( camp_map[keyvalue].first ); + temp_camp->define_camp( point, "faction_base_bare_bones_NPC_camp_0", false ); + } +} + void overmap::place_special_forced( const overmap_special_id &special_id, const tripoint_om_omt &p, om_direction::type dir ) diff --git a/src/overmap.h b/src/overmap.h index 40d758f21bb5c..36f10b36f434d 100644 --- a/src/overmap.h +++ b/src/overmap.h @@ -549,9 +549,13 @@ class overmap void load_legacy_monstergroups( const JsonArray &jsin ); void save_monster_groups( JsonOut &jo ) const; public: + static void load_oter_id_camp_migration( const JsonObject &jo ); static void load_oter_id_migration( const JsonObject &jo ); + static void reset_oter_id_camp_migrations(); static void reset_oter_id_migrations(); + static bool oter_id_should_have_camp( const oter_type_str_id oter ); static bool is_oter_id_obsolete( const std::string &oterid ); + void migrate_camps( const std::vector &points ); void migrate_oter_ids( const std::unordered_map &points ); }; diff --git a/src/savegame.cpp b/src/savegame.cpp index 7e997b808180b..0e3fdec23cfe9 100644 --- a/src/savegame.cpp +++ b/src/savegame.cpp @@ -417,6 +417,7 @@ void overmap::unserialize( const JsonObject &jsobj ) // Extract layers first so predecessor deduplication can happen. if( jsobj.has_member( "layers" ) ) { std::unordered_map oter_id_migrations; + std::vector camps_to_place; JsonArray layers_json = jsobj.get_array( "layers" ); for( int z = 0; z < OVERMAP_LAYERS; ++z ) { @@ -445,6 +446,11 @@ void overmap::unserialize( const JsonObject &jsobj ) debugmsg( "Loaded invalid oter_id '%s'", tmp_ter.c_str() ); tmp_otid = oter_omt_obsolete; } + if( oter_id_should_have_camp( oter_str_id( tmp_ter )->get_type_id() ) ) { + for( int p = i; p < i + count; p++ ) { + camps_to_place.emplace_back( project_combine( pos(), tripoint_om_omt( p, j, z - OVERMAP_DEPTH ) ) ); + } + } } count--; layer[z].terrain[i][j] = tmp_otid; @@ -452,6 +458,7 @@ void overmap::unserialize( const JsonObject &jsobj ) } } migrate_oter_ids( oter_id_migrations ); + migrate_camps( camps_to_place ); } for( JsonMember om_member : jsobj ) { const std::string name = om_member.name(); From 12e455ecf2920f9de749d59b1abba295470aa218 Mon Sep 17 00:00:00 2001 From: RenechCDDA <84619419+RenechCDDA@users.noreply.github.com> Date: Fri, 10 May 2024 07:35:09 -0400 Subject: [PATCH 15/21] Update src/map.h Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- src/map.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/map.h b/src/map.h index ccd452dec89d1..9fb23e2918749 100644 --- a/src/map.h +++ b/src/map.h @@ -1755,7 +1755,8 @@ 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, bool need_validate = true ); + 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; From 40dddf05007addf290d31f8523a6ac8ec0eb657f Mon Sep 17 00:00:00 2001 From: RenechCDDA <84619419+RenechCDDA@users.noreply.github.com> Date: Fri, 10 May 2024 08:04:28 -0400 Subject: [PATCH 16/21] Nix fake IDs --- .../camp_placement.json | 15 --------------- .../mods/Aftershock/migration/camp_placement.json | 2 -- data/mods/Magiclysm/obsolete/camp_placement.json | 3 --- src/overmap.cpp | 1 - 4 files changed, 21 deletions(-) diff --git a/data/json/obsoletion_and_migration_0.I/camp_placement.json b/data/json/obsoletion_and_migration_0.I/camp_placement.json index 3edf7d6904b6f..1f651412d5505 100644 --- a/data/json/obsoletion_and_migration_0.I/camp_placement.json +++ b/data/json/obsoletion_and_migration_0.I/camp_placement.json @@ -1,77 +1,62 @@ [ { "type": "camp_migration", - "id": "refugee_center_camp_migration", "camp_migrations": { "name": "Refugee Center", "overmap_terrain": "evac_center_13", "faction": "free_merchants" } }, { "type": "camp_migration", - "id": "exodii_camp_migration", "camp_migrations": { "name": "Exodii", "overmap_terrain": "exodii_base_x1y2z1", "faction": "exodii" } }, { "type": "camp_migration", - "id": "apis_hive_camp_migration", "camp_migrations": { "name": "???", "overmap_terrain": "hive", "faction": "apis_hive" } }, { "type": "camp_migration", - "id": "lapin_camp_migration", "camp_migrations": { "name": "Lapin", "overmap_terrain": "cabin_lapin", "faction": "lapin" } }, { "type": "camp_migration", - "id": "prisoner_camp_migration", "camp_migrations": { "name": "Holdouts", "overmap_terrain": "prison_island_1_6", "faction": "prisoners" } }, { "type": "camp_migration", - "id": "godco_camp_migration", "camp_migrations": { "name": "New England Church Retreat", "overmap_terrain": "godco_5", "faction": "gods_community" } }, { "type": "camp_migration", - "id": "tacoma_camp_migration", "camp_migrations": { "name": "Tacoma", "overmap_terrain": "ranch_camp_67", "faction": "tacoma_commune" } }, { "type": "camp_migration", - "id": "hub_camp_migration", "camp_migrations": { "name": "Hub 01", "overmap_terrain": "robofachq_surface_entrance", "faction": "robofac" } }, { "type": "camp_migration", - "id": "tacoma_camp_migration", "camp_migrations": { "name": "Cody & Jay", "overmap_terrain": "isolated_house_farm_gunsmith", "faction": "isolated_artisans" } }, { "type": "camp_migration", - "id": "isherwood_camp_migration_1", "camp_migrations": { "name": "Cabin", "overmap_terrain": "cabin_isherwood", "faction": "isherwood_family" } }, { "type": "camp_migration", - "id": "isherwood_camp_migration_2", "camp_migrations": { "name": "Isherwood Stables", "overmap_terrain": "horse_farm_isherwood_6", "faction": "isherwood_family" } }, { "type": "camp_migration", - "id": "isherwood_camp_migration_3", "camp_migrations": { "name": "Isherwood Outcropping", "overmap_terrain": "farm_isherwood_2", "faction": "isherwood_family" } }, { "type": "camp_migration", - "id": "isherwood_camp_migration_4", "camp_migrations": { "name": "Isherwood Farms", "overmap_terrain": "dairy_farm_isherwood_SW", "faction": "isherwood_family" } }, { "type": "camp_migration", - "id": "tacoma_camp_migration", "camp_migrations": { "name": "Merchant", "overmap_terrain": "bunker_shop_b", "faction": "wasteland_scavengers" } }, { "type": "camp_migration", - "id": "tacoma_camp_migration", "camp_migrations": { "name": "The Great Library", "overmap_terrain": "campus_media_0_0_0", "faction": "the_great_library" } } ] diff --git a/data/mods/Aftershock/migration/camp_placement.json b/data/mods/Aftershock/migration/camp_placement.json index 00fcf891e3bac..1b08651b6ab90 100644 --- a/data/mods/Aftershock/migration/camp_placement.json +++ b/data/mods/Aftershock/migration/camp_placement.json @@ -2,12 +2,10 @@ { "//": "Remove all entries after 0.I", "type": "camp_migration", - "id": "PrepNet_camp_migration", "camp_migrations": { "name": "PrepNet", "overmap_terrain": "prepnet_orchard", "faction": "Prepnet_Phyle" } }, { "type": "camp_migration", - "id": "augustmoon_camp_migration", "camp_migrations": { "name": "Port Augustmoon", "overmap_terrain": "augustmoon_main_concourse1", "faction": "UICA" } } ] diff --git a/data/mods/Magiclysm/obsolete/camp_placement.json b/data/mods/Magiclysm/obsolete/camp_placement.json index 4caddcf863451..2497399f684ab 100644 --- a/data/mods/Magiclysm/obsolete/camp_placement.json +++ b/data/mods/Magiclysm/obsolete/camp_placement.json @@ -2,17 +2,14 @@ { "//": "Remove all entries after 0.I", "type": "camp_migration", - "id": "Forge_Wonders_camp_migration", "camp_migrations": { "name": "Forge of Wonders", "overmap_terrain": "forge_3A", "faction": "forge_lords" } }, { "type": "camp_migration", - "id": "augustmoon_camp_migration", "camp_migrations": { "name": "Healer's respite", "overmap_terrain": "magic_shop", "faction": "healers_grey" } }, { "type": "camp_migration", - "id": "augustmoon_camp_migration", "camp_migrations": { "name": "Old Wizard", "overmap_terrain": "lake_retreat_z3", "faction": "wizards_ancient" } } ] diff --git a/src/overmap.cpp b/src/overmap.cpp index 5be589aeddb1f..ca8db62595bc1 100644 --- a/src/overmap.cpp +++ b/src/overmap.cpp @@ -3985,7 +3985,6 @@ void overmap::load_oter_id_camp_migration( const JsonObject &jo ) std::string name; oter_type_str_id oter; faction_id owner; - jo.read( "id", name ); // Dummy read to suppress error, FIXME JsonObject jsobj = jo.get_object( "camp_migrations" ); jsobj.read( "name", name ); jsobj.read( "overmap_terrain", oter ); From 403d2552337fb20c89de018e42f56ca295dcb2eb Mon Sep 17 00:00:00 2001 From: RenechCDDA <84619419+RenechCDDA@users.noreply.github.com> Date: Fri, 10 May 2024 08:48:06 -0400 Subject: [PATCH 17/21] Oops - reset loaded migrations when asked --- src/init.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/init.cpp b/src/init.cpp index a611bf4a300d6..06ea30518a54d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -615,6 +615,7 @@ void DynamicDataLoader::unload_data() overmap_special_migration::reset(); overmap_terrains::reset(); overmap::reset_oter_id_migrations(); + overmap::reset_oter_id_camp_migrations(); profession::reset(); profession_blacklist::reset(); proficiency::reset(); From 93146b517fdfda634341c210d723f7c5a40e76d2 Mon Sep 17 00:00:00 2001 From: RenechCDDA <84619419+RenechCDDA@users.noreply.github.com> Date: Fri, 10 May 2024 19:27:50 -0400 Subject: [PATCH 18/21] Fixes - wasteland scavengers get camps. UICA gets INTMAX food Clang gets silenced --- data/json/npcs/factions.json | 6 +++--- data/json/overmap/overmap_special/specials.json | 11 ++++++++--- data/mods/Aftershock/npcs/factions.json | 4 ++-- data/mods/DinoMod/NPC/NC_BO_BARONYX.json | 1 - src/overmap.cpp | 4 ++-- src/overmap.h | 4 ++-- 6 files changed, 17 insertions(+), 13 deletions(-) diff --git a/data/json/npcs/factions.json b/data/json/npcs/factions.json index d992b10f4913a..075ef1031436c 100644 --- a/data/json/npcs/factions.json +++ b/data/json/npcs/factions.json @@ -416,10 +416,10 @@ "likes_u": 0, "respects_u": 0, "known_by_u": false, - "size": 1, + "size": 100, "power": 100, - "//": "90 days worth of food for 1 person, at 3000kcal/day and full RDA of iron/calcium/vitC", - "fac_food_supply": { "calories": 270000000, "vitamins": { "iron": 8640, "calcium": 8640, "vitC": 8640 } }, + "//": "90 days worth of food for 10 people, at 3000kcal/day and full RDA of iron/calcium/vitC", + "fac_food_supply": { "calories": 2700000000, "vitamins": { "iron": 86400, "calcium": 86400, "vitC": 86400 } }, "wealth": 2500000, "relations": { "lobby_beggars": { "knows your voice": true }, diff --git a/data/json/overmap/overmap_special/specials.json b/data/json/overmap/overmap_special/specials.json index 31d566646f151..16e83082a0101 100644 --- a/data/json/overmap/overmap_special/specials.json +++ b/data/json/overmap/overmap_special/specials.json @@ -6961,7 +6961,7 @@ "type": "overmap_special", "id": "Occupied Chem Lab", "overmaps": [ - { "point": [ 0, 0, 0 ], "overmap": "chemical_lab_ocu_north" }, + { "point": [ 0, 0, 0 ], "overmap": "chemical_lab_ocu_north", "camp": "wasteland_scavengers", "camp_name": "Chemist" }, { "point": [ 0, 0, 1 ], "overmap": "chemical_lab_roof_ocu_north" }, { "point": [ -1, -1, 0 ], "locations": [ "land", "road" ] }, { "point": [ -1, 0, 0 ], "locations": [ "land", "road" ] } @@ -6980,7 +6980,7 @@ "type": "overmap_special", "id": "Occupied Scrap Yard", "overmaps": [ - { "point": [ 0, 0, 0 ], "overmap": "smallscrapyard_ocu_north" }, + { "point": [ 0, 0, 0 ], "overmap": "smallscrapyard_ocu_north", "camp": "wasteland_scavengers", "camp_name": "Scrapper" }, { "point": [ 0, -1, 0 ], "locations": [ "land", "road" ] } ], "connections": [ { "point": [ 0, -1, 0 ], "terrain": "road", "connection": "local_road", "from": [ 0, 0, 0 ] } ], @@ -6997,7 +6997,12 @@ { "point": [ 0, 0, 0 ], "overmap": "lumbermill_0_0_ocu_north" }, { "point": [ 1, 0, 0 ], "overmap": "lumbermill_1_0_ocu_north" }, { "point": [ 0, 1, 0 ], "overmap": "lumbermill_0_1_ocu_north" }, - { "point": [ 1, 1, 0 ], "overmap": "lumbermill_1_1_ocu_north" }, + { + "point": [ 1, 1, 0 ], + "overmap": "lumbermill_1_1_ocu_north", + "camp": "wasteland_scavengers", + "camp_name": "Lumbermill (survivor base)" + }, { "point": [ 0, 0, 1 ], "overmap": "lumbermill_0_0_roof_north" }, { "point": [ 1, 0, 1 ], "overmap": "lumbermill_1_0_roof_north" }, { "point": [ 0, 1, 1 ], "overmap": "lumbermill_0_1_roof_north" }, diff --git a/data/mods/Aftershock/npcs/factions.json b/data/mods/Aftershock/npcs/factions.json index d74423b3b860d..1138ac98d4982 100644 --- a/data/mods/Aftershock/npcs/factions.json +++ b/data/mods/Aftershock/npcs/factions.json @@ -92,8 +92,8 @@ { "item": "UICA_1000d", "fixed_adj": 0 }, { "item": "UICA_10000d", "fixed_adj": 0 } ], - "//": "90 days worth of food for 10 people, at 3000kcal/day and full RDA of iron/calcium/vitC", - "fac_food_supply": { "calories": 2700000000, "vitamins": { "iron": 86400, "calcium": 86400, "vitC": 86400 } }, + "//": "Being an interplantary authority with effectively unlimited resources to draw upon, these numbers are here only as a technical limit. Vitamins are capped at ~90% of the max for a 32-bit integer and calories scaled to match.", + "fac_food_supply": { "calories": 62500000000000, "vitamins": { "iron": 2000000000, "calcium": 2000000000, "vitC": 2000000000 } }, "wealth": 75000, "relations": { "free_merchants": { diff --git a/data/mods/DinoMod/NPC/NC_BO_BARONYX.json b/data/mods/DinoMod/NPC/NC_BO_BARONYX.json index 9d837d80d5c62..ab2b9f7c38835 100644 --- a/data/mods/DinoMod/NPC/NC_BO_BARONYX.json +++ b/data/mods/DinoMod/NPC/NC_BO_BARONYX.json @@ -286,7 +286,6 @@ "size": 25, "power": 20, "currency": "icon", - "//": "Fixme: Not placed as a special, so can't put a camp down for them!", "//2": "90 days worth of food for 10 people, at 3000kcal/day and full RDA of iron/calcium/vitC", "fac_food_supply": { "calories": 2700000000, "vitamins": { "iron": 86400, "calcium": 86400, "vitC": 86400 } }, "wealth": 82500, diff --git a/src/overmap.cpp b/src/overmap.cpp index ca8db62595bc1..1fb3306510c10 100644 --- a/src/overmap.cpp +++ b/src/overmap.cpp @@ -4002,7 +4002,7 @@ void overmap::reset_oter_id_migrations() oter_id_migrations.clear(); } -bool overmap::oter_id_should_have_camp( const oter_type_str_id oter ) +bool overmap::oter_id_should_have_camp( const oter_type_str_id &oter ) { return camp_map.count( oter ) > 0; } @@ -4029,7 +4029,7 @@ void overmap::migrate_oter_ids( const std::unordered_map &points ) +void overmap::migrate_camps( const std::vector &points ) const { for( const tripoint_abs_omt &point : points ) { std::optional bcp = overmap_buffer.find_camp( point.xy() ); diff --git a/src/overmap.h b/src/overmap.h index eff7632fe56e2..0195d36eed3d2 100644 --- a/src/overmap.h +++ b/src/overmap.h @@ -553,9 +553,9 @@ class overmap static void load_oter_id_migration( const JsonObject &jo ); static void reset_oter_id_camp_migrations(); static void reset_oter_id_migrations(); - static bool oter_id_should_have_camp( const oter_type_str_id oter ); + static bool oter_id_should_have_camp( const oter_type_str_id &oter ); static bool is_oter_id_obsolete( const std::string &oterid ); - void migrate_camps( const std::vector &points ); + void migrate_camps( const std::vector &points ) const; void migrate_oter_ids( const std::unordered_map &points ); oter_id get_or_migrate_oter( const std::string &oterid ); }; From 4707ff6f0c82f9b652ccc26c41a5458f9ff57afb Mon Sep 17 00:00:00 2001 From: RenechCDDA <84619419+RenechCDDA@users.noreply.github.com> Date: Sun, 19 May 2024 06:21:24 -0400 Subject: [PATCH 19/21] typo fix thanks Co-authored-by: Fris0uman <41293484+Fris0uman@users.noreply.github.com> --- data/json/recipes/basecamps/special_hardcoded.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/json/recipes/basecamps/special_hardcoded.json b/data/json/recipes/basecamps/special_hardcoded.json index e97158eccfa84..0c37fdd91f8a1 100644 --- a/data/json/recipes/basecamps/special_hardcoded.json +++ b/data/json/recipes/basecamps/special_hardcoded.json @@ -1,6 +1,6 @@ [ { - "//": "This file contains a special NPC-only basecamp whch doesn't place anything, equivalent to the barebones camp. It is placed during mapgen, and should not show up as a valid player option in regular gameplay. The entire purpose is to provide 'water_well' so NPCs don't dehydrate to death.", + "//": "This file contains a special NPC-only basecamp which doesn't place anything, equivalent to the barebones camp. It is placed during mapgen, and should not show up as a valid player option in regular gameplay. The entire purpose is to provide 'water_well' so NPCs don't dehydrate to death.", "//2": "Has hardcoded references in place (overmap.cpp) and overmap::migrate_camps.", "type": "recipe", "activity_level": "NO_EXERCISE", From 303010be208ebf95825d228db711f7965788a3fc Mon Sep 17 00:00:00 2001 From: RenechCDDA <84619419+RenechCDDA@users.noreply.github.com> Date: Tue, 28 May 2024 22:14:54 -0400 Subject: [PATCH 20/21] Update u_has_camp --- src/condition.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/condition.cpp b/src/condition.cpp index 986a25f7f0050..3b26b8b8d8cdd 100644 --- a/src/condition.cpp +++ b/src/condition.cpp @@ -1770,7 +1770,17 @@ conditional_t::func f_math( const JsonObject &jo, const std::string_view member conditional_t::func f_u_has_camp() { return []( dialogue const & ) { - return !get_player_character().camps.empty(); + for( const tripoint_abs_omt &camp_tripoint : get_player_character().camps ) { + std::optional camp = overmap_buffer.find_camp( camp_tripoint.xy() ); + if( !camp ) { + continue; + } + basecamp *bcp = *camp; + if( bcp->get_owner() == get_player_character().get_faction()->id ) { + return true; + } + } + return false; }; } From 8939787ae309e94e289f6258cdb21bb148685904 Mon Sep 17 00:00:00 2001 From: RenechCDDA <84619419+RenechCDDA@users.noreply.github.com> Date: Wed, 29 May 2024 18:58:34 -0400 Subject: [PATCH 21/21] Camp name translations, hopefully? Co-authored-by: Procyonae <45432782+Procyonae@users.noreply.github.com> --- lang/string_extractor/parser.py | 4 +++- lang/string_extractor/parsers/overmap_special.py | 8 ++++++++ src/omdata.h | 2 +- src/overmap.cpp | 15 ++++++++------- 4 files changed, 20 insertions(+), 9 deletions(-) create mode 100644 lang/string_extractor/parsers/overmap_special.py diff --git a/lang/string_extractor/parser.py b/lang/string_extractor/parser.py index 4275e4c2a3eff..24ff1470e1237 100644 --- a/lang/string_extractor/parser.py +++ b/lang/string_extractor/parser.py @@ -61,6 +61,7 @@ from .parsers.movement_mode import parse_movement_mode from .parsers.mutation_category import parse_mutation_category from .parsers.overmap_land_use_code import parse_overmap_land_use_code +from .parsers.overmap_special import parse_overmap_special from .parsers.practice import parse_practice from .parsers.scenario import parse_scenario from .parsers.shop_blacklist import parse_shopkeeper_blacklist @@ -114,6 +115,7 @@ def dummy_parser(json, origin): "body_part": parse_body_part, "book": parse_generic, "butchery_requirement": dummy_parser, + "camp_migration": dummy_parser, "character_mod": parse_character_mod, "charge_removal_blacklist": dummy_parser, "city": parse_city, @@ -193,7 +195,7 @@ def dummy_parser(json, origin): "overmap_connection": dummy_parser, "overmap_land_use_code": parse_overmap_land_use_code, "overmap_location": dummy_parser, - "overmap_special": dummy_parser, + "overmap_special": parse_overmap_special, "overmap_special_migration": dummy_parser, "overmap_terrain": parse_overmap_terrain, "palette": parse_palette, diff --git a/lang/string_extractor/parsers/overmap_special.py b/lang/string_extractor/parsers/overmap_special.py new file mode 100644 index 0000000000000..57e3cc6eb5c53 --- /dev/null +++ b/lang/string_extractor/parsers/overmap_special.py @@ -0,0 +1,8 @@ +from ..write_text import write_text + + +def parse_overmap_special(json, origin): + for overmap in json["overmaps"]: + if "camp_name" in overmap: + write_text(overmap["camp_name"], origin, + comment="Name of NPC faction camp") diff --git a/src/omdata.h b/src/omdata.h index 1203fc13f1edf..04f9460765312 100644 --- a/src/omdata.h +++ b/src/omdata.h @@ -501,7 +501,7 @@ struct overmap_special_terrain : overmap_special_locations { oter_str_id terrain; std::set flags; std::optional camp_owner; - std::string camp_name; + translation camp_name; void deserialize( const JsonObject &om ); }; diff --git a/src/overmap.cpp b/src/overmap.cpp index 60153bd99e71f..0691d94b68d75 100644 --- a/src/overmap.cpp +++ b/src/overmap.cpp @@ -1443,7 +1443,7 @@ struct fixed_overmap_special_data : overmap_special_data { } else { basecamp *temp_camp = *bcp; temp_camp->set_owner( elem.camp_owner.value() ); - temp_camp->set_name( elem.camp_name ); + temp_camp->set_name( elem.camp_name.translated() ); // FIXME? Camp types are raw strings! Not ideal. temp_camp->define_camp( camp_loc, "faction_base_bare_bones_NPC_camp_0", false ); } @@ -3972,7 +3972,7 @@ void overmap::clear_connections_out() } static std::map oter_id_migrations; -static std::map> camp_map; +static std::map> camp_migration_map; void overmap::load_oter_id_migration( const JsonObject &jo ) { @@ -3990,12 +3990,13 @@ void overmap::load_oter_id_camp_migration( const JsonObject &jo ) jsobj.read( "name", name ); jsobj.read( "overmap_terrain", oter ); jsobj.read( "faction", owner ); - camp_map.emplace( oter, std::pair( name, owner ) ); + camp_migration_map.emplace( oter, + std::pair( translation::to_translation( name ), owner ) ); } void overmap::reset_oter_id_camp_migrations() { - camp_map.clear(); + camp_migration_map.clear(); } void overmap::reset_oter_id_migrations() @@ -4005,7 +4006,7 @@ void overmap::reset_oter_id_migrations() bool overmap::oter_id_should_have_camp( const oter_type_str_id &oter ) { - return camp_map.count( oter ) > 0; + return camp_migration_map.count( oter ) > 0; } bool overmap::is_oter_id_obsolete( const std::string &oterid ) @@ -4046,8 +4047,8 @@ void overmap::migrate_camps( const std::vector &points ) const basecamp *temp_camp = *bcp; const oter_type_str_id &keyvalue = ter( project_remain ( point ).remainder_tripoint )->get_type_id(); - temp_camp->set_owner( camp_map[keyvalue].second ); - temp_camp->set_name( camp_map[keyvalue].first ); + temp_camp->set_owner( camp_migration_map[keyvalue].second ); + temp_camp->set_name( camp_migration_map[keyvalue].first.translated() ); temp_camp->define_camp( point, "faction_base_bare_bones_NPC_camp_0", false ); } }