summaryrefslogtreecommitdiff
path: root/revert-24_fix-repair-nanobots-not-working-at-all-on-broken-lim.patch
diff options
context:
space:
mode:
Diffstat (limited to 'revert-24_fix-repair-nanobots-not-working-at-all-on-broken-lim.patch')
-rw-r--r--revert-24_fix-repair-nanobots-not-working-at-all-on-broken-lim.patch214
1 files changed, 214 insertions, 0 deletions
diff --git a/revert-24_fix-repair-nanobots-not-working-at-all-on-broken-lim.patch b/revert-24_fix-repair-nanobots-not-working-at-all-on-broken-lim.patch
new file mode 100644
index 0000000..c1de272
--- /dev/null
+++ b/revert-24_fix-repair-nanobots-not-working-at-all-on-broken-lim.patch
@@ -0,0 +1,214 @@
+From 5da2793a2a464a997b19c9b156cdb6baaaacb081 Mon Sep 17 00:00:00 2001
+From: scarf <greenscarf005@gmail.com>
+Date: Wed, 6 Dec 2023 11:35:40 +0900
+Subject: [PATCH 213/318] fix: repair nanobots not working at all on broken
+ limbs (#3787)
+
+fix: make nanobot work regardless of splint
+---
+ data/json/bionics.json | 2 +-
+ data/json/items/bionics.json | 2 +-
+ src/bionics.cpp | 47 ++++++++++++++++++++----------------
+ src/character.cpp | 11 +++------
+ src/regen.cpp | 35 +++++++++++++++++++++++++++
+ src/regen.h | 18 ++++++++++++++
+ 6 files changed, 85 insertions(+), 30 deletions(-)
+ create mode 100644 src/regen.cpp
+ create mode 100644 src/regen.h
+
+diff --git a/data/json/bionics.json b/data/json/bionics.json
+index 2e4b121ce7f..824be5bad23 100644
+--- a/data/json/bionics.json
++++ b/data/json/bionics.json
+@@ -661,7 +661,7 @@
+ "id": "bio_nanobots",
+ "type": "bionic",
+ "name": { "str": "Repair Nanobots" },
+- "description": "Inside your body is a fleet of tiny dormant robots. While activated they will reduce the intensity of one bleed effect every 30 seconds, and heal all injured body parts by 1 HP (or broken limbs by 1%) every 2 minutes if you have 3 kJ bionic power and 5 kcal per body part. Broken limbs must still be splinted (unless you have specific mutations) to benefit. If you don't have enough, they will prioritize based on the resources you have.",
++ "description": "Inside your body is a fleet of tiny dormant robots. While activated they will reduce the intensity of one bleed effect every 30 seconds, and heal all injured body parts by 1 HP (or broken limbs by 1%) every 2 minutes if you have 3 kJ bionic power and 5 kcal per body part. If you don't have enough, they will prioritize based on the resources you have.",
+ "occupied_bodyparts": [ [ "torso", 10 ] ],
+ "flags": [ "BIONIC_TOGGLED", "BIONIC_NPC_USABLE", "BIONIC_SLEEP_FRIENDLY" ],
+ "act_cost": "300 J",
+diff --git a/data/json/items/bionics.json b/data/json/items/bionics.json
+index 8e06717899b..5a5c9e5a037 100644
+--- a/data/json/items/bionics.json
++++ b/data/json/items/bionics.json
+@@ -610,7 +610,7 @@
+ "type": "BIONIC_ITEM",
+ "name": { "str": "Repair Nanobots CBM" },
+ "looks_like": "bio_int_enhancer",
+- "description": "A fleet of tiny dormant robots. While activated they will reduce the intensity of one bleed effect every 30 seconds, and heal all injured body parts by 1 HP (or broken limbs by 1%) every 2 minutes if you have 3 kJ bionic power and 5 kcal per body part. Broken limbs must still be splinted (unless you have specific mutations) to benefit. If you don't have enough, they will prioritize based on the resources you have.",
++ "description": "A fleet of tiny dormant robots. While activated they will reduce the intensity of one bleed effect every 30 seconds, and heal all injured body parts by 1 HP (or broken limbs by 1%) every 2 minutes if you have 3 kJ bionic power and 5 kcal per body part. If you don't have enough, they will prioritize based on the resources you have.",
+ "price": "9500 USD",
+ "weight": "200 g",
+ "difficulty": 6
+diff --git a/src/bionics.cpp b/src/bionics.cpp
+index 63d72584731..28e79490d37 100644
+--- a/src/bionics.cpp
++++ b/src/bionics.cpp
+@@ -68,6 +68,7 @@
+ #include "point.h"
+ #include "projectile.h"
+ #include "requirements.h"
++#include "regen.h"
+ #include "rng.h"
+ #include "sounds.h"
+ #include "string_formatter.h"
+@@ -1662,28 +1663,32 @@ void Character::process_bionic( bionic &bio )
+ }
+ }
+ if( calendar::once_every( 2_minutes ) ) {
+- std::vector<bodypart_id> damaged_hp_parts;
+- for( const bodypart_id &bp : get_all_body_parts( true ) ) {
+- const int hp_cur = get_part_hp_cur( bp );
+- if( !is_limb_broken( bp ) && hp_cur < get_part_hp_max( bp ) ) {
+- damaged_hp_parts.push_back( bp );
+- }
+- }
+- if( !damaged_hp_parts.empty() ) {
+- // Essential parts are considered 10 HP lower than non-essential parts for the purpose of determining priority.
+- // I'd use the essential_value, but it's tied up in the heal_actor class of iuse_actor.
+- std::sort( damaged_hp_parts.begin(), damaged_hp_parts.end(),
+- [this]( const bodypart_id & a, const bodypart_id & b ) {
+- return ( get_part_hp_cur( a ) - a->essential * 10 ) < ( get_part_hp_cur( b ) - b->essential * 10 );
+- } );
+- for( bodypart_id &bpid : damaged_hp_parts ) {
+- if( !can_use_bionic() ) {
+- return;
+- }
+- heal( bpid, 1 );
+- mod_power_level( -bio.info().power_trigger );
+- mod_stored_kcal( -bio.info().kcal_trigger );
++ // Essential parts are considered 10 HP lower than non-essential parts for the purpose of determining priority.
++ // I'd use the essential_value, but it's tied up in the heal_actor class of iuse_actor.
++ const auto effective_hp = [this]( const bodypart_id & bp ) -> int {
++ return get_part_hp_cur( bp ) - bp->essential * 10;
++ };
++ const auto should_heal = [this]( const bodypart_id & bp ) -> bool {
++ return get_part_hp_cur( bp ) < get_part_hp_max( bp );
++ };
++ const auto sort_by = [effective_hp]( const bodypart_id & a, const bodypart_id & b ) -> bool {
++ return effective_hp( a ) < effective_hp( b );
++ };
++ const auto damaged_parts = [this, should_heal, sort_by]() {
++ const auto xs = get_all_body_parts( true );
++ auto ys = std::vector<bodypart_id> {};
++ std::copy_if( xs.begin(), xs.end(), std::back_inserter( ys ), should_heal );
++ std::sort( ys.begin(), ys.end(), sort_by );
++ return ys;
++ };
++
++ for( bodypart_id &bp : damaged_parts() ) {
++ if( !can_use_bionic() ) {
++ return;
+ }
++ heal_adjusted( *this, bp, 1 );
++ mod_power_level( -bio.info().power_trigger );
++ mod_stored_kcal( -bio.info().kcal_trigger );
+ }
+ }
+ }
+diff --git a/src/character.cpp b/src/character.cpp
+index 9b6c15ce40c..25be749aa56 100644
+--- a/src/character.cpp
++++ b/src/character.cpp
+@@ -1,5 +1,4 @@
+ #include "character.h"
+-#include "bodypart.h"
+ #include "character_encumbrance.h"
+
+ #include <algorithm>
+@@ -82,6 +81,7 @@
+ #include "profession.h"
+ #include "recipe_dictionary.h"
+ #include "ret_val.h"
++#include "regen.h"
+ #include "rng.h"
+ #include "scent_map.h"
+ #include "skill.h"
+@@ -5068,14 +5068,11 @@ void Character::regen( int rate_multiplier )
+ float heal_rate = healing_rate( rest ) * to_turns<int>( 5_minutes );
+ const float broken_regen_mod = clamp( mutation_value( "mending_modifier" ), 0.25f, 1.0f );
+ if( heal_rate > 0.0f ) {
+- const int base_heal = roll_remainder( rate_multiplier * heal_rate );
+- const int broken_heal = roll_remainder( base_heal * broken_regen_mod );
++ const int heal = roll_remainder( rate_multiplier * heal_rate );
+
+ for( const bodypart_id &bp : get_all_body_parts() ) {
+- const bool is_broken = is_limb_broken( bp ) &&
+- !worn_with_flag( flag_SPLINT, bp );
+- heal( bp, is_broken ? broken_heal : base_heal );
+- mod_part_healed_total( bp, is_broken ? broken_heal : base_heal );
++ const int actually_healed = heal_adjusted( *this, bp, heal );
++ mod_part_healed_total( bp, actually_healed );
+ }
+ } else if( heal_rate < 0.0f ) {
+ int rot_rate = roll_remainder( rate_multiplier * -heal_rate );
+diff --git a/src/regen.cpp b/src/regen.cpp
+new file mode 100644
+index 00000000000..f8446c4243d
+--- /dev/null
++++ b/src/regen.cpp
+@@ -0,0 +1,35 @@
++#include "regen.h"
++#include "character.h"
++#include "rng.h"
++
++const flag_id flag_SPLINT( "SPLINT" );
++
++namespace
++{
++
++/// Limb is broken without splint
++auto has_broken_limb_penalty( const Character &c, const bodypart_id &bp ) -> bool
++{
++ return c.is_limb_broken( bp )
++ && !c.worn_with_flag( flag_SPLINT, bp );
++}
++
++/// Broken limbs without splint heal slower up to 25%
++auto mending_modifier( const Character &c ) -> float
++{
++ return clamp( c.mutation_value( "mending_modifier" ), 0.25f, 1.0f );
++}
++
++} // namespace
++
++auto heal_adjusted( Character &c, const bodypart_id &bp, const int heal ) -> int
++{
++ const float broken_regen_mod = mending_modifier( c );
++ const int broken_heal = roll_remainder( heal * broken_regen_mod );
++ const bool is_broken = has_broken_limb_penalty( c, bp );
++ const int actual_heal = is_broken ? broken_heal : heal;
++
++ c.heal( bp, actual_heal );
++
++ return actual_heal;
++}
+diff --git a/src/regen.h b/src/regen.h
+new file mode 100644
+index 00000000000..671a8a0e75d
+--- /dev/null
++++ b/src/regen.h
+@@ -0,0 +1,18 @@
++#pragma once
++#ifndef CATA_SRC_REGEN_H
++#define CATA_SRC_REGEN_H
++
++#include "type_id.h"
++
++class Character;
++
++/// like heal, but actually takes account of
++/// - whether limb suffers from being broken without splint
++/// - `mending_modifier`
++///
++/// @return actually healed amount. used for `mod_part_healed_total`
++///
++/// TODO: merge into `Character::heal`?
++auto heal_adjusted( Character &c, const bodypart_id &bp, const int heal ) -> int;
++
++#endif // CATA_SRC_REGEN_H
+--
+2.42.0
+