Skip to content

Commit 4df0573

Browse files
committed
Monster weakpoints to optional/mandatory
Unfortunately, the "weakpoints" can delete from the "weakpoint sets", the contents of which aren't known until finalization. This requires disabling the 'copy-from' requirement for weakpoints and adding a special reader to handle this.
1 parent 967f9b5 commit 4df0573

File tree

5 files changed

+83
-52
lines changed

5 files changed

+83
-52
lines changed

data/mods/No_Hope/monsters.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,7 @@
503503
"weight": "386 kg",
504504
"hp": 120,
505505
"speed": 200,
506+
"weakpoint_sets": [ "wps_animal_quadruped" ],
506507
"material": [ "flesh" ],
507508
"symbol": "M",
508509
"color": "brown",

src/generic_factory.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1389,6 +1389,7 @@ template<typename Derived>
13891389
class generic_typed_reader
13901390
{
13911391
static constexpr bool read_objects = false;
1392+
static constexpr bool check_extend_delete_copy_from = true;
13921393
public:
13931394
template<typename C, typename Fn>
13941395
// I tried using a member function pointer and couldn't work it out
@@ -1619,8 +1620,11 @@ class generic_typed_reader
16191620
const Derived &derived = static_cast<const Derived &>( *this );
16201621
// or no handler for the container
16211622
if( !was_loaded ) {
1622-
warn_disabled_feature( jo, "extend", member_name, "no copy-from" );
1623-
warn_disabled_feature( jo, "delete", member_name, "no copy-from" );
1623+
// this is gross, but some JSON wants to delete from things loaded by a different member on the same entity
1624+
if( Derived::check_extend_delete_copy_from ) {
1625+
warn_disabled_feature( jo, "extend", member_name, "no copy-from" );
1626+
warn_disabled_feature( jo, "delete", member_name, "no copy-from" );
1627+
}
16241628
warn_disabled_feature( jo, "relative", member_name, "no copy-from" );
16251629
warn_disabled_feature( jo, "proportional", member_name, "no copy-from" );
16261630
}
@@ -2083,6 +2087,20 @@ class time_bound_reader : public bound_reader<T>
20832087
};
20842088
};
20852089

