Skip to content

Commit

Permalink
Initial Implementation Of Replacable Limbs (CleverRaven#65505)
Browse files Browse the repository at this point in the history
* Initial Implementation

* Styling

* handle mono legs

* CLANG appeasement

* clang appease

* de-auto
  • Loading branch information
bombasticSlacks authored May 11, 2023
1 parent 2154707 commit 3fc7b38
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 8 deletions.
92 changes: 92 additions & 0 deletions data/json/body_parts.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,98 @@
],
"sub_parts": [ "torso_upper", "torso_neck", "torso_lower", "torso_hanging_front", "torso_hanging_back", "torso_waist" ]
},
{
"id": "big_head",
"type": "body_part",
"name": "big head",
"accusative": { "ctxt": "bodypart_accusative", "str": "head" },
"heading": "big head",
"heading_multiple": "big heads",
"hp_bar_ui_text": "HEAD",
"encumbrance_text": "Dodging and blocking is hampered.",
"encumbrance_threshold": 10,
"main_part": "big_head",
"connected_to": "big_head",
"opposite_part": "big_head",
"limb_type": "head",
"limb_scores": [ [ "reaction", 0.3 ] ],
"is_vital": true,
"hit_size": 4,
"hit_difficulty": 1.2,
"side": "both",
"grabbing_effect": "grabbing_head",
"stylish_bonus": 3,
"hot_morale_mod": 2,
"cold_morale_mod": 2,
"fire_warmth_bonus": 150,
"squeamish_penalty": 7,
"base_hp": 60,
"drench_capacity": 700,
"smash_message": "You smash the %s with a firm headbutt.",
"smash_efficiency": 0.25,
"bionic_slots": 18,
"flags": [ "LIMB_UPPER" ],
"sub_parts": [ "head_forehead", "head_crown", "head_nape", "head_throat", "head_ear_r", "head_ear_l" ],
"encumbrance_per_weight": [
{ "weight": "1 mg", "encumbrance": 1 },
{ "weight": "300 g", "encumbrance": 4 },
{ "weight": "800 g", "encumbrance": 8 },
{ "weight": "1300 g", "encumbrance": 20 },
{ "weight": "1600 g", "encumbrance": 30 },
{ "weight": "2200 g", "encumbrance": 50 },
{ "weight": "5600 g", "encumbrance": 80 },
{ "weight": "10000 g", "encumbrance": 160 }
],
"effects_on_hit": [
{
"id": "bleed",
"dmg_type": "cut",
"dmg_threshold": 5,
"dmg_scale_increment": 2,
"duration": 60,
"duration_dmg_scaling": 30,
"max_duration": 960
},
{
"id": "bleed",
"dmg_type": "stab",
"dmg_threshold": 1,
"dmg_scale_increment": 1.5,
"duration": 60,
"duration_dmg_scaling": 60,
"max_duration": 1200
},
{
"id": "bleed",
"dmg_type": "bullet",
"dmg_threshold": 1,
"dmg_scale_increment": 1,
"duration": 60,
"duration_dmg_scaling": 60
},
{
"id": "stunned",
"dmg_type": "bash",
"dmg_threshold": 10,
"dmg_scale_increment": 5,
"chance": 10,
"chance_dmg_scaling": 10,
"duration": 1,
"duration_dmg_scaling": 0.5,
"max_duration": 4
},
{
"id": "stunned",
"dmg_threshold": 30,
"dmg_scale_increment": 10,
"chance": 10,
"chance_dmg_scaling": 10,
"duration": 1,
"duration_dmg_scaling": 0.5,
"max_duration": 4
}
]
},
{
"id": "head",
"type": "body_part",
Expand Down
6 changes: 6 additions & 0 deletions data/json/enchantments.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@
{ "lose": "hand_r" }
]
},
{
"type": "enchantment",
"id": "ENCH_DEBUG_BIG_HEAD",
"condition": "ALWAYS",
"modified_bodyparts": [ { "lose": "head" }, { "gain": "big_head" } ]
},
{
"type": "enchantment",
"id": "RM13",
Expand Down
10 changes: 10 additions & 0 deletions data/json/mutations/mutations.json
Original file line number Diff line number Diff line change
Expand Up @@ -8181,6 +8181,16 @@
"enchantments": [ "ENCH_DEBUG_ONLY_HEAD" ],
"debug": true
},
{
"type": "mutation",
"id": "DEBUG_BIG_HEAD",
"name": { "str": "Debug Big Head" },
"points": 99,
"valid": false,
"description": "They said college what make me smart, this is a lot to lug around!",
"enchantments": [ "ENCH_DEBUG_BIG_HEAD" ],
"debug": true
},
{
"type": "mutation",
"id": "DEBUG_NIGHTVISION",
Expand Down
48 changes: 41 additions & 7 deletions src/creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1992,7 +1992,7 @@ bool Creature::has_part( const bodypart_id &id ) const

bodypart *Creature::get_part( const bodypart_id &id )
{
auto found = body.find( id.id() );
auto found = body.find( get_part_id( id ).id() );
if( found == body.end() ) {
debugmsg( "Could not find bodypart %s in %s's body", id.id().c_str(), get_name() );
return nullptr;
Expand All @@ -2002,7 +2002,7 @@ bodypart *Creature::get_part( const bodypart_id &id )

const bodypart *Creature::get_part( const bodypart_id &id ) const
{
auto found = body.find( id.id() );
auto found = body.find( get_part_id( id ).id() );
if( found == body.end() ) {
debugmsg( "Could not find bodypart %s in %s's body", id.id().c_str(), get_name() );
return nullptr;
Expand Down Expand Up @@ -2045,6 +2045,40 @@ static void set_part_helper( Creature &c, const bodypart_id &id,
}
}

bodypart_id Creature::get_part_id( const bodypart_id &id ) const
{
auto found = body.find( id.id() );
if( found == body.end() ) {
// try to find an equivalent part in the body map
for( const std::pair<const bodypart_str_id, bodypart> &bp : body ) {
if( id->part_side == bp.first->part_side &&
id->primary_limb_type() == bp.first->primary_limb_type() ) {
return bp.first;
}
}

// try to find the next best thing
std::pair<bodypart_id, float> best = { body_part_bp_null, 0.0 };
for( const std::pair<const bodypart_str_id, bodypart> &bp : body ) {
for( const std::pair<const body_part_type::type, float> &mp : bp.first->limbtypes ) {
// if the secondary limb type matches and is better than the current
if( mp.first == id->primary_limb_type() && mp.second > best.second ) {
// give an inflated bonus if the part sides match
float bonus = id->part_side == bp.first->part_side ? 1.0 : 0.0;
best = { bp.first, mp.second + bonus };
}
}
}

if( best.first == body_part_bp_null ) {
debugmsg( "Could not find equivalent bodypart id %s in %s's body", id.id().c_str(), get_name() );
}

return best.first;
}
return found->first;
}

int Creature::get_part_hp_cur( const bodypart_id &id ) const
{
return get_part_helper( *this, id, &bodypart::get_hp_cur );
Expand Down Expand Up @@ -2281,7 +2315,7 @@ bodypart_id Creature::get_random_body_part( bool main ) const
return main ? part->main_part.id() : part;
}

static void sort_body_parts( std::vector<bodypart_id> &bps )
static void sort_body_parts( std::vector<bodypart_id> &bps, const Creature *c )
{
// We want to dynamically sort the parts based on their connections as
// defined in json.
Expand All @@ -2293,7 +2327,7 @@ static void sort_body_parts( std::vector<bodypart_id> &bps )
std::unordered_map<bodypart_id, cata::flat_set<bodypart_id>> parts_connected_to;
bodypart_id root_part;
for( const bodypart_id &bp : bps ) {
bodypart_id conn = bp->connected_to;
bodypart_id conn = c->get_part_id( bp->connected_to );
if( conn == bp ) {
root_part = bp;
} else {
Expand Down Expand Up @@ -2326,7 +2360,7 @@ static void sort_body_parts( std::vector<bodypart_id> &bps )
parts_with_no_connections.erase( last );
unaccounted_parts.erase( bp );
topo_sorted_parts.push_back( bp );
bodypart_id conn = bp->connected_to;
bodypart_id conn = c->get_part_id( bp->connected_to );
if( conn == bp ) {
break;
}
Expand Down Expand Up @@ -2410,7 +2444,7 @@ std::vector<bodypart_id> Creature::get_all_body_parts( get_body_part_flags flags
}

if( flags & get_body_part_flags::sorted ) {
sort_body_parts( all_bps );
sort_body_parts( all_bps, this );
}

return all_bps;
Expand Down Expand Up @@ -2448,7 +2482,7 @@ std::vector<bodypart_id> Creature::get_all_body_parts_of_type(
}

if( flags & get_body_part_flags::sorted ) {
sort_body_parts( bodyparts );
sort_body_parts( bodyparts, this );
}

return bodyparts;
Expand Down
3 changes: 3 additions & 0 deletions src/creature.h
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,9 @@ class Creature : public viewer
bodypart *get_part( const bodypart_id &id );
const bodypart *get_part( const bodypart_id &id ) const;

// get the body part id that matches for the character
bodypart_id get_part_id( const bodypart_id &id ) const;

int get_part_hp_cur( const bodypart_id &id ) const;
int get_part_hp_max( const bodypart_id &id ) const;

Expand Down
6 changes: 5 additions & 1 deletion src/widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,11 @@ void widget::set_default_var_range( const avatar &ava )
case widget_var::bp_hp:
// HP for body part
_var_min = 0;
_var_max = ava.get_part_hp_max( only_bp() );
if( ava.has_part( only_bp() ) ) {
_var_max = ava.get_part_hp_max( only_bp() );
} else {
_var_max = 0;
}
break;
case widget_var::bp_encumb:
_var_min = 0;
Expand Down

0 comments on commit 3fc7b38

Please sign in to comment.