Skip to content

Commit 0a86175

Browse files
committed
vehicle item spawn to optional/mandatory
Also clean up variant spawning and fix a bug
1 parent 16d3aaa commit 0a86175

File tree

6 files changed

+46
-62
lines changed

6 files changed

+46
-62
lines changed

doc/JSON/VEHICLES_JSON.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,15 +116,13 @@ and describes the items that may spawn at that location.
116116
TYPE and DATA may be one of:
117117
```jsonc
118118
"items": "itemid" // single item of that type
119-
"items": [ "itemid1", "itemid2", /* ... */ ] // all the items in the array
119+
"items": [ "itemid1", { "id": "itemid2", "variant": "foo" }, /* ... */ ] // all the items in the array
120120
"item_groups": "groupid" // one or more items in the group, depending on
121121
// whether the group is a collection or distribution
122122
"item_groups": [ "groupid1", "groupid2" /* ... */ ] // one or more items for each group
123123
```
124124
the optional keyword "chance" provides an X in 100 chance that a particular item definition will spawn.
125125

126-
If a single item is specified through `"items"`, an itype variant for it can be specified through `"variant"`.
127-
128126
Multiple lines of items may share the same X and Y values.
129127

130128
### Zones list

src/item_factory.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1614,7 +1614,10 @@ void Item_factory::finalize_item_blacklist()
16141614
vehicle_prototype &prototype = const_cast<vehicle_prototype &>( const_prototype );
16151615
for( vehicle_item_spawn &vis : prototype.item_spawns ) {
16161616
auto &vec = vis.item_ids;
1617-
const auto iter = std::remove_if( vec.begin(), vec.end(), item_is_blacklisted );
1617+
auto is_blacklisted = []( const std::pair<itype_id, std::string> &pair ) {
1618+
return item_is_blacklisted( pair.first );
1619+
};
1620+
const auto iter = std::remove_if( vec.begin(), vec.end(), is_blacklisted );
16181621
vec.erase( iter, vec.end() );
16191622
}
16201623
}
@@ -1716,7 +1719,8 @@ void Item_factory::finalize_item_blacklist()
17161719
for( const vehicle_prototype &const_prototype : vehicles::get_all_prototypes() ) {
17171720
vehicle_prototype &prototype = const_cast<vehicle_prototype &>( const_prototype );
17181721
for( vehicle_item_spawn &vis : prototype.item_spawns ) {
1719-
for( itype_id &type_to_spawn : vis.item_ids ) {
1722+
for( std::pair<itype_id, std::string> &spawn_pair : vis.item_ids ) {
1723+
itype_id &type_to_spawn = spawn_pair.first;
17201724
std::map<itype_id, std::vector<migration>>::iterator replacement =
17211725
migrations.find( type_to_spawn );
17221726
if( replacement == migrations.end() ) {

src/veh_type.cpp

Lines changed: 30 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,14 +1327,38 @@ struct veh_proto_part_def_reader : generic_typed_reader<veh_proto_part_def_reade
13271327

13281328
};
13291329

1330-
void vehicle_prototype::load( const JsonObject &jo, std::string_view )
1330+
struct veh_spawn_item_reader : generic_typed_reader<veh_spawn_item_reader> {
1331+
std::pair<itype_id, std::string> get_next( const JsonValue &jv ) const {
1332+
if( jv.test_string() ) {
1333+
return std::make_pair( itype_id( jv.get_string() ), "" );
1334+
}
1335+
JsonObject jo = jv.get_object();
1336+
std::pair<itype_id, std::string> ret;
1337+
mandatory( jo, false, "id", ret.first );
1338+
optional( jo, false, "variant", ret.second );
1339+
return ret;
1340+
}
1341+
};
1342+
1343+
void vehicle_item_spawn::deserialize( const JsonObject &jo )
13311344
{
1332-
vgroups[vgroup_id( id.str() )].add_vehicle( id, 100 );
1333-
optional( jo, was_loaded, "name", name );
1345+
mandatory( jo, false, "x", pos.x() );
1346+
mandatory( jo, false, "y", pos.y() );
13341347

1348+
mandatory( jo, false, "chance", chance, numeric_bound_reader{ 0, 100 } );
13351349

1350+
// constrain both with_magazine and with_ammo to [0-100]
1351+
optional( jo, false, "magazine", with_magazine, numeric_bound_reader{ 0, 100 }, 0 );
1352+
optional( jo, false, "ammo", with_ammo, numeric_bound_reader{ 0, 100 }, 0 );
13361353

1354+
optional( jo, false, "items", item_ids, veh_spawn_item_reader{} );
1355+
optional( jo, false, "item_groups", item_groups, string_id_reader<Item_spawn_data> {} );
1356+
}
13371357

1358+
void vehicle_prototype::load( const JsonObject &jo, std::string_view )
1359+
{
1360+
vgroups[vgroup_id( id.str() )].add_vehicle( id, 100 );
1361+
optional( jo, was_loaded, "name", name );
13381362

13391363
if( jo.has_member( "blueprint" ) ) {
13401364
// currently unused, read to suppress unvisited members warning
@@ -1351,46 +1375,7 @@ void vehicle_prototype::load( const JsonObject &jo, std::string_view )
13511375
parts.insert( parts.end(), tmp.begin(), tmp.end() );
13521376
}
13531377

1354-
for( JsonObject spawn_info : jo.get_array( "items" ) ) {
1355-
vehicle_item_spawn next_spawn;
1356-
next_spawn.pos.x() = spawn_info.get_int( "x" );
1357-
next_spawn.pos.y() = spawn_info.get_int( "y" );
1358-
1359-
next_spawn.chance = spawn_info.get_int( "chance" );
1360-
if( next_spawn.chance <= 0 || next_spawn.chance > 100 ) {
1361-
debugmsg( "Invalid spawn chance in %s (%d, %d): %d%%",
1362-
name, next_spawn.pos.x(), next_spawn.pos.y(), next_spawn.chance );
1363-
}
1364-
1365-
// constrain both with_magazine and with_ammo to [0-100]
1366-
next_spawn.with_magazine = std::max( std::min( spawn_info.get_int( "magazine",
1367-
next_spawn.with_magazine ), 100 ), 0 );
1368-
next_spawn.with_ammo = std::max( std::min( spawn_info.get_int( "ammo",
1369-
next_spawn.with_ammo ), 100 ), 0 );
1370-
1371-
if( spawn_info.has_array( "items" ) ) {
1372-
//Array of items that all spawn together (i.e. jack+tire)
1373-
spawn_info.read( "items", next_spawn.item_ids, true );
1374-
} else if( spawn_info.has_string( "items" ) ) {
1375-
//Treat single item as array
1376-
// And read the gun variant (if it exists)
1377-
if( spawn_info.has_string( "variant" ) ) {
1378-
const std::string variant = spawn_info.get_string( "variant" );
1379-
next_spawn.variant_ids.emplace_back( itype_id( spawn_info.get_string( "items" ) ), variant );
1380-
} else {
1381-
next_spawn.item_ids.emplace_back( spawn_info.get_string( "items" ) );
1382-
}
1383-
}
1384-
if( spawn_info.has_array( "item_groups" ) ) {
1385-
//Pick from a group of items, just like map::place_items
1386-
for( const std::string line : spawn_info.get_array( "item_groups" ) ) {
1387-
next_spawn.item_groups.emplace_back( line );
1388-
}
1389-
} else if( spawn_info.has_string( "item_groups" ) ) {
1390-
next_spawn.item_groups.emplace_back( spawn_info.get_string( "item_groups" ) );
1391-
}
1392-
item_spawns.push_back( std::move( next_spawn ) );
1393-
}
1378+
optional( jo, was_loaded, "items", item_spawns );
13941379

13951380
for( JsonObject jzi : jo.get_array( "zones" ) ) {
13961381
zone_type_id zone_type( jzi.get_member( "type" ).get_string() );
@@ -1687,8 +1672,8 @@ void vehicles::finalize_prototypes()
16871672
proto.name, i.pos.x(), i.pos.y(), i.chance );
16881673
}
16891674
for( auto &j : i.item_ids ) {
1690-
if( !item::type_is_defined( j ) ) {
1691-
debugmsg( "unknown item %s in spawn list of %s", j.c_str(), proto.id.str() );
1675+
if( !item::type_is_defined( j.first ) ) {
1676+
debugmsg( "unknown item %s in spawn list of %s", j.first.c_str(), proto.id.str() );
16921677
}
16931678
}
16941679
for( auto &j : i.item_groups ) {

src/veh_type.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -506,10 +506,11 @@ struct vehicle_item_spawn {
506506
int with_ammo = 0;
507507
/** Chance [0-100%] for items to spawn with their default magazine (if any) */
508508
int with_magazine = 0;
509-
std::vector<itype_id> item_ids;
510-
// item_ids, but for items with variants specified
511-
std::vector<std::pair<itype_id, std::string>> variant_ids;
509+
// item_ids, with variants specified (empty is ignored)
510+
std::vector<std::pair<itype_id, std::string>> item_ids;
512511
std::vector<item_group_id> item_groups;
512+
513+
void deserialize( const JsonObject &jo );
513514
};
514515

515516
/**

src/vehicle.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6405,17 +6405,13 @@ void vehicle::place_spawn_items( map &here )
64056405
continue;
64066406
}
64076407

6408-
for( const itype_id &e : spawn.item_ids ) {
6409-
if( rng_float( 0, 1 ) < spawn_rate ) {
6410-
item spawn( e );
6411-
created.emplace_back( spawn.in_its_container() );
6412-
}
6413-
}
6414-
for( const std::pair<itype_id, std::string> &e : spawn.variant_ids ) {
6408+
for( const std::pair<itype_id, std::string> &e : spawn.item_ids ) {
64156409
if( rng_float( 0, 1 ) < spawn_rate ) {
64166410
item spawn( e.first );
6411+
if( !e.second.empty() ) {
6412+
spawn.set_itype_variant( e.second );
6413+
}
64176414
item added = spawn.in_its_container();
6418-
added.set_itype_variant( e.second );
64196415
created.push_back( added );
64206416
}
64216417
}

tests/vehicle_export_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ static bool operator==( const vehicle_item_spawn &l, const vehicle_item_spawn &r
3030
return l.pos == r.pos && l.chance == r.chance &&
3131
l.with_ammo == r.with_ammo && l.with_magazine == r.with_magazine && l.item_ids == r.item_ids &&
3232
// NOLINTNEXTLINE(misc-redundant-expression)
33-
l.variant_ids == r.variant_ids && l.item_groups == r.item_groups;
33+
l.item_groups == r.item_groups;
3434
}
3535

3636
TEST_CASE( "export_vehicle_test" )

0 commit comments

Comments
 (0)