Skip to content

Commit 4fef3bf

Browse files
authored
Merge pull request #82519 from ehughsbaird/mongen-optional
mandatory/optional for monstergenerator
2 parents 2f7c1ca + 950b87d commit 4fef3bf

File tree

9 files changed

+112
-138
lines changed

9 files changed

+112
-138
lines changed

data/json/monsters/defense_bot.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@
289289
"diff": 100,
290290
"hp": 50,
291291
"speed": 140,
292+
"volume": "100 L",
292293
"material": [ "steel" ],
293294
"symbol": "@",
294295
"color": "red",

src/generic_factory.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,18 @@ bool unicode_codepoint_from_symbol_reader( const JsonObject &jo,
7878
return true;
7979
}
8080

81+
bool unicode_symbol_reader( const JsonObject &jo, const std::string_view member_name,
82+
std::string &member, bool was_loaded )
83+
{
84+
uint32_t codepoint;
85+
bool read = unicode_codepoint_from_symbol_reader( jo, member_name, codepoint, was_loaded );
86+
if( read ) {
87+
member = utf32_to_utf8( codepoint );
88+
return true;
89+
}
90+
return false;
91+
}
92+
8193
float read_proportional_entry( const JsonObject &jo, std::string_view key )
8294
{
8395
if( jo.has_float( key ) ) {

src/generic_factory.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -960,6 +960,12 @@ bool one_char_symbol_reader( const JsonObject &jo, std::string_view member_name,
960960
bool unicode_codepoint_from_symbol_reader(
961961
const JsonObject &jo, std::string_view member_name, uint32_t &member, bool );
962962

963+
/**
964+
* unicode_codepoint_from_symbol_reader, but with a string instead of a codepoint
965+
*/
966+
bool unicode_symbol_reader( const JsonObject &jo, std::string_view member_name, std::string &member,
967+
bool was_loaded );
968+
963969
//Reads a standard single-float "proportional" entry
964970
float read_proportional_entry( const JsonObject &jo, std::string_view key );
965971

src/item.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7480,7 +7480,7 @@ units::volume item::corpse_volume( const mtype *corpse ) const
74807480
if( corpse_volume > 0_ml ) {
74817481
return corpse_volume;
74827482
}
7483-
debugmsg( "invalid monster volume for corpse" );
7483+
debugmsg( "invalid monster volume for corpse of %s", corpse->id.str() );
74847484
return 0_ml;
74857485
}
74867486

src/monstergenerator.cpp

Lines changed: 67 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#include "cached_options.h"
1313
#include "calendar.h"
1414
#include "cata_utility.h"
15-
#include "catacharset.h"
15+
#include "color.h"
1616
#include "condition.h"
1717
#include "creature.h"
1818
#include "damage.h"
@@ -743,79 +743,87 @@ void mon_effect_data::load( const JsonObject &jo )
743743
}
744744
}
745745

746-
void mtype::load( const JsonObject &jo, const std::string &src )
746+
void mount_item_data::deserialize( const JsonObject &jo )
747747
{
748-
bool strict = src == "dda";
748+
optional( jo, false, "tied", tied, itype_id() );
749+
optional( jo, false, "tack", tack, itype_id() );
750+
optional( jo, false, "armor", armor, itype_id() );
751+
optional( jo, false, "storage", storage, itype_id() );
752+
}
749753

