From 972a47b891c312252be55d063e725c7d7d716447 Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Sat, 30 Mar 2024 14:32:29 -0700 Subject: [PATCH 01/23] Step 1: Adds a very crude value for strain At the moment this is just "stamina but worse" and does not do anything. Bear with me. --- data/core/game_balance.json | 14 +++++++ src/character.cpp | 83 +++++++++++++++++++++++++++++++++++++ src/character.h | 7 ++++ src/magic_enchantment.cpp | 3 ++ src/magic_enchantment.h | 3 ++ 5 files changed, 110 insertions(+) diff --git a/data/core/game_balance.json b/data/core/game_balance.json index 628d09254f79c..249b782ebe789 100644 --- a/data/core/game_balance.json +++ b/data/core/game_balance.json @@ -41,6 +41,20 @@ "stype": "int", "value": 15 }, + { + "type": "EXTERNAL_OPTION", + "name": "PLAYER_BASE_STRAIN", + "info": "Sets the base max strain value of the player, before cardio modifiers.", + "stype": "int", + "value": 5500 + }, + { + "type": "EXTERNAL_OPTION", + "name": "PLAYER_BASE_STRAIN_REGEN_RATE", + "info": "Sets base strain regeneration per turn of the player, before modifiers. May be used as an offset in strain draining effects.", + "stype": "float", + "value": 20 + }, { "type": "EXTERNAL_OPTION", "name": "PLAYER_HUNGER_RATE", diff --git a/src/character.cpp b/src/character.cpp index 1aae3d3c9e8c8..4a11ddc39239d 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -561,6 +561,7 @@ Character::Character() : legs_stam_mult = 1.0f; set_stamina( 10000 ); //Temporary value for stamina. It will be reset later from external json option. cardio_acc = 1000; // Temporary cardio accumulator. It will be updated when reset_cardio_acc is called. + set_strain( 10000 ); //As above for stamina set_anatomy( anatomy_human_anatomy ); update_type_of_scent( true ); pkill = 0; @@ -779,6 +780,8 @@ void Character::mod_stat( const std::string &stat, float modifier ) oxygen += modifier; } else if( stat == "stamina" ) { mod_stamina( modifier ); + } else if( stat == "strain" ) { + mod_strain( modifier ); } else if( stat == "str" ) { mod_str_bonus( modifier ); } else if( stat == "dex" ) { @@ -6808,6 +6811,39 @@ void Character::set_stamina( int new_stamina ) stamina = new_stamina; } +int Character::get_strain() const +{ + if( is_npc() ) { + // No point in doing a bunch of checks on NPCs for now since they can't use strain. + return 10000; + } + return strain; +} + +int Character::get_strain_max() const +{ + if( is_npc() ) { + // No point in doing a bunch of checks on NPCs for now since they can't use strain. + return 10000; + } + + // to start with your strain will be determined pretty chonkily as a global setting for "base + // strain", modified by your fitness determined by cardiofit, which should be 1000-3000. + // This is not meant to be permanent, here I am writing this in March 2024. + // Let's hope this doesn't become one of those funny comments. + static const std::string player_base_strain( "PLAYER_BASE_STRAIN" ); + + int max_strain = get_option( player_base_strain ) + get_cardiofit(); + max_strain = enchantment_cache->modify_value( enchant_vals::mod::MAX_STRAIN, max_strain ); + + return max_strain; +} + +void Character::set_strain( int new_strain ) +{ + strain = new_strain; +} + int Character::get_arms_power_use() const { // millijoules @@ -7055,6 +7091,53 @@ void Character::update_stamina( int turns ) set_stamina( std::min( std::max( get_stamina(), 0 ), max_stam ) ); } +void Character::mod_strain( int mod ) +{ + // At least for now, let's just use the same debug trait as stamina. + if( is_npc() || has_trait( trait_DEBUG_STAMINA ) ) { + return; + } + + strain += mod; + strain = clamp( strain, 0, get_strain_max() ); +} + + +void Character::update_strain( int turns ) +{ + static const std::string player_base_strain_regen_rate( "PLAYER_BASE_STRAIN_REGEN_RATE" ); + const float base_regen_rate = get_option( player_base_strain_regen_rate ); + // Your strain regen rate works as a function of how fit you are compared to your body size. + // This allows it to scale more quickly than your strain, so that at higher fitness levels you + // recover faster. For now we are using cardiofit as a stand-in for a dedicated fitness score + // for strain. + const float effective_regen_rate = base_regen_rate * get_cardiofit() / get_cardio_acc_base(); + // Values above or below normal will increase or decrease strain regen + const float mod_regen = enchantment_cache->modify_value( enchant_vals::mod::STRAIN_REGEN_MOD, 0 ); + const float base_multiplier = mod_regen + 1.0f; + // Ensure multiplier is at least 0.1 + const float strain_multiplier = std::max( 0.1f, base_multiplier ); + + // Recover some strain every turn. Start with zero, then increase recovery factor based on + // mutations. Bionics should get added in here eventually. Stimulants are a matter worth + // debating, but aren't appropriate for a first pass. + float strain_recovery = 0.0f; + strain_recovery += strain_multiplier * std::max( 1.0f, effective_regen_rate ); + + strain_recovery = enchantment_cache->modify_value( enchant_vals::mod::REGEN_STRAIN, + strain_recovery ); + + const int max_strain = get_strain_max(); + + // Roll to determine actual stamina recovery over this period + int recover_amount = std::ceil( strain_recovery * turns ); + mod_strain( recover_amount ); + add_msg_debug( debugmode::DF_CHARACTER, "Strain recovery: %d", recover_amount ); + + // Cap at max + set_strain( std::min( std::max( get_strain(), 0 ), max_strain ) ); +} + int Character::get_cardiofit() const { if( is_npc() ) { diff --git a/src/character.h b/src/character.h index 751374d2f7c4a..474f935eac9a2 100644 --- a/src/character.h +++ b/src/character.h @@ -3049,6 +3049,9 @@ class Character : public Creature, public visitable int get_stamina() const; int get_stamina_max() const; void set_stamina( int new_stamina ); + int get_strain() const; + int get_strain_max() const; + void set_strain( int new_strain ); // burn_energy looks at whether to use bionic power depending on how many limbs are cybernetic, then passes to mod_stamina after void burn_energy_arms( int mod ); void burn_energy_legs( int mod ); @@ -3060,6 +3063,9 @@ class Character : public Creature, public visitable /** Regenerates stamina */ void update_stamina( int turns ); + void mod_strain( int mod ); + void update_strain( int turns ); + int get_cardiofit() const; int get_cardio_acc() const; @@ -3985,6 +3991,7 @@ class Character : public Creature, public visitable int hunger; int thirst; int stamina; + int strain; int cardio_acc; int base_cardio_acc; diff --git a/src/magic_enchantment.cpp b/src/magic_enchantment.cpp index b919ee5f4583c..802707fc84e4d 100644 --- a/src/magic_enchantment.cpp +++ b/src/magic_enchantment.cpp @@ -69,6 +69,8 @@ namespace io case enchant_vals::mod::POWER_TRICKLE: return "POWER_TRICKLE"; case enchant_vals::mod::MAX_STAMINA: return "MAX_STAMINA"; case enchant_vals::mod::REGEN_STAMINA: return "REGEN_STAMINA"; + case enchant_vals::mod::MAX_STRAIN: return "MAX_STRAIN"; + case enchant_vals::mod::REGEN_STRAIN: return "REGEN_STRAIN"; case enchant_vals::mod::FAT_TO_MAX_HP: return "FAT_TO_MAX_HP"; case enchant_vals::mod::CARDIO_MULTIPLIER: return "CARDIO_MULTIPLIER"; case enchant_vals::mod::MAX_HP: return "MAX_HP"; @@ -192,6 +194,7 @@ namespace io case enchant_vals::mod::CONSUME_TIME_MOD: return "CONSUME_TIME_MOD"; case enchant_vals::mod::SWEAT_MULTIPLIER: return "SWEAT_MULTIPLIER"; case enchant_vals::mod::STAMINA_REGEN_MOD: return "STAMINA_REGEN_MOD"; + case enchant_vals::mod::STRAIN_REGEN_MOD: return "STRAIN_REGEN_MOD"; case enchant_vals::mod::MOVEMENT_EXERTION_MODIFIER: return "MOVEMENT_EXERTION_MODIFIER"; case enchant_vals::mod::NUM_MOD: break; } diff --git a/src/magic_enchantment.h b/src/magic_enchantment.h index f138a47a16362..ccc9cbec836db 100644 --- a/src/magic_enchantment.h +++ b/src/magic_enchantment.h @@ -46,6 +46,8 @@ enum class mod : int { POWER_TRICKLE, MAX_STAMINA, REGEN_STAMINA, + MAX_STRAIN, + REGEN_STRAIN, FAT_TO_MAX_HP, CARDIO_MULTIPLIER, MAX_HP, // for all limbs! use with caution @@ -170,6 +172,7 @@ enum class mod : int { CONSUME_TIME_MOD, SWEAT_MULTIPLIER, STAMINA_REGEN_MOD, + STRAIN_REGEN_MOD, MOVEMENT_EXERTION_MODIFIER, NUM_MOD }; From 16196d2ef4740bcf7a3a7b370afbd8840f0a6373 Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Sat, 30 Mar 2024 15:05:31 -0700 Subject: [PATCH 02/23] apply strain in a few spots where it is easy Throwing things, drawing bows, and breaking sticks. --- src/character_body.cpp | 1 + src/iuse.cpp | 2 +- src/ranged.cpp | 30 +++++++++++++++--------------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/character_body.cpp b/src/character_body.cpp index 079cfd6a5d4b7..6592dfc611c05 100644 --- a/src/character_body.cpp +++ b/src/character_body.cpp @@ -202,6 +202,7 @@ void Character::update_body( const time_point &from, const time_point &to ) } if( !is_npc() ) { update_stamina( to_turns( to - from ) ); + update_strain( to_turns( to - from ) ); } if( can_recover_oxygen() && oxygen < get_oxygen_max() ) { oxygen += std::max( static_cast( to_turns( to - from ) * get_stamina() * 5 * get_modifier( diff --git a/src/iuse.cpp b/src/iuse.cpp index 0057bb1dbe528..454eedeecdbd2 100644 --- a/src/iuse.cpp +++ b/src/iuse.cpp @@ -8250,7 +8250,7 @@ std::optional iuse::wash_items( Character *p, bool soft_items, bool hard_it std::optional iuse::break_stick( Character *p, item *it, const tripoint & ) { p->mod_moves( -to_moves( 2_seconds ) ); - p->mod_stamina( static_cast( 0.05f * p->get_stamina_max() ) ); + p->mod_strain( static_cast( 0.05f * p->get_strain_max() ) ); if( p->get_str() < 5 ) { p->add_msg_if_player( _( "You are too weak to even try." ) ); diff --git a/src/ranged.cpp b/src/ranged.cpp index 5606a15c808e3..dfaaa02f9ab15 100644 --- a/src/ranged.cpp +++ b/src/ranged.cpp @@ -1118,14 +1118,14 @@ int throw_cost( const Character &c, const item &to_throw ) const int skill_cost = static_cast( ( base_move_cost * ( 20 - throw_skill ) / 20 ) ); ///\EFFECT_DEX increases throwing speed const int dexbonus = c.get_dex(); - const float stamina_ratio = static_cast( c.get_stamina() ) / c.get_stamina_max(); - const float stamina_penalty = 1.0 + std::max( ( 0.25f - stamina_ratio ) * 4.0f, 0.0f ); + const float strain_ratio = static_cast( c.get_strain() ) / c.get_strain_max(); + const float strain_penalty = 1.0 + std::max( ( 0.25f - strain_ratio ) * 4.0f, 0.0f ); int move_cost = base_move_cost; move_cost *= c.get_modifier( character_modifier_melee_thrown_move_lift_mod ); move_cost *= c.get_modifier( character_modifier_melee_thrown_move_balance_mod ); - // Stamina penalty only affects base/2 and encumbrance parts of the cost - move_cost *= stamina_penalty; + // strain penalty only affects base/2 and encumbrance parts of the cost + move_cost *= strain_penalty; move_cost += skill_cost; move_cost -= dexbonus; move_cost = c.enchantment_cache->modify_value( enchant_vals::mod::ATTACK_SPEED, move_cost ); @@ -1317,8 +1317,8 @@ dealt_projectile_attack Character::throw_item( const tripoint &target, const ite const std::optional throw_assist = character_throw_assist( *this ); if( !throw_assist ) { - const int stamina_cost = get_standard_stamina_cost( &thrown ); - mod_stamina( stamina_cost + throwing_skill ); + const int strain_cost = get_standard_stamina_cost( &thrown ); + mod_strain( strain_cost + throwing_skill ); } const float skill_level = throwing_skill_adjusted( *this ); @@ -1490,24 +1490,24 @@ void practice_archery_proficiency( Character &p, const item &relevant ) } } -// Apply stamina cost to archery which decreases due to proficiency -static void mod_stamina_archery( Character &you, const item &relevant ) +// Apply strain cost to archery which decreases due to proficiency +static void mod_strain_archery( Character &you, const item &relevant ) { // Set activity level to 10 * str_ratio, with 10 being max (EXTRA_EXERCISE) // This ratio should never be below 0 and above 1 const float str_ratio = static_cast( relevant.get_min_str() ) / you.str_cur; you.set_activity_level( 10 * str_ratio ); - // Calculate stamina drain based on archery, athletics skill, and effective bow strength ratio + // Calculate srain drain based on archery, athletics skill, and effective bow strength ratio const float archery_skill = you.get_skill_level( skill_archery ); const float athletics_skill = you.get_skill_level( skill_swimming ); const float skill_modifier = ( 2.0f * archery_skill + athletics_skill ) / 3.0f; - const int stamina_cost = pow( 10.0f * str_ratio + 10 - skill_modifier, 2 ); + const int strain_cost = pow( 10.0f * str_ratio + 10 - skill_modifier, 2 ); - you.mod_stamina( -stamina_cost ); + you.mod_strain( -strain_cost ); add_msg_debug( debugmode::DF_RANGED, - "-%i stamina: %.1f str ratio, %.1f skill mod", - stamina_cost, str_ratio, skill_modifier ); + "-%i strain: %.1f str ratio, %.1f skill mod", + strain_cost, str_ratio, skill_modifier ); } static void do_aim( Character &you, const item &relevant, const double min_recoil ) @@ -1522,9 +1522,9 @@ static void do_aim( Character &you, const item &relevant, const double min_recoi if( relevant.gun_skill() == skill_archery ) { practice_archery_proficiency( you, relevant ); - // Only drain stamina on initial draw + // Only drain strain on initial draw if( you.get_moves() == 1 ) { - mod_stamina_archery( you, relevant ); + mod_strain_archery( you, relevant ); } } } else { From 5a6e77d58d17d3a28ba08cd9cdf1e8336ba8ecc8 Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Sun, 31 Mar 2024 09:16:12 -0700 Subject: [PATCH 03/23] burn_energy_arms uses strain too this is a coarse split that assumes all arms usage is the same, but honestly it might work fine. --- src/character.cpp | 17 ++++++++++++++--- src/character.h | 2 ++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/character.cpp b/src/character.cpp index 4a11ddc39239d..a1ab6c81f5faf 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -557,8 +557,9 @@ Character::Character() : set_stim( 0 ); arms_power_use = 0; legs_power_use = 0; - arms_stam_mult = 1.0f; + arms_stam_mult = 0.25f; legs_stam_mult = 1.0f; + arms_strain_mult = 1.0f; set_stamina( 10000 ); //Temporary value for stamina. It will be reset later from external json option. cardio_acc = 1000; // Temporary cardio accumulator. It will be updated when reset_cardio_acc is called. set_strain( 10000 ); //As above for stamina @@ -6866,6 +6867,11 @@ float Character::get_legs_stam_mult() const return legs_stam_mult; } +float Character::get_arms_strain_mult() const +{ + return arms_strain_mult; +} + void Character::recalc_limb_energy_usage() { // calculate energy usage of arms @@ -6882,9 +6888,11 @@ void Character::recalc_limb_energy_usage() } arms_power_use = bionic_powercost; if( bionic_limb_count > 0 ) { - arms_stam_mult = 1 - ( bionic_limb_count / total_limb_count ); + arms_stam_mult = 0.25f * ( 1 - ( bionic_limb_count / total_limb_count ) ); + arms_strain_mult = 1 - ( bionic_limb_count / total_limb_count ); } else { - arms_stam_mult = 1.0f; + arms_stam_mult = 0.25f; + arms_strain_mult = 1.0f; } //sanity check ourselves in debug add_msg_debug( debugmode::DF_CHAR_HEALTH, "Total arms in use: %.1f, Bionic arms: %.1f", @@ -6892,6 +6900,7 @@ void Character::recalc_limb_energy_usage() bionic_limb_count ); add_msg_debug( debugmode::DF_CHAR_HEALTH, "bionic power per arms stamina: %d", arms_power_use ); add_msg_debug( debugmode::DF_CHAR_HEALTH, "arms stam usage mult by %.1f", arms_stam_mult ); + add_msg_debug( debugmode::DF_CHAR_HEALTH, "arms strain usage mult by %.1f", arms_strain_mult ); // calculate energy usage of legs total_limb_count = 0.0f; @@ -6922,6 +6931,7 @@ void Character::recalc_limb_energy_usage() void Character::burn_energy_arms( int mod ) { mod_stamina( mod * get_arms_stam_mult() ); + mod_strain( mod * get_arms_strain_mult() ); if( get_arms_power_use() > 0 ) { mod_power_level( units::from_millijoule( mod * get_arms_power_use() ) ); } @@ -6938,6 +6948,7 @@ void Character::burn_energy_legs( int mod ) void Character::burn_energy_all( int mod ) { mod_stamina( mod * ( get_arms_stam_mult() + get_legs_stam_mult() ) * 0.5f ); + mod_strain( mod * ( get_arms_strain_mult() * 0.5f ) ); if( ( get_arms_power_use() + get_legs_power_use() ) > 0 ) { mod_power_level( units::from_millijoule( mod * ( get_arms_power_use() + get_legs_power_use() ) ) ); } diff --git a/src/character.h b/src/character.h index 474f935eac9a2..ec426360551ac 100644 --- a/src/character.h +++ b/src/character.h @@ -620,11 +620,13 @@ class Character : public Creature, public visitable int legs_power_use; // millijoules float arms_stam_mult; float legs_stam_mult; + float arms_strain_mult; /** Getters for above stats */ int get_arms_power_use() const; int get_legs_power_use() const; float get_arms_stam_mult() const; float get_legs_stam_mult() const; + float get_arms_strain_mult() const; private: /** Modifiers to character speed, with descriptions */ From d1643a7b82b40ef1b3308af90551e205f3f3e511 Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Fri, 5 Apr 2024 13:10:51 -0700 Subject: [PATCH 04/23] Widget quick fix by Renech Still needs work but it's a start --- data/json/ui/layout.json | 2 +- data/json/ui/stamina.json | 25 +++++++++++++++++++++++++ src/widget.cpp | 9 +++++++++ src/widget.h | 1 + 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/data/json/ui/layout.json b/data/json/ui/layout.json index d5d2a460df45c..3e1036e0c6793 100644 --- a/data/json/ui/layout.json +++ b/data/json/ui/layout.json @@ -99,7 +99,7 @@ "style": "layout", "label": "Stamina/Weariness", "arrange": "rows", - "widgets": [ "stamina_graph", "activity_desc", "weariness_desc", "weary_malus_desc" ] + "widgets": [ "stamina_graph", "strain_graph", "activity_desc", "weariness_desc", "weary_malus_desc" ] }, { "id": "mood_focus_layout", diff --git a/data/json/ui/stamina.json b/data/json/ui/stamina.json index 59119a8a83f0f..5e9bfa0bb2173 100644 --- a/data/json/ui/stamina.json +++ b/data/json/ui/stamina.json @@ -24,6 +24,31 @@ "width": 10, "symbols": ".\\|" }, + { + "id": "strain_widget", + "type": "widget", + "var": "strain_widget", + "colors": [ "c_red", "c_light_red", "c_yellow", "c_light_green", "c_green" ] + }, + { + "id": "strain_graph_classic", + "type": "widget", + "copy-from": "strain_widget", + "label": "Strain", + "style": "graph", + "width": 5, + "symbols": ".\\|" + }, + { + "id": "strain_graph", + "type": "widget", + "copy-from": "strain_widget", + "//": "Like the classic 5-bar stamina graph, but twice as wide", + "label": "Strain", + "style": "graph", + "width": 10, + "symbols": ".\\|" + }, { "id": "stamina_num_label", "type": "widget", diff --git a/src/widget.cpp b/src/widget.cpp index 326aba020d6e1..17ee75a2398e6 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -82,6 +82,8 @@ std::string enum_to_string( widget_var data ) return "speed"; case widget_var::stamina: return "stamina"; + case widget_var::strain: + return "strain"; case widget_var::fatigue: return "fatigue"; case widget_var::health: @@ -671,6 +673,10 @@ void widget::set_default_var_range( const avatar &ava ) _var_max = ava.get_stamina_max(); // No normal defined, unless we want max stamina to be colored white? (maybe) break; + case widget_var::strain: + _var_min = 0; + _var_max = ava.get_strain_max(); // IDK, fill me in Erk + break; case widget_var::weariness_level: _var_min = 0; _var_max = 10; @@ -748,6 +754,9 @@ int widget::get_var_value( const avatar &ava ) const case widget_var::stamina: value = ava.get_stamina(); break; + case widget_var::strain: + value = ava.get_strain(); // IDK, fill me in erk! + break; case widget_var::mana: value = ava.magic->available_mana(); break; diff --git a/src/widget.h b/src/widget.h index ef7771566b805..4a2b57cb8d818 100644 --- a/src/widget.h +++ b/src/widget.h @@ -24,6 +24,7 @@ enum class widget_var : int { sound, // Current sound level, integer speed, // Current speed, integer stamina, // Current stamina 0-10000, greater being fuller stamina reserves + strain, // Current strain something something IDK the implementation fatigue, // Current fatigue, integer health, // Current hidden health value, -200 to +200 mana, // Current available mana, integer From c63d889b8d158423b1f5998e26d90320ba2b28e6 Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Fri, 5 Apr 2024 16:26:30 -0700 Subject: [PATCH 05/23] Fix widget. Strain works now. --- data/json/ui/stamina.json | 4 ++-- src/widget.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/data/json/ui/stamina.json b/data/json/ui/stamina.json index 5e9bfa0bb2173..7650c07ca3418 100644 --- a/data/json/ui/stamina.json +++ b/data/json/ui/stamina.json @@ -27,8 +27,8 @@ { "id": "strain_widget", "type": "widget", - "var": "strain_widget", - "colors": [ "c_red", "c_light_red", "c_yellow", "c_light_green", "c_green" ] + "var": "strain", + "colors": [ "c_green", "c_light_green", "c_yellow", "c_light_red", "c_red" ] }, { "id": "strain_graph_classic", diff --git a/src/widget.cpp b/src/widget.cpp index 17ee75a2398e6..c97d1c5b8976e 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -675,7 +675,7 @@ void widget::set_default_var_range( const avatar &ava ) break; case widget_var::strain: _var_min = 0; - _var_max = ava.get_strain_max(); // IDK, fill me in Erk + _var_max = ava.get_strain_max(); break; case widget_var::weariness_level: _var_min = 0; @@ -755,7 +755,7 @@ int widget::get_var_value( const avatar &ava ) const value = ava.get_stamina(); break; case widget_var::strain: - value = ava.get_strain(); // IDK, fill me in erk! + value = ava.get_strain_max() - ava.get_strain(); break; case widget_var::mana: value = ava.magic->available_mana(); From 9d2dd4ff805f64a9920725b59cfd4cf128c31afd Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Fri, 5 Apr 2024 16:40:12 -0700 Subject: [PATCH 06/23] some balance adjustments --- data/core/game_balance.json | 4 ++-- src/character.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/data/core/game_balance.json b/data/core/game_balance.json index 249b782ebe789..99c9b459eb061 100644 --- a/data/core/game_balance.json +++ b/data/core/game_balance.json @@ -46,14 +46,14 @@ "name": "PLAYER_BASE_STRAIN", "info": "Sets the base max strain value of the player, before cardio modifiers.", "stype": "int", - "value": 5500 + "value": 500 }, { "type": "EXTERNAL_OPTION", "name": "PLAYER_BASE_STRAIN_REGEN_RATE", "info": "Sets base strain regeneration per turn of the player, before modifiers. May be used as an offset in strain draining effects.", "stype": "float", - "value": 20 + "value": 50 }, { "type": "EXTERNAL_OPTION", diff --git a/src/character.cpp b/src/character.cpp index a1ab6c81f5faf..3d8344e430571 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -6834,7 +6834,7 @@ int Character::get_strain_max() const // Let's hope this doesn't become one of those funny comments. static const std::string player_base_strain( "PLAYER_BASE_STRAIN" ); - int max_strain = get_option( player_base_strain ) + get_cardiofit(); + int max_strain = get_option( player_base_strain ) + get_cardiofit() / 10; max_strain = enchantment_cache->modify_value( enchant_vals::mod::MAX_STRAIN, max_strain ); return max_strain; From bef204edae557afdddbb74ceca256e84304c9f1c Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Fri, 5 Apr 2024 23:20:28 -0700 Subject: [PATCH 07/23] this isn't working but should stop attacks at high strain --- data/core/game_balance.json | 2 +- src/handle_action.cpp | 5 +++++ src/melee.cpp | 18 ++++++++++++------ 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/data/core/game_balance.json b/data/core/game_balance.json index 99c9b459eb061..98288361417b6 100644 --- a/data/core/game_balance.json +++ b/data/core/game_balance.json @@ -53,7 +53,7 @@ "name": "PLAYER_BASE_STRAIN_REGEN_RATE", "info": "Sets base strain regeneration per turn of the player, before modifiers. May be used as an offset in strain draining effects.", "stype": "float", - "value": 50 + "value": 20 }, { "type": "EXTERNAL_OPTION", diff --git a/src/handle_action.cpp b/src/handle_action.cpp index c297ab5fc57aa..2bbfd6fab1127 100644 --- a/src/handle_action.cpp +++ b/src/handle_action.cpp @@ -862,6 +862,11 @@ static void smash() if( player_character.is_mounted() ) { mech_smash = true; } + + if( !mech_smash && player_character.get_strain() != player_character.get_strain_max() && player_character.get_strain() < 2 * player_character.get_standard_stamina_cost() ){ + add_msg( m_bad, _( "Your muscles are too strained to smash!" ) ); + return; + } const bool allow_floor_bash = debug_mode; // Should later become "true" const std::optional smashp_ = choose_adjacent( _( "Smash where?" ), allow_floor_bash ); diff --git a/src/melee.cpp b/src/melee.cpp index cfca573150bb5..e7463ef4e82c6 100644 --- a/src/melee.cpp +++ b/src/melee.cpp @@ -654,6 +654,18 @@ bool Character::melee_attack_abstract( Creature &t, bool allow_special, } const bool hits = hit_spread >= 0; + + /** @EFFECT_MELEE reduces stamina cost of melee attacks */ + const int deft_bonus = !hits && has_trait( trait_DEFT ) ? 50 : 0; + const int base_stam = get_base_melee_stamina_cost(); + const int total_stam = enchantment_cache->modify_value( + enchant_vals::mod::MELEE_STAMINA_CONSUMPTION, + get_total_melee_stamina_cost() ); + + if( get_strain() != get_strain_max() && get_strain() < std::min( 50, total_stam + deft_bonus ) ){ + add_msg( m_bad, _( "Your muscles are too strained to make an attack!" ) ); + return false; + } if( monster *m = t.as_monster() ) { cata::event e = cata::event::make( getID(), @@ -936,12 +948,6 @@ bool Character::melee_attack_abstract( Creature &t, bool allow_special, handle_melee_wear( cur_weapon ); } - /** @EFFECT_MELEE reduces stamina cost of melee attacks */ - const int deft_bonus = !hits && has_trait( trait_DEFT ) ? 50 : 0; - const int base_stam = get_base_melee_stamina_cost(); - const int total_stam = enchantment_cache->modify_value( - enchant_vals::mod::MELEE_STAMINA_CONSUMPTION, - get_total_melee_stamina_cost() ); burn_energy_arms( std::min( -50, total_stam + deft_bonus ) ); add_msg_debug( debugmode::DF_MELEE, "Stamina burn base/total (capped at -50): %d/%d", base_stam, From 3758a56b9aac6b37a7b389774766871c4bb3a491 Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Sat, 6 Apr 2024 11:25:40 -0700 Subject: [PATCH 08/23] Too much strain stops you from bashing and smashing It works now. Still a bit clunky. weariness also impacts strain recovery at high levels. --- data/core/game_balance.json | 2 +- src/character.cpp | 4 +++- src/handle_action.cpp | 2 +- src/melee.cpp | 6 +++++- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/data/core/game_balance.json b/data/core/game_balance.json index 98288361417b6..e125042aba4c5 100644 --- a/data/core/game_balance.json +++ b/data/core/game_balance.json @@ -53,7 +53,7 @@ "name": "PLAYER_BASE_STRAIN_REGEN_RATE", "info": "Sets base strain regeneration per turn of the player, before modifiers. May be used as an offset in strain draining effects.", "stype": "float", - "value": 20 + "value": 40 }, { "type": "EXTERNAL_OPTION", diff --git a/src/character.cpp b/src/character.cpp index 3d8344e430571..5be3f9b13e281 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -7122,7 +7122,9 @@ void Character::update_strain( int turns ) // This allows it to scale more quickly than your strain, so that at higher fitness levels you // recover faster. For now we are using cardiofit as a stand-in for a dedicated fitness score // for strain. - const float effective_regen_rate = base_regen_rate * get_cardiofit() / get_cardio_acc_base(); + const float effective_regen_rate = base_regen_rate * ( get_cardiofit() / get_cardio_acc_base() ) + * std::min( 1.0f, 2000.0f/weariness()); + add_msg( m_bad, _( "effective regen rate: %f, base rate: %f, cardio mod: %d, weary mod: %f" ), effective_regen_rate, base_regen_rate, get_cardiofit() / get_cardio_acc_base(), std::min( 1.0f, 2000.0f/weariness()) ); // Values above or below normal will increase or decrease strain regen const float mod_regen = enchantment_cache->modify_value( enchant_vals::mod::STRAIN_REGEN_MOD, 0 ); const float base_multiplier = mod_regen + 1.0f; diff --git a/src/handle_action.cpp b/src/handle_action.cpp index 2bbfd6fab1127..41ab36e9385ac 100644 --- a/src/handle_action.cpp +++ b/src/handle_action.cpp @@ -863,7 +863,7 @@ static void smash() mech_smash = true; } - if( !mech_smash && player_character.get_strain() != player_character.get_strain_max() && player_character.get_strain() < 2 * player_character.get_standard_stamina_cost() ){ + if( !mech_smash && player_character.get_strain() <= player_character.get_strain_max() * 0.25 ){ add_msg( m_bad, _( "Your muscles are too strained to smash!" ) ); return; } diff --git a/src/melee.cpp b/src/melee.cpp index e7463ef4e82c6..945e97d1ec2bc 100644 --- a/src/melee.cpp +++ b/src/melee.cpp @@ -571,6 +571,10 @@ bool Character::melee_attack( Creature &t, bool allow_special, const matec_id &f if( !is_adjacent( &t, true ) ) { return false; } + if( get_strain() <= 0 ){ + add_msg( m_bad, _( "NO ATTACK FOR YOU!" ) ); + return false; + } // Max out recoil & reset aim point recoil = MAX_RECOIL; @@ -662,7 +666,7 @@ bool Character::melee_attack_abstract( Creature &t, bool allow_special, enchant_vals::mod::MELEE_STAMINA_CONSUMPTION, get_total_melee_stamina_cost() ); - if( get_strain() != get_strain_max() && get_strain() < std::min( 50, total_stam + deft_bonus ) ){ + if( get_strain() != get_strain_max() && get_strain() < abs( std::min( -50, total_stam + deft_bonus ) ) ){ add_msg( m_bad, _( "Your muscles are too strained to make an attack!" ) ); return false; } From 83e468bf375aead8c569e186bd6332d736ab0db2 Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Sat, 6 Apr 2024 23:10:07 -0700 Subject: [PATCH 09/23] Nearly ready for primetime maybe tune strain to target ~8-10 sledge swings Add burn --- data/core/game_balance.json | 4 +-- src/character.cpp | 72 +++++++++++++++++++++++++++++++++---- src/character.h | 5 +++ src/melee.cpp | 8 ++--- 4 files changed, 76 insertions(+), 13 deletions(-) diff --git a/data/core/game_balance.json b/data/core/game_balance.json index 6e00c89966ab0..21ad3637545d1 100644 --- a/data/core/game_balance.json +++ b/data/core/game_balance.json @@ -46,14 +46,14 @@ "name": "PLAYER_BASE_STRAIN", "info": "Sets the base max strain value of the player, before cardio modifiers.", "stype": "int", - "value": 500 + "value": 4000 }, { "type": "EXTERNAL_OPTION", "name": "PLAYER_BASE_STRAIN_REGEN_RATE", "info": "Sets base strain regeneration per turn of the player, before modifiers. May be used as an offset in strain draining effects.", "stype": "float", - "value": 40 + "value": 120 }, { "type": "EXTERNAL_OPTION", diff --git a/src/character.cpp b/src/character.cpp index 0fd6131af4531..e9423055db534 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -568,7 +568,8 @@ Character::Character() : arms_strain_mult = 1.0f; set_stamina( 10000 ); //Temporary value for stamina. It will be reset later from external json option. cardio_acc = 1000; // Temporary cardio accumulator. It will be updated when reset_cardio_acc is called. - set_strain( 10000 ); //As above for stamina + set_strain( 5000 ); //As above for stamina + set_strain_burn( 0 ); //As above for stamina set_anatomy( anatomy_human_anatomy ); update_type_of_scent( true ); pkill = 0; @@ -6825,6 +6826,15 @@ int Character::get_strain() const return strain; } +int Character::get_strain_burn() const +{ + if( is_npc() ) { + // No point in doing a bunch of checks on NPCs for now since they can't use strain. + return 0; + } + return strain_burn; +} + int Character::get_strain_max() const { if( is_npc() ) { @@ -6838,8 +6848,12 @@ int Character::get_strain_max() const // Let's hope this doesn't become one of those funny comments. static const std::string player_base_strain( "PLAYER_BASE_STRAIN" ); - int max_strain = get_option( player_base_strain ) + get_cardiofit() / 10; + int max_strain = get_option( player_base_strain ) + get_cardiofit() / 5; max_strain = enchantment_cache->modify_value( enchant_vals::mod::MAX_STRAIN, max_strain ); + + // max possible strain is reduced by muscle burn, which takes longer to recover. However, + // your muscles should never be so strained that you can't do anything at all. + max_strain = std::max( max_strain / 4, max_strain - get_strain_burn() ); return max_strain; } @@ -6849,6 +6863,11 @@ void Character::set_strain( int new_strain ) strain = new_strain; } +void Character::set_strain_burn( int new_strain_burn ) +{ + strain_burn = new_strain_burn; +} + int Character::get_arms_power_use() const { // millijoules @@ -7112,14 +7131,46 @@ void Character::mod_strain( int mod ) if( is_npc() || has_trait( trait_DEBUG_STAMINA ) ) { return; } - strain += mod; + if ( mod < 0 ) { + used_strain_this_turn = true; + add_msg_debug( debugmode::DF_CHARACTER, "Used strain this turn, recovery disabled" ); + } + + if ( mod < 0 && strain < get_strain_max() / 2 ) { + // if strain is decreasing and getting into the higher numbers, bump burn up. + // burn rises a little regardless, but far more if you're doing something really + // powerful. + int burn = mod * -2; + add_msg_debug( debugmode::DF_CHARACTER, "Burn increased by %i", burn ); + mod_strain_burn( burn ); + } strain = clamp( strain, 0, get_strain_max() ); } +void Character::mod_strain_burn( int mod ) +{ + if( is_npc() ) { + return; + } + + strain_burn += mod; + strain_burn = clamp( strain_burn, 0, get_strain_max() ); +} + void Character::update_strain( int turns ) { + if ( used_strain_this_turn ){ + // Don't recover strain if we used it, just flip the flag. + // This is necessary because strain recovers so quickly that without this, + // it's not possible to build up strain on lightweight things. + turns -= 1; + used_strain_this_turn = false; + if( turns == 0 ){ + return; + } + } static const std::string player_base_strain_regen_rate( "PLAYER_BASE_STRAIN_REGEN_RATE" ); const float base_regen_rate = get_option( player_base_strain_regen_rate ); // Your strain regen rate works as a function of how fit you are compared to your body size. @@ -7128,7 +7179,7 @@ void Character::update_strain( int turns ) // for strain. const float effective_regen_rate = base_regen_rate * ( get_cardiofit() / get_cardio_acc_base() ) * std::min( 1.0f, 2000.0f/weariness()); - add_msg( m_bad, _( "effective regen rate: %f, base rate: %f, cardio mod: %d, weary mod: %f" ), effective_regen_rate, base_regen_rate, get_cardiofit() / get_cardio_acc_base(), std::min( 1.0f, 2000.0f/weariness()) ); + add_msg_debug( debugmode::DF_CHARACTER, "effective strain regen rate: %f, base rate: %f, cardio mod: %d, weary mod: %f", effective_regen_rate, base_regen_rate, get_cardiofit() / get_cardio_acc_base(), std::min( 1.0f, 2000.0f / weariness()) ); // Values above or below normal will increase or decrease strain regen const float mod_regen = enchantment_cache->modify_value( enchant_vals::mod::STRAIN_REGEN_MOD, 0 ); const float base_multiplier = mod_regen + 1.0f; @@ -7144,12 +7195,21 @@ void Character::update_strain( int turns ) strain_recovery = enchantment_cache->modify_value( enchant_vals::mod::REGEN_STRAIN, strain_recovery ); + const int current_strain = get_strain(); const int max_strain = get_strain_max(); + const int current_strain_burn = get_strain_burn(); - // Roll to determine actual stamina recovery over this period int recover_amount = std::ceil( strain_recovery * turns ); + int recover_burn_amount = 0; mod_strain( recover_amount ); - add_msg_debug( debugmode::DF_CHARACTER, "Strain recovery: %d", recover_amount ); + if( current_strain > max_strain / 2 ) { + recover_burn_amount = std::max( 1, recover_amount / 50); + mod_strain_burn( recover_burn_amount * -1 ); + } + add_msg_debug( debugmode::DF_CHARACTER, "Current strain: %i, Max strain: %i, Current burn: %i", current_strain, + max_strain, current_strain_burn ); + add_msg_debug( debugmode::DF_CHARACTER, "Strain recovery: %i, burn recovery: %i", recover_amount, + recover_burn_amount ); // Cap at max set_strain( std::min( std::max( get_strain(), 0 ), max_strain ) ); diff --git a/src/character.h b/src/character.h index 1b61f937d153b..fbf5dee637b13 100644 --- a/src/character.h +++ b/src/character.h @@ -3072,7 +3072,9 @@ class Character : public Creature, public visitable void set_stamina( int new_stamina ); int get_strain() const; int get_strain_max() const; + int get_strain_burn() const; void set_strain( int new_strain ); + void set_strain_burn( int new_strain_burn ); // burn_energy looks at whether to use bionic power depending on how many limbs are cybernetic, then passes to mod_stamina after void burn_energy_arms( int mod ); void burn_energy_legs( int mod ); @@ -3086,6 +3088,7 @@ class Character : public Creature, public visitable void mod_strain( int mod ); void update_strain( int turns ); + void mod_strain_burn( int mod ); int get_cardiofit() const; @@ -4013,6 +4016,8 @@ class Character : public Creature, public visitable int thirst; int stamina; int strain; + int strain_burn; + bool used_strain_this_turn = false; int cardio_acc; int base_cardio_acc; diff --git a/src/melee.cpp b/src/melee.cpp index 6f6c104be0bc0..b4980081475a2 100644 --- a/src/melee.cpp +++ b/src/melee.cpp @@ -573,10 +573,6 @@ bool Character::melee_attack( Creature &t, bool allow_special, const matec_id &f if( !is_adjacent( &t, true ) ) { return false; } - if( get_strain() <= 0 ){ - add_msg( m_bad, _( "NO ATTACK FOR YOU!" ) ); - return false; - } // Max out recoil & reset aim point recoil = MAX_RECOIL; @@ -676,9 +672,11 @@ bool Character::melee_attack_abstract( Creature &t, bool allow_special, const int total_stam = enchantment_cache->modify_value( enchant_vals::mod::MELEE_STAMINA_CONSUMPTION, get_total_melee_stamina_cost() ); + const int strain_cost = std::min( -50, total_stam + deft_bonus ); - if( get_strain() != get_strain_max() && get_strain() < abs( std::min( -50, total_stam + deft_bonus ) ) ){ + if( get_strain() < get_strain_max() * 0.75 && get_strain() < abs( strain_cost ) ){ add_msg( m_bad, _( "Your muscles are too strained to make an attack!" ) ); + add_msg_debug( debugmode::DF_CHARACTER, "Strain cost: %i, max strain: %1 strain left: %i", strain_cost, get_strain_max(), get_strain() ); return false; } From f1dfaaab87ef38117a189ebb039c036cc9cab477 Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Sat, 6 Apr 2024 23:32:44 -0700 Subject: [PATCH 10/23] Astyle this was a lot of work to accomplish --- src/character.cpp | 35 ++++++++++++++++++++--------------- src/handle_action.cpp | 4 ++-- src/melee.cpp | 9 +++++---- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/character.cpp b/src/character.cpp index e9423055db534..fe4bf3e5a6eeb 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -6850,8 +6850,8 @@ int Character::get_strain_max() const int max_strain = get_option( player_base_strain ) + get_cardiofit() / 5; max_strain = enchantment_cache->modify_value( enchant_vals::mod::MAX_STRAIN, max_strain ); - - // max possible strain is reduced by muscle burn, which takes longer to recover. However, + + // max possible strain is reduced by muscle burn, which takes longer to recover. However, // your muscles should never be so strained that you can't do anything at all. max_strain = std::max( max_strain / 4, max_strain - get_strain_burn() ); @@ -7132,12 +7132,13 @@ void Character::mod_strain( int mod ) return; } strain += mod; - if ( mod < 0 ) { + if( mod < 0 ) { used_strain_this_turn = true; - add_msg_debug( debugmode::DF_CHARACTER, "Used strain this turn, recovery disabled" ); + add_msg_debug( debugmode::DF_CHARACTER, + "Used strain this turn, recovery disabled" ); } - - if ( mod < 0 && strain < get_strain_max() / 2 ) { + + if( mod < 0 && strain < get_strain_max() / 2 ) { // if strain is decreasing and getting into the higher numbers, bump burn up. // burn rises a little regardless, but far more if you're doing something really // powerful. @@ -7161,13 +7162,13 @@ void Character::mod_strain_burn( int mod ) void Character::update_strain( int turns ) { - if ( used_strain_this_turn ){ + if( used_strain_this_turn ) { // Don't recover strain if we used it, just flip the flag. // This is necessary because strain recovers so quickly that without this, // it's not possible to build up strain on lightweight things. turns -= 1; used_strain_this_turn = false; - if( turns == 0 ){ + if( turns == 0 ) { return; } } @@ -7177,9 +7178,12 @@ void Character::update_strain( int turns ) // This allows it to scale more quickly than your strain, so that at higher fitness levels you // recover faster. For now we are using cardiofit as a stand-in for a dedicated fitness score // for strain. - const float effective_regen_rate = base_regen_rate * ( get_cardiofit() / get_cardio_acc_base() ) - * std::min( 1.0f, 2000.0f/weariness()); - add_msg_debug( debugmode::DF_CHARACTER, "effective strain regen rate: %f, base rate: %f, cardio mod: %d, weary mod: %f", effective_regen_rate, base_regen_rate, get_cardiofit() / get_cardio_acc_base(), std::min( 1.0f, 2000.0f / weariness()) ); + const float effective_regen_rate = base_regen_rate * ( get_cardiofit() / get_cardio_acc_base() ) + * std::min( 1.0f, 2000.0f / weariness() ); + add_msg_debug( debugmode::DF_CHARACTER, + "effective strain regen rate: %f, base rate: %f, cardio mod: %d, weary mod: %f", + effective_regen_rate, base_regen_rate, get_cardiofit() / get_cardio_acc_base(), std::min( 1.0f, + 2000.0f / weariness() ) ); // Values above or below normal will increase or decrease strain regen const float mod_regen = enchantment_cache->modify_value( enchant_vals::mod::STRAIN_REGEN_MOD, 0 ); const float base_multiplier = mod_regen + 1.0f; @@ -7203,13 +7207,14 @@ void Character::update_strain( int turns ) int recover_burn_amount = 0; mod_strain( recover_amount ); if( current_strain > max_strain / 2 ) { - recover_burn_amount = std::max( 1, recover_amount / 50); + recover_burn_amount = std::max( 1, recover_amount / 50 ); mod_strain_burn( recover_burn_amount * -1 ); } - add_msg_debug( debugmode::DF_CHARACTER, "Current strain: %i, Max strain: %i, Current burn: %i", current_strain, - max_strain, current_strain_burn ); + add_msg_debug( debugmode::DF_CHARACTER, "Current strain: %i, Max strain: %i, Current burn: %i", + current_strain, + max_strain, current_strain_burn ); add_msg_debug( debugmode::DF_CHARACTER, "Strain recovery: %i, burn recovery: %i", recover_amount, - recover_burn_amount ); + recover_burn_amount ); // Cap at max set_strain( std::min( std::max( get_strain(), 0 ), max_strain ) ); diff --git a/src/handle_action.cpp b/src/handle_action.cpp index 9cab121a34061..e47165461d962 100644 --- a/src/handle_action.cpp +++ b/src/handle_action.cpp @@ -864,8 +864,8 @@ static void smash() if( player_character.is_mounted() ) { mech_smash = true; } - - if( !mech_smash && player_character.get_strain() <= player_character.get_strain_max() * 0.25 ){ + + if( !mech_smash && player_character.get_strain() <= player_character.get_strain_max() * 0.25 ) { add_msg( m_bad, _( "Your muscles are too strained to smash!" ) ); return; } diff --git a/src/melee.cpp b/src/melee.cpp index b4980081475a2..2758d3ce20cac 100644 --- a/src/melee.cpp +++ b/src/melee.cpp @@ -665,7 +665,7 @@ bool Character::melee_attack_abstract( Creature &t, bool allow_special, } const bool hits = hit_spread >= 0; - + /** @EFFECT_MELEE reduces stamina cost of melee attacks */ const int deft_bonus = !hits && has_trait( trait_DEFT ) ? 50 : 0; const int base_stam = get_base_melee_stamina_cost(); @@ -673,10 +673,11 @@ bool Character::melee_attack_abstract( Creature &t, bool allow_special, enchant_vals::mod::MELEE_STAMINA_CONSUMPTION, get_total_melee_stamina_cost() ); const int strain_cost = std::min( -50, total_stam + deft_bonus ); - - if( get_strain() < get_strain_max() * 0.75 && get_strain() < abs( strain_cost ) ){ + + if( get_strain() < get_strain_max() * 0.75 && get_strain() < abs( strain_cost ) ) { add_msg( m_bad, _( "Your muscles are too strained to make an attack!" ) ); - add_msg_debug( debugmode::DF_CHARACTER, "Strain cost: %i, max strain: %1 strain left: %i", strain_cost, get_strain_max(), get_strain() ); + add_msg_debug( debugmode::DF_CHARACTER, "Strain cost: %i, max strain: %1 strain left: %i", + strain_cost, get_strain_max(), get_strain() ); return false; } From e3a9e2e696f52b3d4ba758b8a1000fe68078cd32 Mon Sep 17 00:00:00 2001 From: RenechCDDA <84619419+RenechCDDA@users.noreply.github.com> Date: Mon, 8 Apr 2024 15:37:36 -0400 Subject: [PATCH 11/23] I SHOULD NOT BE TRUSTED WITH UI (#32) * Make strain and burn accessible through dialogue * HORRIBLE strain widget please don't follow my example * Prettify strain sidebar * Don't overlap IDs --- data/json/ui/layout.json | 2 +- data/json/ui/strain.json | 251 +++++++++++++++++++++++++++++++++++++++ doc/NPCs.md | 3 + src/condition.cpp | 4 + src/talker.h | 10 ++ src/talker_character.cpp | 15 +++ src/talker_character.h | 3 + 7 files changed, 287 insertions(+), 1 deletion(-) create mode 100644 data/json/ui/strain.json diff --git a/data/json/ui/layout.json b/data/json/ui/layout.json index 17cf35193d07f..6a1d8ee789a5e 100644 --- a/data/json/ui/layout.json +++ b/data/json/ui/layout.json @@ -99,7 +99,7 @@ "style": "layout", "label": "Stamina/Weariness", "arrange": "rows", - "widgets": [ "stamina_graph", "strain_graph", "activity_desc", "weariness_desc", "weary_malus_desc" ] + "widgets": [ "stamina_graph", "strain_and_burn_fake_graph", "activity_desc", "weariness_desc", "weary_malus_desc" ] }, { "id": "mood_focus_layout", diff --git a/data/json/ui/strain.json b/data/json/ui/strain.json new file mode 100644 index 0000000000000..adb7156785199 --- /dev/null +++ b/data/json/ui/strain.json @@ -0,0 +1,251 @@ +[ + { + "id": "strain_and_burn_fake_graph", + "type": "widget", + "style": "symbol", + "label": "Strain", + "label_align": "left", + "width": 10, + "clauses": [ + { + "//0": "To those this may offend,", + "//1": "Sorry.", + "//2": "/* ----- BEGIN: STRAIN LISTING ----- */", + "condition": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') / 10 - 1" ] }, + "id": "strain_1", + "color": "yellow", + "sym": "=" + }, + { + "condition": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') / 10 * 2 - 1" ] }, + "id": "strain_2", + "color": "yellow", + "sym": "=" + }, + { + "condition": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') / 10 * 3 - 1" ] }, + "id": "strain_3", + "color": "yellow", + "sym": "=" + }, + { + "condition": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') / 10 * 4 - 1" ] }, + "id": "strain_4", + "color": "yellow", + "sym": "=" + }, + { + "condition": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') / 10 * 5 - 1" ] }, + "id": "strain_5", + "color": "yellow", + "sym": "=" + }, + { + "condition": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') / 10 * 6 - 1" ] }, + "id": "strain_6", + "color": "yellow", + "sym": "=" + }, + { + "condition": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') / 10 * 7 - 1" ] }, + "id": "strain_7", + "color": "yellow", + "sym": "=" + }, + { + "condition": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') / 10 * 8 - 1" ] }, + "id": "strain_8", + "color": "yellow", + "sym": "=" + }, + { + "condition": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') / 10 * 9 - 1" ] }, + "id": "strain_9", + "color": "yellow", + "sym": "=" + }, + { + "condition": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') - 1" ] }, + "id": "strain_10", + "color": "yellow", + "sym": "=", + "//0": "/* ----- END: STRAIN LISTING ----- */" + }, + { + "//0": "/* ----- BEGIN: SEPERATOR LISTING ----- */", + "condition": { + "and": [ + { "not": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') / 10 - 1" ] } }, + { "not": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') / 10 - 1" ] } } + ] + }, + "id": "seperator_1", + "color": "white", + "sym": "-" + }, + { + "condition": { + "and": [ + { "not": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') / 10 * 2 - 1" ] } }, + { "not": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') / 10 * 2 - 1" ] } } + ] + }, + "id": "seperator_2", + "color": "white", + "sym": "-" + }, + { + "condition": { + "and": [ + { "not": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') / 10 * 3- 1" ] } }, + { "not": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') / 10 * 3 - 1" ] } } + ] + }, + "id": "seperator_3", + "color": "white", + "sym": "-" + }, + { + "condition": { + "and": [ + { "not": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') / 10 * 4 - 1" ] } }, + { "not": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') / 10 * 5 - 1" ] } } + ] + }, + "id": "seperator_4", + "color": "white", + "sym": "-" + }, + { + "condition": { + "and": [ + { "not": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') / 10 * 5 - 1" ] } }, + { "not": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') / 10 * 5 - 1" ] } } + ] + }, + "id": "seperator_5", + "color": "white", + "sym": "-" + }, + { + "condition": { + "and": [ + { "not": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') / 10 * 6 - 1" ] } }, + { "not": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') / 10 * 6 - 1" ] } } + ] + }, + "id": "seperator_6", + "color": "white", + "sym": "-" + }, + { + "condition": { + "and": [ + { "not": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') / 10 * 7 - 1" ] } }, + { "not": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') / 10 * 7 - 1" ] } } + ] + }, + "id": "seperator_7", + "color": "white", + "sym": "-" + }, + { + "condition": { + "and": [ + { "not": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') / 10 * 8 - 1" ] } }, + { "not": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') / 10 * 8 - 1" ] } } + ] + }, + "id": "seperator_8", + "color": "white", + "sym": "-" + }, + { + "condition": { + "and": [ + { "not": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') / 10 * 9 - 1" ] } }, + { "not": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') / 10 * 9 - 1" ] } } + ] + }, + "id": "seperator_9", + "color": "white", + "sym": "-" + }, + { + "condition": { + "and": [ + { "not": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') - 1" ] } }, + { "not": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') - 1" ] } } + ] + }, + "id": "seperator_10", + "color": "white", + "sym": "-", + "//0": "/* ----- END: SEPARATOR LISTING ----- */" + }, + { + "//0": "/* ----- BEGIN: BURN LISTING ----- */", + "condition": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') / 10 - 1" ] }, + "id": "burn_1", + "color": "red", + "sym": "#" + }, + { + "condition": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') / 10 * 2 - 1" ] }, + "id": "burn_2", + "color": "red", + "sym": "#" + }, + { + "condition": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') / 10 * 3 - 1" ] }, + "id": "burn_3", + "color": "red", + "sym": "#" + }, + { + "condition": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') / 10 * 4 - 1" ] }, + "id": "burn_4", + "color": "red", + "sym": "#" + }, + { + "condition": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') / 10 * 5 - 1" ] }, + "id": "burn_5", + "color": "red", + "sym": "#" + }, + { + "condition": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') / 10 * 6 - 1" ] }, + "id": "burn_6", + "color": "red", + "sym": "#" + }, + { + "condition": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') / 10 * 7 - 1" ] }, + "id": "burn_7", + "color": "red", + "sym": "#" + }, + { + "condition": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') / 10 * 8 - 1" ] }, + "id": "burn_8", + "color": "red", + "sym": "#" + }, + { + "condition": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') / 10 * 9 - 1" ] }, + "id": "burn_9", + "color": "red", + "sym": "#" + }, + { + "condition": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') - 1" ] }, + "id": "burn_10", + "color": "red", + "sym": "#", + "//0": "/* ----- END: BURN LISTING ----- */" + } + ], + "default_clause": { "sym": "----------", "color": "white" } + } +] diff --git a/doc/NPCs.md b/doc/NPCs.md index 78648d101b69f..82e0ef2486d4e 100644 --- a/doc/NPCs.md +++ b/doc/NPCs.md @@ -1423,6 +1423,9 @@ These can be read or written to with `val()`. | `stim` | ✅ | Current stim level. | | `stored_kcal` | ✅ | Stored kcal in the character's body. 55'000 is considered healthy. | | `stored_kcal_percentage` | ✅ | a value of 100 represents 55'000 kcal, which is considered healthy. | +| `strain` | ✅ | Current muscle strain. Note that this value decreases with activity, the values are the inverse of what you might expect. | +| `strain_burn` | ❌ | Current muscle burn. | +| `strain_max` | ❌ | Maximum muscle strain. Note that this value decreases with activity, scaling with acquired burn. | | `strength`
`dexterity`
`intelligence`
`pereception` | ✅ | Current attributes | | `strength_base`
`dexterity_base`
`intelligence_base`
`perception_base` | ✅ | Base attributes | | `strength_bonus`
`dexterity_bonus`
`intelligence_bonus`
`pereception_bonus` | ✅ | Bonus attributes | diff --git a/src/condition.cpp b/src/condition.cpp index b4358fb4a6d48..aff1204ac4925 100644 --- a/src/condition.cpp +++ b/src/condition.cpp @@ -2050,6 +2050,9 @@ std::unordered_map const f_get_vals { "stored_kcal", &talker::get_stored_kcal }, { "strength_base", &talker::get_str_max }, { "strength_bonus", &talker::get_str_bonus }, + { "strain", &talker::get_strain }, + { "strain_burn", &talker::get_strain_burn }, + { "strain_max", &talker::get_strain_max }, { "strength", &talker::str_cur }, { "thirst", &talker::get_thirst }, { "volume", &talker::get_volume }, @@ -2159,6 +2162,7 @@ std::unordered_map const f_set_vals { "stored_kcal", &talker::set_stored_kcal }, { "strength_base", &talker::set_str_max }, { "strength_bonus", &talker::set_str_bonus }, + { "strain", &talker::set_strain }, { "thirst", &talker::set_thirst }, }; } // namespace diff --git a/src/talker.h b/src/talker.h index 93c15a074b2f2..1ed6d8ffcce08 100644 --- a/src/talker.h +++ b/src/talker.h @@ -622,6 +622,16 @@ class talker return 0; } virtual void set_stamina( int ) {} + virtual int get_strain_burn() const { + return 0; + } + virtual int get_strain_max() const { + return 0; + } + virtual int get_strain() const { + return 0; + } + virtual void set_strain( int ) {} virtual int get_sleep_deprivation() const { return 0; } diff --git a/src/talker_character.cpp b/src/talker_character.cpp index c03d4eb9afe7c..38f89f00a6c9e 100644 --- a/src/talker_character.cpp +++ b/src/talker_character.cpp @@ -865,6 +865,21 @@ void talker_character::set_pkill( int amount ) me_chr->set_painkiller( amount ); } +int talker_character_const::get_strain() const +{ + return me_chr_const->get_strain(); +} + +int talker_character_const::get_strain_max() const +{ + return me_chr_const->get_strain_max(); +} + +int talker_character_const::get_strain_burn() const +{ + return me_chr_const->get_strain_burn(); +} + int talker_character_const::get_stamina() const { return me_chr_const->get_stamina(); diff --git a/src/talker_character.h b/src/talker_character.h index 7d8aade527950..8bde4ea8aa14b 100644 --- a/src/talker_character.h +++ b/src/talker_character.h @@ -179,6 +179,9 @@ class talker_character_const: public talker_cloner int get_addiction_turns( const addiction_id &add_id ) const override; int get_pkill() const override; int get_stamina() const override; + int get_strain() const override; + int get_strain_max() const override; + int get_strain_burn() const override; int get_sleep_deprivation() const override; int get_kill_xp() const override; int get_age() const override; From a5a320c651b799d0473b3357ecc2b621747f10a0 Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Mon, 8 Apr 2024 17:15:15 -0700 Subject: [PATCH 12/23] modify burn to not build too fast also recovers slower, balance still pending --- data/core/game_balance.json | 2 +- src/character.cpp | 21 +++++++++++++++++---- src/character.h | 1 + 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/data/core/game_balance.json b/data/core/game_balance.json index 21ad3637545d1..7627f97f236d7 100644 --- a/data/core/game_balance.json +++ b/data/core/game_balance.json @@ -46,7 +46,7 @@ "name": "PLAYER_BASE_STRAIN", "info": "Sets the base max strain value of the player, before cardio modifiers.", "stype": "int", - "value": 4000 + "value": 3000 }, { "type": "EXTERNAL_OPTION", diff --git a/src/character.cpp b/src/character.cpp index fe4bf3e5a6eeb..c97e1b9c45354 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -7132,21 +7132,24 @@ void Character::mod_strain( int mod ) return; } strain += mod; + int max_strain = get_strain_max(); + if( mod < 0 ) { used_strain_this_turn = true; add_msg_debug( debugmode::DF_CHARACTER, "Used strain this turn, recovery disabled" ); } - if( mod < 0 && strain < get_strain_max() / 2 ) { + if( mod < 0 && strain < max_strain / 2 ) { // if strain is decreasing and getting into the higher numbers, bump burn up. // burn rises a little regardless, but far more if you're doing something really // powerful. - int burn = mod * -2; + int burn_denominator = -18 + clamp( max_strain / ( strain + 1 ), 2, 8 ); + int burn = mod / burn_denominator; add_msg_debug( debugmode::DF_CHARACTER, "Burn increased by %i", burn ); mod_strain_burn( burn ); } - strain = clamp( strain, 0, get_strain_max() ); + strain = clamp( strain, 0, max_strain ); } void Character::mod_strain_burn( int mod ) @@ -7207,7 +7210,17 @@ void Character::update_strain( int turns ) int recover_burn_amount = 0; mod_strain( recover_amount ); if( current_strain > max_strain / 2 ) { - recover_burn_amount = std::max( 1, recover_amount / 50 ); + // this should get a bonus if we're sleeping or resting. + recover_burn_amount = recover_amount / 100; + if( recover_burn_amount <= 0 ) { + if( recover_burn_ticker <= 0 ) { + // make sure that we never completely stop recovering burn + recover_burn_amount = 1; + recover_burn_ticker = 4; + } else { + recover_burn_ticker -= 1; + } + } mod_strain_burn( recover_burn_amount * -1 ); } add_msg_debug( debugmode::DF_CHARACTER, "Current strain: %i, Max strain: %i, Current burn: %i", diff --git a/src/character.h b/src/character.h index fbf5dee637b13..979656ae3d43c 100644 --- a/src/character.h +++ b/src/character.h @@ -4018,6 +4018,7 @@ class Character : public Creature, public visitable int strain; int strain_burn; bool used_strain_this_turn = false; + bool recover_burn_ticker = 4; int cardio_acc; int base_cardio_acc; From 5ac22d5f475541c1d159998c02938ffd7460cecb Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Thu, 11 Apr 2024 15:49:45 -0700 Subject: [PATCH 13/23] Update src/character.h Co-authored-by: fungamer2-2 <56766520+fungamer2-2@users.noreply.github.com> --- src/character.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/character.h b/src/character.h index 979656ae3d43c..2909f2e43b448 100644 --- a/src/character.h +++ b/src/character.h @@ -4018,7 +4018,7 @@ class Character : public Creature, public visitable int strain; int strain_burn; bool used_strain_this_turn = false; - bool recover_burn_ticker = 4; + int recover_burn_ticker = 4; int cardio_acc; int base_cardio_acc; From d3e443741c8d2b83165ac7f2ac19b1796a2a5ede Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Fri, 12 Apr 2024 21:53:17 -0700 Subject: [PATCH 14/23] Update effective_dps_test.cpp --- tests/effective_dps_test.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/effective_dps_test.cpp b/tests/effective_dps_test.cpp index be92d0a3c7b96..27f24752900b3 100644 --- a/tests/effective_dps_test.cpp +++ b/tests/effective_dps_test.cpp @@ -57,7 +57,8 @@ static double weapon_dps_trials( avatar &attacker, monster &defender, item &weap const int starting_hp = defender.get_hp_max(); defender.set_hp( starting_hp ); - // Attack once + // Attack once, ignoring strain + attacker.set_strain( 10000 ); attacker.melee_attack_abstract( defender, false, matec_id( "" ) ); // Tally total damage and moves From 505953ccbd4591d45c50851e441b49fe8e5c658b Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Fri, 12 Apr 2024 21:55:09 -0700 Subject: [PATCH 15/23] Update strain.json --- data/json/ui/strain.json | 8 -------- 1 file changed, 8 deletions(-) diff --git a/data/json/ui/strain.json b/data/json/ui/strain.json index adb7156785199..625cc8c7801a5 100644 --- a/data/json/ui/strain.json +++ b/data/json/ui/strain.json @@ -8,9 +8,6 @@ "width": 10, "clauses": [ { - "//0": "To those this may offend,", - "//1": "Sorry.", - "//2": "/* ----- BEGIN: STRAIN LISTING ----- */", "condition": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') / 10 - 1" ] }, "id": "strain_1", "color": "yellow", @@ -69,10 +66,8 @@ "id": "strain_10", "color": "yellow", "sym": "=", - "//0": "/* ----- END: STRAIN LISTING ----- */" }, { - "//0": "/* ----- BEGIN: SEPERATOR LISTING ----- */", "condition": { "and": [ { "not": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') / 10 - 1" ] } }, @@ -181,10 +176,8 @@ "id": "seperator_10", "color": "white", "sym": "-", - "//0": "/* ----- END: SEPARATOR LISTING ----- */" }, { - "//0": "/* ----- BEGIN: BURN LISTING ----- */", "condition": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') / 10 - 1" ] }, "id": "burn_1", "color": "red", @@ -243,7 +236,6 @@ "id": "burn_10", "color": "red", "sym": "#", - "//0": "/* ----- END: BURN LISTING ----- */" } ], "default_clause": { "sym": "----------", "color": "white" } From 24b468c0381d4b5e72c1b6bbb29d58f92e655f7a Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Fri, 12 Apr 2024 22:04:27 -0700 Subject: [PATCH 16/23] Update strain.json --- data/json/ui/strain.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data/json/ui/strain.json b/data/json/ui/strain.json index 625cc8c7801a5..8131f8f37fada 100644 --- a/data/json/ui/strain.json +++ b/data/json/ui/strain.json @@ -65,7 +65,7 @@ "condition": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') - 1" ] }, "id": "strain_10", "color": "yellow", - "sym": "=", + "sym": "=" }, { "condition": { @@ -175,7 +175,7 @@ }, "id": "seperator_10", "color": "white", - "sym": "-", + "sym": "-" }, { "condition": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') / 10 - 1" ] }, @@ -235,7 +235,7 @@ "condition": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') - 1" ] }, "id": "burn_10", "color": "red", - "sym": "#", + "sym": "#" } ], "default_clause": { "sym": "----------", "color": "white" } From ed29c78a0653ea4b288407fe81d84989d824a419 Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Fri, 12 Apr 2024 23:14:25 -0700 Subject: [PATCH 17/23] Try to fix text analyzer --- data/json/ui/strain.json | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/data/json/ui/strain.json b/data/json/ui/strain.json index 8131f8f37fada..97c710ba62a18 100644 --- a/data/json/ui/strain.json +++ b/data/json/ui/strain.json @@ -8,6 +8,9 @@ "width": 10, "clauses": [ { + "//0": "To those this may offend,", + "//1": "Sorry.", + "//2": "/* ----- BEGIN: STRAIN LISTING ----- */", "condition": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') / 10 - 1" ] }, "id": "strain_1", "color": "yellow", @@ -65,9 +68,11 @@ "condition": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') - 1" ] }, "id": "strain_10", "color": "yellow", - "sym": "=" + "sym": "=", + "//0": "/* ----- END: STRAIN LISTING ----- */" }, { + "//0": "/* ----- BEGIN: SEPERATOR LISTING ----- */", "condition": { "and": [ { "not": { "math": [ "u_val('strain') + u_val('strain_burn')", "<=", "u_val('strain_max') / 10 - 1" ] } }, @@ -175,9 +180,11 @@ }, "id": "seperator_10", "color": "white", - "sym": "-" + "sym": "-", + "//0": "/* ----- END: SEPARATOR LISTING ----- */" }, { + "//0": "/* ----- BEGIN: BURN LISTING ----- */", "condition": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') / 10 - 1" ] }, "id": "burn_1", "color": "red", @@ -235,9 +242,10 @@ "condition": { "math": [ "u_val('strain_burn')", ">=", "u_val('strain_max') - 1" ] }, "id": "burn_10", "color": "red", - "sym": "#" + "sym": "#", + "//0": "/* ----- END: BURN LISTING ----- */" } ], - "default_clause": { "sym": "----------", "color": "white" } + "default_clause": { "text": "----------", "color": "white" } } ] From eeda6a8511482b87bf8d9c05b220a18d71a9c44f Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Sat, 13 Apr 2024 17:03:04 -0700 Subject: [PATCH 18/23] adjust and disable tests while strain is in flux --- tests/enchantments_test.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/enchantments_test.cpp b/tests/enchantments_test.cpp index f32344ad0b48d..6ac1e44c6391f 100644 --- a/tests/enchantments_test.cpp +++ b/tests/enchantments_test.cpp @@ -247,7 +247,9 @@ TEST_CASE( "Enchantment_ATTACK_SPEED_test", "[magic][enchantments]" ) // 25 moves per attack INFO( "10 attacks cost only 250 moves" ); moves_spent_on_attacks = test_melee_attack_attack_speed( guy ); - REQUIRE( moves_spent_on_attacks == -250 ); + // STRAIN TESTING This test has been made more wobbly while strain mechanics are being balanced + REQUIRE( moves_spent_on_attacks <= -250 ); + // REQUIRE( moves_spent_on_attacks == -250 ); clear_avatar(); @@ -282,6 +284,8 @@ static int test_melee_attack_attack_stamina( Character &guy ) return guy.get_stamina(); } +/* STRAIN TESTING: These stamina values are currently in flux. +This test will need to be reactivated once strain costs stabilize, and a version for strain added. TEST_CASE( "Enchantment_MELEE_STAMINA_CONSUMPTION_test", "[magic][enchantments]" ) { @@ -326,6 +330,7 @@ TEST_CASE( "Enchantment_MELEE_STAMINA_CONSUMPTION_test", "[magic][enchantments]" REQUIRE( stamina_spent == 3300 ); clear_avatar(); } +*/ TEST_CASE( "Enchantment_BONUS_DODGE_test", "[magic][enchantments]" ) { From e82b078e2cc6d21934f0c54f2bdc432fefbec504 Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Sat, 13 Apr 2024 17:47:04 -0700 Subject: [PATCH 19/23] Update enchantments_test.cpp --- tests/enchantments_test.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/enchantments_test.cpp b/tests/enchantments_test.cpp index 6ac1e44c6391f..faa52d5f3057b 100644 --- a/tests/enchantments_test.cpp +++ b/tests/enchantments_test.cpp @@ -262,6 +262,9 @@ TEST_CASE( "Enchantment_ATTACK_SPEED_test", "[magic][enchantments]" ) } +/* STRAIN TESTING: These stamina values are currently in flux. +This test will need to be reactivated once strain costs stabilize, and a version for strain added. + static int test_melee_attack_attack_stamina( Character &guy ) { int i = 0; @@ -284,9 +287,6 @@ static int test_melee_attack_attack_stamina( Character &guy ) return guy.get_stamina(); } -/* STRAIN TESTING: These stamina values are currently in flux. -This test will need to be reactivated once strain costs stabilize, and a version for strain added. - TEST_CASE( "Enchantment_MELEE_STAMINA_CONSUMPTION_test", "[magic][enchantments]" ) { clear_map(); From f71c39f1a06b1068eb5d8efc9fd645fee2e46db9 Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Sun, 14 Apr 2024 10:52:37 -0700 Subject: [PATCH 20/23] ensure strain doesn't run out in attack tests --- tests/eoc_test.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/eoc_test.cpp b/tests/eoc_test.cpp index fce034c121eb5..2d197328a1443 100644 --- a/tests/eoc_test.cpp +++ b/tests/eoc_test.cpp @@ -1145,6 +1145,7 @@ TEST_CASE( "EOC_combat_event_test", "[eoc]" ) npc &npc_dst_melee = spawn_npc( get_avatar().pos().xy() + point_south, "thug" ); item weapon_item( itype_test_knife_combat ); get_avatar().wield( weapon_item ); + get_avatar().set_strain( 10000 ); get_avatar().melee_attack( npc_dst_melee, false ); CHECK( get_avatar().get_value( "npctalk_var_test_event_last_event" ) == @@ -1157,6 +1158,7 @@ TEST_CASE( "EOC_combat_event_test", "[eoc]" ) // character_melee_attacks_monster clear_map(); monster &mon_dst_melee = spawn_test_monster( "mon_zombie", get_avatar().pos() + tripoint_east ); + get_avatar().set_strain( 10000 ); get_avatar().melee_attack( mon_dst_melee, false ); CHECK( get_avatar().get_value( "npctalk_var_test_event_last_event" ) == From 1ae56f1a298564436380d173ddc59494ac76bb9b Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Sun, 14 Apr 2024 11:10:45 -0700 Subject: [PATCH 21/23] Update enchantments_test.cpp --- tests/enchantments_test.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/enchantments_test.cpp b/tests/enchantments_test.cpp index e151e6b34e4bc..c2e0d7c82695b 100644 --- a/tests/enchantments_test.cpp +++ b/tests/enchantments_test.cpp @@ -219,6 +219,7 @@ static int test_melee_attack_attack_speed( Character &guy, Creature &mon ) guy.melee_attack_abstract( mon, false, matec_id( "" ) ); add_msg( "attack %i: attack cost: %i, total amount of moves: %i", i, prev_attack - guy.get_moves(), guy.get_moves() ); + guy.set_strain( 10000 ); guy.set_stamina( guy.get_stamina_max() ); //Reset reset! guy.set_sleepiness( 0 ); i++; @@ -251,9 +252,7 @@ TEST_CASE( "Enchantment_ATTACK_SPEED_test", "[magic][enchantments]" ) INFO( "10 attacks cost only 250 moves" ); moves_spent_on_attacks = test_melee_attack_attack_speed( guy, mon ); - // STRAIN TESTING This test has been made more wobbly while strain mechanics are being balanced - REQUIRE( moves_spent_on_attacks <= -250 ); - // REQUIRE( moves_spent_on_attacks == -250 ); + REQUIRE( moves_spent_on_attacks == -250 ); clear_avatar(); From eee1889eefbf184afbd3f43c18f81c05c2917638 Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Sun, 14 Apr 2024 11:11:07 -0700 Subject: [PATCH 22/23] Update tests/enchantments_test.cpp Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- tests/enchantments_test.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/enchantments_test.cpp b/tests/enchantments_test.cpp index c2e0d7c82695b..3df74b1dd6233 100644 --- a/tests/enchantments_test.cpp +++ b/tests/enchantments_test.cpp @@ -250,7 +250,6 @@ TEST_CASE( "Enchantment_ATTACK_SPEED_test", "[magic][enchantments]" ) guy.i_add( item( "test_ATTACK_SPEED_ench_item" ) ); // 25 moves per attack INFO( "10 attacks cost only 250 moves" ); - moves_spent_on_attacks = test_melee_attack_attack_speed( guy, mon ); REQUIRE( moves_spent_on_attacks == -250 ); clear_avatar(); From c9bf64efa7676ec70ed85bbb3422e3cdc7d2b654 Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Sun, 14 Apr 2024 13:22:58 -0700 Subject: [PATCH 23/23] Update monster_attack_test.cpp --- tests/monster_attack_test.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/monster_attack_test.cpp b/tests/monster_attack_test.cpp index 72313b4c8409a..1b80d35888068 100644 --- a/tests/monster_attack_test.cpp +++ b/tests/monster_attack_test.cpp @@ -85,6 +85,7 @@ static void test_monster_attack( const tripoint &target_offset, bool expect_atta Character &you = get_player_character(); clear_avatar(); you.setpos( target_location ); + you.set_strain( 10000 ); // ensure strain not running out monster &test_monster = spawn_test_monster( monster_type, attacker_location ); test_monster.set_dest( you.get_location() ); reset_caches( a_zlev, t_zlev ); @@ -104,6 +105,7 @@ static void test_monster_attack( const tripoint &target_offset, bool expect_atta monster &target_monster = spawn_test_monster( monster_type, target_location ); reset_caches( a_zlev, t_zlev ); CHECK( you.sees( target_monster ) == expect_vision ); + you.set_strain( 10000 ); // ensure strain not running out if( special_attack == nullptr ) { CHECK( you.melee_attack( target_monster, false ) == expect_attack ); }