Skip to content

Commit ee40df2

Browse files
committed
mandatory/optional for weakpoints
Expand use of manadtory/optional, as they have the best error reporting and support for extended JSON features.
1 parent a2284a1 commit ee40df2

File tree

3 files changed

+107
-83
lines changed

3 files changed

+107
-83
lines changed

src/generic_factory.h

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,6 +1208,49 @@ struct handler<std::map<Key, Val>> {
12081208
}
12091209
static constexpr bool is_container = true;
12101210
};
1211+
1212+
template<typename Key, typename Val>
1213+
struct handler<std::unordered_map<Key, Val>> {
1214+
void clear( std::unordered_map<Key, Val> &container ) const {
1215+
container.clear();
1216+
}
1217+
bool insert( std::unordered_map<Key, Val> &container, const std::pair<Key, Val> &data ) const {
1218+
// emplace can fail if the key already exists
1219+
if( !container.emplace( data ).second ) {
1220+
debugmsg( "Insert of <%s, %s> failed, key already exists",
1221+
data_string( data.first ), data_string( data.second ) );
1222+
return false;
1223+
}
1224+
return true;
1225+
}
1226+
bool relative( std::unordered_map<Key, Val> &container, const std::pair<Key, Val> &data ) const {
1227+
if constexpr( !supports_relative<Val>::value ) {
1228+
debugmsg( "relative not supported by type %s", demangle( typeid( Val ).name() ) );
1229+
return false;
1230+
} else {
1231+
const auto iter = container.find( data.first );
1232+
if( iter == container.end() ) {
1233+
debugmsg( "No %s to perform relative of %s on",
1234+
data_string( data.first ), data_string( data.second ) );
1235+
return false;
1236+
}
1237+
iter->second += data.second;
1238+
}
1239+
return true;
1240+
}
1241+
bool erase( std::unordered_map<Key, Val> &container, const std::pair<Key, Val> &data ) const {
1242+
const auto iter = container.find( data.first );
1243+
if( iter != container.end() ) {
1244+
container.erase( iter );
1245+
} else {
1246+
debugmsg( "Did not remove <%s, %s> in delete", data_string( data.first ),
1247+
data_string( data.second ) );
1248+
return false;
1249+
}
1250+
return true;
1251+
}
1252+
static constexpr bool is_container = true;
1253+
};
12111254
} // namespace reader_detail
12121255