754+
void revive_type::deserialize( const JsonObject &jo )
755+
{
756+
// FIXME: reader for read_condition
757+
read_condition( jo, "condition", condition, true );
758+
if( jo.has_string( "monster" ) ) {
759+
mandatory( jo, false, "monster", revive_mon );
760+
} else {
761+
mandatory( jo, false, "monster_group", revive_monster_group );
762+
}
763+
}
764+
765+
void mtype::load( const JsonObject &jo, const std::string &src )
766+
{
750767
MonsterGenerator &gen = MonsterGenerator::generator();
751768

752769
name.make_plural();
753770
mandatory( jo, was_loaded, "name", name );
754771

755772
optional( jo, was_loaded, "description", description );
756773

757-
assign( jo, "ascii_picture", picture_id );
774+
optional( jo, was_loaded, "ascii_picture", picture_id );
758775

759-
if( jo.has_member( "material" ) ) {
760-
mat.clear();
761-
for( const std::string &m : jo.get_tags( "material" ) ) {
762-
mat.emplace( m, 1 );
763-
mat_portion_total += 1;
764-
}
765-
}
766-
if( mat.empty() ) { // Assign a default "flesh" material to prevent crash (#48988)
767-
mat.emplace( material_flesh, 1 );
768-
mat_portion_total += 1;
776+
// Assign a default "flesh" material to prevent crash (#48988)
777+
optional( jo, was_loaded, "material", mat, weighted_string_id_reader<material_id, int> {1}, {{{material_flesh, 1}}} );
778+
mat_portion_total = 0;
779+
for( const std::pair<const material_id, int> &pr : mat ) {
780+
mat_portion_total += pr.second;
769781
}
782+
770783
optional( jo, was_loaded, "species", species, string_id_reader<::species_type> {} );
771784
optional( jo, was_loaded, "categories", categories, auto_flags_reader<> {} );
772785

773786
// See monfaction.cpp
774-
if( !was_loaded || jo.has_member( "default_faction" ) ) {
775-
default_faction = mfaction_str_id( jo.get_string( "default_faction" ) );
776-
}
787+
mandatory( jo, was_loaded, "default_faction", default_faction );
788+
789+
mandatory( jo, was_loaded, "symbol", sym, unicode_symbol_reader );
777790

778-
if( !was_loaded || jo.has_member( "symbol" ) ) {
779-
sym = jo.get_string( "symbol" );
780-
if( utf8_width( sym ) != 1 ) {
781-
jo.throw_error_at( "symbol", "monster symbol should be exactly one console cell width" );
782-
}
783-
}
784791
if( was_loaded && jo.has_member( "copy-from" ) && looks_like.empty() ) {
785792
looks_like = jo.get_string( "copy-from" );
786793
}
787-
jo.read( "looks_like", looks_like );
794+
optional( jo, was_loaded, "looks_like", looks_like, looks_like );
788795

789-
assign( jo, "bodytype", bodytype );
790-
assign( jo, "color", color );
791-
assign( jo, "volume", volume, strict, 0_ml );
792-
assign( jo, "weight", weight, strict, 0_gram );
796+
optional( jo, was_loaded, "bodytype", bodytype );
797+
optional( jo, was_loaded, "color", color, nc_color_reader{}, c_white );
798+
optional( jo, was_loaded, "volume", volume, units_bound_reader<units::volume> { 0_ml } );
799+
optional( jo, was_loaded, "weight", weight, units_bound_reader<units::mass> { 0_gram } );
793800

794801
optional( jo, was_loaded, "phase", phase, make_flag_reader( gen.phase_map, "phase id" ),
795802
phase_id::SOLID );
796803

797-
assign( jo, "diff", difficulty_base, strict, 0 );
798-
assign( jo, "hp", hp, strict, 1 );
799-
assign( jo, "speed", speed, strict, 0 );
800-
assign( jo, "aggression", agro, strict, -100, 100 );
801-
assign( jo, "morale", morale, strict );
802-
assign( jo, "stomach_size", stomach_size, strict );
803-
assign( jo, "amount_eaten", amount_eaten, strict );
804+
optional( jo, was_loaded, "diff", difficulty_base, numeric_bound_reader<int> {0}, 0 );
805+
optional( jo, was_loaded, "hp", hp, numeric_bound_reader<int> {1} );
806+
optional( jo, was_loaded, "speed", speed, numeric_bound_reader<int> {0}, 0 );
807+
optional( jo, was_loaded, "aggression", agro, numeric_bound_reader<int> {-100, 100}, 0 );
808+
optional( jo, was_loaded, "morale", morale, 0 );
809+
optional( jo, was_loaded, "stomach_size", stomach_size, 0 );
804810

805-
assign( jo, "tracking_distance", tracking_distance, strict, 3 );
811+
optional( jo, was_loaded, "tracking_distance", tracking_distance, numeric_bound_reader<int> {3},
812+
8 );
806813

807-
assign( jo, "mountable_weight_ratio", mountable_weight_ratio, strict );
814+
optional( jo, was_loaded, "mountable_weight_ratio", mountable_weight_ratio, 0.2f );
808815

809-
assign( jo, "attack_cost", attack_cost, strict, 0 );
810-
assign( jo, "melee_skill", melee_skill, strict, 0 );
811-
assign( jo, "melee_dice", melee_dice, strict, 0 );
812-
assign( jo, "melee_dice_sides", melee_sides, strict, 0 );
816+
optional( jo, was_loaded, "attack_cost", attack_cost, numeric_bound_reader<int> {0}, 100 );
817+
optional( jo, was_loaded, "melee_skill", melee_skill, numeric_bound_reader<int> {0}, 0 );
818+
optional( jo, was_loaded, "melee_dice", melee_dice, numeric_bound_reader<int> {0}, 0 );
819+
optional( jo, was_loaded, "melee_dice_sides", melee_sides, numeric_bound_reader<int> {0}, 0 );
813820
optional( jo, was_loaded, "melee_dice_ap", melee_dice_ap, 0 );
814821

815-
assign( jo, "grab_strength", grab_strength, strict, 0 );
822+
optional( jo, was_loaded, "grab_strength", grab_strength, numeric_bound_reader<int> {0}, 1 );
816823

817-
assign( jo, "dodge", sk_dodge, strict, 0 );
824+
optional( jo, was_loaded, "dodge", sk_dodge, numeric_bound_reader<int> {0} );
818825

826+
// FIXME: load resistances by reader class
819827
if( jo.has_object( "armor" ) ) {
820828
armor = load_resistances_instance( jo.get_object( "armor" ) );
821829
}
@@ -907,7 +915,8 @@ void mtype::load( const JsonObject &jo, const std::string &src )
907915
}
908916
}
909917

