From 80e01eb5908d74f5fa0ba5f93387555c09a0ac20 Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Mon, 29 May 2023 18:26:18 -0500 Subject: [PATCH 01/25] Streamline has_trait_flag behavior --- src/mutation.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/mutation.cpp b/src/mutation.cpp index 5173ce56e98c..03a1f30198d7 100644 --- a/src/mutation.cpp +++ b/src/mutation.cpp @@ -105,10 +105,8 @@ bool Character::has_trait( const trait_id &b ) const bool Character::has_trait_flag( const std::string &b ) const { - // UGLY, SLOW, should be cached as my_mutation_flags or something - for( const trait_id &mut : get_mutations() ) { - const mutation_branch &mut_data = mut.obj(); - if( mut_data.flags.count( b ) > 0 ) { + for( const mutation_branch *mut : cached_mutations ) { + if( mut->flags.count( b ) > 0 ) { return true; } } From 18e159e89cda7caf793357485937a27e1a029925 Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Fri, 2 Jun 2023 16:30:25 -0500 Subject: [PATCH 02/25] Start work on it --- src/flag_trait.cpp | 126 +++++++++++++++++++++++++++++++++++++++++++++ src/flag_trait.h | 60 +++++++++++++++++++++ src/init.cpp | 5 ++ 3 files changed, 191 insertions(+) create mode 100644 src/flag_trait.cpp create mode 100644 src/flag_trait.h diff --git a/src/flag_trait.cpp b/src/flag_trait.cpp new file mode 100644 index 000000000000..99b9e7c9f7d0 --- /dev/null +++ b/src/flag_trait.cpp @@ -0,0 +1,126 @@ +#include "flag.h" + +#include + +#include "debug.h" +#include "json.h" +#include "type_id.h" +#include "generic_factory.h" + +const trait_flag_str_id flag_NULL = trait_flag_str_id( "null" ); // intentionally invalid flag + +namespace +{ +generic_factory json_trait_flags_all( "json_trait_flags" ); +} // namespace + +/** @relates int_id */ +template<> +bool trait_flag_id ::is_valid() const +{ + return json_trait_flags_all.is_valid( *this ); +} + +/** @relates int_id */ +template<> +const json_trait_flag &trait_flag_id::obj() const +{ + return json_trait_flags_all.obj( *this ); +} + +/** @relates int_id */ +template<> +const trait_flag_str_id &trait_flag_id::id() const +{ + return json_trait_flags_all.convert( *this ); +} + +/** @relates string_id */ +template<> +bool trait_flag_str_id ::is_valid() const +{ + return json_trait_flags_all.is_valid( *this ); +} + +/** @relates string_id */ +template<> +const json_trait_flag &trait_flag_str_id::obj() const +{ + return json_trait_flags_all.obj( *this ); +} + +/** @relates string_id */ +template<> +trait_flag_id trait_flag_str_id::id() const +{ + return json_trait_flags_all.convert( *this, trait_flag_id( -1 ) ); +} + +/** @relates int_id */ +template<> +trait_flag_id::int_id( const trait_flag_str_id &id ) : _id( id.id() ) +{ +} + +json_trait_flag::operator bool() const +{ + return id.is_valid(); +} + +const json_trait_flag &json_trait_flag::get( const std::string &id ) +{ + static const json_trait_flag null_value = json_trait_flag(); + const trait_flag_str_id f_id( id ); + return f_id.is_valid() ? *f_id : null_value; +} + +void json_trait_flag::load( const JsonObject &jo, const std::string & ) +{ + // Remember these for conversion of the other shit. + // optional( jo, was_loaded, "inherit", inherit_, true ); + // optional( jo, was_loaded, "craft_inherit", craft_inherit_, false ); + // optional( jo, was_loaded, "taste_mod", taste_mod_ ); + // jo.get_member( "context" ); + optional( jo, was_loaded, "conflicts", conflicts_ ); + optional( jo, was_loaded, "restriction", restriction_ ); +} + +void json_trait_flag::check_consistency() +{ + json_trait_flags_all.check(); +} + +void json_trait_flag::reset() +{ + json_trait_flags_all.reset(); +} + +void json_trait_flag::load_all( const JsonObject &jo, const std::string &src ) +{ + json_trait_flags_all.load( jo, src ); +} + +void json_trait_flag::check() const +{ + for( const auto &conflicting : conflicts_ ) { + if( !trait_flag_str_id( conflicting ).is_valid() ) { + debugmsg( "trait flag definition %s specifies unknown conflicting field %s", id.str(), + conflicting ); + } + } +} + +void json_trait_flag::finalize_all() +{ + json_trait_flags_all.finalize(); +} + +bool json_trait_flag::is_ready() +{ + return !json_trait_flags_all.empty(); +} + +const std::vector &json_trait_flag::get_all() +{ + return json_trait_flags_all.get_all(); +} diff --git a/src/flag_trait.h b/src/flag_trait.h new file mode 100644 index 000000000000..baa2044860a7 --- /dev/null +++ b/src/flag_trait.h @@ -0,0 +1,60 @@ +#pragma once +#ifndef CATA_SRC_FLAG_H +#define CATA_SRC_FLAG_H + +#include +#include + +#include "translations.h" +#include "type_id.h" +class JsonObject; + +extern const trait_flag_str_id flag_NULL; + +class json_trait_flag +{ + friend class DynamicDataLoader; + friend class generic_factory; + + public: + // used by generic_factory + trait_flag_str_id id = flag_NULL; + bool was_loaded = false; + + json_trait_flag() = default; + + /** Fetches flag definition (or null flag if not found) */ + static const json_trait_flag &get( const std::string &id ); + + /** Is this a valid (non-null) flag */ + operator bool() const; + + void check() const; + + /** true, if flags were loaded */ + static bool is_ready(); + + static const std::vector &get_all(); + + private: + translation info_; + translation restriction_; + std::set conflicts_; + + /** Load flag definition from JSON */ + void load( const JsonObject &jo, const std::string &src ); + + /** Load all flags from JSON */ + static void load_all( const JsonObject &jo, const std::string &src ); + + /** finalize */ + static void finalize_all( ); + + /** Check consistency of all loaded flags */ + static void check_consistency(); + + /** Clear all loaded flags (invalidating any pointers) */ + static void reset(); +}; + +#endif // CATA_SRC_FLAG_H diff --git a/src/init.cpp b/src/init.cpp index 06d4a0fb189d..af68f0b2a4a0 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -44,6 +44,7 @@ #include "filesystem.h" #include "fstream_utils.h" #include "flag.h" +#include "flag_trait.h" #include "gates.h" #include "harvest.h" #include "item_action.h" @@ -248,6 +249,7 @@ void DynamicDataLoader::initialize() add( "WORLD_OPTION", &load_world_option ); add( "EXTERNAL_OPTION", &load_external_option ); add( "json_flag", &json_flag::load_all ); + add( "mutation_flag", &json_trait_flag::load_all ); add( "fault", &fault::load_fault ); add( "field_type", &field_types::load ); add( "weather_type", &weather_types::load ); @@ -569,6 +571,7 @@ void DynamicDataLoader::unload_data() item_action_generator::generator().reset(); item_controller->reset(); json_flag::reset(); + json_trait_flag::reset(); MapExtras::reset(); mapgen_palette::reset(); materials::reset(); @@ -647,6 +650,7 @@ void DynamicDataLoader::finalize_loaded_data( loading_ui &ui ) using named_entry = std::pair>; const std::vector entries = {{ { _( "Flags" ), &json_flag::finalize_all }, + { _( "Mutation Flags" ), &json_trait_flag::finalize_all }, { _( "Body parts" ), &body_part_type::finalize_all }, { _( "Bionics" ), &bionic_data::finalize_all }, { _( "Weather types" ), &weather_types::finalize_all }, @@ -727,6 +731,7 @@ void DynamicDataLoader::check_consistency( loading_ui &ui ) using named_entry = std::pair>; const std::vector entries = {{ { _( "Flags" ), &json_flag::check_consistency }, + { _( "Mutation Flags" ), &json_trait_flag::check_consistency }, { _( "Crafting requirements" ), []() { From bb42ae263ed621287c693ab00b9bea1637852227 Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Fri, 2 Jun 2023 18:25:31 -0500 Subject: [PATCH 03/25] Update type_id.h --- src/type_id.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/type_id.h b/src/type_id.h index fed78f471067..fae447247343 100644 --- a/src/type_id.h +++ b/src/type_id.h @@ -212,4 +212,8 @@ class json_flag; using flag_id = int_id; using flag_str_id = string_id; +class json_trait_flag; +using trait_flag_id = int_id; +using trait_flag_str_id = string_id; + #endif // CATA_SRC_TYPE_ID_H From 8fdc5e8c14d5f10928f0162a84a20fc3a11e81c3 Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Mon, 26 Jun 2023 09:27:28 -0500 Subject: [PATCH 04/25] Update the thing --- src/flag_trait.cpp | 3 ++- src/flag_trait.h | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/flag_trait.cpp b/src/flag_trait.cpp index 99b9e7c9f7d0..3437c9c5bd1c 100644 --- a/src/flag_trait.cpp +++ b/src/flag_trait.cpp @@ -3,11 +3,12 @@ #include #include "debug.h" +#include "flag_trait.h" #include "json.h" #include "type_id.h" #include "generic_factory.h" -const trait_flag_str_id flag_NULL = trait_flag_str_id( "null" ); // intentionally invalid flag +const trait_flag_str_id trait_flag_NULL = trait_flag_str_id( "null" ); // intentionally invalid flag namespace { diff --git a/src/flag_trait.h b/src/flag_trait.h index baa2044860a7..ebcae96af482 100644 --- a/src/flag_trait.h +++ b/src/flag_trait.h @@ -9,7 +9,7 @@ #include "type_id.h" class JsonObject; -extern const trait_flag_str_id flag_NULL; +extern const trait_flag_str_id trait_flag_NULL; class json_trait_flag { @@ -18,7 +18,7 @@ class json_trait_flag public: // used by generic_factory - trait_flag_str_id id = flag_NULL; + trait_flag_str_id id = trait_flag_NULL; bool was_loaded = false; json_trait_flag() = default; From 517c39b4b26a31b1094ced842e25f23177ad019c Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Fri, 1 Sep 2023 12:02:57 -0500 Subject: [PATCH 05/25] Commit latest fixes --- src/flag_trait.cpp | 2 -- src/flag_trait.h | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/flag_trait.cpp b/src/flag_trait.cpp index 3437c9c5bd1c..148facfd6f5f 100644 --- a/src/flag_trait.cpp +++ b/src/flag_trait.cpp @@ -1,5 +1,3 @@ -#include "flag.h" - #include #include "debug.h" diff --git a/src/flag_trait.h b/src/flag_trait.h index ebcae96af482..aa30b117e079 100644 --- a/src/flag_trait.h +++ b/src/flag_trait.h @@ -1,6 +1,6 @@ #pragma once #ifndef CATA_SRC_FLAG_H -#define CATA_SRC_FLAG_H +#define CATA_SRC_FLAG_TRAIT_H #include #include @@ -57,4 +57,4 @@ class json_trait_flag static void reset(); }; -#endif // CATA_SRC_FLAG_H +#endif // CATA_SRC_FLAG_TRAIT_H From 4bc145a72f5d0ba90ca6071dd08644734cd0f9be Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Fri, 1 Sep 2023 13:59:36 -0500 Subject: [PATCH 06/25] Update flag_trait.h --- src/flag_trait.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flag_trait.h b/src/flag_trait.h index aa30b117e079..8ce569f8e273 100644 --- a/src/flag_trait.h +++ b/src/flag_trait.h @@ -1,5 +1,5 @@ #pragma once -#ifndef CATA_SRC_FLAG_H +#ifndef CATA_SRC_FLAG_TRAIT_H #define CATA_SRC_FLAG_TRAIT_H #include From 43d62f8e079005671deb0d61d607fc29f00e9e2d Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Mon, 11 Sep 2023 16:53:53 -0500 Subject: [PATCH 07/25] Commit what I have for now --- src/activity_handlers.cpp | 6 +++--- src/character.cpp | 21 +++++++++------------ src/character.h | 2 +- src/consumption.cpp | 2 +- src/item.cpp | 2 +- src/iuse_actor.cpp | 8 ++++---- src/magic.cpp | 4 ++-- src/mondeath.cpp | 10 +++++----- src/mutation.cpp | 2 +- 9 files changed, 27 insertions(+), 30 deletions(-) diff --git a/src/activity_handlers.cpp b/src/activity_handlers.cpp index b44978b21e92..7cb3c474fb0c 100644 --- a/src/activity_handlers.cpp +++ b/src/activity_handlers.cpp @@ -246,9 +246,9 @@ static const quality_id qual_LOCKPICK( "LOCKPICK" ); static const species_id HUMAN( "HUMAN" ); static const species_id ZOMBIE( "ZOMBIE" ); -static const std::string trait_flag_CANNIBAL( "CANNIBAL" ); -static const std::string trait_flag_PSYCHOPATH( "PSYCHOPATH" ); -static const std::string trait_flag_SAPIOVORE( "SAPIOVORE" ); +static const trait_flag_str_id trait_flag_CANNIBAL( "CANNIBAL" ); +static const trait_flag_str_id trait_flag_PSYCHOPATH( "PSYCHOPATH" ); +static const trait_flag_str_id trait_flag_SAPIOVORE( "SAPIOVORE" ); static const bionic_id bio_ears( "bio_ears" ); static const bionic_id bio_painkiller( "bio_painkiller" ); diff --git a/src/character.cpp b/src/character.cpp index cb2dec4555c6..9e950664411d 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -3445,16 +3445,16 @@ void Character::practice( const skill_id &id, int amount, int cap, bool suppress amount = 0; } } - if( has_trait_flag( "PRED2" ) && skill.is_combat_skill() ) { + if( has_trait_flag( trait_flag_str_id( "PRED2" ) ) && skill.is_combat_skill() ) { if( one_in( 3 ) ) { amount *= 2; } } - if( has_trait_flag( "PRED3" ) && skill.is_combat_skill() ) { + if( has_trait_flag( trait_flag_str_id( "PRED3" ) ) && skill.is_combat_skill() ) { amount *= 2; } - if( has_trait_flag( "PRED4" ) && skill.is_combat_skill() ) { + if( has_trait_flag( trait_flag_str_id( "PRED4" ) ) && skill.is_combat_skill() ) { amount *= 3; } @@ -3488,7 +3488,7 @@ void Character::practice( const skill_id &id, int amount, int cap, bool suppress focus_pool -= chance_to_drop / 100; // Apex Predators don't think about much other than killing. // They don't lose Focus when practicing combat skills. - if( ( rng( 1, 100 ) <= ( chance_to_drop % 100 ) ) && ( !( has_trait_flag( "PRED4" ) && + if( ( rng( 1, 100 ) <= ( chance_to_drop % 100 ) ) && ( !( has_trait_flag( trait_flag_str_id( "PRED4" ) ) && skill.is_combat_skill() ) ) ) { focus_pool--; } @@ -3599,17 +3599,14 @@ void Character::apply_skill_boost() void Character::do_skill_rust() { const int rust_rate_tmp = rust_rate(); - static const std::string PRED2( "PRED2" ); - static const std::string PRED3( "PRED3" ); - static const std::string PRED4( "PRED4" ); for( std::pair &pair : *_skills ) { const Skill &aSkill = *pair.first; SkillLevel &skill_level_obj = pair.second; if( aSkill.is_combat_skill() && - ( ( has_trait_flag( PRED2 ) && calendar::once_every( 8_hours ) ) || - ( has_trait_flag( PRED3 ) && calendar::once_every( 4_hours ) ) || - ( has_trait_flag( PRED4 ) && calendar::once_every( 3_hours ) ) ) ) { + ( ( has_trait_flag( trait_flag_str_id( "PRED2" ) ) && calendar::once_every( 8_hours ) ) || + ( has_trait_flag( trait_flag_str_id( "PRED3" ) ) && calendar::once_every( 4_hours ) ) || + ( has_trait_flag( trait_flag_str_id( "PRED4" ) ) && calendar::once_every( 3_hours ) ) ) ) { // Their brain is optimized to remember this if( one_in( 13 ) ) { // They've already passed the roll to avoid rust at @@ -4437,7 +4434,7 @@ std::pair Character::get_fatigue_description() const void Character::mod_thirst( int nthirst ) { - if( has_trait_flag( "NO_THIRST" ) ) { + if( has_trait_flag( trait_flag_str_id( "NO_THIRST" ) ) ) { return; } set_thirst( std::max( -100, thirst + nthirst ) ); @@ -7077,7 +7074,7 @@ void Character::set_rad( int new_rad ) void Character::mod_rad( int mod ) { - if( has_trait_flag( "NO_RADIATION" ) ) { + if( has_trait_flag( trait_flag_str_id( "NO_RADIATION" ) ) ) { return; } set_rad( std::max( 0, get_rad() + mod ) ); diff --git a/src/character.h b/src/character.h index c3ff9d3f7ebf..d48b461d6cab 100644 --- a/src/character.h +++ b/src/character.h @@ -703,7 +703,7 @@ class Character : public Creature, public visitable /** Returns true if the player has the entered starting trait */ bool has_base_trait( const trait_id &b ) const; /** Returns true if player has a trait with a flag */ - bool has_trait_flag( const std::string &b ) const; + bool has_trait_flag( const trait_flag_id &b ) const; /** Returns true if character has a trait which cancels the entered trait. */ bool has_opposite_trait( const trait_id &flag ) const; diff --git a/src/consumption.cpp b/src/consumption.cpp index 344bdcda4f13..979e3ea7bb50 100644 --- a/src/consumption.cpp +++ b/src/consumption.cpp @@ -755,7 +755,7 @@ ret_val Character::will_eat( const item &food, bool interactive ) } const bool carnivore = has_trait( trait_CARNIVORE ); - if( food.has_flag( flag_CANNIBALISM ) && !has_trait_flag( "CANNIBAL" ) ) { + if( food.has_flag( flag_CANNIBALISM ) && !has_trait_flag( trait_flag_str_id( "CANNIBAL" ) ) ) { add_consequence( _( "The thought of eating human flesh makes you feel sick." ), edible_rating::cannibalism ); } diff --git a/src/item.cpp b/src/item.cpp index 10f9c46324d1..a6e0f5dd46b8 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -156,7 +156,7 @@ static const quality_id qual_JACK( "JACK" ); static const quality_id qual_LIFT( "LIFT" ); static const species_id ROBOT( "ROBOT" ); -static const std::string trait_flag_CANNIBAL( "CANNIBAL" ); +static const trait_flag_str_id trait_flag_CANNIBAL( "CANNIBAL" ); static const bionic_id bio_digestion( "bio_digestion" ); diff --git a/src/iuse_actor.cpp b/src/iuse_actor.cpp index feba98829f30..4b2cde781009 100644 --- a/src/iuse_actor.cpp +++ b/src/iuse_actor.cpp @@ -2050,9 +2050,9 @@ int enzlave_actor::use( player &p, item &it, bool t, const tripoint & ) const int tolerance_level = 9; if( p.has_trait( trait_PSYCHOPATH ) || p.has_trait( trait_SAPIOVORE ) ) { tolerance_level = 0; - } else if( p.has_trait_flag( "PRED4" ) ) { + } else if( p.has_trait_flag( trait_flag_str_id( "PRED4" ) ) ) { tolerance_level = 5; - } else if( p.has_trait_flag( "PRED3" ) ) { + } else if( p.has_trait_flag( trait_flag_str_id( "PRED3" ) ) ) { tolerance_level = 7; } @@ -2096,9 +2096,9 @@ int enzlave_actor::use( player &p, item &it, bool t, const tripoint & ) const if( p.has_trait( trait_PACIFIST ) ) { moraleMalus *= 5; maxMalus *= 3; - } else if( p.has_trait_flag( "PRED1" ) ) { + } else if( p.has_trait_flag( trait_flag_str_id( "PRED1" ) ) ) { moraleMalus /= 4; - } else if( p.has_trait_flag( "PRED2" ) ) { + } else if( p.has_trait_flag( trait_flag_str_id( "PRED2" ) ) ) { moraleMalus /= 5; } diff --git a/src/magic.cpp b/src/magic.cpp index 7815169c505f..df38dfec12ae 100644 --- a/src/magic.cpp +++ b/src/magic.cpp @@ -758,13 +758,13 @@ float spell::spell_fail( const Character &guy ) const return 1.0f; } float fail_chance = std::pow( ( effective_skill - 30.0f ) / 30.0f, 2 ); - if( has_flag( spell_flag::SOMATIC ) && !guy.has_trait_flag( "SUBTLE_SPELL" ) ) { + if( has_flag( spell_flag::SOMATIC ) && !guy.has_trait_flag( trait_flag_str_id( "SUBTLE_SPELL" ) ) ) { // the first 20 points of encumbrance combined is ignored const int arms_encumb = std::max( 0, guy.encumb( bp_arm_l ) + guy.encumb( bp_arm_r ) - 20 ); // each encumbrance point beyond the "gray" color counts as half an additional fail % fail_chance += arms_encumb / 200.0f; } - if( has_flag( spell_flag::VERBAL ) && !guy.has_trait_flag( "SILENT_SPELL" ) ) { + if( has_flag( spell_flag::VERBAL ) && !guy.has_trait_flag( trait_flag_str_id( "SILENT_SPELL" ) ) ) { // a little bit of mouth encumbrance is allowed, but not much const int mouth_encumb = std::max( 0, guy.encumb( bp_mouth ) - 5 ); fail_chance += mouth_encumb / 100.0f; diff --git a/src/mondeath.cpp b/src/mondeath.cpp index 4b4ebc740618..68b63d44a691 100644 --- a/src/mondeath.cpp +++ b/src/mondeath.cpp @@ -438,8 +438,8 @@ void mdeath::guilt( monster &z ) guilt_tresholds[50] = _( "You regret killing %s." ); guilt_tresholds[25] = _( "You feel remorse for killing %s." ); - if( g->u.has_trait( trait_PSYCHOPATH ) || g->u.has_trait_flag( "PRED3" ) || - g->u.has_trait_flag( "PRED4" ) || g->u.has_trait( trait_KILLER ) ) { + if( g->u.has_trait( trait_PSYCHOPATH ) || g->u.has_trait_flag( trait_flag_str_id( "PRED3" ) || + g->u.has_trait_flag( trait_flag_str_id( "PRED4" ) || g->u.has_trait( trait_KILLER ) ) { return; } if( rl_dist( z.pos(), g->u.pos() ) > MAX_GUILT_DISTANCE ) { @@ -458,7 +458,7 @@ void mdeath::guilt( monster &z ) "about their deaths anymore." ), z.name( maxKills ) ); } return; - } else if( ( g->u.has_trait_flag( "PRED1" ) ) || ( g->u.has_trait_flag( "PRED2" ) ) ) { + } else if( ( g->u.has_trait_flag( trait_flag_str_id( "PRED1" ) ) || ( g->u.has_trait_flag( trait_flag_str_id( "PRED2" ) ) ) { msg = ( _( "Culling the weak is distasteful, but necessary." ) ); msgtype = m_neutral; } else { @@ -481,9 +481,9 @@ void mdeath::guilt( monster &z ) moraleMalus /= 10; if( g->u.has_trait( trait_PACIFIST ) ) { moraleMalus *= 5; - } else if( g->u.has_trait_flag( "PRED1" ) ) { + } else if( g->u.has_trait_flag( trait_flag_str_id( "PRED1" ) ) { moraleMalus /= 4; - } else if( g->u.has_trait_flag( "PRED2" ) ) { + } else if( g->u.has_trait_flag( trait_flag_str_id( "PRED2" ) ) { moraleMalus /= 5; } } diff --git a/src/mutation.cpp b/src/mutation.cpp index 03a1f30198d7..38a86f0d5174 100644 --- a/src/mutation.cpp +++ b/src/mutation.cpp @@ -103,7 +103,7 @@ bool Character::has_trait( const trait_id &b ) const return my_mutations.count( b ) || enchantment_cache->get_mutations().count( b ); } -bool Character::has_trait_flag( const std::string &b ) const +bool Character::has_trait_flag( const trait_flag_id &b ) const { for( const mutation_branch *mut : cached_mutations ) { if( mut->flags.count( b ) > 0 ) { From 3ba4f47c54b7f0ef7b1fc07ca2c537f56db02e2c Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 21:54:48 +0000 Subject: [PATCH 08/25] style(autofix.ci): automated formatting --- src/character.cpp | 5 +++-- src/magic.cpp | 3 ++- src/mondeath.cpp | 53 ++++++++++++++++++++++++----------------------- 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/character.cpp b/src/character.cpp index 9e950664411d..116743b12c5e 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -3488,8 +3488,9 @@ void Character::practice( const skill_id &id, int amount, int cap, bool suppress focus_pool -= chance_to_drop / 100; // Apex Predators don't think about much other than killing. // They don't lose Focus when practicing combat skills. - if( ( rng( 1, 100 ) <= ( chance_to_drop % 100 ) ) && ( !( has_trait_flag( trait_flag_str_id( "PRED4" ) ) && - skill.is_combat_skill() ) ) ) { + if( ( rng( 1, 100 ) <= ( chance_to_drop % 100 ) ) && + ( !( has_trait_flag( trait_flag_str_id( "PRED4" ) ) && + skill.is_combat_skill() ) ) ) { focus_pool--; } } diff --git a/src/magic.cpp b/src/magic.cpp index df38dfec12ae..5e21de7cd950 100644 --- a/src/magic.cpp +++ b/src/magic.cpp @@ -758,7 +758,8 @@ float spell::spell_fail( const Character &guy ) const return 1.0f; } float fail_chance = std::pow( ( effective_skill - 30.0f ) / 30.0f, 2 ); - if( has_flag( spell_flag::SOMATIC ) && !guy.has_trait_flag( trait_flag_str_id( "SUBTLE_SPELL" ) ) ) { + if( has_flag( spell_flag::SOMATIC ) && + !guy.has_trait_flag( trait_flag_str_id( "SUBTLE_SPELL" ) ) ) { // the first 20 points of encumbrance combined is ignored const int arms_encumb = std::max( 0, guy.encumb( bp_arm_l ) + guy.encumb( bp_arm_r ) - 20 ); // each encumbrance point beyond the "gray" color counts as half an additional fail % diff --git a/src/mondeath.cpp b/src/mondeath.cpp index 68b63d44a691..b826c11d1025 100644 --- a/src/mondeath.cpp +++ b/src/mondeath.cpp @@ -439,27 +439,28 @@ void mdeath::guilt( monster &z ) guilt_tresholds[25] = _( "You feel remorse for killing %s." ); if( g->u.has_trait( trait_PSYCHOPATH ) || g->u.has_trait_flag( trait_flag_str_id( "PRED3" ) || - g->u.has_trait_flag( trait_flag_str_id( "PRED4" ) || g->u.has_trait( trait_KILLER ) ) { - return; - } - if( rl_dist( z.pos(), g->u.pos() ) > MAX_GUILT_DISTANCE ) { - // Too far away, we can deal with it. - return; - } - if( z.get_hp() >= 0 ) { - // We probably didn't kill it - return; - } - if( kill_count >= maxKills ) { - // player no longer cares - if( kill_count == maxKills ) { + g->u.has_trait_flag( trait_flag_str_id( "PRED4" ) || g->u.has_trait( trait_KILLER ) ) { + return; +} +if( rl_dist( z.pos(), g->u.pos() ) > MAX_GUILT_DISTANCE ) { + // Too far away, we can deal with it. + return; +} +if( z.get_hp() >= 0 ) { + // We probably didn't kill it + return; +} +if( kill_count >= maxKills ) { + // player no longer cares + if( kill_count == maxKills ) { //~ Message after killing a lot of monsters which would normally affect the morale negatively. %s is the monster name, it will be pluralized with a number of 100. add_msg( m_good, _( "After killing so many bloody %s you no longer care " "about their deaths anymore." ), z.name( maxKills ) ); } return; - } else if( ( g->u.has_trait_flag( trait_flag_str_id( "PRED1" ) ) || ( g->u.has_trait_flag( trait_flag_str_id( "PRED2" ) ) ) { - msg = ( _( "Culling the weak is distasteful, but necessary." ) ); + } else if( ( g->u.has_trait_flag( trait_flag_str_id( "PRED1" ) ) || + ( g->u.has_trait_flag( trait_flag_str_id( "PRED2" ) ) ) { + msg = ( _( "Culling the weak is distasteful, but necessary." ) ); msgtype = m_neutral; } else { msgtype = m_bad; @@ -474,20 +475,20 @@ void mdeath::guilt( monster &z ) add_msg( msgtype, msg, z.name() ); int moraleMalus = -50 * ( 1.0 - ( static_cast( kill_count ) / maxKills ) ); - int maxMalus = -250 * ( 1.0 - ( static_cast( kill_count ) / maxKills ) ); - time_duration duration = 30_minutes * ( 1.0 - ( static_cast( kill_count ) / maxKills ) ); - time_duration decayDelay = 3_minutes * ( 1.0 - ( static_cast( kill_count ) / maxKills ) ); + int maxMalus = -250 * ( 1.0 - ( static_cast( kill_count ) / maxKills ) ); + time_duration duration = 30_minutes * ( 1.0 - ( static_cast( kill_count ) / maxKills ) ); + time_duration decayDelay = 3_minutes * ( 1.0 - ( static_cast( kill_count ) / maxKills ) ); if( z.type->in_species( ZOMBIE ) ) { - moraleMalus /= 10; - if( g->u.has_trait( trait_PACIFIST ) ) { + moraleMalus /= 10; + if( g->u.has_trait( trait_PACIFIST ) ) { moraleMalus *= 5; } else if( g->u.has_trait_flag( trait_flag_str_id( "PRED1" ) ) { - moraleMalus /= 4; - } else if( g->u.has_trait_flag( trait_flag_str_id( "PRED2" ) ) { - moraleMalus /= 5; - } + moraleMalus /= 4; + } else if( g->u.has_trait_flag( trait_flag_str_id( "PRED2" ) ) { + moraleMalus /= 5; } - g->u.add_morale( MORALE_KILLED_MONSTER, moraleMalus, maxMalus, duration, decayDelay ); +} +g->u.add_morale( MORALE_KILLED_MONSTER, moraleMalus, maxMalus, duration, decayDelay ); } From 91b516ed5c9b2707a38e5f0aa48a99484140a3f1 Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Mon, 11 Sep 2023 17:04:59 -0500 Subject: [PATCH 09/25] Update condition.cpp --- src/condition.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/condition.cpp b/src/condition.cpp index 5fe862e12e4c..ab953eec120b 100644 --- a/src/condition.cpp +++ b/src/condition.cpp @@ -134,7 +134,7 @@ void conditional_t::set_has_trait_flag( const JsonObject &jo, const std::stri if( trait_flag_to_check == "MUTATION_THRESHOLD" ) { return actor->crossed_threshold(); } - return actor->has_trait_flag( trait_flag_to_check ); + return actor->has_trait_flag( trait_flag_str_id( trait_flag_to_check ) ); }; } From 5208b394a0894330a8bf690dc0b0e706bbc8f95d Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Mon, 11 Sep 2023 18:33:47 -0500 Subject: [PATCH 10/25] And that should be the basics of the code --- src/character.cpp | 2 +- src/melee.cpp | 10 +++++----- src/mondeath.cpp | 12 ++++++------ src/mutation.cpp | 2 +- src/mutation.h | 2 +- src/mutation_data.cpp | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/character.cpp b/src/character.cpp index 116743b12c5e..b20c29d643cd 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -7801,7 +7801,7 @@ void Character::set_highest_cat_level() // Then use the map to set the category levels for( const std::pair &i : dependency_map ) { const mutation_branch &mdata = i.first.obj(); - if( !mdata.flags.count( "NON_THRESH" ) ) { + if( !mdata.flags.count( trait_flag_str_id( "NON_THRESH" ) ) ) { for( const std::string &cat : mdata.category ) { // Decay category strength based on how far it is from the current mutation mutation_category_level[cat] += 8 / static_cast( std::pow( 2, i.second ) ); diff --git a/src/melee.cpp b/src/melee.cpp index 1ea17223dacd..6484ee3c068c 100644 --- a/src/melee.cpp +++ b/src/melee.cpp @@ -966,12 +966,12 @@ void Character::roll_bash_damage( bool crit, damage_instance &di, bool average, if( left_empty || right_empty ) { float per_hand = 0.0f; for( const trait_id &mut : get_mutations() ) { - if( mut->flags.count( "NEED_ACTIVE_TO_MELEE" ) > 0 && !has_active_mutation( mut ) ) { + if( mut->flags.count( trait_flag_str_id( "NEED_ACTIVE_TO_MELEE" ) ) > 0 && !has_active_mutation( mut ) ) { continue; } float unarmed_bonus = 0.0f; const int bash_bonus = mut->bash_dmg_bonus; - if( mut->flags.count( "UNARMED_BONUS" ) > 0 && bash_bonus > 0 ) { + if( mut->flags.count( trait_flag_str_id( "UNARMED_BONUS" ) ) > 0 && bash_bonus > 0 ) { unarmed_bonus += std::min( get_skill_level( skill_unarmed ) / 2, 4 ); } per_hand += bash_bonus + unarmed_bonus; @@ -1054,12 +1054,12 @@ void Character::roll_cut_damage( bool crit, damage_instance &di, bool average, } for( const trait_id &mut : get_mutations() ) { - if( mut->flags.count( "NEED_ACTIVE_TO_MELEE" ) > 0 && !has_active_mutation( mut ) ) { + if( mut->flags.count( trait_flag_str_id( "NEED_ACTIVE_TO_MELEE" ) ) > 0 && !has_active_mutation( mut ) ) { continue; } float unarmed_bonus = 0.0f; const int cut_bonus = mut->cut_dmg_bonus; - if( mut->flags.count( "UNARMED_BONUS" ) > 0 && cut_bonus > 0 ) { + if( mut->flags.count( trait_flag_str_id( "UNARMED_BONUS" ) ) > 0 && cut_bonus > 0 ) { unarmed_bonus += std::min( get_skill_level( skill_unarmed ) / 2, 4 ); } per_hand += cut_bonus + unarmed_bonus; @@ -1126,7 +1126,7 @@ void Character::roll_stab_damage( bool crit, damage_instance &di, bool /*average for( const trait_id &mut : get_mutations() ) { int stab_bonus = mut->pierce_dmg_bonus; int unarmed_bonus = 0; - if( mut->flags.count( "UNARMED_BONUS" ) > 0 && stab_bonus > 0 ) { + if( mut->flags.count( trait_flag_str_id( "UNARMED_BONUS" ) ) > 0 && stab_bonus > 0 ) { unarmed_bonus = std::min( unarmed_skill / 2, 4 ); } diff --git a/src/mondeath.cpp b/src/mondeath.cpp index b826c11d1025..bb0bc3a6a9a7 100644 --- a/src/mondeath.cpp +++ b/src/mondeath.cpp @@ -438,8 +438,8 @@ void mdeath::guilt( monster &z ) guilt_tresholds[50] = _( "You regret killing %s." ); guilt_tresholds[25] = _( "You feel remorse for killing %s." ); - if( g->u.has_trait( trait_PSYCHOPATH ) || g->u.has_trait_flag( trait_flag_str_id( "PRED3" ) || - g->u.has_trait_flag( trait_flag_str_id( "PRED4" ) || g->u.has_trait( trait_KILLER ) ) { + if( g->u.has_trait( trait_PSYCHOPATH ) || g->u.has_trait_flag( trait_flag_str_id( "PRED3" ) ) || + g->u.has_trait_flag( trait_flag_str_id( "PRED4" ) ) || g->u.has_trait( trait_KILLER ) ) { return; } if( rl_dist( z.pos(), g->u.pos() ) > MAX_GUILT_DISTANCE ) { @@ -458,8 +458,8 @@ if( kill_count >= maxKills ) { "about their deaths anymore." ), z.name( maxKills ) ); } return; - } else if( ( g->u.has_trait_flag( trait_flag_str_id( "PRED1" ) ) || - ( g->u.has_trait_flag( trait_flag_str_id( "PRED2" ) ) ) { + + } else if( ( g->u.has_trait_flag( trait_flag_str_id( "PRED1" ) ) ) || ( g->u.has_trait_flag( trait_flag_str_id( "PRED1" ) ) ) ) { msg = ( _( "Culling the weak is distasteful, but necessary." ) ); msgtype = m_neutral; } else { @@ -482,9 +482,9 @@ if( kill_count >= maxKills ) { moraleMalus /= 10; if( g->u.has_trait( trait_PACIFIST ) ) { moraleMalus *= 5; - } else if( g->u.has_trait_flag( trait_flag_str_id( "PRED1" ) ) { + } else if( g->u.has_trait_flag( trait_flag_str_id( "PRED1" ) ) ) { moraleMalus /= 4; - } else if( g->u.has_trait_flag( trait_flag_str_id( "PRED2" ) ) { + } else if( g->u.has_trait_flag( trait_flag_str_id( "PRED2" ) ) ) { moraleMalus /= 5; } } diff --git a/src/mutation.cpp b/src/mutation.cpp index 38a86f0d5174..43c5595b58f2 100644 --- a/src/mutation.cpp +++ b/src/mutation.cpp @@ -106,7 +106,7 @@ bool Character::has_trait( const trait_id &b ) const bool Character::has_trait_flag( const trait_flag_id &b ) const { for( const mutation_branch *mut : cached_mutations ) { - if( mut->flags.count( b ) > 0 ) { + if( mut->flags.count( trait_flag_str_id( b ) ) > 0 ) { return true; } } diff --git a/src/mutation.h b/src/mutation.h index 8e82983e2d7a..f0011e812055 100644 --- a/src/mutation.h +++ b/src/mutation.h @@ -263,7 +263,7 @@ struct mutation_branch { std::vector replacements; // Mutations that replace this one std::vector additions; // Mutations that add to this one std::vector category; // Mutation Categories - std::set flags; // Mutation flags + std::set flags; // Mutation flags std::map protection; // Mutation wet effects std::map encumbrance_always; // Mutation encumbrance that always applies // Mutation encumbrance that applies when covered with unfitting item diff --git a/src/mutation_data.cpp b/src/mutation_data.cpp index 9c95b97873e4..9fc35dfeced4 100644 --- a/src/mutation_data.cpp +++ b/src/mutation_data.cpp @@ -455,7 +455,7 @@ void mutation_branch::load( const JsonObject &jo, const std::string & ) optional( jo, was_loaded, "cancels", cancels, trait_reader{} ); optional( jo, was_loaded, "changes_to", replacements, trait_reader{} ); optional( jo, was_loaded, "leads_to", additions, trait_reader{} ); - optional( jo, was_loaded, "flags", flags, string_reader{} ); + optional( jo, was_loaded, "flags", flags, auto_flags_reader {}); optional( jo, was_loaded, "types", types, string_reader{} ); optional( jo, was_loaded, "enchantments", enchantments ); From 015da098599908c9cb02a25bfd2801744da102ef Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 23:34:39 +0000 Subject: [PATCH 11/25] style(autofix.ci): automated formatting --- src/melee.cpp | 6 +++-- src/mondeath.cpp | 53 ++++++++++++++++++++++--------------------- src/mutation_data.cpp | 2 +- 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/melee.cpp b/src/melee.cpp index 6484ee3c068c..31963740cab6 100644 --- a/src/melee.cpp +++ b/src/melee.cpp @@ -966,7 +966,8 @@ void Character::roll_bash_damage( bool crit, damage_instance &di, bool average, if( left_empty || right_empty ) { float per_hand = 0.0f; for( const trait_id &mut : get_mutations() ) { - if( mut->flags.count( trait_flag_str_id( "NEED_ACTIVE_TO_MELEE" ) ) > 0 && !has_active_mutation( mut ) ) { + if( mut->flags.count( trait_flag_str_id( "NEED_ACTIVE_TO_MELEE" ) ) > 0 && + !has_active_mutation( mut ) ) { continue; } float unarmed_bonus = 0.0f; @@ -1054,7 +1055,8 @@ void Character::roll_cut_damage( bool crit, damage_instance &di, bool average, } for( const trait_id &mut : get_mutations() ) { - if( mut->flags.count( trait_flag_str_id( "NEED_ACTIVE_TO_MELEE" ) ) > 0 && !has_active_mutation( mut ) ) { + if( mut->flags.count( trait_flag_str_id( "NEED_ACTIVE_TO_MELEE" ) ) > 0 && + !has_active_mutation( mut ) ) { continue; } float unarmed_bonus = 0.0f; diff --git a/src/mondeath.cpp b/src/mondeath.cpp index bb0bc3a6a9a7..142838fcad0f 100644 --- a/src/mondeath.cpp +++ b/src/mondeath.cpp @@ -439,28 +439,29 @@ void mdeath::guilt( monster &z ) guilt_tresholds[25] = _( "You feel remorse for killing %s." ); if( g->u.has_trait( trait_PSYCHOPATH ) || g->u.has_trait_flag( trait_flag_str_id( "PRED3" ) ) || - g->u.has_trait_flag( trait_flag_str_id( "PRED4" ) ) || g->u.has_trait( trait_KILLER ) ) { - return; -} -if( rl_dist( z.pos(), g->u.pos() ) > MAX_GUILT_DISTANCE ) { - // Too far away, we can deal with it. - return; -} -if( z.get_hp() >= 0 ) { - // We probably didn't kill it - return; -} -if( kill_count >= maxKills ) { - // player no longer cares - if( kill_count == maxKills ) { + g->u.has_trait_flag( trait_flag_str_id( "PRED4" ) ) || g->u.has_trait( trait_KILLER ) ) { + return; + } + if( rl_dist( z.pos(), g->u.pos() ) > MAX_GUILT_DISTANCE ) { + // Too far away, we can deal with it. + return; + } + if( z.get_hp() >= 0 ) { + // We probably didn't kill it + return; + } + if( kill_count >= maxKills ) { + // player no longer cares + if( kill_count == maxKills ) { //~ Message after killing a lot of monsters which would normally affect the morale negatively. %s is the monster name, it will be pluralized with a number of 100. add_msg( m_good, _( "After killing so many bloody %s you no longer care " "about their deaths anymore." ), z.name( maxKills ) ); } return; - } else if( ( g->u.has_trait_flag( trait_flag_str_id( "PRED1" ) ) ) || ( g->u.has_trait_flag( trait_flag_str_id( "PRED1" ) ) ) ) { - msg = ( _( "Culling the weak is distasteful, but necessary." ) ); + } else if( ( g->u.has_trait_flag( trait_flag_str_id( "PRED1" ) ) ) || + ( g->u.has_trait_flag( trait_flag_str_id( "PRED1" ) ) ) ) { + msg = ( _( "Culling the weak is distasteful, but necessary." ) ); msgtype = m_neutral; } else { msgtype = m_bad; @@ -475,20 +476,20 @@ if( kill_count >= maxKills ) { add_msg( msgtype, msg, z.name() ); int moraleMalus = -50 * ( 1.0 - ( static_cast( kill_count ) / maxKills ) ); - int maxMalus = -250 * ( 1.0 - ( static_cast( kill_count ) / maxKills ) ); - time_duration duration = 30_minutes * ( 1.0 - ( static_cast( kill_count ) / maxKills ) ); - time_duration decayDelay = 3_minutes * ( 1.0 - ( static_cast( kill_count ) / maxKills ) ); + int maxMalus = -250 * ( 1.0 - ( static_cast( kill_count ) / maxKills ) ); + time_duration duration = 30_minutes * ( 1.0 - ( static_cast( kill_count ) / maxKills ) ); + time_duration decayDelay = 3_minutes * ( 1.0 - ( static_cast( kill_count ) / maxKills ) ); if( z.type->in_species( ZOMBIE ) ) { - moraleMalus /= 10; - if( g->u.has_trait( trait_PACIFIST ) ) { + moraleMalus /= 10; + if( g->u.has_trait( trait_PACIFIST ) ) { moraleMalus *= 5; } else if( g->u.has_trait_flag( trait_flag_str_id( "PRED1" ) ) ) { - moraleMalus /= 4; - } else if( g->u.has_trait_flag( trait_flag_str_id( "PRED2" ) ) ) { - moraleMalus /= 5; + moraleMalus /= 4; + } else if( g->u.has_trait_flag( trait_flag_str_id( "PRED2" ) ) ) { + moraleMalus /= 5; + } } -} -g->u.add_morale( MORALE_KILLED_MONSTER, moraleMalus, maxMalus, duration, decayDelay ); + g->u.add_morale( MORALE_KILLED_MONSTER, moraleMalus, maxMalus, duration, decayDelay ); } diff --git a/src/mutation_data.cpp b/src/mutation_data.cpp index 9fc35dfeced4..deea24faccae 100644 --- a/src/mutation_data.cpp +++ b/src/mutation_data.cpp @@ -455,7 +455,7 @@ void mutation_branch::load( const JsonObject &jo, const std::string & ) optional( jo, was_loaded, "cancels", cancels, trait_reader{} ); optional( jo, was_loaded, "changes_to", replacements, trait_reader{} ); optional( jo, was_loaded, "leads_to", additions, trait_reader{} ); - optional( jo, was_loaded, "flags", flags, auto_flags_reader {}); + optional( jo, was_loaded, "flags", flags, auto_flags_reader {} ); optional( jo, was_loaded, "types", types, string_reader{} ); optional( jo, was_loaded, "enchantments", enchantments ); From 14bf363ce1c87456bd1a2d25eea13e27100b2aaf Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Mon, 11 Sep 2023 20:23:34 -0500 Subject: [PATCH 12/25] Start up the JSON work next --- data/json/flags.json | 6 ---- data/json/flags_mutation.json | 54 +++++++++++++++++++++++++++++++++++ src/flag_trait.cpp | 5 ---- 3 files changed, 54 insertions(+), 11 deletions(-) create mode 100644 data/json/flags_mutation.json diff --git a/data/json/flags.json b/data/json/flags.json index 99b5ffda108e..f76a71b5b3b3 100644 --- a/data/json/flags.json +++ b/data/json/flags.json @@ -1047,12 +1047,6 @@ "context": [ "SPELL" ], "//": "pain altering spells can't be resisted (like with the deadened trait)" }, - { - "id": "NON_THRESH", - "type": "json_flag", - "context": [ "mutation" ], - "//": "This mutation does not count toward thresholds at all." - }, { "id": "EFFECT_FEATHER_FALL", "context": [ ], diff --git a/data/json/flags_mutation.json b/data/json/flags_mutation.json new file mode 100644 index 000000000000..973f5e0b4475 --- /dev/null +++ b/data/json/flags_mutation.json @@ -0,0 +1,54 @@ +[ + { + "id": "CANNIBAL", + "type": "mutation_flag" + }, + { + "id": "NO_THIRST", + "type": "mutation_flag" + }, + { + "id": "NO_RADIATION", + "type": "mutation_flag" + }, + { + "id": "NON_THRESH", + "type": "mutation_flag" + }, + { + "id": "PSYCHOPATH", + "type": "mutation_flag" + }, + { + "id": "PRED1", + "type": "mutation_flag", + "conflicts": [ "PRED2", "PRED3", "PRED4" ] + }, + { + "id": "PRED2", + "type": "mutation_flag", + "conflicts": [ "PRED1", "PRED3", "PRED4" ] + }, + { + "id": "PRED3", + "type": "mutation_flag", + "conflicts": [ "PRED1", "PRED2", "PRED4" ] + }, + { + "id": "PRED4", + "type": "mutation_flag", + "conflicts": [ "PRED1", "PRED2", "PRED3" ] + }, + { + "id": "SAPIOVORE", + "type": "mutation_flag" + }, + { + "id": "SILENT_SPELL", + "type": "mutation_flag" + }, + { + "id": "SUBTLE_SPELL", + "type": "mutation_flag" + } +] diff --git a/src/flag_trait.cpp b/src/flag_trait.cpp index 148facfd6f5f..0d338a75c39a 100644 --- a/src/flag_trait.cpp +++ b/src/flag_trait.cpp @@ -75,11 +75,6 @@ const json_trait_flag &json_trait_flag::get( const std::string &id ) void json_trait_flag::load( const JsonObject &jo, const std::string & ) { - // Remember these for conversion of the other shit. - // optional( jo, was_loaded, "inherit", inherit_, true ); - // optional( jo, was_loaded, "craft_inherit", craft_inherit_, false ); - // optional( jo, was_loaded, "taste_mod", taste_mod_ ); - // jo.get_member( "context" ); optional( jo, was_loaded, "conflicts", conflicts_ ); optional( jo, was_loaded, "restriction", restriction_ ); } From e453011dc64411a881a756982e0893ef6a9b5987 Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Tue, 12 Sep 2023 00:08:13 -0500 Subject: [PATCH 13/25] Update flags_mutation.json --- data/json/flags_mutation.json | 69 +++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/data/json/flags_mutation.json b/data/json/flags_mutation.json index 973f5e0b4475..76ebd0780246 100644 --- a/data/json/flags_mutation.json +++ b/data/json/flags_mutation.json @@ -3,6 +3,71 @@ "id": "CANNIBAL", "type": "mutation_flag" }, + { + "id": "hair_black", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "hair_blond", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "hair_brown", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "hair_crewcut", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "hair_fro", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "hair_gray", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "hair_long", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "hair_medium", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "hair_mohawk", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "hair_red", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "hair_short", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "hair_white", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "mycus", + "//": "This trait flag is used in dialogue JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, { "id": "NO_THIRST", "type": "mutation_flag" @@ -50,5 +115,9 @@ { "id": "SUBTLE_SPELL", "type": "mutation_flag" + }, + { + "id": "UNARMED_BONUS", + "type": "mutation_flag" } ] From 023ac0e88373cf48af694b537d319d5a75887b75 Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Tue, 12 Sep 2023 00:27:58 -0500 Subject: [PATCH 14/25] Update JSON_FLAGS.md --- doc/JSON_FLAGS.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/doc/JSON_FLAGS.md b/doc/JSON_FLAGS.md index 719955c97bbc..acffeb3b7340 100644 --- a/doc/JSON_FLAGS.md +++ b/doc/JSON_FLAGS.md @@ -1249,10 +1249,25 @@ example, impale and scratch. ## Mutations -#### Flags +#### Mutation Flags + +Mutation flags use a different JSON type from other flags, see json/flags_mutation.json. Primary difference is that `conflicts` and `requires` are the only additional properties that can be added to them. + +The following show all trait flags that are currently used by the game's code. Trait flags must also be defined in JSON if they are to be used in NPC dialogue conditions. +- `CANNIBAL` No morale penalty from butchery human corpses, skips warning you about human meat. NOTE: this only skips the warning, the actual morale effects of eating human flesh still require one of the relevant traits. Custom traits with this flag will skip the warning and suffer the morale penalty. +- `NEED_ACTIVE_TO_MELEE` A mutation with this flag will only provide unarmed bonuses if it's been toggled on. - `NO_RADIATION` This mutation grants immunity to radiations. - `NO_THIRST` Your thirst is not modified by food or drinks. +- `NON_THRESH` Mutations with this flag will not count towards the mutation strength (and thus ability to breach a mutation threshold) of any categories it counts as belonging to. +- `PRED1` Reduces morale impact of enzlaving zombie corpses, reduces morale impact of killing monsters with the `GUILT` flag. +- `PRED2` Increases EXP gain from combat, negates skill rust of combat skills (if skill rust is enabled), reduces morale impact of enzlaving zombie corpses, reduces morale impact of killing monsters with the `GUILT` flag. +- `PRED3` Increases EXP gain from combat, negates skill rust of combat skills (if skill rust is enabled), increases tolerance for enzlaving zombies while already depressed, negates morale impact of killing monsters with the `GUILT` flag. +- `PRED4` Increases EXP gain from combat, prevents EXP gain from combat from affecting focus, negates skill rust of combat skills (if skill rust is enabled), negates morale impact of enzlaving zombie corpses, increases tolerance for enzlaving zombies while already depressed, negates morale impact of killing monsters with the `GUILT` flag. +- `PSYCHOPATH` No morale penalty from butchering human corpses. +- `SAPIVORE` No morale penalty from butcheing human corpses. +- `SILENT_SPELL` Negates the negative impact of mouth encumbrance on spells with the `VERBAL` flag. +- `SUBTLE_SPELL` Negates the negative impact of arm encumbrance on spells with the `SOMATIC` flag. - `UNARMED_BONUS` You get a bonus to unarmed bash and cut damage equal to unarmed_skill/2 up to 4. ### Categories From c58bb3c0d5996cd0d6db52aec424f18d38ac869e Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Tue, 12 Sep 2023 05:29:04 +0000 Subject: [PATCH 15/25] style(autofix.ci): automated formatting --- doc/JSON_FLAGS.md | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/doc/JSON_FLAGS.md b/doc/JSON_FLAGS.md index acffeb3b7340..4f9228d60af6 100644 --- a/doc/JSON_FLAGS.md +++ b/doc/JSON_FLAGS.md @@ -1251,19 +1251,35 @@ example, impale and scratch. #### Mutation Flags -Mutation flags use a different JSON type from other flags, see json/flags_mutation.json. Primary difference is that `conflicts` and `requires` are the only additional properties that can be added to them. - -The following show all trait flags that are currently used by the game's code. Trait flags must also be defined in JSON if they are to be used in NPC dialogue conditions. - -- `CANNIBAL` No morale penalty from butchery human corpses, skips warning you about human meat. NOTE: this only skips the warning, the actual morale effects of eating human flesh still require one of the relevant traits. Custom traits with this flag will skip the warning and suffer the morale penalty. -- `NEED_ACTIVE_TO_MELEE` A mutation with this flag will only provide unarmed bonuses if it's been toggled on. +Mutation flags use a different JSON type from other flags, see json/flags_mutation.json. Primary +difference is that `conflicts` and `requires` are the only additional properties that can be added +to them. + +The following show all trait flags that are currently used by the game's code. Trait flags must also +be defined in JSON if they are to be used in NPC dialogue conditions. + +- `CANNIBAL` No morale penalty from butchery human corpses, skips warning you about human meat. + NOTE: this only skips the warning, the actual morale effects of eating human flesh still require + one of the relevant traits. Custom traits with this flag will skip the warning and suffer the + morale penalty. +- `NEED_ACTIVE_TO_MELEE` A mutation with this flag will only provide unarmed bonuses if it's been + toggled on. - `NO_RADIATION` This mutation grants immunity to radiations. - `NO_THIRST` Your thirst is not modified by food or drinks. -- `NON_THRESH` Mutations with this flag will not count towards the mutation strength (and thus ability to breach a mutation threshold) of any categories it counts as belonging to. -- `PRED1` Reduces morale impact of enzlaving zombie corpses, reduces morale impact of killing monsters with the `GUILT` flag. -- `PRED2` Increases EXP gain from combat, negates skill rust of combat skills (if skill rust is enabled), reduces morale impact of enzlaving zombie corpses, reduces morale impact of killing monsters with the `GUILT` flag. -- `PRED3` Increases EXP gain from combat, negates skill rust of combat skills (if skill rust is enabled), increases tolerance for enzlaving zombies while already depressed, negates morale impact of killing monsters with the `GUILT` flag. -- `PRED4` Increases EXP gain from combat, prevents EXP gain from combat from affecting focus, negates skill rust of combat skills (if skill rust is enabled), negates morale impact of enzlaving zombie corpses, increases tolerance for enzlaving zombies while already depressed, negates morale impact of killing monsters with the `GUILT` flag. +- `NON_THRESH` Mutations with this flag will not count towards the mutation strength (and thus + ability to breach a mutation threshold) of any categories it counts as belonging to. +- `PRED1` Reduces morale impact of enzlaving zombie corpses, reduces morale impact of killing + monsters with the `GUILT` flag. +- `PRED2` Increases EXP gain from combat, negates skill rust of combat skills (if skill rust is + enabled), reduces morale impact of enzlaving zombie corpses, reduces morale impact of killing + monsters with the `GUILT` flag. +- `PRED3` Increases EXP gain from combat, negates skill rust of combat skills (if skill rust is + enabled), increases tolerance for enzlaving zombies while already depressed, negates morale impact + of killing monsters with the `GUILT` flag. +- `PRED4` Increases EXP gain from combat, prevents EXP gain from combat from affecting focus, + negates skill rust of combat skills (if skill rust is enabled), negates morale impact of enzlaving + zombie corpses, increases tolerance for enzlaving zombies while already depressed, negates morale + impact of killing monsters with the `GUILT` flag. - `PSYCHOPATH` No morale penalty from butchering human corpses. - `SAPIVORE` No morale penalty from butcheing human corpses. - `SILENT_SPELL` Negates the negative impact of mouth encumbrance on spells with the `VERBAL` flag. From 1190097c687e39d76165126f80bd3b010e26814e Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Tue, 12 Sep 2023 00:38:14 -0500 Subject: [PATCH 16/25] Update flags_mutation.json --- data/json/flags_mutation.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/data/json/flags_mutation.json b/data/json/flags_mutation.json index 76ebd0780246..9461c625ac41 100644 --- a/data/json/flags_mutation.json +++ b/data/json/flags_mutation.json @@ -1,4 +1,9 @@ [ + { + "id": "BG_SURVIVAL_STORY", + "//": "This trait flag is used in dialogue JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, { "id": "CANNIBAL", "type": "mutation_flag" From f6310b93b0954234f648ad9c634355cbba76ab2f Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Thu, 21 Sep 2023 17:38:38 -0500 Subject: [PATCH 17/25] Update string_id_null_ids.cpp --- src/string_id_null_ids.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/string_id_null_ids.cpp b/src/string_id_null_ids.cpp index f58922822d49..f272078e8bd4 100644 --- a/src/string_id_null_ids.cpp +++ b/src/string_id_null_ids.cpp @@ -32,6 +32,7 @@ MAKE_NULL_ID( recipe, "null" ) MAKE_NULL_ID( translation, "null" ) MAKE_NULL_ID( Item_group, "" ) MAKE_NULL_ID( morale_type_data, "" ) +MAKE_NULL_ID( json_trait_flag, "null" ) #define MAKE_NULL_ID2( type, ... ) \ struct type; \ From d6f9d1c296e1c653bc5e7d3b087464394d71c739 Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Thu, 21 Sep 2023 17:42:03 -0500 Subject: [PATCH 18/25] Apply suggestions from code review Co-authored-by: Olanti --- src/flag_trait.cpp | 2 -- src/flag_trait.h | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/flag_trait.cpp b/src/flag_trait.cpp index 0d338a75c39a..262c795c73a7 100644 --- a/src/flag_trait.cpp +++ b/src/flag_trait.cpp @@ -6,8 +6,6 @@ #include "type_id.h" #include "generic_factory.h" -const trait_flag_str_id trait_flag_NULL = trait_flag_str_id( "null" ); // intentionally invalid flag - namespace { generic_factory json_trait_flags_all( "json_trait_flags" ); diff --git a/src/flag_trait.h b/src/flag_trait.h index 8ce569f8e273..3176a3f0058d 100644 --- a/src/flag_trait.h +++ b/src/flag_trait.h @@ -9,8 +9,6 @@ #include "type_id.h" class JsonObject; -extern const trait_flag_str_id trait_flag_NULL; - class json_trait_flag { friend class DynamicDataLoader; @@ -18,7 +16,7 @@ class json_trait_flag public: // used by generic_factory - trait_flag_str_id id = trait_flag_NULL; + trait_flag_str_id id = json_trait_flag::NULL_ID(); bool was_loaded = false; json_trait_flag() = default; From dcec706f27a6315eb6bc2a691cfe5b22d8fb1794 Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Thu, 21 Sep 2023 18:37:40 -0500 Subject: [PATCH 19/25] Do some of the suggested things --- data/json/flags_mutation.json | 4 ++++ src/character.h | 2 +- src/consumption.cpp | 4 +++- src/flag_trait.cpp | 1 - src/flag_trait.h | 6 ++---- src/mutation.cpp | 4 ++-- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/data/json/flags_mutation.json b/data/json/flags_mutation.json index 9461c625ac41..1f842fee11ad 100644 --- a/data/json/flags_mutation.json +++ b/data/json/flags_mutation.json @@ -73,6 +73,10 @@ "//": "This trait flag is used in dialogue JSON, with no hardcode usage at present.", "type": "mutation_flag" }, + { + "id": "NEED_ACTIVE_TO_MELEE", + "type": "mutation_flag" + }, { "id": "NO_THIRST", "type": "mutation_flag" diff --git a/src/character.h b/src/character.h index d48b461d6cab..6c9351347beb 100644 --- a/src/character.h +++ b/src/character.h @@ -703,7 +703,7 @@ class Character : public Creature, public visitable /** Returns true if the player has the entered starting trait */ bool has_base_trait( const trait_id &b ) const; /** Returns true if player has a trait with a flag */ - bool has_trait_flag( const trait_flag_id &b ) const; + bool has_trait_flag( const trait_flag_str_id &b ) const; /** Returns true if character has a trait which cancels the entered trait. */ bool has_opposite_trait( const trait_id &flag ) const; diff --git a/src/consumption.cpp b/src/consumption.cpp index 979e3ea7bb50..285a7ba6d40b 100644 --- a/src/consumption.cpp +++ b/src/consumption.cpp @@ -118,6 +118,8 @@ static const trait_id trait_THRESH_URSINE( "THRESH_URSINE" ); static const trait_id trait_VEGETARIAN( "VEGETARIAN" ); static const trait_id trait_WATERSLEEP( "WATERSLEEP" ); +static const trait_flag_str_id trait_flag_CANNIBAL( "CANNIBAL" ); + static const std::string flag_HIDDEN_HALLU( "HIDDEN_HALLU" ); static const std::string flag_ALLERGEN_EGG( "ALLERGEN_EGG" ); static const std::string flag_ALLERGEN_FRUIT( "ALLERGEN_FRUIT" ); @@ -755,7 +757,7 @@ ret_val Character::will_eat( const item &food, bool interactive ) } const bool carnivore = has_trait( trait_CARNIVORE ); - if( food.has_flag( flag_CANNIBALISM ) && !has_trait_flag( trait_flag_str_id( "CANNIBAL" ) ) ) { + if( food.has_flag( flag_CANNIBALISM ) && !has_trait_flag( trait_flag_CANNIBAL ) ) { add_consequence( _( "The thought of eating human flesh makes you feel sick." ), edible_rating::cannibalism ); } diff --git a/src/flag_trait.cpp b/src/flag_trait.cpp index 262c795c73a7..fd4c2049db60 100644 --- a/src/flag_trait.cpp +++ b/src/flag_trait.cpp @@ -74,7 +74,6 @@ const json_trait_flag &json_trait_flag::get( const std::string &id ) void json_trait_flag::load( const JsonObject &jo, const std::string & ) { optional( jo, was_loaded, "conflicts", conflicts_ ); - optional( jo, was_loaded, "restriction", restriction_ ); } void json_trait_flag::check_consistency() diff --git a/src/flag_trait.h b/src/flag_trait.h index 3176a3f0058d..32dfe2dbfb5d 100644 --- a/src/flag_trait.h +++ b/src/flag_trait.h @@ -16,7 +16,7 @@ class json_trait_flag public: // used by generic_factory - trait_flag_str_id id = json_trait_flag::NULL_ID(); + trait_flag_str_id id = trait_flag_str_id::NULL_ID(); bool was_loaded = false; json_trait_flag() = default; @@ -35,9 +35,7 @@ class json_trait_flag static const std::vector &get_all(); private: - translation info_; - translation restriction_; - std::set conflicts_; + std::set conflicts_; /** Load flag definition from JSON */ void load( const JsonObject &jo, const std::string &src ); diff --git a/src/mutation.cpp b/src/mutation.cpp index 43c5595b58f2..a9d044dd5943 100644 --- a/src/mutation.cpp +++ b/src/mutation.cpp @@ -103,10 +103,10 @@ bool Character::has_trait( const trait_id &b ) const return my_mutations.count( b ) || enchantment_cache->get_mutations().count( b ); } -bool Character::has_trait_flag( const trait_flag_id &b ) const +bool Character::has_trait_flag( const trait_flag_str_id &b ) const { for( const mutation_branch *mut : cached_mutations ) { - if( mut->flags.count( trait_flag_str_id( b ) ) > 0 ) { + if( mut->flags.count( b ) > 0 ) { return true; } } From 0ec493b9615689c12e379e5e5574e9aa53bd996f Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Sat, 23 Sep 2023 13:20:49 -0500 Subject: [PATCH 20/25] Work on part of the requests --- data/json/flags_mutation.json | 4 ++++ src/condition.cpp | 13 +++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/data/json/flags_mutation.json b/data/json/flags_mutation.json index 1f842fee11ad..4860e688bc99 100644 --- a/data/json/flags_mutation.json +++ b/data/json/flags_mutation.json @@ -73,6 +73,10 @@ "//": "This trait flag is used in dialogue JSON, with no hardcode usage at present.", "type": "mutation_flag" }, + { + "id": "MUTATION_THRESHOLD", + "type": "mutation_flag" + }, { "id": "NEED_ACTIVE_TO_MELEE", "type": "mutation_flag" diff --git a/src/condition.cpp b/src/condition.cpp index 7316dd673306..b5b94e7cd347 100644 --- a/src/condition.cpp +++ b/src/condition.cpp @@ -126,16 +126,21 @@ template void conditional_t::set_has_trait_flag( const JsonObject &jo, const std::string &member, bool is_npc ) { - const std::string &trait_flag_to_check = jo.get_string( member ); - condition = [trait_flag_to_check, is_npc]( const T & d ) { + const std::string &raw = jo.get_string( member ); + const trait_flag_str_id trait_flag_to_check( raw ); + if( !trait_flag_to_check.is_valid() ) { + jo.show_warning( string_format( "Invalid trait flag %s", raw ), member ); + } + const bool check_threshold = trait_flag_to_check == trait_flag_str_id( "MUTATION_THRESHOLD" ); + condition = [trait_flag_to_check, check_threshold, is_npc]( const T & d ) { player *actor = d.alpha; if( is_npc ) { actor = dynamic_cast( d.beta ); } - if( trait_flag_to_check == "MUTATION_THRESHOLD" ) { + if( check_threshold ) { return actor->crossed_threshold(); } - return actor->has_trait_flag( trait_flag_str_id( trait_flag_to_check ) ); + return actor->has_trait_flag( trait_flag_to_check ); }; } From 0b9af0e9998cff7d38e723f75ad35c8681d8fdd1 Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Sat, 23 Sep 2023 13:45:56 -0500 Subject: [PATCH 21/25] Add the validation thingy --- data/json/obsoletion/mutations.json | 1 - src/mutation_data.cpp | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/data/json/obsoletion/mutations.json b/data/json/obsoletion/mutations.json index 94c1dbf5ae74..12c5621cc777 100644 --- a/data/json/obsoletion/mutations.json +++ b/data/json/obsoletion/mutations.json @@ -130,7 +130,6 @@ "points": 2, "description": "Your body is simply immune to diseases. You will never catch an ambient disease.", "prereqs": [ "DISRESISTANT" ], - "flags": [ "NO_DISEASE" ], "valid": false }, { diff --git a/src/mutation_data.cpp b/src/mutation_data.cpp index deea24faccae..37af2f708f7e 100644 --- a/src/mutation_data.cpp +++ b/src/mutation_data.cpp @@ -609,6 +609,11 @@ void mutation_branch::check_consistency() for( const enchantment_id &ench : mdata.enchantments ) { ench->check(); } + for( const auto &flag : mdata.flags ) { + if( !flag.is_valid() ) { + debugmsg( "mutation %s refers to undefined mutation flag %s", mid, flag ); + } + } ::check_consistency( mdata.prereqs, mid, "prereq" ); ::check_consistency( mdata.prereqs2, mid, "prereqs2" ); ::check_consistency( mdata.threshreq, mid, "threshreq" ); From 00bb0aa6d9a07fc2c81af15946f06ba30a71318b Mon Sep 17 00:00:00 2001 From: scarf Date: Mon, 25 Sep 2023 21:08:45 +0900 Subject: [PATCH 22/25] refactor: extract `trait_flag_str_id` for `PRED` --- src/character.cpp | 19 ++++++++++++------- src/iuse_actor.cpp | 13 +++++++++---- src/mondeath.cpp | 17 +++++++++++------ 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/character.cpp b/src/character.cpp index bbe57041ad05..691886c3fd10 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -378,6 +378,11 @@ static const flag_str_id flag_BIONIC_ARMOR_INTERFACE( "BIONIC_ARMOR_INTERFACE" ) static const mtype_id mon_player_blob( "mon_player_blob" ); static const mtype_id mon_shadow_snake( "mon_shadow_snake" ); +static const trait_flag_str_id trait_flag_PRED1( "PRED1" ); +static const trait_flag_str_id trait_flag_PRED2( "PRED2" ); +static const trait_flag_str_id trait_flag_PRED3( "PRED3" ); +static const trait_flag_str_id trait_flag_PRED4( "PRED4" ); + namespace io { @@ -3446,16 +3451,16 @@ void Character::practice( const skill_id &id, int amount, int cap, bool suppress amount = 0; } } - if( has_trait_flag( trait_flag_str_id( "PRED2" ) ) && skill.is_combat_skill() ) { + if( has_trait_flag( trait_flag_PRED2 ) && skill.is_combat_skill() ) { if( one_in( 3 ) ) { amount *= 2; } } - if( has_trait_flag( trait_flag_str_id( "PRED3" ) ) && skill.is_combat_skill() ) { + if( has_trait_flag( trait_flag_PRED3 ) && skill.is_combat_skill() ) { amount *= 2; } - if( has_trait_flag( trait_flag_str_id( "PRED4" ) ) && skill.is_combat_skill() ) { + if( has_trait_flag( trait_flag_PRED4 ) && skill.is_combat_skill() ) { amount *= 3; } @@ -3490,7 +3495,7 @@ void Character::practice( const skill_id &id, int amount, int cap, bool suppress // Apex Predators don't think about much other than killing. // They don't lose Focus when practicing combat skills. if( ( rng( 1, 100 ) <= ( chance_to_drop % 100 ) ) && - ( !( has_trait_flag( trait_flag_str_id( "PRED4" ) ) && + ( !( has_trait_flag( trait_flag_PRED4 ) && skill.is_combat_skill() ) ) ) { focus_pool--; } @@ -3606,9 +3611,9 @@ void Character::do_skill_rust() SkillLevel &skill_level_obj = pair.second; if( aSkill.is_combat_skill() && - ( ( has_trait_flag( trait_flag_str_id( "PRED2" ) ) && calendar::once_every( 8_hours ) ) || - ( has_trait_flag( trait_flag_str_id( "PRED3" ) ) && calendar::once_every( 4_hours ) ) || - ( has_trait_flag( trait_flag_str_id( "PRED4" ) ) && calendar::once_every( 3_hours ) ) ) ) { + ( ( has_trait_flag( trait_flag_PRED2 ) && calendar::once_every( 8_hours ) ) || + ( has_trait_flag( trait_flag_PRED3 ) && calendar::once_every( 4_hours ) ) || + ( has_trait_flag( trait_flag_PRED4 ) && calendar::once_every( 3_hours ) ) ) ) { // Their brain is optimized to remember this if( one_in( 13 ) ) { // They've already passed the roll to avoid rust at diff --git a/src/iuse_actor.cpp b/src/iuse_actor.cpp index 6627f2dfe5e5..e7410146cdc3 100644 --- a/src/iuse_actor.cpp +++ b/src/iuse_actor.cpp @@ -152,6 +152,11 @@ static const std::string flag_UNDERSIZE( "UNDERSIZE" ); static const std::string flag_VARSIZE( "VARSIZE" ); static const std::string flag_POWERARMOR_MOD( "POWERARMOR_MOD" ); +static const trait_flag_str_id trait_flag_PRED1( "PRED1" ); +static const trait_flag_str_id trait_flag_PRED2( "PRED2" ); +static const trait_flag_str_id trait_flag_PRED3( "PRED3" ); +static const trait_flag_str_id trait_flag_PRED4( "PRED4" ); + class npc; std::unique_ptr iuse_transform::clone() const @@ -2091,9 +2096,9 @@ int enzlave_actor::use( player &p, item &it, bool t, const tripoint & ) const int tolerance_level = 9; if( p.has_trait( trait_PSYCHOPATH ) || p.has_trait( trait_SAPIOVORE ) ) { tolerance_level = 0; - } else if( p.has_trait_flag( trait_flag_str_id( "PRED4" ) ) ) { + } else if( p.has_trait_flag( trait_flag_PRED4 ) ) { tolerance_level = 5; - } else if( p.has_trait_flag( trait_flag_str_id( "PRED3" ) ) ) { + } else if( p.has_trait_flag( trait_flag_PRED3 ) ) { tolerance_level = 7; } @@ -2137,9 +2142,9 @@ int enzlave_actor::use( player &p, item &it, bool t, const tripoint & ) const if( p.has_trait( trait_PACIFIST ) ) { moraleMalus *= 5; maxMalus *= 3; - } else if( p.has_trait_flag( trait_flag_str_id( "PRED1" ) ) ) { + } else if( p.has_trait_flag( trait_flag_PRED1 ) ) { moraleMalus /= 4; - } else if( p.has_trait_flag( trait_flag_str_id( "PRED2" ) ) ) { + } else if( p.has_trait_flag( trait_flag_PRED2 ) ) { moraleMalus /= 5; } diff --git a/src/mondeath.cpp b/src/mondeath.cpp index 142838fcad0f..218602eb43ac 100644 --- a/src/mondeath.cpp +++ b/src/mondeath.cpp @@ -85,6 +85,11 @@ static const trait_id trait_KILLER( "KILLER" ); static const trait_id trait_PACIFIST( "PACIFIST" ); static const trait_id trait_PSYCHOPATH( "PSYCHOPATH" ); +static const trait_flag_str_id trait_flag_PRED1( "PRED1" ); +static const trait_flag_str_id trait_flag_PRED2( "PRED2" ); +static const trait_flag_str_id trait_flag_PRED3( "PRED3" ); +static const trait_flag_str_id trait_flag_PRED4( "PRED4" ); + void mdeath::normal( monster &z ) { if( z.no_corpse_quiet ) { @@ -438,8 +443,8 @@ void mdeath::guilt( monster &z ) guilt_tresholds[50] = _( "You regret killing %s." ); guilt_tresholds[25] = _( "You feel remorse for killing %s." ); - if( g->u.has_trait( trait_PSYCHOPATH ) || g->u.has_trait_flag( trait_flag_str_id( "PRED3" ) ) || - g->u.has_trait_flag( trait_flag_str_id( "PRED4" ) ) || g->u.has_trait( trait_KILLER ) ) { + if( g->u.has_trait( trait_PSYCHOPATH ) || g->u.has_trait_flag( trait_flag_PRED3 ) || + g->u.has_trait_flag( trait_flag_PRED4 ) || g->u.has_trait( trait_KILLER ) ) { return; } if( rl_dist( z.pos(), g->u.pos() ) > MAX_GUILT_DISTANCE ) { @@ -459,8 +464,8 @@ void mdeath::guilt( monster &z ) } return; - } else if( ( g->u.has_trait_flag( trait_flag_str_id( "PRED1" ) ) ) || - ( g->u.has_trait_flag( trait_flag_str_id( "PRED1" ) ) ) ) { + } else if( ( g->u.has_trait_flag( trait_flag_PRED1 ) ) || + ( g->u.has_trait_flag( trait_flag_PRED1 ) ) ) { msg = ( _( "Culling the weak is distasteful, but necessary." ) ); msgtype = m_neutral; } else { @@ -483,9 +488,9 @@ void mdeath::guilt( monster &z ) moraleMalus /= 10; if( g->u.has_trait( trait_PACIFIST ) ) { moraleMalus *= 5; - } else if( g->u.has_trait_flag( trait_flag_str_id( "PRED1" ) ) ) { + } else if( g->u.has_trait_flag( trait_flag_PRED1 ) ) { moraleMalus /= 4; - } else if( g->u.has_trait_flag( trait_flag_str_id( "PRED2" ) ) ) { + } else if( g->u.has_trait_flag( trait_flag_PRED2 ) ) { moraleMalus /= 5; } } From 9328f83c5d6c9abb81b5f9221f7f6486e0b4693f Mon Sep 17 00:00:00 2001 From: scarf Date: Mon, 25 Sep 2023 21:15:16 +0900 Subject: [PATCH 23/25] refactor: remove `conflicts` usage Co-authored-by: olanti-p --- data/json/flags_mutation.json | 12 ++++-------- src/flag_trait.cpp | 3 +-- src/flag_trait.h | 4 ++-- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/data/json/flags_mutation.json b/data/json/flags_mutation.json index 4860e688bc99..b2ec7e307c83 100644 --- a/data/json/flags_mutation.json +++ b/data/json/flags_mutation.json @@ -99,23 +99,19 @@ }, { "id": "PRED1", - "type": "mutation_flag", - "conflicts": [ "PRED2", "PRED3", "PRED4" ] + "type": "mutation_flag" }, { "id": "PRED2", - "type": "mutation_flag", - "conflicts": [ "PRED1", "PRED3", "PRED4" ] + "type": "mutation_flag" }, { "id": "PRED3", - "type": "mutation_flag", - "conflicts": [ "PRED1", "PRED2", "PRED4" ] + "type": "mutation_flag" }, { "id": "PRED4", - "type": "mutation_flag", - "conflicts": [ "PRED1", "PRED2", "PRED3" ] + "type": "mutation_flag" }, { "id": "SAPIOVORE", diff --git a/src/flag_trait.cpp b/src/flag_trait.cpp index fd4c2049db60..9824feab956b 100644 --- a/src/flag_trait.cpp +++ b/src/flag_trait.cpp @@ -71,9 +71,8 @@ const json_trait_flag &json_trait_flag::get( const std::string &id ) return f_id.is_valid() ? *f_id : null_value; } -void json_trait_flag::load( const JsonObject &jo, const std::string & ) +void json_trait_flag::load( const JsonObject &, const std::string & ) { - optional( jo, was_loaded, "conflicts", conflicts_ ); } void json_trait_flag::check_consistency() diff --git a/src/flag_trait.h b/src/flag_trait.h index 32dfe2dbfb5d..68cb479f6ef1 100644 --- a/src/flag_trait.h +++ b/src/flag_trait.h @@ -5,8 +5,8 @@ #include #include -#include "translations.h" #include "type_id.h" + class JsonObject; class json_trait_flag @@ -37,7 +37,7 @@ class json_trait_flag private: std::set conflicts_; - /** Load flag definition from JSON */ + /** Load flag definition from JSON (NO-OP) */ void load( const JsonObject &jo, const std::string &src ); /** Load all flags from JSON */ From 814327e3e5afd7a726cd1463c5dd9d2a103b53f1 Mon Sep 17 00:00:00 2001 From: scarf Date: Mon, 25 Sep 2023 21:25:00 +0900 Subject: [PATCH 24/25] refactor: extract other trait flag ids Co-authored-by: olanti-p --- src/character.cpp | 10 +++++++--- src/condition.cpp | 4 ++-- src/magic.cpp | 6 ++++-- src/melee.cpp | 13 ++++++++----- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/character.cpp b/src/character.cpp index 691886c3fd10..9d6b3c5debd7 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -383,6 +383,10 @@ static const trait_flag_str_id trait_flag_PRED2( "PRED2" ); static const trait_flag_str_id trait_flag_PRED3( "PRED3" ); static const trait_flag_str_id trait_flag_PRED4( "PRED4" ); +static const trait_flag_str_id flag_NO_THIRST( "NO_THIRST" ); +static const trait_flag_str_id flag_NO_RADIATION( "NO_RADIATION" ); +static const trait_flag_str_id flag_NON_THRESH( "NON_THRESH" ); + namespace io { @@ -4441,7 +4445,7 @@ std::pair Character::get_fatigue_description() const void Character::mod_thirst( int nthirst ) { - if( has_trait_flag( trait_flag_str_id( "NO_THIRST" ) ) ) { + if( has_trait_flag( flag_NO_THIRST ) ) { return; } set_thirst( std::max( -100, thirst + nthirst ) ); @@ -7087,7 +7091,7 @@ void Character::set_rad( int new_rad ) void Character::mod_rad( int mod ) { - if( has_trait_flag( trait_flag_str_id( "NO_RADIATION" ) ) ) { + if( has_trait_flag( flag_NO_RADIATION ) ) { return; } set_rad( std::max( 0, get_rad() + mod ) ); @@ -7813,7 +7817,7 @@ void Character::set_highest_cat_level() // Then use the map to set the category levels for( const std::pair &i : dependency_map ) { const mutation_branch &mdata = i.first.obj(); - if( !mdata.flags.count( trait_flag_str_id( "NON_THRESH" ) ) ) { + if( !mdata.flags.count( flag_NON_THRESH ) ) { for( const std::string &cat : mdata.category ) { // Decay category strength based on how far it is from the current mutation mutation_category_level[cat] += 8 / static_cast( std::pow( 2, i.second ) ); diff --git a/src/condition.cpp b/src/condition.cpp index b5b94e7cd347..dc0b64503bb7 100644 --- a/src/condition.cpp +++ b/src/condition.cpp @@ -46,7 +46,7 @@ class basecamp; class recipe; static const efftype_id effect_currently_busy( "currently_busy" ); - +static const trait_flag_str_id flag_MUTATION_THRESHOLD( "MUTATION_THRESHOLD" ); // throws an error on failure, so no need to return std::string get_talk_varname( const JsonObject &jo, const std::string &member, bool check_value ) { @@ -131,7 +131,7 @@ void conditional_t::set_has_trait_flag( const JsonObject &jo, const std::stri if( !trait_flag_to_check.is_valid() ) { jo.show_warning( string_format( "Invalid trait flag %s", raw ), member ); } - const bool check_threshold = trait_flag_to_check == trait_flag_str_id( "MUTATION_THRESHOLD" ); + const bool check_threshold = trait_flag_to_check == flag_MUTATION_THRESHOLD; condition = [trait_flag_to_check, check_threshold, is_npc]( const T & d ) { player *actor = d.alpha; if( is_npc ) { diff --git a/src/magic.cpp b/src/magic.cpp index 5e21de7cd950..172b9480cdb8 100644 --- a/src/magic.cpp +++ b/src/magic.cpp @@ -48,6 +48,8 @@ #include "units.h" static const trait_id trait_NONE( "NONE" ); +static const trait_flag_str_id trait_flag_SUBTLE_SPELL( "SUBTLE_SPELL" ); +static const trait_flag_str_id trait_flag_SILENT_SPELL( "SILENT_SPELL" ); namespace io { @@ -759,13 +761,13 @@ float spell::spell_fail( const Character &guy ) const } float fail_chance = std::pow( ( effective_skill - 30.0f ) / 30.0f, 2 ); if( has_flag( spell_flag::SOMATIC ) && - !guy.has_trait_flag( trait_flag_str_id( "SUBTLE_SPELL" ) ) ) { + !guy.has_trait_flag( trait_flag_SUBTLE_SPELL ) ) { // the first 20 points of encumbrance combined is ignored const int arms_encumb = std::max( 0, guy.encumb( bp_arm_l ) + guy.encumb( bp_arm_r ) - 20 ); // each encumbrance point beyond the "gray" color counts as half an additional fail % fail_chance += arms_encumb / 200.0f; } - if( has_flag( spell_flag::VERBAL ) && !guy.has_trait_flag( trait_flag_str_id( "SILENT_SPELL" ) ) ) { + if( has_flag( spell_flag::VERBAL ) && !guy.has_trait_flag( trait_flag_SILENT_SPELL ) ) { // a little bit of mouth encumbrance is allowed, but not much const int mouth_encumb = std::max( 0, guy.encumb( bp_mouth ) - 5 ); fail_chance += mouth_encumb / 100.0f; diff --git a/src/melee.cpp b/src/melee.cpp index 42504711f7ef..d4aab29e3949 100644 --- a/src/melee.cpp +++ b/src/melee.cpp @@ -113,6 +113,9 @@ static const trait_id trait_PROF_SKATER( "PROF_SKATER" ); static const trait_id trait_VINES2( "VINES2" ); static const trait_id trait_VINES3( "VINES3" ); +static const trait_flag_str_id trait_flag_NEED_ACTIVE_TO_MELEE( "NEED_ACTIVE_TO_MELEE" ); +static const trait_flag_str_id trait_flag_UNARMED_BONUS( "UNARMED_BONUS" ); + static const efftype_id effect_amigara( "amigara" ); static const species_id HUMAN( "HUMAN" ); @@ -966,13 +969,13 @@ void Character::roll_bash_damage( bool crit, damage_instance &di, bool average, if( left_empty || right_empty ) { float per_hand = 0.0f; for( const trait_id &mut : get_mutations() ) { - if( mut->flags.count( trait_flag_str_id( "NEED_ACTIVE_TO_MELEE" ) ) > 0 && + if( mut->flags.count( trait_flag_NEED_ACTIVE_TO_MELEE ) > 0 && !has_active_mutation( mut ) ) { continue; } float unarmed_bonus = 0.0f; const int bash_bonus = mut->bash_dmg_bonus; - if( mut->flags.count( trait_flag_str_id( "UNARMED_BONUS" ) ) > 0 && bash_bonus > 0 ) { + if( mut->flags.count( trait_flag_UNARMED_BONUS ) > 0 && bash_bonus > 0 ) { unarmed_bonus += std::min( get_skill_level( skill_unarmed ) / 2, 4 ); } per_hand += bash_bonus + unarmed_bonus; @@ -1055,13 +1058,13 @@ void Character::roll_cut_damage( bool crit, damage_instance &di, bool average, } for( const trait_id &mut : get_mutations() ) { - if( mut->flags.count( trait_flag_str_id( "NEED_ACTIVE_TO_MELEE" ) ) > 0 && + if( mut->flags.count( trait_flag_NEED_ACTIVE_TO_MELEE ) > 0 && !has_active_mutation( mut ) ) { continue; } float unarmed_bonus = 0.0f; const int cut_bonus = mut->cut_dmg_bonus; - if( mut->flags.count( trait_flag_str_id( "UNARMED_BONUS" ) ) > 0 && cut_bonus > 0 ) { + if( mut->flags.count( trait_flag_UNARMED_BONUS ) > 0 && cut_bonus > 0 ) { unarmed_bonus += std::min( get_skill_level( skill_unarmed ) / 2, 4 ); } per_hand += cut_bonus + unarmed_bonus; @@ -1128,7 +1131,7 @@ void Character::roll_stab_damage( bool crit, damage_instance &di, bool /*average for( const trait_id &mut : get_mutations() ) { int stab_bonus = mut->pierce_dmg_bonus; int unarmed_bonus = 0; - if( mut->flags.count( trait_flag_str_id( "UNARMED_BONUS" ) ) > 0 && stab_bonus > 0 ) { + if( mut->flags.count( trait_flag_UNARMED_BONUS ) > 0 && stab_bonus > 0 ) { unarmed_bonus = std::min( unarmed_skill / 2, 4 ); } From e84051185111807be03a66cfde036a4e7b026bd7 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Mon, 25 Sep 2023 12:32:22 +0000 Subject: [PATCH 25/25] style(autofix.ci): automated formatting --- src/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e1f15113d78d..843e9fef3317 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -33,7 +33,6 @@ add_custom_command( ${CMAKE_SOURCE_DIR}/src/version.cmake WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - # Build tiles version if requested if (TILES) setup_library(cataclysm-tiles-common)