Skip to content

Commit

Permalink
Limb secondary types (CleverRaven#54478)
Browse files Browse the repository at this point in the history
Co-authored-by: Venera3 <[email protected]>
  • Loading branch information
Venera3 and Venera3 authored Jan 16, 2022
1 parent f8f948d commit e49949d
Show file tree
Hide file tree
Showing 8 changed files with 35 additions and 16 deletions.
4 changes: 2 additions & 2 deletions doc/JSON_FLAGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -338,12 +338,12 @@ Some armor flags, such as `WATCH` and `ALARMCLOCK` are compatible with other ite

## Bodyparts

-```ALWAYS_BLOCK``` This nonstandard bodypart is eligible to block in unarmed combat even if your martial arts don't allow such blocks. No effect without `NONSTANDARD_BLOCK`
-```ALWAYS_BLOCK``` This nonstandard bodypart is always eligible to block in unarmed combat even if your martial arts don't allow such blocks.
-```IGNORE_TEMP``` This bodypart is ignored for temperature calculations
-```LIMB_LOWER``` This bodypart is close to the ground, and as such has a higher chance to be attacked by small monsters - hitsize is tripled for creatures that can't attack upper limbs.
-```LIMB_UPPER``` This bodypart is high off the ground, and as such can't be attacked by small monsters - unless they have the `FLIES` or have `ATTACK_UPPER` flags`
- ````MEND_LIMB``` This bodypart can heal from being broken without needing a splint.
-```NONSTANDARD_BLOCK``` This limb is different enough that martial arts' arm/leg blocks aren't applicable - blocking with this limb is unlocked by reaching the MA's `nonstandard_block` level, unless the limb also has `ALWAYS_BLOCK`
-```NONSTANDARD_BLOCK``` This limb is different enough that martial arts' arm/leg blocks aren't applicable - blocking with this limb is unlocked by reaching the MA's `nonstandard_block` level, unless the limb also has `ALWAYS_BLOCK`. Either block flag is **required** for non-arm / non-leg limbs to be eligible to block.


## Books
Expand Down
2 changes: 2 additions & 0 deletions doc/JSON_INFO.md
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,8 @@ For information about tools with option to export ASCII art in format ready to b
|--- |---
| `id` | (_mandatory_) Unique ID. Must be one continuous word, use underscores if necessary.
| `name` | (_mandatory_) In-game name displayed.
| `limb_type` | (_mandatory_) Type of limb, as defined by `bodypart.h`. Certain functions will check only a given bodypart type for their purposes. Currently implemented types are: `head, torso, sensor, mouth, arm, hand, leg, foot, wing, tail, other`.
| `secondary_types` | (_optional_) List of secondary limb types for the bodypart, to include it in relevant calculations.
| `accusative` | (_mandatory_) Accusative form for this bodypart.
| `heading` | (_mandatory_) How it's displayed in headings.
| `heading_multiple` | (_mandatory_) Plural form of heading.
Expand Down
30 changes: 19 additions & 11 deletions src/anatomy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ static const anatomy_id anatomy_human_anatomy( "human_anatomy" );
static const json_character_flag json_flag_ALWAYS_BLOCK( "ALWAYS_BLOCK" );
static const json_character_flag json_flag_LIMB_LOWER( "LIMB_LOWER" );
static const json_character_flag json_flag_LIMB_UPPER( "LIMB_UPPER" );
static const json_character_flag json_flag_NONSTANDARD_BLOCK( "NONSTANDARD_BLOCK" );

static const limb_score_id limb_score_block( "block" );

Expand Down Expand Up @@ -229,31 +230,38 @@ bodypart_id anatomy::select_blocking_part( const Creature *blocker, bool arm, bo
// Weigh shielded bodyparts higher
block_score *= u->worn_with_flag( flag_BLOCK_WHILE_WORN, bp ) ? 5 : 1;
}
body_part_type::type limb_type = bp->limb_type;

// Filter out nonblocking / broken limbs
if( block_score == 0 ) {
add_msg_debug( debugmode::DF_MELEE, "BP %s discarded, no blocking score",
body_part_name( bp ) );
continue;
}

// Filter out arm and leg types TODO consolidate into one if
if( limb_type == body_part_type::type::arm && !arm &&
!bp->has_flag( json_flag_ALWAYS_BLOCK ) ) {
add_msg_debug( debugmode::DF_MELEE, "BP %s discarded, no arm blocks allowed",
// Always blocking limbs block always (if they have a block score)
if( bp->has_flag( json_flag_ALWAYS_BLOCK ) ) {
block_scores.add( bp, block_score );
add_msg_debug( debugmode::DF_MELEE, "BP %s always blocks",
body_part_name( bp ) );
continue;
}

if( limb_type == body_part_type::type::leg && !leg &&
!bp->has_flag( json_flag_ALWAYS_BLOCK ) ) {
// Can we block with our normal boring arm?
if( bp->has_type( body_part_type::type::arm ) && !bp->has_flag( json_flag_NONSTANDARD_BLOCK ) &&
!arm ) {
add_msg_debug( debugmode::DF_MELEE, "BP %s discarded, no arm blocks allowed",
body_part_name( bp ) );
continue;
// Can we block with our normal boring legs?
} else if( bp->has_type( body_part_type::type::leg ) &&
!bp->has_flag( json_flag_NONSTANDARD_BLOCK ) && !leg ) {
add_msg_debug( debugmode::DF_MELEE, "BP %s discarded, no leg blocks allowed",
body_part_name( bp ) );
continue;
}

if( limb_type != body_part_type::type::arm && limb_type != body_part_type::type::leg &&
!nonstandard ) {
// Can we block with our non-normal non-arms/non-legs?
} else if( ( ( !bp->has_type( body_part_type::type::arm ) &&
!bp->has_type( body_part_type::type::leg ) ) || bp->has_flag( json_flag_NONSTANDARD_BLOCK ) ) &&
!nonstandard ) {
add_msg_debug( debugmode::DF_MELEE, "BP %s discarded, no nonstandard blocks allowed",
body_part_name( bp ) );
continue;
Expand Down
6 changes: 6 additions & 0 deletions src/bodypart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,11 @@ void body_part_type::load_bp( const JsonObject &jo, const std::string &src )
body_part_factory.load( jo, src );
}

bool body_part_type::has_type( const body_part_type::type &type ) const
{
return limb_type == type || secondary_types.count( type ) > 0;
}

bool body_part_type::has_flag( const json_character_flag &flag ) const
{
return flags.count( flag ) > 0;
Expand Down Expand Up @@ -307,6 +312,7 @@ void body_part_type::load( const JsonObject &jo, const std::string & )
optional( jo, was_loaded, "is_limb", is_limb, false );
optional( jo, was_loaded, "is_vital", is_vital, false );
mandatory( jo, was_loaded, "limb_type", limb_type );
optional( jo, was_loaded, "secondary_types", secondary_types );
optional( jo, was_loaded, "encumb_impacts_dodge", encumb_impacts_dodge, false );

// tokens are actually legacy code that should be on their way out.
Expand Down
2 changes: 2 additions & 0 deletions src/bodypart.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ struct body_part_type {
// Parts with no opposites have BOTH here
side part_side = side::BOTH;
body_part_type::type limb_type = body_part_type::type::num_types;
cata::flat_set <body_part_type::type> secondary_types;
bool has_type( const body_part_type::type &type ) const;

// Threshold to start encumbrance scaling
int encumbrance_threshold = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/character_attire.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ bool Character::is_wearing_shoes( const side &check_side ) const

for( const bodypart_id &part : get_all_body_parts() ) {
// Is any right|left foot...
if( part->limb_type != body_part_type::type::foot ) {
if( !part->has_type( body_part_type::type::foot ) ) {
continue;
}
for( const item &worn_item : worn ) {
Expand Down
2 changes: 1 addition & 1 deletion src/creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2378,7 +2378,7 @@ std::vector<bodypart_id> Creature::get_all_body_parts_of_type(
if( only_main && elem.first->main_part != elem.first ) {
continue;
}
if( elem.first->limb_type == part_type ) {
if( elem.first->has_type( part_type ) ) {
bodyparts.emplace_back( elem.first );
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/mutation_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,8 @@ void mutation_branch::load( const JsonObject &jo, const std::string & )
for( const std::string &type_string : ao.get_tags( "part_types" ) ) {
for( const body_part_type &bp : body_part_type::get_all() ) {
if( type_string == "ALL" ||
bp.limb_type == io::string_to_enum<body_part_type::type>( type_string ) ) {
bp.limb_type == io::string_to_enum<body_part_type::type>( type_string ) ||
bp.secondary_types.count( io::string_to_enum<body_part_type::type>( type_string ) ) > 0 ) {
armor[bp.id] += res;
}
}
Expand Down

0 comments on commit e49949d

Please sign in to comment.