910-
assign( jo, "status_chance_multiplier", status_chance_multiplier, strict, 0.0f, 5.0f );
918+
optional( jo, was_loaded, "status_chance_multiplier", status_chance_multiplier, numeric_bound_reader{0.0f, 5.0f},
919+
1.f );
911920

912921
if( !was_loaded || jo.has_array( "families" ) ) {
913922
families.clear();
@@ -935,27 +944,8 @@ void mtype::load( const JsonObject &jo, const std::string &src )
935944
optional( jo, was_loaded, "absorb_move_cost_min", absorb_move_cost_min, 1 );
936945
optional( jo, was_loaded, "absorb_move_cost_max", absorb_move_cost_max, -1 );
937946

938-
if( jo.has_member( "absorb_material" ) ) {
939-
absorb_material.clear();
940-
if( jo.has_array( "absorb_material" ) ) {
941-
for( std::string mat : jo.get_string_array( "absorb_material" ) ) {
942-
absorb_material.emplace_back( mat );
943-
}
944-
} else {
945-
absorb_material.emplace_back( jo.get_string( "absorb_material" ) );
946-
}
947-
}
948-
949-
if( jo.has_member( "no_absorb_material" ) ) {
950-
no_absorb_material.clear();
951-
if( jo.has_array( "no_absorb_material" ) ) {
952-
for( std::string mat : jo.get_string_array( "no_absorb_material" ) ) {
953-
no_absorb_material.emplace_back( mat );
954-
}
955-
} else {
956-
no_absorb_material.emplace_back( jo.get_string( "no_absorb_material" ) );
957-
}
958-
}
947+
optional( jo, was_loaded, "absorb_material", absorb_material );
948+
optional( jo, was_loaded, "no_absorb_material", no_absorb_material );
959949

960950
optional( jo, was_loaded, "bleed_rate", bleed_rate, 100 );
961951

@@ -999,8 +989,8 @@ void mtype::load( const JsonObject &jo, const std::string &src )
999989
}
1000990