2090+
struct weakpoints;
2091+
2092+
struct weakpoints_reader : generic_typed_reader<weakpoints_reader> {
2093+
static constexpr bool check_extend_delete_copy_from = false;
2094+
2095+
std::set<std::string> &deleted;
2096+
2097+
explicit weakpoints_reader( std::set<std::string> &del ) : deleted( del ) {}
2098+
2099+
weakpoints get_next( const JsonValue &jv ) const;
2100+
bool do_extend( const JsonObject &jo, std::string_view name, weakpoints &member ) const;
2101+
bool do_delete( const JsonObject &jo, std::string_view name, weakpoints &member ) const;
2102+
};
2103+
20862104
/**
20872105
* Only for external use in legacy code where migrating to `class translation`
20882106
* is impractical. For new code load with `class translation` instead.

src/monstergenerator.cpp

Lines changed: 2 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -862,58 +862,10 @@ void mtype::load( const JsonObject &jo, const std::string &src )
862862
// Load each set of weakpoints.
863863
// Each subsequent weakpoint set overwrites
864864
// matching weakpoints from the previous set.
865-
if( jo.has_array( "weakpoint_sets" ) ) {
866-
weakpoints_deferred.clear();
867-
for( JsonValue jval : jo.get_array( "weakpoint_sets" ) ) {
868-
weakpoints_deferred.emplace_back( jval.get_string() );
869-
}
870-
}
871-
865+
optional( jo, was_loaded, "weakpoint_sets", weakpoints_deferred, auto_flags_reader<weakpoints_id> {} );
872866
// Finally, inline weakpoints overwrite
873867
// any matching weakpoints from the previous sets.
874-
if( jo.has_array( "weakpoints" ) ) {
875-
weakpoints_deferred_inline.clear();
876-
::weakpoints tmp_wp;
877-
tmp_wp.load( jo.get_array( "weakpoints" ) );
878-
weakpoints_deferred_inline.add_from_set( tmp_wp, true );
879-
}
880-
881-
if( jo.has_object( "extend" ) ) {
882-
JsonObject tmp = jo.get_object( "extend" );
883-
tmp.allow_omitted_members();
884-
if( tmp.has_array( "weakpoint_sets" ) ) {
885-
for( JsonValue jval : tmp.get_array( "weakpoint_sets" ) ) {
886-
weakpoints_deferred.emplace_back( jval.get_string() );
887-
}
888-
}
889-
if( tmp.has_array( "weakpoints" ) ) {
890-
::weakpoints tmp_wp;
891-
tmp_wp.load( tmp.get_array( "weakpoints" ) );
892-
weakpoints_deferred_inline.add_from_set( tmp_wp, true );
893-
}
894-
}
895-
896-
if( jo.has_object( "delete" ) ) {
897-
JsonObject tmp = jo.get_object( "delete" );
898-
tmp.allow_omitted_members();
899-
if( tmp.has_array( "weakpoint_sets" ) ) {
900-
for( JsonValue jval : tmp.get_array( "weakpoint_sets" ) ) {
901-
weakpoints_id set_id( jval.get_string() );
902-
auto iter = std::find( weakpoints_deferred.begin(), weakpoints_deferred.end(), set_id );
903-
if( iter != weakpoints_deferred.end() ) {
904-
weakpoints_deferred.erase( iter );
905-
}
906-
}
907-
}
908-
if( tmp.has_array( "weakpoints" ) ) {
909-
::weakpoints tmp_wp;
910-
tmp_wp.load( tmp.get_array( "weakpoints" ) );
911-
for( const weakpoint &wp_del : tmp_wp.weakpoint_list ) {
912-
weakpoints_deferred_deleted.emplace( wp_del.id );
913-
}
914-
weakpoints_deferred_inline.del_from_set( tmp_wp );
915-
}
916-
}
868+
optional( jo, was_loaded, "weakpoints", weakpoints_deferred_inline, weakpoints_reader{weakpoints_deferred_deleted} );
917869

918870
optional( jo, was_loaded, "status_chance_multiplier", status_chance_multiplier, numeric_bound_reader{0.0f, 5.0f},
919871
1.f );

src/weakpoint.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <algorithm>
44
#include <cmath>
55
#include <memory>
6+
#include <set>
67
#include <string>
78
#include <utility>
89

@@ -579,6 +580,61 @@ void weakpoints::clear()
579580
weakpoint_list.clear();
580581
}
581582

583+
void weakpoints::deserialize( const JsonValue &jv )
584+
{
585+
load( jv.get_array() );
586+
}
587+
588+
bool weakpoints::handle_extend( const JsonValue &jv )
589+
{
590+
weakpoints tmp;
591+
tmp.deserialize( jv );
592+
add_from_set( tmp, true );
593+
return true;
594+
}
595+
596+
bool weakpoints::handle_delete( const JsonValue &jv )
597+
{
598+
weakpoints tmp;
599+
tmp.deserialize( jv );
600+
del_from_set( tmp );
601+
return true;
602+
}
603+
604+
weakpoints weakpoints_reader::get_next( const JsonValue &jv ) const
605+
{
606+
weakpoints ret;
607+
if( !jv.read( ret ) ) {
608+
jv.throw_error( "Invalid weakpoints format" );
609+
}
610+
return ret;
611+
}
612+
613+
bool weakpoints_reader::do_extend( const JsonObject &jo, const std::string_view name,
614+
weakpoints &member ) const
615+
{
616+
if( !jo.has_member( name ) ) {
617+
return false;
618+
}
619+
return member.handle_extend( jo.get_member( name ) );
620+
}
621+
622+
bool weakpoints_reader::do_delete( const JsonObject &jo, const std::string_view name,
623+
weakpoints &member ) const
624+
{
625+
if( !jo.has_member( name ) ) {
626+
return false;
627+
}
628+
weakpoints tmp;
629+
tmp.deserialize( jo.get_member( name ) );
630+
// deferred delete for weakpoints from sets
631+
for( const weakpoint &del : tmp.weakpoint_list ) {
632+
deleted.emplace( del.id );
633+
}
634+
member.del_from_set( tmp );
635+
return true;
636+
}
637+
582638
void weakpoints::load( const JsonArray &ja )
583639
{
584640
for( const JsonObject jo : ja ) {

src/weakpoint.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,10 @@ struct weakpoints {
198198
void finalize();
199199
void check() const;
200200

201+
void deserialize( const JsonValue &jv );
202+
bool handle_extend( const JsonValue &jv );
203+
bool handle_delete( const JsonValue &jv );
204+
201205
/********************* weakpoint_set handling ****************************/
202206
// load standalone JSON type
203207
void load( const JsonObject &jo, std::string_view src );

0 commit comments

Comments
 (0)