Skip to content

Commit 6c4cbe1

Browse files
committed
Use mandatory/optional for some monster values
Only the easy ones - several have hand-rolled extend/delete/relative/proportional support, and those are not converted. mandatory/optional have the best support for these extended features and report when they don't work.
1 parent e0277cd commit 6c4cbe1

File tree

4 files changed

+91
-135
lines changed

4 files changed

+91
-135
lines changed

src/monstergenerator.cpp

Lines changed: 67 additions & 128 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,78 +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 );
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 );
803810

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

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

808-
assign( jo, "attack_cost", attack_cost, strict, 0 );
809-
assign( jo, "melee_skill", melee_skill, strict, 0 );
810-
assign( jo, "melee_dice", melee_dice, strict, 0 );
811-
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 );
812820
optional( jo, was_loaded, "melee_dice_ap", melee_dice_ap, 0 );
813821

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

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

826+
// FIXME: load resistances by reader class
818827
if( jo.has_object( "armor" ) ) {
819828
armor = load_resistances_instance( jo.get_object( "armor" ) );
820829
}
@@ -906,7 +915,8 @@ void mtype::load( const JsonObject &jo, const std::string &src )
906915
}
907916
}
908917

909-
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 );
910920

911921
if( !was_loaded || jo.has_array( "families" ) ) {
912922
families.clear();
@@ -934,27 +944,8 @@ void mtype::load( const JsonObject &jo, const std::string &src )
934944
optional( jo, was_loaded, "absorb_move_cost_min", absorb_move_cost_min, 1 );
935945
optional( jo, was_loaded, "absorb_move_cost_max", absorb_move_cost_max, -1 );
936946

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

959950
optional( jo, was_loaded, "bleed_rate", bleed_rate, 100 );
960951

@@ -998,8 +989,8 @@ void mtype::load( const JsonObject &jo, const std::string &src )
998989
}
999990

1000991

1001-
assign( jo, "vision_day", vision_day, strict, 0 );
1002-
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 );
1003994

1004995
optional( jo, was_loaded, "regenerates", regenerates, 0 );
1005996
optional( jo, was_loaded, "regenerates_in_dark", regenerates_in_dark, false );
@@ -1031,26 +1022,9 @@ void mtype::load( const JsonObject &jo, const std::string &src )
10311022
optional( jo, was_loaded, "mech_str_bonus", mech_str_bonus, 0 );
10321023
optional( jo, was_loaded, "mech_battery", mech_battery, itype_id() );
10331024

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

10551029
optional( jo, was_loaded, "zombify_into", zombify_into, string_id_reader<::mtype> {},
10561030
mtype_id() );
@@ -1060,28 +1034,12 @@ void mtype::load( const JsonObject &jo, const std::string &src )
10601034

10611035
optional( jo, was_loaded, "aggro_character", aggro_character, true );
10621036

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

10721039
optional( jo, was_loaded, "melee_damage", melee_damage );
10731040

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

10861044
if( jo.has_member( "death_drops" ) ) {
10871045
death_drops =
@@ -1090,38 +1048,19 @@ void mtype::load( const JsonObject &jo, const std::string &src )
10901048
}
10911049

10921050
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() );
10931053

10941054
optional( jo, was_loaded, "dissect", dissect );
10951055

10961056
optional( jo, was_loaded, "decay", decay );
10971057

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

11081060
optional( jo, was_loaded, "speed_description", speed_desc, speed_description_DEFAULT );
11091061
optional( jo, was_loaded, "death_function", mdeath_effect );
11101062

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

11261065
if( jo.has_member( "special_when_hit" ) ) {
11271066
JsonArray jsarr = jo.get_array( "special_when_hit" );

src/mtype.h

Lines changed: 7 additions & 0 deletions
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 {

src/shearing.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,12 @@ void shearing_entry::load( const JsonObject &jo )
3737
{
3838
mandatory( jo, was_loaded, "result", result );
3939

40-
optional( jo, was_loaded, "ratio_mass", ratio_mass );
41-
ratio_mass = std::max( 0.00f, ratio_mass );
40+
optional( jo, was_loaded, "ratio_mass", ratio_mass, numeric_bound_reader<float> {0.f} );
4241

43-
optional( jo, was_loaded, "ratio_volume", ratio_volume );
44-
ratio_volume = std::max( 0.00f, ratio_volume );
42+
optional( jo, was_loaded, "ratio_volume", ratio_volume, numeric_bound_reader<float> {0.f} );
4543

4644
if( jo.has_int( "amount" ) ) {
47-
mandatory( jo, was_loaded, "amount", amount );
48-
amount = std::max( 0, amount );
45+
mandatory( jo, was_loaded, "amount", amount, numeric_bound_reader<int> {0} );
4946
} else if( jo.has_array( "amount" ) ) {
5047
std::vector<int> amount_random = jo.get_int_array( "amount" );
5148
random_min = std::max( 0, amount_random[0] );
@@ -56,6 +53,12 @@ void shearing_entry::load( const JsonObject &jo )
5653
}
5754
}
5855

56+
void shearing_data::deserialize( const JsonArray &ja )
57+
{
58+
ja.read( entries_ );
59+
valid_ = !entries_.empty();
60+
}
61+
5962
shearing_data::shearing_data( std::vector<shearing_entry> &shearing_entries )
6063
{
6164
if( !shearing_entries.empty() ) {

src/shearing.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
#pragma once
2-
#include "type_id.h"
32
#ifndef CATA_SRC_SHEARING_H
43
#define CATA_SRC_SHEARING_H
54

65
#include <vector>
76

7+
#include "type_id.h"
8+
9+
class JsonArray;
810
class JsonObject;
911
class monster;
1012

@@ -25,6 +27,9 @@ struct shearing_entry {
2527

2628
bool was_loaded = false;
2729
void load( const JsonObject &jo );
30+
void deserialize( const JsonObject &jo ) {
31+
load( jo );
32+
}
2833
};
2934

3035
class shearing_data
@@ -43,6 +48,8 @@ class shearing_data
4348

4449
std::vector<shearing_roll> roll_all( const monster &mon ) const;
4550

51+
void deserialize( const JsonArray &ja );
52+
4653
private:
4754
bool valid_ = false;
4855
std::vector<shearing_entry> entries_;

0 commit comments

Comments
 (0)