1001991

1002-
assign( jo, "vision_day", vision_day, strict, 0 );
1003-
assign( jo, "vision_night", vision_night, strict, 0 );
992+
optional( jo, was_loaded, "vision_day", vision_day, numeric_bound_reader{0}, 40 );
993+
optional( jo, was_loaded, "vision_night", vision_night, numeric_bound_reader{0}, 1 );
1004994

1005995
optional( jo, was_loaded, "regenerates", regenerates, 0 );
1006996
optional( jo, was_loaded, "regenerates_in_dark", regenerates_in_dark, false );
@@ -1032,26 +1022,9 @@ void mtype::load( const JsonObject &jo, const std::string &src )
10321022
optional( jo, was_loaded, "mech_str_bonus", mech_str_bonus, 0 );
10331023
optional( jo, was_loaded, "mech_battery", mech_battery, itype_id() );
10341024

1035-
if( jo.has_object( "mount_items" ) ) {
1036-
JsonObject jo_mount_items = jo.get_object( "mount_items" );
1037-
optional( jo_mount_items, was_loaded, "tied", mount_items.tied, itype_id() );
1038-
optional( jo_mount_items, was_loaded, "tack", mount_items.tack, itype_id() );
1039-
optional( jo_mount_items, was_loaded, "armor", mount_items.armor, itype_id() );
1040-
optional( jo_mount_items, was_loaded, "storage", mount_items.storage, itype_id() );
1041-
}
1042-
1043-
if( jo.has_array( "revive_forms" ) ) {
1044-
revive_type foo;
1045-
for( JsonObject jo_form : jo.get_array( "revive_forms" ) ) {
1046-
read_condition( jo_form, "condition", foo.condition, true );
1047-
if( jo_form.has_string( "monster" ) ) {
1048-
mandatory( jo_form, was_loaded, "monster", foo.revive_mon );
1049-
} else {
1050-
mandatory( jo_form, was_loaded, "monster_group", foo.revive_monster_group );
1051-
}
1052-
revive_types.push_back( foo );
1053-
}
1054-
}
1025+
optional( jo, was_loaded, "mount_items", mount_items );
1026+
1027+
optional( jo, was_loaded, "revive_forms", revive_types );
10551028

10561029
optional( jo, was_loaded, "zombify_into", zombify_into, string_id_reader<::mtype> {},
10571030
mtype_id() );
@@ -1061,28 +1034,12 @@ void mtype::load( const JsonObject &jo, const std::string &src )
10611034

10621035
optional( jo, was_loaded, "aggro_character", aggro_character, true );
10631036

1064-
if( jo.has_array( "attack_effs" ) ) {
1065-
atk_effs.clear();
1066-
for( const JsonObject effect_jo : jo.get_array( "attack_effs" ) ) {
1067-
mon_effect_data effect;
1068-
effect.load( effect_jo );
1069-
atk_effs.push_back( std::move( effect ) );
1070-
}
1071-
}
1037+
optional( jo, was_loaded, "attack_effs", atk_effs );
10721038

10731039
optional( jo, was_loaded, "melee_damage", melee_damage );
10741040

1075-
if( jo.has_array( "scents_tracked" ) ) {
1076-
for( const std::string line : jo.get_array( "scents_tracked" ) ) {
1077-
scents_tracked.emplace( line );
1078-
}
1079-
}
1080-
1081-
if( jo.has_array( "scents_ignored" ) ) {
1082-
for( const std::string line : jo.get_array( "scents_ignored" ) ) {
1083-
scents_ignored.emplace( line );
1084-
}
1085-
}
1041+
optional( jo, was_loaded, "scents_tracked", scents_tracked );
1042+
optional( jo, was_loaded, "scents_ignored", scents_ignored );
10861043

