From 8bf2018ebd71280a1547260a16395aaa8ff5fe4d Mon Sep 17 00:00:00 2001 From: Joshua Chin Date: Thu, 2 Sep 2021 20:58:17 -0400 Subject: [PATCH 01/16] Modify load_damage_array to specify default --- src/damage.cpp | 5 +++-- src/damage.h | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/damage.cpp b/src/damage.cpp index 61e89aa443f6c..2b2fdfbe8a8c6 100644 --- a/src/damage.cpp +++ b/src/damage.cpp @@ -430,10 +430,11 @@ damage_instance load_damage_instance_inherit( const JsonArray &jarr, const damag return di; } -std::array( damage_type::NUM )> load_damage_array( const JsonObject &jo ) +std::array( damage_type::NUM )> load_damage_array( const JsonObject &jo, + float default ) { std::array( damage_type::NUM )> ret; - float init_val = jo.get_float( "all", 0.0f ); + float init_val = jo.get_float( "all", default ); float phys = jo.get_float( "physical", init_val ); ret[ static_cast( damage_type::BASH ) ] = jo.get_float( "bash", phys ); diff --git a/src/damage.h b/src/damage.h index 53236657eba49..3ab3974a90e4d 100644 --- a/src/damage.h +++ b/src/damage.h @@ -151,6 +151,7 @@ resistances load_resistances_instance( const JsonObject &jo ); // Returns damage or resistance data // Handles some shorthands -std::array( damage_type::NUM )> load_damage_array( const JsonObject &jo ); +std::array( damage_type::NUM )> load_damage_array( const JsonObject &jo, + float default = 0.0f ); #endif // CATA_SRC_DAMAGE_H From aee0907e1a93dbe4523eb78260fcf7b8674f246b Mon Sep 17 00:00:00 2001 From: Joshua Chin Date: Thu, 2 Sep 2021 21:06:12 -0400 Subject: [PATCH 02/16] Add weakpoint.h --- src/weakpoint.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 src/weakpoint.h diff --git a/src/weakpoint.h b/src/weakpoint.h new file mode 100644 index 0000000000000..91e533f79c729 --- /dev/null +++ b/src/weakpoint.h @@ -0,0 +1,44 @@ +#pragma once +#ifndef CATA_SRC_WEAKPOINT_H +#define CATA_SRC_WEAKPOINT_H + +#include +#include +#include + +#include "creature.h" +#include "damage.h" + +class JsonArray; +class JsonObject; + +struct weakpoint { + // Name of the weakpoint. + std::string name = ""; + // Probability of hitting the weakpoint. Can be increased by skill. + float coverage = 0; + // Multiplier for existing armor values. Defaults to 1. + std::array( damage_type::NUM )> armor_mult; + // Constant offset for multiplied armor values. Defaults to 0. + std::array( damage_type::NUM )> armor_offset; + + weakpoint(); + // Apply the armor multipliers and offsets to a set of resistances. + void apply_to(resistances& resistances); + void load( const JsonObject &obj ); +}; + +struct weakpoints { + // List of weakpoints. Each weakpoint should have a unique name. + std::vector weakpoints; + + // Selects a weakpoint to hit. + weakpoint &select_weakpoint( Creature */*source*/ ) const; + + weakpoints(); + // Adds a weakpoint, possibly overriding a weakpoint with the same name. + void add_weakpoint(weakpoint* weakpoint); + // Removes all weakpoints with the given name. + void remove_weakpoint(std::string weakpoint_name); + void load( const JsonArray &obj ); +}; From 84b59623371b9c45ec53650f3efb60bf89d6f8b5 Mon Sep 17 00:00:00 2001 From: Joshua Chin Date: Thu, 2 Sep 2021 21:42:36 -0400 Subject: [PATCH 03/16] Implement weakpoint.cpp --- src/weakpoint.cpp | 72 +++++++++++++++++++++++++++++++++++++++++++++++ src/weakpoint.h | 24 ++++++++-------- 2 files changed, 85 insertions(+), 11 deletions(-) create mode 100644 src/weakpoint.cpp diff --git a/src/weakpoint.cpp b/src/weakpoint.cpp new file mode 100644 index 0000000000000..9e78f5e0cebd3 --- /dev/null +++ b/src/weakpoint.cpp @@ -0,0 +1,72 @@ +#include "weakpoint.h" + +#include +#include + +#include "assign.h" +#include "creature.h" +#include "damage.h" +#include "rng.h" + +class JsonArray; +class JsonObject; + +weakpoint::weakpoint() +{ + // arrays must be filled manually to avoid UB. + armor_mult.fill( 1.0f ); + armor_offset.fill( 0.0f ); +} + +void weakpoint::load( const JsonObject &obj ) +{ + assign( jo, "id", id ); + assign( jo, "name", name ); + assign( jo, "coverage", 0.0f, 1.0f ); + if( jo.has_object( "armor_mult" ) ) { + armor_mult = load_damage_array( jo.get_object( "armor_mult" ), 1.0f ); + } + if( jo.has_object( "armor_offset" ) ) { + armor_mult = load_damage_array( jo.get_object( "armor_offset" ), 0.0f ); + } + // Set the ID to the name, if not provided. + if( id.empty() ) { + id = name; + } +} + +void weakpoint::apply_to( resistances &resistances ) +{ + for( damage_type d = damage_type::None; d < damage_type::NUM; ++d ) { + int idx = static_cast( d ); + float r = resistances.get_resist( d ); + resistances.set_resist( armor_mult[idx] * r + armor_offset[idx] ); + } +} + +float hit_chance( Creature */*source*/ ) const +{ + return coverage; +} + +weakpoint *weakpoints::select_weakpoint( Creature *source ) const +{ + float idx = rng_float( 0.0f, 1.0f ); + for( const weakpoint &weakpoint : weakpoints ) { + float hit_chance = weakpoint.hit_chance( source ); + if( hit_chance <= idx ) { + return &weakpoint; + } + idx -= hit_chance; + } + return &default_weakpoint; +} + +void weakpoints::load( const JsonArray &ja ) +{ + while( ja.has_more() ) { + weakpoint tmp; + tmp.load( ja.next_object ); + weakpoints.push_back( std::move( tmp ) ); + } +} diff --git a/src/weakpoint.h b/src/weakpoint.h index 91e533f79c729..3d0cdc5cf3d64 100644 --- a/src/weakpoint.h +++ b/src/weakpoint.h @@ -13,10 +13,12 @@ class JsonArray; class JsonObject; struct weakpoint { - // Name of the weakpoint. + // ID of the weakpoint. Equal to the name, if not provided. + std::string id = ""; + // Name of the weakpoint. Can be empty. std::string name = ""; - // Probability of hitting the weakpoint. Can be increased by skill. - float coverage = 0; + // Base probability of hitting the weakpoint. Can be increased by skill. + float coverage = 1.0f; // Multiplier for existing armor values. Defaults to 1. std::array( damage_type::NUM )> armor_mult; // Constant offset for multiplied armor values. Defaults to 0. @@ -24,21 +26,21 @@ struct weakpoint { weakpoint(); // Apply the armor multipliers and offsets to a set of resistances. - void apply_to(resistances& resistances); + void apply_to( resistances &resistances ) const; + // Return the change of the creature hitting the weakpoint. + float hit_chance( Creature */*source*/ ) const; void load( const JsonObject &obj ); }; struct weakpoints { - // List of weakpoints. Each weakpoint should have a unique name. + // List of weakpoints. Each weakpoint should have a unique id. std::vector weakpoints; + // Default weakpoint to return. + weakpoint default_weakpoint; // Selects a weakpoint to hit. - weakpoint &select_weakpoint( Creature */*source*/ ) const; + weakpoint *select_weakpoint( Creature *source ) const; weakpoints(); - // Adds a weakpoint, possibly overriding a weakpoint with the same name. - void add_weakpoint(weakpoint* weakpoint); - // Removes all weakpoints with the given name. - void remove_weakpoint(std::string weakpoint_name); - void load( const JsonArray &obj ); + void load( const JsonArray &ja ); }; From 4cb7bf97ad2a51e5c5163739f4ae2f33b42e923e Mon Sep 17 00:00:00 2001 From: Joshua Chin Date: Thu, 2 Sep 2021 21:57:04 -0400 Subject: [PATCH 04/16] Various compiler fixes --- src/damage.cpp | 4 ++-- src/damage.h | 2 +- src/weakpoint.cpp | 25 ++++++++++++------------- src/weakpoint.h | 8 +++++--- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/damage.cpp b/src/damage.cpp index 2b2fdfbe8a8c6..52f098bbb9c9f 100644 --- a/src/damage.cpp +++ b/src/damage.cpp @@ -431,10 +431,10 @@ damage_instance load_damage_instance_inherit( const JsonArray &jarr, const damag } std::array( damage_type::NUM )> load_damage_array( const JsonObject &jo, - float default ) + float default_value ) { std::array( damage_type::NUM )> ret; - float init_val = jo.get_float( "all", default ); + float init_val = jo.get_float( "all", default_value ); float phys = jo.get_float( "physical", init_val ); ret[ static_cast( damage_type::BASH ) ] = jo.get_float( "bash", phys ); diff --git a/src/damage.h b/src/damage.h index 3ab3974a90e4d..3a5093ed616a6 100644 --- a/src/damage.h +++ b/src/damage.h @@ -152,6 +152,6 @@ resistances load_resistances_instance( const JsonObject &jo ); // Returns damage or resistance data // Handles some shorthands std::array( damage_type::NUM )> load_damage_array( const JsonObject &jo, - float default = 0.0f ); + float default_value = 0.0f ); #endif // CATA_SRC_DAMAGE_H diff --git a/src/weakpoint.cpp b/src/weakpoint.cpp index 9e78f5e0cebd3..7a1a59cb315c1 100644 --- a/src/weakpoint.cpp +++ b/src/weakpoint.cpp @@ -18,11 +18,11 @@ weakpoint::weakpoint() armor_offset.fill( 0.0f ); } -void weakpoint::load( const JsonObject &obj ) +void weakpoint::load( const JsonObject &jo ) { assign( jo, "id", id ); assign( jo, "name", name ); - assign( jo, "coverage", 0.0f, 1.0f ); + assign( jo, "coverage", coverage, 0.0f, 1.0f ); if( jo.has_object( "armor_mult" ) ) { armor_mult = load_damage_array( jo.get_object( "armor_mult" ), 1.0f ); } @@ -35,24 +35,23 @@ void weakpoint::load( const JsonObject &obj ) } } -void weakpoint::apply_to( resistances &resistances ) +void weakpoint::apply_to( resistances &resistances ) const { - for( damage_type d = damage_type::None; d < damage_type::NUM; ++d ) { - int idx = static_cast( d ); - float r = resistances.get_resist( d ); - resistances.set_resist( armor_mult[idx] * r + armor_offset[idx] ); + for( int i = 0; i < static_cast( damage_type::NUM ); ++i ) { + resistances.resist_vals[i] *= armor_mult[i]; + resistances.resist_vals[i] *= armor_offset[i]; } } -float hit_chance( Creature */*source*/ ) const +float weakpoint::hit_chance( Creature */*source*/ ) const { return coverage; } -weakpoint *weakpoints::select_weakpoint( Creature *source ) const +const weakpoint *weakpoints::select_weakpoint( Creature *source ) const { float idx = rng_float( 0.0f, 1.0f ); - for( const weakpoint &weakpoint : weakpoints ) { + for( const weakpoint &weakpoint : weakpoint_list ) { float hit_chance = weakpoint.hit_chance( source ); if( hit_chance <= idx ) { return &weakpoint; @@ -64,9 +63,9 @@ weakpoint *weakpoints::select_weakpoint( Creature *source ) const void weakpoints::load( const JsonArray &ja ) { - while( ja.has_more() ) { + for( const JsonObject &jo : ja ) { weakpoint tmp; - tmp.load( ja.next_object ); - weakpoints.push_back( std::move( tmp ) ); + tmp.load( jo ); + weakpoint_list.push_back( std::move( tmp ) ); } } diff --git a/src/weakpoint.h b/src/weakpoint.h index 3d0cdc5cf3d64..191f59856ead3 100644 --- a/src/weakpoint.h +++ b/src/weakpoint.h @@ -29,18 +29,20 @@ struct weakpoint { void apply_to( resistances &resistances ) const; // Return the change of the creature hitting the weakpoint. float hit_chance( Creature */*source*/ ) const; - void load( const JsonObject &obj ); + void load( const JsonObject &jo ); }; struct weakpoints { // List of weakpoints. Each weakpoint should have a unique id. - std::vector weakpoints; + std::vector weakpoint_list; // Default weakpoint to return. weakpoint default_weakpoint; // Selects a weakpoint to hit. - weakpoint *select_weakpoint( Creature *source ) const; + const weakpoint *select_weakpoint( Creature *source ) const; weakpoints(); void load( const JsonArray &ja ); }; + +#endif // CATA_SRC_WEAKPOINT_H \ No newline at end of file From 52331f7ba71bb571f281b6138e374807080a033d Mon Sep 17 00:00:00 2001 From: Joshua Chin Date: Thu, 2 Sep 2021 22:00:55 -0400 Subject: [PATCH 05/16] Add weakpoints to mtype. --- src/monstergenerator.cpp | 6 ++++++ src/mtype.h | 2 ++ src/weakpoint.cpp | 4 ++++ src/weakpoint.h | 1 + 4 files changed, 13 insertions(+) diff --git a/src/monstergenerator.cpp b/src/monstergenerator.cpp index 6213362657ba9..74ca5b7799457 100644 --- a/src/monstergenerator.cpp +++ b/src/monstergenerator.cpp @@ -34,6 +34,7 @@ #include "rng.h" #include "translations.h" #include "units.h" +#include "weakpoints.h" namespace behavior { @@ -717,6 +718,11 @@ void mtype::load( const JsonObject &jo, const std::string &src ) assign( jo, "armor_acid", armor_acid, strict, 0 ); assign( jo, "armor_fire", armor_fire, strict, 0 ); + if (jo.has_array("weakpoints")) { + weakpoints.clear(); + weakpoints.load(jo.get_array("weakpoints")); + } + optional( jo, was_loaded, "bleed_rate", bleed_rate, 100 ); assign( jo, "vision_day", vision_day, strict, 0 ); diff --git a/src/mtype.h b/src/mtype.h index 47cc9d237d04c..58db048ab9b1c 100644 --- a/src/mtype.h +++ b/src/mtype.h @@ -22,6 +22,7 @@ #include "translations.h" #include "type_id.h" #include "units.h" // IWYU pragma: keep +#include "weakpoints.h" class Creature; class monster; @@ -327,6 +328,7 @@ struct mtype { int armor_bullet = -1; /** innate armor vs. bullet */ int armor_acid = -1; /** innate armor vs. acid */ int armor_fire = -1; /** innate armor vs. fire */ + weakpoints weakpoints; // Bleed rate in percent, 0 makes the monster immune to bleeding int bleed_rate = 100; diff --git a/src/weakpoint.cpp b/src/weakpoint.cpp index 7a1a59cb315c1..8f7dfbc50a233 100644 --- a/src/weakpoint.cpp +++ b/src/weakpoint.cpp @@ -61,6 +61,10 @@ const weakpoint *weakpoints::select_weakpoint( Creature *source ) const return &default_weakpoint; } +void weakpoints::clear() { + weakpoint_list.clear(); +} + void weakpoints::load( const JsonArray &ja ) { for( const JsonObject &jo : ja ) { diff --git a/src/weakpoint.h b/src/weakpoint.h index 191f59856ead3..189780bcd7257 100644 --- a/src/weakpoint.h +++ b/src/weakpoint.h @@ -42,6 +42,7 @@ struct weakpoints { const weakpoint *select_weakpoint( Creature *source ) const; weakpoints(); + void clear(); void load( const JsonArray &ja ); }; From df93345a914de557c8c5d575029d1b104513f93d Mon Sep 17 00:00:00 2001 From: Joshua Chin Date: Thu, 2 Sep 2021 22:05:39 -0400 Subject: [PATCH 06/16] Let weakpoints modify monster armor. --- src/monster.cpp | 7 ++++++- src/weakpoint.cpp | 6 +++--- src/weakpoint.h | 4 ++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/monster.cpp b/src/monster.cpp index 21c1382528cdb..a7c3c352c5270 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -1492,7 +1492,12 @@ void monster::absorb_hit( const bodypart_id &, damage_instance &dam ) for( auto &elem : dam.damage_units ) { add_msg_debug( debugmode::DF_MONSTER, "Dam Type: %s :: Ar Pen: %.1f :: Armor Mult: %.1f", name_by_dt( elem.type ), elem.res_pen, elem.res_mult ); - elem.amount -= std::min( resistances( *this ).get_effective_resist( elem ) + + resistances r = resistances( *this ); + weakpoint* weakpoint = type->weakpoints.select_weakpoint(); + weakpoint.apply_to(r); + add_msg_debug( debugmode::DF_MONSTER, "Weakpoint: %s", + weakpoint.id ); + elem.amount -= std::min( r.get_effective_resist( elem ) + get_worn_armor_val( elem.type ), elem.amount ); } } diff --git a/src/weakpoint.cpp b/src/weakpoint.cpp index 8f7dfbc50a233..af91fea826e2e 100644 --- a/src/weakpoint.cpp +++ b/src/weakpoint.cpp @@ -43,16 +43,16 @@ void weakpoint::apply_to( resistances &resistances ) const } } -float weakpoint::hit_chance( Creature */*source*/ ) const +float weakpoint::hit_chance( ) const { return coverage; } -const weakpoint *weakpoints::select_weakpoint( Creature *source ) const +const weakpoint *weakpoints::select_weakpoint( ) const { float idx = rng_float( 0.0f, 1.0f ); for( const weakpoint &weakpoint : weakpoint_list ) { - float hit_chance = weakpoint.hit_chance( source ); + float hit_chance = weakpoint.hit_chance( ); if( hit_chance <= idx ) { return &weakpoint; } diff --git a/src/weakpoint.h b/src/weakpoint.h index 189780bcd7257..1367b6ac11d01 100644 --- a/src/weakpoint.h +++ b/src/weakpoint.h @@ -28,7 +28,7 @@ struct weakpoint { // Apply the armor multipliers and offsets to a set of resistances. void apply_to( resistances &resistances ) const; // Return the change of the creature hitting the weakpoint. - float hit_chance( Creature */*source*/ ) const; + float hit_chance( ) const; void load( const JsonObject &jo ); }; @@ -39,7 +39,7 @@ struct weakpoints { weakpoint default_weakpoint; // Selects a weakpoint to hit. - const weakpoint *select_weakpoint( Creature *source ) const; + const weakpoint *select_weakpoint( ) const; weakpoints(); void clear(); From c927f615266b292d6c04c795d5fbe6fe02b83079 Mon Sep 17 00:00:00 2001 From: Joshua Chin Date: Thu, 2 Sep 2021 22:07:54 -0400 Subject: [PATCH 07/16] Compiler fixes --- src/monster.cpp | 7 ++++--- src/monstergenerator.cpp | 4 ++-- src/mtype.h | 2 +- src/weakpoint.cpp | 5 +++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/monster.cpp b/src/monster.cpp index a7c3c352c5270..824b0d4cde4df 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -62,6 +62,7 @@ #include "trap.h" #include "units.h" #include "viewer.h" +#include "weakpoint.h" #include "weather.h" static const efftype_id effect_badpoison( "badpoison" ); @@ -1493,10 +1494,10 @@ void monster::absorb_hit( const bodypart_id &, damage_instance &dam ) add_msg_debug( debugmode::DF_MONSTER, "Dam Type: %s :: Ar Pen: %.1f :: Armor Mult: %.1f", name_by_dt( elem.type ), elem.res_pen, elem.res_mult ); resistances r = resistances( *this ); - weakpoint* weakpoint = type->weakpoints.select_weakpoint(); - weakpoint.apply_to(r); + const weakpoint *weakpoint = type->weakpoints.select_weakpoint(); + weakpoint->apply_to( r ); add_msg_debug( debugmode::DF_MONSTER, "Weakpoint: %s", - weakpoint.id ); + weakpoint->id ); elem.amount -= std::min( r.get_effective_resist( elem ) + get_worn_armor_val( elem.type ), elem.amount ); } diff --git a/src/monstergenerator.cpp b/src/monstergenerator.cpp index 74ca5b7799457..8f6e8f15701c9 100644 --- a/src/monstergenerator.cpp +++ b/src/monstergenerator.cpp @@ -718,9 +718,9 @@ void mtype::load( const JsonObject &jo, const std::string &src ) assign( jo, "armor_acid", armor_acid, strict, 0 ); assign( jo, "armor_fire", armor_fire, strict, 0 ); - if (jo.has_array("weakpoints")) { + if( jo.has_array( "weakpoints" ) ) { weakpoints.clear(); - weakpoints.load(jo.get_array("weakpoints")); + weakpoints.load( jo.get_array( "weakpoints" ) ); } optional( jo, was_loaded, "bleed_rate", bleed_rate, 100 ); diff --git a/src/mtype.h b/src/mtype.h index 58db048ab9b1c..aad6278b2e666 100644 --- a/src/mtype.h +++ b/src/mtype.h @@ -22,7 +22,7 @@ #include "translations.h" #include "type_id.h" #include "units.h" // IWYU pragma: keep -#include "weakpoints.h" +#include "weakpoint.h" class Creature; class monster; diff --git a/src/weakpoint.cpp b/src/weakpoint.cpp index af91fea826e2e..439b6809622a7 100644 --- a/src/weakpoint.cpp +++ b/src/weakpoint.cpp @@ -52,7 +52,7 @@ const weakpoint *weakpoints::select_weakpoint( ) const { float idx = rng_float( 0.0f, 1.0f ); for( const weakpoint &weakpoint : weakpoint_list ) { - float hit_chance = weakpoint.hit_chance( ); + float hit_chance = weakpoint.hit_chance( ); if( hit_chance <= idx ) { return &weakpoint; } @@ -61,7 +61,8 @@ const weakpoint *weakpoints::select_weakpoint( ) const return &default_weakpoint; } -void weakpoints::clear() { +void weakpoints::clear() +{ weakpoint_list.clear(); } From 401809c72246ea9c82dad6b3d2230a73165e4359 Mon Sep 17 00:00:00 2001 From: Joshua Chin Date: Thu, 2 Sep 2021 23:51:33 -0400 Subject: [PATCH 08/16] weakpoint bugfixes. --- data/json/monsters/misc.json | 9 +++++++++ src/monster.cpp | 12 +++++++----- src/monstergenerator.cpp | 2 +- src/mtype.cpp | 1 + src/weakpoint.cpp | 13 ++++++++----- 5 files changed, 26 insertions(+), 11 deletions(-) diff --git a/data/json/monsters/misc.json b/data/json/monsters/misc.json index fa6229dc48077..1b025fd040c9b 100644 --- a/data/json/monsters/misc.json +++ b/data/json/monsters/misc.json @@ -17,6 +17,15 @@ "morale": 100, "melee_cut": 0, "vision_day": 1, + "armor_bullet": 100, + "weakpoints": [ + { + "name": "knee", + "armor_mult": { "bullet": 0.0 }, + "armor_offset": { "bullet": 20 }, + "coverage": 0.5 + } + ], "harvest": "exempt", "death_function": { "corpse_type": "NO_CORPSE", "message": "The %s melts away." }, "regenerates": 50, diff --git a/src/monster.cpp b/src/monster.cpp index 824b0d4cde4df..59462e3ee7948 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -1490,14 +1490,16 @@ bool monster::block_hit( Creature *, bodypart_id &, damage_instance & ) void monster::absorb_hit( const bodypart_id &, damage_instance &dam ) { + resistances r = resistances( *this ); + const weakpoint *weakpoint = type->weakpoints.select_weakpoint(); + weakpoint->apply_to( r ); for( auto &elem : dam.damage_units ) { add_msg_debug( debugmode::DF_MONSTER, "Dam Type: %s :: Ar Pen: %.1f :: Armor Mult: %.1f", name_by_dt( elem.type ), elem.res_pen, elem.res_mult ); - resistances r = resistances( *this ); - const weakpoint *weakpoint = type->weakpoints.select_weakpoint(); - weakpoint->apply_to( r ); - add_msg_debug( debugmode::DF_MONSTER, "Weakpoint: %s", - weakpoint->id ); + add_msg_debug( debugmode::DF_MONSTER, "Weakpoint: %s :: Armor Mult: %.1f :: Armor Offset: %.1f :: Resist: %.1f", + weakpoint->id, weakpoint->armor_mult[static_cast(elem.type)], + weakpoint->armor_offset[static_cast(elem.type)], + r.get_effective_resist( elem )); elem.amount -= std::min( r.get_effective_resist( elem ) + get_worn_armor_val( elem.type ), elem.amount ); } diff --git a/src/monstergenerator.cpp b/src/monstergenerator.cpp index 8f6e8f15701c9..7f2a90b5c7af2 100644 --- a/src/monstergenerator.cpp +++ b/src/monstergenerator.cpp @@ -34,7 +34,7 @@ #include "rng.h" #include "translations.h" #include "units.h" -#include "weakpoints.h" +#include "weakpoint.h" namespace behavior { diff --git a/src/mtype.cpp b/src/mtype.cpp index f17da63217314..01b564ceda3b5 100644 --- a/src/mtype.cpp +++ b/src/mtype.cpp @@ -14,6 +14,7 @@ #include "monstergenerator.h" #include "translations.h" #include "units.h" +#include "weakpoint.h" static const itype_id itype_bone( "bone" ); static const itype_id itype_bone_tainted( "bone_tainted" ); diff --git a/src/weakpoint.cpp b/src/weakpoint.cpp index 439b6809622a7..f7f2d73e96232 100644 --- a/src/weakpoint.cpp +++ b/src/weakpoint.cpp @@ -6,6 +6,7 @@ #include "assign.h" #include "creature.h" #include "damage.h" +#include "item.h" #include "rng.h" class JsonArray; @@ -22,12 +23,12 @@ void weakpoint::load( const JsonObject &jo ) { assign( jo, "id", id ); assign( jo, "name", name ); - assign( jo, "coverage", coverage, 0.0f, 1.0f ); + assign( jo, "coverage", coverage, false, 0.0f, 1.0f ); if( jo.has_object( "armor_mult" ) ) { armor_mult = load_damage_array( jo.get_object( "armor_mult" ), 1.0f ); } if( jo.has_object( "armor_offset" ) ) { - armor_mult = load_damage_array( jo.get_object( "armor_offset" ), 0.0f ); + armor_offset = load_damage_array( jo.get_object( "armor_offset" ), 0.0f ); } // Set the ID to the name, if not provided. if( id.empty() ) { @@ -39,16 +40,18 @@ void weakpoint::apply_to( resistances &resistances ) const { for( int i = 0; i < static_cast( damage_type::NUM ); ++i ) { resistances.resist_vals[i] *= armor_mult[i]; - resistances.resist_vals[i] *= armor_offset[i]; + resistances.resist_vals[i] += armor_offset[i]; } } -float weakpoint::hit_chance( ) const +float weakpoint::hit_chance() const { return coverage; } -const weakpoint *weakpoints::select_weakpoint( ) const +weakpoints::weakpoints() {} + +const weakpoint *weakpoints::select_weakpoint() const { float idx = rng_float( 0.0f, 1.0f ); for( const weakpoint &weakpoint : weakpoint_list ) { From b525b2263ee96b588100457920e8f208b1f5cc20 Mon Sep 17 00:00:00 2001 From: Joshua Chin Date: Thu, 2 Sep 2021 23:53:20 -0400 Subject: [PATCH 09/16] Run astyle --- src/monster.cpp | 9 +++++---- src/weakpoint.cpp | 2 -- src/weakpoint.h | 1 - 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/monster.cpp b/src/monster.cpp index 59462e3ee7948..a1a05212fa826 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -1496,10 +1496,11 @@ void monster::absorb_hit( const bodypart_id &, damage_instance &dam ) for( auto &elem : dam.damage_units ) { add_msg_debug( debugmode::DF_MONSTER, "Dam Type: %s :: Ar Pen: %.1f :: Armor Mult: %.1f", name_by_dt( elem.type ), elem.res_pen, elem.res_mult ); - add_msg_debug( debugmode::DF_MONSTER, "Weakpoint: %s :: Armor Mult: %.1f :: Armor Offset: %.1f :: Resist: %.1f", - weakpoint->id, weakpoint->armor_mult[static_cast(elem.type)], - weakpoint->armor_offset[static_cast(elem.type)], - r.get_effective_resist( elem )); + add_msg_debug( debugmode::DF_MONSTER, + "Weakpoint: %s :: Armor Mult: %.1f :: Armor Offset: %.1f :: Resist: %.1f", + weakpoint->id, weakpoint->armor_mult[static_cast( elem.type )], + weakpoint->armor_offset[static_cast( elem.type )], + r.get_effective_resist( elem ) ); elem.amount -= std::min( r.get_effective_resist( elem ) + get_worn_armor_val( elem.type ), elem.amount ); } diff --git a/src/weakpoint.cpp b/src/weakpoint.cpp index f7f2d73e96232..eac0760b69c93 100644 --- a/src/weakpoint.cpp +++ b/src/weakpoint.cpp @@ -49,8 +49,6 @@ float weakpoint::hit_chance() const return coverage; } -weakpoints::weakpoints() {} - const weakpoint *weakpoints::select_weakpoint() const { float idx = rng_float( 0.0f, 1.0f ); diff --git a/src/weakpoint.h b/src/weakpoint.h index 1367b6ac11d01..b594ca1c3dbe1 100644 --- a/src/weakpoint.h +++ b/src/weakpoint.h @@ -41,7 +41,6 @@ struct weakpoints { // Selects a weakpoint to hit. const weakpoint *select_weakpoint( ) const; - weakpoints(); void clear(); void load( const JsonArray &ja ); }; From 9ac4536c18e7ade16945f02c905a1e0e21753a83 Mon Sep 17 00:00:00 2001 From: Joshua Chin Date: Fri, 3 Sep 2021 00:28:38 -0400 Subject: [PATCH 10/16] Add json documentation --- doc/MONSTERS.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/doc/MONSTERS.md b/doc/MONSTERS.md index 32c3b73870e22..9e70991f7b18d 100644 --- a/doc/MONSTERS.md +++ b/doc/MONSTERS.md @@ -63,6 +63,7 @@ Monsters may also have any of these optional properties: | `armor_stab` | (integer) Monster's protection from stab damage | `armor_acid` | (integer) Monster's protection from acid damage | `armor_fire` | (integer) Monster's protection from fire damage +| `weakpoints` | (array of objects) Weakpoints in the monster's protection | `vision_day` | (integer) Vision range in full daylight, with `50` being the typical maximum | `vision_night` | (integer) Vision range in total darkness, ex. coyote `5`, bear `10`, sewer rat `30`, flaming eye `40` | `tracking_distance` | (integer) Amount of tiles the monster will keep between itself and its current tracked enemy or followed leader. Defaults to `3`. @@ -315,6 +316,18 @@ Amount of cutting damage added to die roll on monster melee attack. Monster protection from bashing, cutting, stabbing, acid and fire damage. +## "weakpoints" +(array of objects, optional) + +Weakpoints in the monster's protection. + +| field | description +| --- | --- +| `name` | Name of the weakpoint. +| `coverage` | Base probability of hitting the weakpoint. May be increased by skill level. +| `armor_multiplier` | multipler on the monster's base protection when hitting the weakpoint. +| `armor_offset` | offset on the monster's protection, after applying the multiplier. + ## "vision_day", "vision_night" (integer, optional) From edc3cfba23d4b304c91751b71be9ccf505fbe943 Mon Sep 17 00:00:00 2001 From: Joshua Chin Date: Fri, 3 Sep 2021 01:13:13 -0400 Subject: [PATCH 11/16] Run json_formatter --- data/json/monsters/misc.json | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/data/json/monsters/misc.json b/data/json/monsters/misc.json index 1b025fd040c9b..2eb3383b607c5 100644 --- a/data/json/monsters/misc.json +++ b/data/json/monsters/misc.json @@ -18,14 +18,7 @@ "melee_cut": 0, "vision_day": 1, "armor_bullet": 100, - "weakpoints": [ - { - "name": "knee", - "armor_mult": { "bullet": 0.0 }, - "armor_offset": { "bullet": 20 }, - "coverage": 0.5 - } - ], + "weakpoints": [ { "name": "knee", "armor_mult": { "bullet": 0.0 }, "armor_offset": { "bullet": 20 }, "coverage": 0.5 } ], "harvest": "exempt", "death_function": { "corpse_type": "NO_CORPSE", "message": "The %s melts away." }, "regenerates": 50, From cc77a584732398cb2fae615bbe08a978c62d86a5 Mon Sep 17 00:00:00 2001 From: Joshua Chin Date: Fri, 3 Sep 2021 10:37:10 -0400 Subject: [PATCH 12/16] Run clang tidy --- src/weakpoint.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/weakpoint.h b/src/weakpoint.h index b594ca1c3dbe1..f89dcbb3473b2 100644 --- a/src/weakpoint.h +++ b/src/weakpoint.h @@ -14,9 +14,9 @@ class JsonObject; struct weakpoint { // ID of the weakpoint. Equal to the name, if not provided. - std::string id = ""; + std::string id; // Name of the weakpoint. Can be empty. - std::string name = ""; + std::string name; // Base probability of hitting the weakpoint. Can be increased by skill. float coverage = 1.0f; // Multiplier for existing armor values. Defaults to 1. From fd684b13003141c2450d7bf6e93d047f3b77754a Mon Sep 17 00:00:00 2001 From: Joshua Chin Date: Fri, 3 Sep 2021 11:00:51 -0400 Subject: [PATCH 13/16] Fix GCC-only warning --- src/mtype.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mtype.h b/src/mtype.h index aad6278b2e666..8ef1009b9e2f8 100644 --- a/src/mtype.h +++ b/src/mtype.h @@ -328,7 +328,7 @@ struct mtype { int armor_bullet = -1; /** innate armor vs. bullet */ int armor_acid = -1; /** innate armor vs. acid */ int armor_fire = -1; /** innate armor vs. fire */ - weakpoints weakpoints; + ::weakpoints weakpoints; // Bleed rate in percent, 0 makes the monster immune to bleeding int bleed_rate = 100; From eaa50ef9d3793accd8f93a128b386068b9e8ccd8 Mon Sep 17 00:00:00 2001 From: Joshua Chin Date: Fri, 3 Sep 2021 11:01:09 -0400 Subject: [PATCH 14/16] clang-tidy --- src/weakpoint.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/weakpoint.cpp b/src/weakpoint.cpp index eac0760b69c93..03a0b1a927b5e 100644 --- a/src/weakpoint.cpp +++ b/src/weakpoint.cpp @@ -69,7 +69,7 @@ void weakpoints::clear() void weakpoints::load( const JsonArray &ja ) { - for( const JsonObject &jo : ja ) { + for( const JsonObject jo : ja ) { weakpoint tmp; tmp.load( jo ); weakpoint_list.push_back( std::move( tmp ) ); From feab1edf9c9ced10c4b91d1c49a450d1ba4c7462 Mon Sep 17 00:00:00 2001 From: Joshua Chin Date: Fri, 3 Sep 2021 11:34:12 -0400 Subject: [PATCH 15/16] Clarify weakpoint docs and switch to percentage coverage. --- data/json/monsters/misc.json | 2 +- doc/MONSTERS.md | 4 ++-- src/weakpoint.cpp | 4 ++-- src/weakpoint.h | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/data/json/monsters/misc.json b/data/json/monsters/misc.json index 2eb3383b607c5..c8307abd2db84 100644 --- a/data/json/monsters/misc.json +++ b/data/json/monsters/misc.json @@ -18,7 +18,7 @@ "melee_cut": 0, "vision_day": 1, "armor_bullet": 100, - "weakpoints": [ { "name": "knee", "armor_mult": { "bullet": 0.0 }, "armor_offset": { "bullet": 20 }, "coverage": 0.5 } ], + "weakpoints": [ { "name": "knee", "armor_mult": { "bullet": 0.0 }, "armor_offset": { "bullet": 20 }, "coverage": 50 } ], "harvest": "exempt", "death_function": { "corpse_type": "NO_CORPSE", "message": "The %s melts away." }, "regenerates": 50, diff --git a/doc/MONSTERS.md b/doc/MONSTERS.md index 9e70991f7b18d..026bbc6877f7d 100644 --- a/doc/MONSTERS.md +++ b/doc/MONSTERS.md @@ -324,9 +324,9 @@ Weakpoints in the monster's protection. | field | description | --- | --- | `name` | Name of the weakpoint. -| `coverage` | Base probability of hitting the weakpoint. May be increased by skill level. +| `coverage` | Base percentage chance of hitting the weakpoint. May be increased by skill level. (e.g. A coverage of 5 means a 5% base chance of hitting the weakpoint) | `armor_multiplier` | multipler on the monster's base protection when hitting the weakpoint. -| `armor_offset` | offset on the monster's protection, after applying the multiplier. +| `armor_offset` | a flat value added to the monster's protection, after applying the multiplier. ## "vision_day", "vision_night" (integer, optional) diff --git a/src/weakpoint.cpp b/src/weakpoint.cpp index 03a0b1a927b5e..94cf4ea195185 100644 --- a/src/weakpoint.cpp +++ b/src/weakpoint.cpp @@ -23,7 +23,7 @@ void weakpoint::load( const JsonObject &jo ) { assign( jo, "id", id ); assign( jo, "name", name ); - assign( jo, "coverage", coverage, false, 0.0f, 1.0f ); + assign( jo, "coverage", coverage, false, 0.0f, 100.0f ); if( jo.has_object( "armor_mult" ) ) { armor_mult = load_damage_array( jo.get_object( "armor_mult" ), 1.0f ); } @@ -51,7 +51,7 @@ float weakpoint::hit_chance() const const weakpoint *weakpoints::select_weakpoint() const { - float idx = rng_float( 0.0f, 1.0f ); + float idx = rng_float( 0.0f, 100.0f ); for( const weakpoint &weakpoint : weakpoint_list ) { float hit_chance = weakpoint.hit_chance( ); if( hit_chance <= idx ) { diff --git a/src/weakpoint.h b/src/weakpoint.h index f89dcbb3473b2..8bda93422f6f3 100644 --- a/src/weakpoint.h +++ b/src/weakpoint.h @@ -17,8 +17,8 @@ struct weakpoint { std::string id; // Name of the weakpoint. Can be empty. std::string name; - // Base probability of hitting the weakpoint. Can be increased by skill. - float coverage = 1.0f; + // Percent chance of hitting the weakpoint. Can be increased by skill. + float coverage = 100.0f; // Multiplier for existing armor values. Defaults to 1. std::array( damage_type::NUM )> armor_mult; // Constant offset for multiplied armor values. Defaults to 0. From 11f2f55a0ac2af4259823997bd3169a3ab59d596 Mon Sep 17 00:00:00 2001 From: Joshua Chin Date: Fri, 3 Sep 2021 14:07:03 -0400 Subject: [PATCH 16/16] Rename armor offset to armor penalty, flipping the sign. --- data/json/monsters/misc.json | 2 +- doc/MONSTERS.md | 2 +- src/monster.cpp | 4 ++-- src/weakpoint.cpp | 8 ++++---- src/weakpoint.h | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/data/json/monsters/misc.json b/data/json/monsters/misc.json index c8307abd2db84..8b51827e63795 100644 --- a/data/json/monsters/misc.json +++ b/data/json/monsters/misc.json @@ -18,7 +18,7 @@ "melee_cut": 0, "vision_day": 1, "armor_bullet": 100, - "weakpoints": [ { "name": "knee", "armor_mult": { "bullet": 0.0 }, "armor_offset": { "bullet": 20 }, "coverage": 50 } ], + "weakpoints": [ { "name": "knee", "armor_mult": { "bullet": 0.5 }, "armor_penalty": { "bullet": 25 }, "coverage": 50 } ], "harvest": "exempt", "death_function": { "corpse_type": "NO_CORPSE", "message": "The %s melts away." }, "regenerates": 50, diff --git a/doc/MONSTERS.md b/doc/MONSTERS.md index 026bbc6877f7d..9d13314f0d984 100644 --- a/doc/MONSTERS.md +++ b/doc/MONSTERS.md @@ -326,7 +326,7 @@ Weakpoints in the monster's protection. | `name` | Name of the weakpoint. | `coverage` | Base percentage chance of hitting the weakpoint. May be increased by skill level. (e.g. A coverage of 5 means a 5% base chance of hitting the weakpoint) | `armor_multiplier` | multipler on the monster's base protection when hitting the weakpoint. -| `armor_offset` | a flat value added to the monster's protection, after applying the multiplier. +| `armor_penalty` | a flat penalty to the monster's protection, applied after the multiplier. ## "vision_day", "vision_night" (integer, optional) diff --git a/src/monster.cpp b/src/monster.cpp index a1a05212fa826..2d76c3c06a04a 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -1497,9 +1497,9 @@ void monster::absorb_hit( const bodypart_id &, damage_instance &dam ) add_msg_debug( debugmode::DF_MONSTER, "Dam Type: %s :: Ar Pen: %.1f :: Armor Mult: %.1f", name_by_dt( elem.type ), elem.res_pen, elem.res_mult ); add_msg_debug( debugmode::DF_MONSTER, - "Weakpoint: %s :: Armor Mult: %.1f :: Armor Offset: %.1f :: Resist: %.1f", + "Weakpoint: %s :: Armor Mult: %.1f :: Armor Penalty: %.1f :: Resist: %.1f", weakpoint->id, weakpoint->armor_mult[static_cast( elem.type )], - weakpoint->armor_offset[static_cast( elem.type )], + weakpoint->armor_penalty[static_cast( elem.type )], r.get_effective_resist( elem ) ); elem.amount -= std::min( r.get_effective_resist( elem ) + get_worn_armor_val( elem.type ), elem.amount ); diff --git a/src/weakpoint.cpp b/src/weakpoint.cpp index 94cf4ea195185..a04c3d4371bc7 100644 --- a/src/weakpoint.cpp +++ b/src/weakpoint.cpp @@ -16,7 +16,7 @@ weakpoint::weakpoint() { // arrays must be filled manually to avoid UB. armor_mult.fill( 1.0f ); - armor_offset.fill( 0.0f ); + armor_penalty.fill( 0.0f ); } void weakpoint::load( const JsonObject &jo ) @@ -27,8 +27,8 @@ void weakpoint::load( const JsonObject &jo ) if( jo.has_object( "armor_mult" ) ) { armor_mult = load_damage_array( jo.get_object( "armor_mult" ), 1.0f ); } - if( jo.has_object( "armor_offset" ) ) { - armor_offset = load_damage_array( jo.get_object( "armor_offset" ), 0.0f ); + if( jo.has_object( "armor_penalty" ) ) { + armor_penalty = load_damage_array( jo.get_object( "armor_penalty" ), 0.0f ); } // Set the ID to the name, if not provided. if( id.empty() ) { @@ -40,7 +40,7 @@ void weakpoint::apply_to( resistances &resistances ) const { for( int i = 0; i < static_cast( damage_type::NUM ); ++i ) { resistances.resist_vals[i] *= armor_mult[i]; - resistances.resist_vals[i] += armor_offset[i]; + resistances.resist_vals[i] -= armor_penalty[i]; } } diff --git a/src/weakpoint.h b/src/weakpoint.h index 8bda93422f6f3..f3fc39c313577 100644 --- a/src/weakpoint.h +++ b/src/weakpoint.h @@ -21,8 +21,8 @@ struct weakpoint { float coverage = 100.0f; // Multiplier for existing armor values. Defaults to 1. std::array( damage_type::NUM )> armor_mult; - // Constant offset for multiplied armor values. Defaults to 0. - std::array( damage_type::NUM )> armor_offset; + // Flat penalty to armor values. Applied after the multiplier. + std::array( damage_type::NUM )> armor_penalty; weakpoint(); // Apply the armor multipliers and offsets to a set of resistances.