12131256
/**
@@ -1688,6 +1731,32 @@ class generic_map_reader : public generic_typed_reader<generic_map_reader<K, V>>
16881731
}
16891732
};
16901733

1734+
// Support shorthand for a single value.
1735+
template<typename T>
1736+
class pair_reader : public generic_typed_reader<pair_reader<T>>
1737+
{
1738+
public:
1739+
std::pair<T, T> get_next( const JsonValue &jv ) const {
1740+
if( jv.test_float() ) {
1741+
T val;
1742+
jv.read( val, true );
1743+
return std::make_pair( val, val );
1744+
}
1745+
if( !jv.test_array() ) {
1746+
jv.throw_error( "bad pair" );
1747+
}
1748+
JsonArray ja = jv.get_array();
1749+
if( ja.size() != 2 ) {
1750+
ja.throw_error( "Must have 2 elements" );
1751+
}
1752+
T l;
1753+
T h;
1754+
ja[0].read( l, true );
1755+
ja[1].read( h, true );
1756+
return std::make_pair( l, h );
1757+
}
1758+
};
1759+
16911760
template<typename T>
16921761
static T bound_check( T low, T high, const JsonValue &jv, T read_value )
16931762
{

src/weakpoint.cpp

Lines changed: 32 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
#include <string>
77
#include <utility>
88

9-
#include "assign.h"
109
#include "calendar.h"
1110
#include "character.h"
1211
#include "condition.h"
@@ -123,13 +122,10 @@ void weakpoint_family::load( const JsonValue &jsin )
123122
proficiency = proficiency_id( id );
124123
} else {
125124
JsonObject jo = jsin.get_object();
126-
assign( jo, "id", id );
127-
assign( jo, "proficiency", proficiency );
128-
assign( jo, "bonus", bonus );
129-
assign( jo, "penalty", penalty );
130-
if( !jo.has_string( "id" ) ) {
131-
id = static_cast<std::string>( proficiency );
132-
}
125+
mandatory( jo, false, "proficiency", proficiency );
126+
optional( jo, false, "id", id, proficiency.str() );
127+
optional( jo, false, "bonus", bonus );
128+
optional( jo, false, "penalty", penalty );
133129
}
134130
}
135131

@@ -304,41 +300,14 @@ void weakpoint_effect::apply_to( Creature &target, int total_damage,
304300

305301
void weakpoint_effect::load( const JsonObject &jo )
306302
{
307-
if( jo.has_string( "effect" ) ) {
308-
assign( jo, "effect", effect );
309-
}
310-
if( jo.has_array( "effect_on_conditions" ) ) {
311-
assign( jo, "effect_on_conditions", effect_on_conditions );
312-
}
313-
if( jo.has_float( "chance" ) ) {
314-
assign( jo, "chance", chance, false, 0.0f, 100.0f );
315-
}
316-
if( jo.has_bool( "permanent" ) ) {
317-
assign( jo, "permanent", permanent );
318-
}
319-
if( jo.has_string( "message" ) ) {
320-
assign( jo, "message", message );
321-
}
322-
323-
// Support shorthand for a single value.
324-
if( jo.has_int( "duration" ) ) {
325-
int i = jo.get_int( "duration", 0 );
326-
duration = {i, i};
327-
} else if( jo.has_array( "duration" ) ) {
328-
assign( jo, "duration", duration );
329-
}
330-
if( jo.has_int( "intensity" ) ) {
331-
int i = jo.get_int( "intensity", 0 );
332-
intensity = {i, i};
333-
} else if( jo.has_array( "intensity" ) ) {
334-
assign( jo, "intensity", intensity );
335-
}
336-
if( jo.has_float( "damage_required" ) ) {
337-
float f = jo.get_float( "damage_required", 0.0f );
338-
damage_required = {f, f};
339-
} else if( jo.has_array( "damage_required" ) ) {
340-
assign( jo, "damage_required", damage_required );
341-
}
303+
optional( jo, false, "effect", effect );
304+
optional( jo, false, "effect_on_conditions", effect_on_conditions );
305+
optional( jo, false, "chance", chance, numeric_bound_reader{0.f, 100.f} );
306+
optional( jo, false, "permanent", permanent );
307+
optional( jo, false, "message", message );
308+
optional( jo, false, "duration", duration, pair_reader<int> {} );
309+
optional( jo, false, "intensity", intensity, pair_reader<int> {} );
310+
optional( jo, false, "damage_required", damage_required, pair_reader<float> {} );
342311
}
343312

344313
weakpoint_attack::weakpoint_attack() :
@@ -419,52 +388,32 @@ weakpoint::weakpoint() : coverage_mult( 1.0f ), difficulty( -100.0f )
419388

420389
void weakpoint::load( const JsonObject &jo )
421390
{
422-
assign( jo, "id", id );
423-
assign( jo, "name", name );
424-
assign( jo, "coverage", coverage, false, 0.0f, 100.0f );
425-
if( jo.has_bool( "is_good" ) ) {
426-
assign( jo, "is_good", is_good );
427-
}
428-
if( is_good && jo.has_bool( "is_head" ) ) {
429-
assign( jo, "is_head", is_head );
430-
}
431-
if( jo.has_object( "armor_mult" ) ) {
432-
armor_mult = load_damage_map( jo.get_object( "armor_mult" ) );
433-
}
434-
if( jo.has_object( "armor_penalty" ) ) {
435-
armor_penalty = load_damage_map( jo.get_object( "armor_penalty" ) );
436-
}
437-
if( jo.has_object( "damage_mult" ) ) {
438-
damage_mult = load_damage_map( jo.get_object( "damage_mult" ) );
439-
}
440-
if( jo.has_object( "crit_mult" ) ) {
441-
crit_mult = load_damage_map( jo.get_object( "crit_mult" ) );
391+
if( jo.has_member( "id" ) ) {
392+
mandatory( jo, false, "id", id );
442393
} else {
443-
// Default to damage multiplier, if crit multipler is not specified.
444-
crit_mult = damage_mult;
394+
mandatory( jo, false, "name", id );
445395
}
396+
optional( jo, false, "name", name );
397+
optional( jo, false, "coverage", coverage, numeric_bound_reader{0.0f, 100.0f}, 100.f );
398+
optional( jo, false, "is_good", is_good, true );
399+
// ???
400+
if( is_good ) {
401+
optional( jo, false, "is_head", is_head, false );
402+
}
403+
optional( jo, false, "armor_mult", armor_mult, generic_map_reader<damage_type_id, float> {} );
404+
optional( jo, false, "armor_penalty", armor_penalty, generic_map_reader<damage_type_id, float> {} );
405+
optional( jo, false, "damage_mult", damage_mult, generic_map_reader<damage_type_id, float> {} );
406+
optional( jo, false, "crit_mult", crit_mult, generic_map_reader<damage_type_id, float> {},
407+
damage_mult );
408+
409+
// FIXME: read conditions with optional
446410
if( jo.has_member( "condition" ) ) {
447411
read_condition( jo, "condition", condition, false );
448412
has_condition = true;
449413
}
450-
if( jo.has_array( "effects" ) ) {
451-
for( const JsonObject effect_jo : jo.get_array( "effects" ) ) {
452-
weakpoint_effect effect;
453-
effect.load( effect_jo );
454-
effects.push_back( std::move( effect ) );
455-
}
456-
}
457-
if( jo.has_object( "coverage_mult" ) ) {
458-
coverage_mult.load( jo.get_object( "coverage_mult" ) );
459-
}
460-
if( jo.has_object( "difficulty" ) ) {
461-
difficulty.load( jo.get_object( "difficulty" ) );
462-
}
463-
464-
// Set the ID to the name, if not provided.
465-
if( !jo.has_string( "id" ) ) {
466-
assign( jo, "name", id );
467-
}
414+
optional( jo, false, "effects", effects );
415+
optional( jo, false, "coverage_mult", coverage_mult, weakpoint_difficulty( 1.f ) );
416+
optional( jo, false, "difficulty", difficulty, weakpoint_difficulty( -100.f ) );
468417
}
469418

470419
void weakpoint::check() const

src/weakpoint.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ struct weakpoint_effect {
8989
// Maybe apply an effect to the target.
9090
void apply_to( Creature &target, int total_damage, const weakpoint_attack &attack ) const;
9191
void load( const JsonObject &jo );
92+
void deserialize( const JsonObject &jo ) {
93+
load( jo );
94+
}
9295
};
9396

9497
struct weakpoint_difficulty {
@@ -97,6 +100,9 @@ struct weakpoint_difficulty {
97100
explicit weakpoint_difficulty( float default_value );
98101
float of( const weakpoint_attack &attack ) const;
99102
void load( const JsonObject &jo );
103+
void deserialize( const JsonObject &jo ) {
104+
load( jo );
105+
}
100106
};
101107

102108
struct weakpoint_family {

0 commit comments

Comments
 (0)