10871044
if( jo.has_member( "death_drops" ) ) {
10881045
death_drops =
@@ -1091,38 +1048,19 @@ void mtype::load( const JsonObject &jo, const std::string &src )
10911048
}
10921049

10931050
assign( jo, "harvest", harvest );
1051+
// FIXME: assign doesn't trigger issues that optional does???
1052+
//optional( jo, was_loaded, "harvest", harvest, harvest_id::NULL_ID() );
10941053

10951054
optional( jo, was_loaded, "dissect", dissect );
10961055

10971056
optional( jo, was_loaded, "decay", decay );
10981057

1099-
if( jo.has_array( "shearing" ) ) {
1100-
std::vector<shearing_entry> entries;
1101-
for( JsonObject shearing_entry : jo.get_array( "shearing" ) ) {
1102-
struct shearing_entry entry {};
1103-
entry.load( shearing_entry );
1104-
entries.emplace_back( entry );
1105-
}
1106-
shearing = shearing_data( entries );
1107-
}
1058+
optional( jo, was_loaded, "shearing", shearing );
11081059

11091060
optional( jo, was_loaded, "speed_description", speed_desc, speed_description_DEFAULT );
11101061
optional( jo, was_loaded, "death_function", mdeath_effect );
11111062

1112-
if( jo.has_array( "emit_fields" ) ) {
1113-
JsonArray jar = jo.get_array( "emit_fields" );
1114-
if( jar.has_string( 0 ) ) { // TEMPORARY until 0.F
1115-
for( const std::string id : jar ) {
1116-
emit_fields.emplace( emit_id( id ), 1_seconds );
1117-
}
1118-
} else {
1119-
while( jar.has_more() ) {
1120-
JsonObject obj = jar.next_object();
1121-
emit_fields.emplace( emit_id( obj.get_string( "emit_id" ) ),
1122-
read_from_json_string<time_duration>( obj.get_member( "delay" ), time_duration::units ) );
1123-
}
1124-
}
1125-
}
1063+
optional( jo, was_loaded, "emit_fields", emit_fields, named_pair_reader<emit_id, time_duration> {"emit_id", "delay"} );
11261064

11271065
if( jo.has_member( "special_when_hit" ) ) {
11281066
JsonArray jsarr = jo.get_array( "special_when_hit" );

src/mtype.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,9 @@ struct mon_effect_data {
235235

236236
mon_effect_data();
237237
void load( const JsonObject &jo );
238+
void deserialize( const JsonObject &jo ) {
239+
load( jo );
240+
}
238241
};
239242

240243
/** Pet food data */
@@ -303,6 +306,8 @@ struct mount_item_data {
303306
* If this monster is a rideable mount that spawns with storage bags, this is the storage item id
304307
*/
305308
itype_id storage;
309+
310+
void deserialize( const JsonObject &jo );
306311
};
307312

308313
struct reproduction_type {
@@ -316,6 +321,8 @@ struct revive_type {
316321
std::function<bool( const_dialogue const & )> condition;
317322
mtype_id revive_mon = mtype_id::NULL_ID();
318323
mongroup_id revive_monster_group = mongroup_id::NULL_ID();
324+
325+
void deserialize( const JsonObject &jo );
319326
};
320327

321328
struct mtype {
@@ -463,7 +470,6 @@ struct mtype {
463470
int agro = 0; /** chance will attack [-100,100] */
464471
int morale = 0; /** initial morale level at spawn */
465472
int stomach_size = 0; /** how many times this monster will eat */
466-
int amount_eaten = 0; /** how many times it has eaten */
467473

468474
// how close the monster is willing to approach its target while under the MATT_FOLLOW attitude
469475
int tracking_distance = 8;

0 commit comments

Comments
 (0)