From 9a3c7190aa51a0fa0ab033b3b479c85689401a76 Mon Sep 17 00:00:00 2001 From: Fris0uman Date: Fri, 8 Jul 2022 22:09:09 +0200 Subject: [PATCH 01/11] Replace time as int with time_duration for bionics --- data/json/bionics.json | 66 +++++++++++++++++++++--------------------- src/bionics.cpp | 25 ++++++++++------ src/bionics.h | 4 +-- src/bionics_ui.cpp | 6 ++-- 4 files changed, 54 insertions(+), 47 deletions(-) diff --git a/data/json/bionics.json b/data/json/bionics.json index 669ab9e5c7bb0..63eef90d2d11c 100644 --- a/data/json/bionics.json +++ b/data/json/bionics.json @@ -17,7 +17,7 @@ "act_cost": 10, "react_cost": 10, "trigger_cost": "25kJ", - "time": 1 + "time": "1 s" }, { "id": "bio_alarm", @@ -29,7 +29,7 @@ "act_cost": "1 J", "react_cost": "1 J", "trigger_cost": "25 kJ", - "time": 1 + "time": "1 s" }, { "id": "bio_ankles", @@ -470,7 +470,7 @@ "fuel_options": [ "battery" ], "fuel_efficiency": 1, "fuel_capacity": 2000, - "time": 1, + "time": "1 s", "flags": [ "BIONIC_POWER_SOURCE", "BIONIC_TOGGLED", "BIONIC_NPC_USABLE" ] }, { @@ -527,7 +527,7 @@ "description": "You have a complex port surgically mounted above your hip. While active, it will recharge bionic power when connected to a power source via jumper cable.", "occupied_bodyparts": [ [ "torso", 7 ] ], "is_remote_fueled": true, - "time": 1, + "time": "1 s", "fuel_efficiency": 1, "flags": [ "BIONIC_POWER_SOURCE", "BIONIC_SHOCKPROOF", "BIONIC_TOGGLED" ] }, @@ -638,7 +638,7 @@ ], "act_cost": "100 J", "react_cost": "100 J", - "time": 1, + "time": "1 s", "flags": [ "BIONIC_TOGGLED" ], "active_flags": [ "CLIMATE_CONTROL" ] }, @@ -661,7 +661,7 @@ ], "act_cost": "30 kJ", "react_cost": "30 kJ", - "time": 1, + "time": "1 s", "enchantments": [ { "condition": "ACTIVE", "ench_effects": [ { "effect": "invisibility", "intensity": 1 } ] } ], "flags": [ "BIONIC_TOGGLED" ] }, @@ -673,7 +673,7 @@ "occupied_bodyparts": [ [ "head", 3 ] ], "act_cost": "20 J", "react_cost": "20 J", - "time": 1, + "time": "1 s", "known_ma_styles": [ "style_aikido", "style_barbaran", @@ -825,7 +825,7 @@ "fuel_capacity": 400, "fuel_efficiency": 0.5, "exothermic_power_gen": true, - "time": 1, + "time": "1 s", "flags": [ "BIONIC_POWER_SOURCE", "BIONIC_NPC_USABLE", "BIONIC_SHOCKPROOF", "BIONIC_TOGGLED" ] }, { @@ -838,7 +838,7 @@ "fuel_capacity": 750, "fuel_efficiency": 0.35, "exothermic_power_gen": true, - "time": 5, + "time": "5 s", "flags": [ "BIONIC_POWER_SOURCE", "BIONIC_NPC_USABLE", "BIONIC_SHOCKPROOF", "BIONIC_TOGGLED" ] }, { @@ -848,7 +848,7 @@ "description": "This unit draws moisture from the surrounding air, which slowly trickles directly into your blood stream. It may fail in very dry environments.", "occupied_bodyparts": [ [ "torso", 5 ] ], "react_cost": "60 J", - "time": 1, + "time": "1 s", "flags": [ "BIONIC_TOGGLED" ] }, { @@ -921,7 +921,7 @@ "active_flags": [ "ELECTRIC_IMMUNE" ], "act_cost": "5 J", "react_cost": "5 J", - "time": 1 + "time": "1 s" }, { "id": "bio_fingerhack", @@ -948,7 +948,7 @@ "occupied_bodyparts": [ [ "head", 1 ] ], "act_cost": "3 J", "react_cost": "3 J", - "time": 1, + "time": "1 s", "flags": [ "BIONIC_TOGGLED" ], "enchantments": [ { "condition": "ACTIVE", "values": [ { "value": "LUMINATION", "add": 60 } ] } ] }, @@ -959,7 +959,7 @@ "description": "A small LED display just beneath your dermal layer can be illuminated on command to show patterns of your choice at dim or bright luminosity. It doesn't provide enough light to comfortably read or craft, but it can suffice if you have nothing else.", "act_cost": "1 J", "react_cost": "1 J", - "time": 1, + "time": "1 s", "flags": [ "BIONIC_TOGGLED" ], "enchantments": [ { "condition": "ACTIVE", "values": [ { "value": "LUMINATION", "add": 5 } ] } ] }, @@ -997,7 +997,7 @@ "flags": [ "BIONIC_TOGGLED" ], "act_cost": "200 J", "react_cost": "200 J", - "time": 1 + "time": "1 s" }, { "id": "bio_heat_absorb", @@ -1040,7 +1040,7 @@ "active_flags": [ "HEATSINK" ], "act_cost": "1 kJ", "react_cost": "1 kJ", - "time": 1 + "time": "1 s" }, { "id": "bio_hydraulics", @@ -1051,7 +1051,7 @@ "flags": [ "BIONIC_TOGGLED", "BIONIC_NPC_USABLE" ], "act_cost": "10 kJ", "react_cost": "10 kJ", - "time": 1 + "time": "1 s" }, { "id": "bio_infrared", @@ -1063,7 +1063,7 @@ "active_flags": [ "INFRARED" ], "act_cost": "5 J", "react_cost": "5 J", - "time": 1 + "time": "1 s" }, { "id": "bio_int_enhancer", @@ -1109,7 +1109,7 @@ "flags": [ "BIONIC_TOGGLED", "BIONIC_SLEEP_FRIENDLY", "BIONIC_NPC_USABLE" ], "act_cost": "5 J", "react_cost": "5 J", - "time": 1, + "time": "1 s", "enchantments": [ { "condition": "ACTIVE", @@ -1166,7 +1166,7 @@ "act_cost": "2 J", "react_cost": "2 J", "trigger_cost": "25 J", - "time": 1, + "time": "1 s", "enchantments": [ { "condition": "ACTIVE", @@ -1187,7 +1187,7 @@ "occupied_bodyparts": [ [ "torso", 20 ] ], "fuel_options": [ "metabolism" ], "fuel_efficiency": 0.25, - "time": 1, + "time": "1 s", "flags": [ "BIONIC_POWER_SOURCE", "BIONIC_TOGGLED", "BIONIC_NPC_USABLE" ] }, { @@ -1208,7 +1208,7 @@ "flags": [ "BIONIC_TOGGLED", "BIONIC_NPC_USABLE", "BIONIC_SLEEP_FRIENDLY" ], "act_cost": "80 J", "react_cost": "40 J", - "time": 1 + "time": "1 s" }, { "id": "bio_night", @@ -1226,7 +1226,7 @@ ], "act_cost": "9 kJ", "react_cost": "9 kJ", - "time": 1 + "time": "1 s" }, { "id": "bio_night_vision", @@ -1238,7 +1238,7 @@ "active_flags": [ "NIGHT_VISION" ], "act_cost": "10 J", "react_cost": "10 J", - "time": 1 + "time": "1 s" }, { "id": "bio_noise", @@ -1267,7 +1267,7 @@ "act_cost": "10 kJ", "react_cost": "10 kJ", "trigger_cost": "1 kJ", - "time": 1 + "time": "1 s" }, { "id": "bio_painkiller", @@ -1295,7 +1295,7 @@ "occupied_bodyparts": [ [ "torso", 4 ], [ "head", 1 ] ], "flags": [ "BIONIC_ARMOR_INTERFACE", "BIONIC_TOGGLED" ], "react_cost": 1, - "time": 1 + "time": "1 s" }, { "id": "bio_power_armor_interface_mkII", @@ -1305,7 +1305,7 @@ "occupied_bodyparts": [ [ "torso", 3 ], [ "head", 2 ] ], "flags": [ "BIONIC_ARMOR_INTERFACE", "BIONIC_TOGGLED" ], "react_cost": 1, - "time": 2 + "time": "2 s" }, { "id": "bio_power_storage", @@ -1343,7 +1343,7 @@ "act_cost": "3 J", "react_cost": "3 J", "trigger_cost": "250 kJ", - "time": 1 + "time": "1 s" }, { "id": "bio_purifier", @@ -1373,7 +1373,7 @@ "act_cost": "1 kJ", "react_cost": "100 J", "trigger_cost": "10 kJ", - "time": 1 + "time": "1 s" }, { "id": "bio_razors", @@ -1410,7 +1410,7 @@ "occupied_bodyparts": [ [ "head", 2 ] ], "flags": [ "BIONIC_TOGGLED" ], "react_cost": 1, - "time": 24 + "time": "24 s" }, { "id": "bio_resonator", @@ -1430,7 +1430,7 @@ "active_flags": [ "NO_SCENT" ], "act_cost": 1, "react_cost": 1, - "time": 60 + "time": "1 m" }, { "id": "bio_shakes", @@ -1451,7 +1451,7 @@ "occupied_bodyparts": [ [ "head", 1 ], [ "torso", 1 ] ], "act_cost": 0, "react_cost": "1 kJ", - "time": 100 + "time": "100 s" }, { "id": "bio_shock", @@ -1671,7 +1671,7 @@ "act_cost": "6 J", "react_cost": "6 J", "trigger_cost": "75 kJ", - "time": 1 + "time": "1 s" }, { "id": "bio_ups", @@ -1718,7 +1718,7 @@ "fuel_capacity": 500, "fuel_efficiency": 0.25, "exothermic_power_gen": true, - "time": 1, + "time": "1 s", "flags": [ "BIONIC_TOGGLED", "BIONIC_POWER_SOURCE", "BIONIC_NPC_USABLE" ] }, { diff --git a/src/bionics.cpp b/src/bionics.cpp index 3c6434a787c0b..f1c85474b5db1 100644 --- a/src/bionics.cpp +++ b/src/bionics.cpp @@ -343,7 +343,7 @@ void bionic_data::load( const JsonObject &jsobj, const std::string & ) assign( jsobj, "trigger_cost", power_trigger, false, 0_kJ ); assign( jsobj, "power_trickle", power_trickle, false, 0_kJ ); - optional( jsobj, was_loaded, "time", charge_time, 0 ); + optional( jsobj, was_loaded, "time", charge_time, 0_turns ); optional( jsobj, was_loaded, "flags", flags ); optional( jsobj, was_loaded, "active_flags", active_flags ); @@ -471,7 +471,7 @@ void bionic_data::load( const JsonObject &jsobj, const std::string & ) activated = has_flag( STATIC( json_character_flag( json_flag_BIONIC_TOGGLED ) ) ) || power_activate > 0_kJ || - charge_time > 0; + charge_time > 0_turns; if( has_flag( STATIC( json_character_flag( "BIONIC_FAULTY" ) ) ) ) { faulty_bionics.push_back( id ); @@ -722,9 +722,9 @@ bool Character::activate_bionic( bionic &bio, bool eff_only, bool *close_bionics // We can actually activate now, do activation-y things mod_power_level( -bio.info().power_activate ); - bio.powered = bio.info().has_flag( json_flag_BIONIC_TOGGLED ) || bio.info().charge_time > 0; + bio.powered = bio.info().has_flag( json_flag_BIONIC_TOGGLED ) || bio.info().charge_time > 0_turns; - if( bio.info().charge_time > 0 ) { + if( bio.info().charge_time > 0_turns ) { bio.charge_timer = bio.info().charge_time; } if( !bio.id->enchantments.empty() ) { @@ -1780,13 +1780,13 @@ void Character::process_bionic( bionic &bio ) } // These might be affected by environmental conditions, status effects, faulty bionics, etc. - int discharge_rate = 1; + time_duration discharge_rate = 1_turns; units::energy cost = 0_mJ; - bio.charge_timer = std::max( 0, bio.charge_timer - discharge_rate ); - if( bio.charge_timer <= 0 ) { - if( bio.info().charge_time > 0 ) { + bio.charge_timer = std::max( 0_turns, bio.charge_timer - discharge_rate ); + if( bio.charge_timer <= 0_turns ) { + if( bio.info().charge_time > 0_turns ) { if( bio.info().has_flag( STATIC( json_character_flag( "BIONIC_POWER_SOURCE" ) ) ) ) { // Convert fuel to bionic power burn_fuel( bio, result ); @@ -3312,7 +3312,14 @@ void bionic::deserialize( const JsonObject &jo ) id = bionic_id( jo.get_string( "id" ) ); invlet = jo.get_int( "invlet" ); powered = jo.get_bool( "powered" ); - charge_timer = jo.get_int( "charge" ); + + //Remove After 0.G + if( jo.has_int( "charge" ) ) { + charge_timer = time_duration::from_turns( jo.get_int( "charge" ) ); + } else { + jo.read( "charge_timer", charge_timer ); + } + if( jo.has_int( "incapacitated_time" ) ) { incapacitated_time = 1_turns * jo.get_int( "incapacitated_time" ); diff --git a/src/bionics.h b/src/bionics.h index 494fccd4c1163..18f8a0290eb18 100644 --- a/src/bionics.h +++ b/src/bionics.h @@ -48,7 +48,7 @@ struct bionic_data { /** Amount of free energy the bionic generates each turn regardless of activation state*/ units::energy power_trickle = 0_kJ; /** How often a bionic draws or produces power while active in turns */ - int charge_time = 0; + time_duration charge_time = 0_turns; /** Power bank size **/ units::energy capacity = 0_kJ; /** If true multiples of this can be installed */ @@ -197,7 +197,7 @@ struct bionic { using bionic_uid = unsigned int; bionic_id id; - int charge_timer = 0; + time_duration charge_timer = 0_turns; char invlet = 'a'; bool powered = false; /* An amount of time during which this bionic has been rendered inoperative. */ diff --git a/src/bionics_ui.cpp b/src/bionics_ui.cpp index 32dae33e0ec01..bd68a4a3b0d52 100644 --- a/src/bionics_ui.cpp +++ b/src/bionics_ui.cpp @@ -315,11 +315,11 @@ static std::string build_bionic_poweronly_string( const bionic &bio ) properties.push_back( string_format( _( "%s trigger" ), units::display( bio_data.power_trigger ) ) ); } - if( bio_data.charge_time > 0 && bio_data.power_over_time > 0_kJ ) { - properties.push_back( bio_data.charge_time == 1 + if( bio_data.charge_time > 0_turns && bio_data.power_over_time > 0_kJ ) { + properties.push_back( bio_data.charge_time == 1_turns ? string_format( _( "%s/turn" ), units::display( bio_data.power_over_time ) ) : string_format( _( "%s/%d turns" ), units::display( bio_data.power_over_time ), - bio_data.charge_time ) ); + to_turns( bio_data.charge_time ) ) ); } if( bio_data.has_flag( STATIC( json_character_flag( "BIONIC_TOGGLED" ) ) ) ) { properties.emplace_back( bio.powered ? _( "ON" ) : _( "OFF" ) ); From d5e1e9020869a3b1f2d3884880ba073e6e8384a5 Mon Sep 17 00:00:00 2001 From: Fris0uman Date: Sat, 9 Jul 2022 09:53:35 +0200 Subject: [PATCH 02/11] update mods --- data/mods/Aftershock/player/bionics.json | 26 +++++++++++------------ data/mods/Aftershock/player/obsolete.json | 2 +- data/mods/Magiclysm/bionics.json | 2 +- data/mods/TEST_DATA/bionics.json | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/data/mods/Aftershock/player/bionics.json b/data/mods/Aftershock/player/bionics.json index d72b004462084..bc9431618486f 100644 --- a/data/mods/Aftershock/player/bionics.json +++ b/data/mods/Aftershock/player/bionics.json @@ -7,7 +7,7 @@ "occupied_bodyparts": [ [ "torso", 10 ] ], "fuel_options": [ "sunlight" ], "fuel_efficiency": 1.0, - "time": 1, + "time": "1 s" "flags": [ "BIONIC_POWER_SOURCE", "BIONIC_TOGGLED" ] }, { @@ -19,7 +19,7 @@ "flags": [ "BIONIC_TOGGLED" ], "act_cost": "2 kJ", "react_cost": "2 kJ", - "time": 10 + "time": "10 s" }, { "id": "afs_bio_missiles", @@ -48,7 +48,7 @@ "flags": [ "BIONIC_TOGGLED", "BIONIC_SLEEP_FRIENDLY" ], "act_cost": "5 J", "react_cost": "5 J", - "time": 200 + "time": "200 s" }, { "id": "afs_bio_melee_counteraction", @@ -60,7 +60,7 @@ "enchantments": [ "melee_counteraction" ], "act_cost": "12 kJ", "react_cost": "12 kJ", - "time": 1 + "time": "1 s" }, { "id": "afs_bio_melee_optimization_unit", @@ -72,7 +72,7 @@ "enchantments": [ "melee_optimization" ], "act_cost": "12 kJ", "react_cost": "12 kJ", - "time": 1 + "time": "1 s" }, { "id": "bio_forcefield_bash_cut_weak", @@ -83,7 +83,7 @@ "available_upgrades": [ "bio_forcefield_bash_cut_medium", "bio_forcefield_bash_cut_heavy" ], "act_cost": "1 kJ", "react_cost": "1 kJ", - "time": 1, + "time": "1 s" "enchantments": [ "forcefield_bash_cut_weak" ], "flags": [ "BIONIC_TOGGLED" ] }, @@ -97,7 +97,7 @@ "available_upgrades": [ "bio_forcefield_bash_cut_heavy" ], "act_cost": "5 kJ", "react_cost": "5 kJ", - "time": 1, + "time": "1 s" "enchantments": [ "forcefield_bash_cut_medium" ], "flags": [ "BIONIC_TOGGLED" ] }, @@ -110,7 +110,7 @@ "upgraded_bionic": "bio_forcefield_bash_cut_medium", "act_cost": "10 kJ", "react_cost": "10 kJ", - "time": 1, + "time": "1 s" "enchantments": [ "forcefield_bash_cut_heavy" ], "flags": [ "BIONIC_TOGGLED" ] }, @@ -123,7 +123,7 @@ "available_upgrades": [ "bio_forcefield_ballistic_medium", "bio_forcefield_ballistic_heavy" ], "act_cost": "1 kJ", "react_cost": "1 kJ", - "time": 1, + "time": "1 s" "enchantments": [ "forcefield_ballistic_piercing_weak" ], "flags": [ "BIONIC_TOGGLED" ] }, @@ -137,7 +137,7 @@ "available_upgrades": [ "bio_forcefield_ballistic_heavy" ], "act_cost": "5 kJ", "react_cost": "5 kJ", - "time": 1, + "time": "1 s" "enchantments": [ "forcefield_ballistic_piercing_medium" ], "flags": [ "BIONIC_TOGGLED" ] }, @@ -150,7 +150,7 @@ "upgraded_bionic": "bio_forcefield_ballistic_medium", "act_cost": "10 kJ", "react_cost": "10 kJ", - "time": 1, + "time": "1 s" "enchantments": [ "forcefield_ballistic_piercing_heavy" ], "flags": [ "BIONIC_TOGGLED" ] }, @@ -170,7 +170,7 @@ "occupied_bodyparts": [ [ "torso", 10 ], [ "head", 2 ], [ "arm_l", 3 ], [ "arm_r", 3 ], [ "leg_l", 3 ], [ "leg_r", 3 ] ], "act_cost": "12 kJ", "spell_on_activation": { "id": "afs_translocation", "hit_self": true }, - "time": 5 + "time": "5 s" }, { "id": "afs_bio_cranialbomb", @@ -190,7 +190,7 @@ "enchantments": [ "protect_cold" ], "act_cost": "1 kJ", "react_cost": "1 kJ", - "time": 10 + "time": "10 s" }, { "type": "bionic", diff --git a/data/mods/Aftershock/player/obsolete.json b/data/mods/Aftershock/player/obsolete.json index 72805e0a491a7..6f8fd44381646 100644 --- a/data/mods/Aftershock/player/obsolete.json +++ b/data/mods/Aftershock/player/obsolete.json @@ -15,7 +15,7 @@ "occupied_bodyparts": [ [ "torso", 10 ] ], "fuel_options": [ "wind" ], "fuel_efficiency": 0.25, - "time": 1, + "time": "1 s", "flags": [ "BIONIC_POWER_SOURCE", "BIONIC_TOGGLED" ] } ] diff --git a/data/mods/Magiclysm/bionics.json b/data/mods/Magiclysm/bionics.json index e086a37924aa6..f9acad72c1071 100644 --- a/data/mods/Magiclysm/bionics.json +++ b/data/mods/Magiclysm/bionics.json @@ -9,7 +9,7 @@ "fuel_capacity": 100, "fuel_efficiency": 0.6, "exothermic_power_gen": true, - "time": 6, + "time": "6 s", "flags": [ "BIONIC_TOGGLED", "BIONIC_POWER_SOURCE" ] } ] diff --git a/data/mods/TEST_DATA/bionics.json b/data/mods/TEST_DATA/bionics.json index 0c24566b3502e..55608a378ac48 100644 --- a/data/mods/TEST_DATA/bionics.json +++ b/data/mods/TEST_DATA/bionics.json @@ -11,6 +11,6 @@ "react_cost": "9 kJ", "included": true, "//": "not actually included, this is a trick to not have to add an item version.", - "time": 1 + "time": "1 s" } ] From a5c9dccbc9025eece647bda64f65369ddb9e1e52 Mon Sep 17 00:00:00 2001 From: Fris0uman Date: Sat, 9 Jul 2022 10:18:09 +0200 Subject: [PATCH 03/11] time in mutation data --- data/json/mutations/mutations.json | 16 ++++++++-------- src/character.h | 8 ++++---- src/mutation.cpp | 16 ++++++++-------- src/mutation.h | 2 +- src/mutation_data.cpp | 2 +- src/mutation_ui.cpp | 10 +++++----- src/savegame_json.cpp | 8 +++++++- src/suffer.cpp | 8 ++++---- 8 files changed, 38 insertions(+), 32 deletions(-) diff --git a/data/json/mutations/mutations.json b/data/json/mutations/mutations.json index 01f918ecb3d8f..fe0f45155977f 100644 --- a/data/json/mutations/mutations.json +++ b/data/json/mutations/mutations.json @@ -155,7 +155,7 @@ "points": -1, "description": "A photophore has grown from your head. You can't consciously control it, and it might start to shine in response to your emotions or your physiological state.", "cost": 9, - "time": 810000, + "time": "225 h", "kcal": true, "encumbrance_covered": [ [ "head", 5 ] ], "changes_to": [ "BIOLUM1" ], @@ -206,7 +206,7 @@ "description": "A photophore has grown from your head; you can make it glow softly. This will make you very visible in the dark, ideal for attracting a partner during mating season.", "active": true, "cost": 9, - "time": 810000, + "time": "225 h", "kcal": true, "encumbrance_covered": [ [ "head", 5 ] ], "types": [ "BIOLUM" ], @@ -233,7 +233,7 @@ "description": "You can make your photophore glow brightly.", "active": true, "cost": 9, - "time": 405000, + "time": "112 h 30 m", "kcal": true, "encumbrance_covered": [ [ "head", 5 ] ], "types": [ "BIOLUM" ], @@ -894,7 +894,7 @@ "category": [ "BEAST" ], "active": true, "cost": 90, - "time": 10, + "time": "10 s", "fatigue": true, "kcal": true, "thirst": true, @@ -3853,7 +3853,7 @@ "copy-from": "EATHEALTH", "valid": false, "cost": 9, - "time": 1, + "time": "1 s", "kcal": true, "healing_awake": 300.0, "healing_resting": 350.0, @@ -4475,7 +4475,7 @@ "category": [ "INSECT" ], "active": true, "cost": 3, - "time": 1, + "time": "1 s", "fatigue": true, "kcal": true, "thirst": true, @@ -4620,7 +4620,7 @@ "category": [ "GASTROPOD" ], "active": true, "cost": 174, - "time": 100, + "time": "100 s", "thirst": true, "kcal": true }, @@ -4730,7 +4730,7 @@ "leads_to": [ "WEB_RAPPEL", "WEB_ROPE" ], "active": true, "cost": 69, - "time": 100, + "time": "100 s", "kcal": true, "thirst": true }, diff --git a/src/character.h b/src/character.h index eebf7b5f96758..7c3f08fcffa36 100644 --- a/src/character.h +++ b/src/character.h @@ -1321,9 +1321,9 @@ class Character : public Creature, public visitable bool has_active_mutation( const trait_id &b ) const; - int get_cost_timer( const trait_id &mut_id ) const; - void set_cost_timer( const trait_id &mut, int set ); - void mod_cost_timer( const trait_id &mut, int mod ); + time_duration get_cost_timer( const trait_id &mut_id ) const; + void set_cost_timer( const trait_id &mut, time_duration set ); + void mod_cost_timer( const trait_id &mut, time_duration mod ); /** Picks a random valid mutation and gives it to the Character, possibly removing/changing others along the way */ void mutate( const int &true_random_chance, bool use_vitamins ); @@ -3304,7 +3304,7 @@ class Character : public Creature, public visitable * to its cost (@ref mutation_branch::cost). When those costs have been paid, this * is reset to @ref mutation_branch::cooldown. */ - int charge = 0; + time_duration charge = 0_turns; bool show_sprite = true; diff --git a/src/mutation.cpp b/src/mutation.cpp index 71a32f68e2a02..bf15caea0e545 100644 --- a/src/mutation.cpp +++ b/src/mutation.cpp @@ -537,7 +537,7 @@ bool Character::has_active_mutation( const trait_id &b ) const return iter != my_mutations.end() && iter->second.powered; } -int Character::get_cost_timer( const trait_id &mut ) const +time_duration Character::get_cost_timer( const trait_id &mut ) const { const auto iter = my_mutations.find( mut ); if( iter != my_mutations.end() ) { @@ -545,10 +545,10 @@ int Character::get_cost_timer( const trait_id &mut ) const } else { debugmsg( "Tried to get cost timer of %s but doesn't have this mutation.", mut.c_str() ); } - return 0; + return 0_turns; } -void Character::set_cost_timer( const trait_id &mut, int set ) +void Character::set_cost_timer( const trait_id &mut, time_duration set ) { const auto iter = my_mutations.find( mut ); if( iter != my_mutations.end() ) { @@ -558,7 +558,7 @@ void Character::set_cost_timer( const trait_id &mut, int set ) } } -void Character::mod_cost_timer( const trait_id &mut, int mod ) +void Character::mod_cost_timer( const trait_id &mut, time_duration mod ) { set_cost_timer( mut, get_cost_timer( mut ) + mod ); } @@ -673,13 +673,13 @@ void Character::activate_mutation( const trait_id &mut ) mutation_name( mut ) ); return; } - if( tdata.powered && tdata.charge > 0 ) { + if( tdata.powered && tdata.charge > 0_turns ) { // Already-on units just lose a bit of charge - tdata.charge--; + tdata.charge -= 1_turns; } else { // Not-on units, or those with zero charge, have to pay the power cost - if( mdata.cooldown > 0 ) { - tdata.charge = mdata.cooldown - 1; + if( mdata.cooldown > 0_turns ) { + tdata.charge = mdata.cooldown - 1_turns; } if( mdata.hunger ) { // burn some energy diff --git a/src/mutation.h b/src/mutation.h index e0b175b2c5e95..a266d28f1fea7 100644 --- a/src/mutation.h +++ b/src/mutation.h @@ -195,7 +195,7 @@ struct mutation_branch { int ugliness = 0; int cost = 0; // costs are consumed every cooldown turns, - int cooldown = 0; + time_duration cooldown = 0_turns; // bodytemp elements: int bodytemp_min = 0; int bodytemp_max = 0; diff --git a/src/mutation_data.cpp b/src/mutation_data.cpp index 526a8aacf90ed..09fa908abb8ae 100644 --- a/src/mutation_data.cpp +++ b/src/mutation_data.cpp @@ -320,7 +320,7 @@ void mutation_branch::load( const JsonObject &jo, const std::string & ) optional( jo, was_loaded, "destroys_gear", destroys_gear, false ); optional( jo, was_loaded, "allow_soft_gear", allow_soft_gear, false ); optional( jo, was_loaded, "cost", cost, 0 ); - optional( jo, was_loaded, "time", cooldown, 0 ); + optional( jo, was_loaded, "time", cooldown, 0_turns ); optional( jo, was_loaded, "kcal", hunger, false ); optional( jo, was_loaded, "thirst", thirst, false ); optional( jo, was_loaded, "fatigue", fatigue, false ); diff --git a/src/mutation_ui.cpp b/src/mutation_ui.cpp index ea99f954c4920..81963b9a2766c 100644 --- a/src/mutation_ui.cpp +++ b/src/mutation_ui.cpp @@ -318,13 +318,13 @@ void avatar::power_mutations() resource_unit += _( " fatigue" ); } mut_desc += mutation_name( md.id ); - if( md.cost > 0 && md.cooldown > 0 ) { - mut_desc += string_format( _( " - %d%s / %d turns" ), - md.cost, resource_unit, md.cooldown ); + if( md.cost > 0 && md.cooldown > 0_turns ) { + mut_desc += string_format( _( " - %d%s / %s" ), + md.cost, resource_unit, to_string_clipped( md.cooldown ) ); } else if( md.cost > 0 ) { mut_desc += string_format( _( " - %d%s" ), md.cost, resource_unit ); - } else if( md.cooldown > 0 ) { - mut_desc += string_format( _( " - %d turns" ), md.cooldown ); + } else if( md.cooldown > 0_turns ) { + mut_desc += string_format( _( " - %s" ), to_string_clipped( md.cooldown ) ); } if( td.powered ) { mut_desc += _( " - Active" ); diff --git a/src/savegame_json.cpp b/src/savegame_json.cpp index 746a99a50b12b..d624237817f5e 100644 --- a/src/savegame_json.cpp +++ b/src/savegame_json.cpp @@ -532,7 +532,13 @@ void Character::trait_data::deserialize( const JsonObject &data ) { data.allow_omitted_members(); data.read( "key", key ); - data.read( "charge", charge ); + + //Remove after 0.G + if( data.has_int( "charge" ) ) { + charge = time_duration::from_turns( data.get_int( "charge" ) ); + } else { + data.read( "charge", charge ); + } data.read( "powered", powered ); data.read( "show_sprite", show_sprite ); if( data.has_member( "variant-parent" ) ) { diff --git a/src/suffer.cpp b/src/suffer.cpp index c691420548ece..1e47cb9784a3a 100644 --- a/src/suffer.cpp +++ b/src/suffer.cpp @@ -232,13 +232,13 @@ void suffer::water_damage( Character &you, const trait_id &mut_id ) void suffer::mutation_power( Character &you, const trait_id &mut_id ) { - if( you.get_cost_timer( mut_id ) > 0 ) { + if( you.get_cost_timer( mut_id ) > 0_turns ) { // Not ready to consume cost yet, the timer ticks on - you.mod_cost_timer( mut_id, -1 ); + you.mod_cost_timer( mut_id, -1_turns ); } else { // Ready to consume cost: pay the power cost and reset timer - if( mut_id->cooldown > 0 ) { - you.set_cost_timer( mut_id, mut_id->cooldown - 1 ); + if( mut_id->cooldown > 0_turns ) { + you.set_cost_timer( mut_id, mut_id->cooldown - 1_turns ); } if( mut_id->hunger ) { if( you.get_bmi() < character_weight_category::underweight ) { From 1b820fb490e19c3e332cc13833f74c3eab02daa6 Mon Sep 17 00:00:00 2001 From: Fris0uman Date: Sat, 9 Jul 2022 13:23:16 +0200 Subject: [PATCH 04/11] Construction time is string only --- src/construction.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/construction.cpp b/src/construction.cpp index 2d5b5431269fc..5dc5802575365 100644 --- a/src/construction.cpp +++ b/src/construction.cpp @@ -1867,9 +1867,7 @@ void load_construction( const JsonObject &jo ) } con.category = construction_category_id( jo.get_string( "category", "OTHER" ) ); - if( jo.has_int( "time" ) ) { - con.time = to_moves( time_duration::from_minutes( jo.get_int( "time" ) ) ); - } else if( jo.has_string( "time" ) ) { + if( jo.has_string( "time" ) ) { con.time = to_moves( read_from_json_string( jo.get_member( "time" ), time_duration::units ) ); } From b9937e2c1d42251127094f4e678e74a6dd360c01 Mon Sep 17 00:00:00 2001 From: Fris0uman Date: Sat, 9 Jul 2022 14:22:24 +0200 Subject: [PATCH 05/11] recipe time is string only --- data/json/recipes/food/brewing.json | 4 ++-- data/json/recipes/food/distill.json | 2 +- data/json/uncraft/generic.json | 2 +- data/mods/Aftershock/player/bionics.json | 14 ++++++------ .../Aftershock/recipes/armor_recipes.json | 2 +- .../recipes/comestible_recipes.json | 2 +- .../recipes/frankenstein_recipes.json | 2 +- data/mods/Aftershock/recipes/gun_recipes.json | 2 +- data/mods/Aftershock/recipes/mutagens.json | 8 +++---- .../Aftershock/recipes/recipe_overrides.json | 22 +++++++++---------- data/mods/Aftershock/recipes/recipes.json | 20 ++++++++--------- .../Aftershock/recipes/robot_recipes.json | 2 +- data/mods/Aftershock/recipes/uncraft.json | 4 ++-- .../recipes/blaze_construction_recipes.json | 6 ++--- .../recipes/blaze_other_recipes.json | 6 ++--- .../mods/CRT_EXPANSION/items/crt_recipes.json | 6 ++--- .../CrazyCataclysm/crazy_aperturepotato.json | 2 +- .../CrazyCataclysm/crazy_comestibles.json | 2 +- data/mods/innawood/recipes/distill.json | 2 +- src/recipe.cpp | 16 ++++---------- 20 files changed, 59 insertions(+), 67 deletions(-) diff --git a/data/json/recipes/food/brewing.json b/data/json/recipes/food/brewing.json index 32e581da1707b..b67199a3ab6b9 100644 --- a/data/json/recipes/food/brewing.json +++ b/data/json/recipes/food/brewing.json @@ -7,7 +7,7 @@ "subcategory": "CSC_FOOD_BREW", "skill_used": "cooking", "difficulty": 3, - "time": 40000, + "time": "6 m 40 s", "autolearn": true, "//": "Should be taught by a flag/mutation rather than autolearned", "batch_time_factors": [ 80, 4 ], @@ -23,7 +23,7 @@ "subcategory": "CSC_FOOD_BREW", "skill_used": "cooking", "difficulty": 3, - "time": 40000, + "time": "6 m 40 s", "autolearn": true, "//": "Should be taught by a flag/mutation rather than autolearned", "batch_time_factors": [ 80, 4 ], diff --git a/data/json/recipes/food/distill.json b/data/json/recipes/food/distill.json index 5a3efebdee0c7..616069ffe5c44 100644 --- a/data/json/recipes/food/distill.json +++ b/data/json/recipes/food/distill.json @@ -24,7 +24,7 @@ "subcategory": "CSC_FOOD_BREW", "skill_used": "cooking", "difficulty": 4, - "time": 30000, + "time": "5 m", "batch_time_factors": [ 50, 4 ], "book_learn": [ [ "distilling_cookbook", 4 ] ], "qualities": [ { "id": "BOIL", "level": 2 }, { "id": "DISTILL", "level": 2 } ], diff --git a/data/json/uncraft/generic.json b/data/json/uncraft/generic.json index 3d79c1f3fe1cf..6e88751ef7f02 100644 --- a/data/json/uncraft/generic.json +++ b/data/json/uncraft/generic.json @@ -3,7 +3,7 @@ "result": "blade_scythe", "type": "uncraft", "activity_level": "MODERATE_EXERCISE", - "time": 0, + "time": "0 s", "components": [ [ [ "steel_lump", 1 ] ] ] }, { diff --git a/data/mods/Aftershock/player/bionics.json b/data/mods/Aftershock/player/bionics.json index bc9431618486f..76fecc9437b0f 100644 --- a/data/mods/Aftershock/player/bionics.json +++ b/data/mods/Aftershock/player/bionics.json @@ -7,7 +7,7 @@ "occupied_bodyparts": [ [ "torso", 10 ] ], "fuel_options": [ "sunlight" ], "fuel_efficiency": 1.0, - "time": "1 s" + "time": "1 s", "flags": [ "BIONIC_POWER_SOURCE", "BIONIC_TOGGLED" ] }, { @@ -83,7 +83,7 @@ "available_upgrades": [ "bio_forcefield_bash_cut_medium", "bio_forcefield_bash_cut_heavy" ], "act_cost": "1 kJ", "react_cost": "1 kJ", - "time": "1 s" + "time": "1 s", "enchantments": [ "forcefield_bash_cut_weak" ], "flags": [ "BIONIC_TOGGLED" ] }, @@ -97,7 +97,7 @@ "available_upgrades": [ "bio_forcefield_bash_cut_heavy" ], "act_cost": "5 kJ", "react_cost": "5 kJ", - "time": "1 s" + "time": "1 s", "enchantments": [ "forcefield_bash_cut_medium" ], "flags": [ "BIONIC_TOGGLED" ] }, @@ -110,7 +110,7 @@ "upgraded_bionic": "bio_forcefield_bash_cut_medium", "act_cost": "10 kJ", "react_cost": "10 kJ", - "time": "1 s" + "time": "1 s", "enchantments": [ "forcefield_bash_cut_heavy" ], "flags": [ "BIONIC_TOGGLED" ] }, @@ -123,7 +123,7 @@ "available_upgrades": [ "bio_forcefield_ballistic_medium", "bio_forcefield_ballistic_heavy" ], "act_cost": "1 kJ", "react_cost": "1 kJ", - "time": "1 s" + "time": "1 s", "enchantments": [ "forcefield_ballistic_piercing_weak" ], "flags": [ "BIONIC_TOGGLED" ] }, @@ -137,7 +137,7 @@ "available_upgrades": [ "bio_forcefield_ballistic_heavy" ], "act_cost": "5 kJ", "react_cost": "5 kJ", - "time": "1 s" + "time": "1 s", "enchantments": [ "forcefield_ballistic_piercing_medium" ], "flags": [ "BIONIC_TOGGLED" ] }, @@ -150,7 +150,7 @@ "upgraded_bionic": "bio_forcefield_ballistic_medium", "act_cost": "10 kJ", "react_cost": "10 kJ", - "time": "1 s" + "time": "1 s", "enchantments": [ "forcefield_ballistic_piercing_heavy" ], "flags": [ "BIONIC_TOGGLED" ] }, diff --git a/data/mods/Aftershock/recipes/armor_recipes.json b/data/mods/Aftershock/recipes/armor_recipes.json index 5f64eb71df510..c2e2b44db2173 100644 --- a/data/mods/Aftershock/recipes/armor_recipes.json +++ b/data/mods/Aftershock/recipes/armor_recipes.json @@ -7,7 +7,7 @@ "subcategory": "CSC_ARMOR_TORSO", "skill_used": "tailor", "difficulty": 1, - "time": 10000, + "time": "100 s", "autolearn": true, "reversible": true, "using": [ [ "sewing_standard", 14 ] ], diff --git a/data/mods/Aftershock/recipes/comestible_recipes.json b/data/mods/Aftershock/recipes/comestible_recipes.json index 8022dba1186a6..a73c74a2c74f7 100644 --- a/data/mods/Aftershock/recipes/comestible_recipes.json +++ b/data/mods/Aftershock/recipes/comestible_recipes.json @@ -20,7 +20,7 @@ "category": "CC_FOOD", "subcategory": "CSC_FOOD_BREAD", "skill_used": "cooking", - "time": 500, + "time": "5 s", "autolearn": true, "qualities": [ { "id": "CONTAIN", "level": 1 } ], "components": [ [ [ "afs_calorie_pill", 1 ] ], [ [ "water", 1 ], [ "water_clean", 1 ] ] ] diff --git a/data/mods/Aftershock/recipes/frankenstein_recipes.json b/data/mods/Aftershock/recipes/frankenstein_recipes.json index 8aa9f117db5a8..7407fd4e0003c 100644 --- a/data/mods/Aftershock/recipes/frankenstein_recipes.json +++ b/data/mods/Aftershock/recipes/frankenstein_recipes.json @@ -8,7 +8,7 @@ "skill_used": "electronics", "skills_required": [ "firstaid", 8 ], "difficulty": 7, - "time": 50000, + "time": "500 s", "reversible": true, "decomp_learn": 5, "book_learn": [ [ "cyrus'_notes", 7 ] ], diff --git a/data/mods/Aftershock/recipes/gun_recipes.json b/data/mods/Aftershock/recipes/gun_recipes.json index e8f6fa95d525d..98da2ffffa23a 100644 --- a/data/mods/Aftershock/recipes/gun_recipes.json +++ b/data/mods/Aftershock/recipes/gun_recipes.json @@ -8,7 +8,7 @@ "skill_used": "electronics", "difficulty": 4, "byproducts": [ [ "afs_energy_storage_2" ] ], - "time": 300000, + "time": "50 m", "autolearn": [ [ "electronics", 6 ] ], "book_learn": [ [ "advanced_electronics", 3 ], [ "textbook_electronics", 3 ] ], "qualities": [ { "id": "SCREW_FINE", "level": 1 } ], diff --git a/data/mods/Aftershock/recipes/mutagens.json b/data/mods/Aftershock/recipes/mutagens.json index 7b376c2ccb729..26795ee2d5d99 100644 --- a/data/mods/Aftershock/recipes/mutagens.json +++ b/data/mods/Aftershock/recipes/mutagens.json @@ -8,7 +8,7 @@ "skill_used": "chemistry", "skills_required": [ "firstaid", 6 ], "difficulty": 10, - "time": 120000, + "time": "20 m", "tools": [ [ [ "surface_heat", 30, "LIST" ] ] ], "book_learn": [ [ "recipe_uplift", 9 ] ], "qualities": [ { "id": "CHEM", "level": 3 } ], @@ -23,7 +23,7 @@ "skill_used": "chemistry", "skills_required": [ "firstaid", 6 ], "difficulty": 10, - "time": 120000, + "time": "20 m", "tools": [ [ [ "surface_heat", 30, "LIST" ] ] ], "book_learn": [ [ "recipe_uplift", 9 ] ], "qualities": [ { "id": "CHEM", "level": 3 } ], @@ -43,7 +43,7 @@ "skill_used": "chemistry", "skills_required": [ "firstaid", 6 ], "difficulty": 10, - "time": 120000, + "time": "20 m", "tools": [ [ [ "surface_heat", 30, "LIST" ] ] ], "book_learn": [ [ "millyficents_diary", 9 ] ], "qualities": [ { "id": "CHEM", "level": 3 } ], @@ -58,7 +58,7 @@ "skill_used": "chemistry", "skills_required": [ "firstaid", 6 ], "difficulty": 10, - "time": 120000, + "time": "20 m", "tools": [ [ [ "surface_heat", 30, "LIST" ] ] ], "book_learn": [ [ "millyficents_diary", 9 ] ], "qualities": [ { "id": "CHEM", "level": 3 } ], diff --git a/data/mods/Aftershock/recipes/recipe_overrides.json b/data/mods/Aftershock/recipes/recipe_overrides.json index 43c5476c6237d..0f81c8b83fa14 100644 --- a/data/mods/Aftershock/recipes/recipe_overrides.json +++ b/data/mods/Aftershock/recipes/recipe_overrides.json @@ -7,7 +7,7 @@ "subcategory": "CSC_ELECTRONIC_TOOLS", "skill_used": "electronics", "difficulty": 4, - "time": 3000, + "time": "30 s", "reversible": true, "book_learn": [ [ "recipe_caseless", 8 ], [ "textbook_atomic_lab", 3 ] ], "qualities": [ { "id": "SCREW", "level": 1 } ], @@ -28,7 +28,7 @@ "subcategory": "CSC_ELECTRONIC_LIGHTING", "skill_used": "electronics", "difficulty": 3, - "time": 20000, + "time": "3 m 20 s", "reversible": true, "book_learn": [ [ "recipe_caseless", 6 ], [ "textbook_atomic_lab", 3 ] ], "qualities": [ { "id": "SCREW", "level": 1 } ], @@ -48,7 +48,7 @@ "subcategory": "CSC_ELECTRONIC_LIGHTING", "skill_used": "electronics", "difficulty": 3, - "time": 30000, + "time": "5 m", "reversible": true, "book_learn": [ [ "recipe_caseless", 6 ], [ "textbook_atomic_lab", 3 ] ], "qualities": [ { "id": "SCREW", "level": 1 } ], @@ -67,7 +67,7 @@ "category": "CC_FOOD", "subcategory": "CSC_FOOD_MEAT", "skill_used": "cooking", - "time": 7000, + "time": "1 m 10 s", "autolearn": true, "batch_time_factors": [ 70, 1 ], "qualities": [ { "id": "COOK", "level": 1 } ], @@ -83,7 +83,7 @@ "subcategory": "CSC_FOOD_MEAT", "skill_used": "cooking", "difficulty": 1, - "time": 5000, + "time": "50 s", "autolearn": true, "batch_time_factors": [ 70, 1 ], "qualities": [ { "id": "COOK", "level": 1 } ], @@ -135,7 +135,7 @@ "skill_used": "cooking", "difficulty": 6, "charges": 1, - "time": 20000, + "time": "3 m 20 s", "book_learn": [ [ "mag_cooking", 4 ], [ "mag_glam", 5 ] ], "qualities": [ { "id": "CUT", "level": 2 }, { "id": "COOK", "level": 3 } ], "tools": [ [ [ "surface_heat", 20, "LIST" ] ] ], @@ -149,7 +149,7 @@ "subcategory": "CSC_FOOD_MEAT", "skill_used": "cooking", "skills_required": [ "survival", 2 ], - "time": 10000, + "time": "100 s", "charges": 2, "book_learn": [ [ "cookbook", 1 ], [ "scots_cookbook", 2 ] ], "difficulty": 3, @@ -166,7 +166,7 @@ "subcategory": "CSC_FOOD_MEAT", "skill_used": "cooking", "difficulty": 4, - "time": 25000, + "time": "4 m 10 s", "book_learn": [ [ "cookbook", 2 ] ], "qualities": [ { "id": "COOK", "level": 2 }, { "id": "CUT", "level": 2 } ], "tools": [ [ [ "surface_heat", 25, "LIST" ] ] ], @@ -187,7 +187,7 @@ "subcategory": "CSC_FOOD_MEAT", "skill_used": "cooking", "difficulty": 4, - "time": 60000, + "time": "10 m", "charges": 1, "book_learn": [ [ "cookbook", 2 ], [ "family_cookbook", 2 ] ], "qualities": [ { "id": "COOK", "level": 3 }, { "id": "CUT", "level": 2 } ], @@ -211,7 +211,7 @@ "subcategory": "CSC_FOOD_MEAT", "skill_used": "cooking", "difficulty": 3, - "time": 10000, + "time": "100 s", "batch_time_factors": [ 70, 1 ], "book_learn": [ [ "scots_cookbook", 2 ], [ "cookbook", 1 ], [ "textbook_survival", 3 ] ], "qualities": [ { "id": "COOK", "level": 3 } ], @@ -226,7 +226,7 @@ "subcategory": "CSC_ELECTRONIC_PARTS", "skill_used": "electronics", "difficulty": 3, - "time": 50000, + "time": "8 m 20 s", "reversible": true, "autolearn": [ [ "electronics", 2 ] ], "using": [ [ "soldering_standard", 35 ] ], diff --git a/data/mods/Aftershock/recipes/recipes.json b/data/mods/Aftershock/recipes/recipes.json index 5582c172679ff..921b42253642c 100644 --- a/data/mods/Aftershock/recipes/recipes.json +++ b/data/mods/Aftershock/recipes/recipes.json @@ -8,7 +8,7 @@ "skill_used": "electronics", "skills_required": [ "fabrication", 2 ], "difficulty": 1, - "time": 5000, + "time": "50 s", "book_learn": [ [ "manual_electronics", 1 ], [ "mag_electronics", 1 ], [ "textbook_anarch", 1 ] ], "qualities": [ { "id": "SCREW", "level": 1 } ], "components": [ @@ -26,7 +26,7 @@ "skill_used": "mechanics", "skills_required": [ "electronics", 5 ], "difficulty": 10, - "time": 360000, + "time": "1 h", "reversible": true, "decomp_learn": 10, "book_learn": [ [ "textbook_atomic_lab", 5 ] ], @@ -50,7 +50,7 @@ "skill_used": "mechanics", "skills_required": [ "electronics", 4 ], "difficulty": 8, - "time": 30000, + "time": "5 m", "book_learn": [ [ "textbook_atomic_lab", 5 ] ], "qualities": [ { "id": "SCREW", "level": 1 }, { "id": "WRENCH", "level": 1 } ], "components": [ [ [ "canister_empty", 1 ] ], [ [ "plut_slurry", 10 ], [ "plut_slurry_dense", 5 ] ], [ [ "power_supply", 2 ] ] ] @@ -64,7 +64,7 @@ "subcategory": "CSC_ELECTRONIC_COMPONENTS", "skill_used": "electronics", "difficulty": 6, - "time": 30000, + "time": "5 m", "book_learn": [ [ "textbook_atomic_lab", 3 ] ], "qualities": [ { "id": "SCREW", "level": 1 } ], "components": [ @@ -82,7 +82,7 @@ "skill_used": "mechanics", "skills_required": [ "melee", 2 ], "difficulty": 4, - "time": 30000, + "time": "5 m", "autolearn": true, "qualities": [ { "id": "SAW_M", "level": 1 }, { "id": "CUT", "level": 2 }, { "id": "SCREW", "level": 1 } ], "components": [ [ [ "afs_power_cutter", 1 ] ], [ [ "steel_chunk", 3 ], [ "scrap", 6 ] ] ], @@ -95,7 +95,7 @@ "category": "CC_OTHER", "subcategory": "CSC_OTHER_TOOLS", "skill_used": "electronics", - "time": 20000, + "time": "3 m 20 s", "difficulty": 3, "book_learn": [ [ "mag_electronics", 3 ], [ "manual_electronics", 2 ] ], "using": [ [ "soldering_standard", 10 ] ], @@ -116,7 +116,7 @@ "subcategory": "CSC_OTHER_PARTS", "skill_used": "fabrication", "difficulty": 1, - "time": 8000, + "time": "80 s", "reversible": true, "autolearn": true, "using": [ [ "welding_standard", 6 ] ], @@ -145,7 +145,7 @@ "subcategory": "CSC_ELECTRONIC_TOOLS", "skill_used": "electronics", "difficulty": 5, - "time": 30000, + "time": "5 m", "book_learn": [ [ "recipe_caseless", 5 ], [ "textbook_atomic_lab", 4 ] ], "qualities": [ { "id": "SCREW", "level": 1 } ], "//": "Conversion of a normal smartphone into an atomic one by replacing the power supply.", @@ -159,7 +159,7 @@ "subcategory": "CSC_WEAPON_RANGED", "skill_used": "electronics", "difficulty": 5, - "time": 300000, + "time": "50 m", "reversible": true, "autolearn": [ [ "electronics", 4 ] ], "book_learn": [ [ "advanced_electronics", 3 ], [ "textbook_electronics", 3 ] ], @@ -181,7 +181,7 @@ "subcategory": "CSC_ELECTRONIC_COMPONENTS", "skill_used": "electronics", "difficulty": 5, - "time": 5000, + "time": "50 s", "autolearn": [ [ "electronics", 7 ] ], "book_learn": [ [ "textbook_atomic", 5 ] ], "qualities": [ { "id": "SCREW", "level": 1 }, { "id": "SAW_M", "level": 1 } ], diff --git a/data/mods/Aftershock/recipes/robot_recipes.json b/data/mods/Aftershock/recipes/robot_recipes.json index 9b9374968ba41..0116c6a37346e 100644 --- a/data/mods/Aftershock/recipes/robot_recipes.json +++ b/data/mods/Aftershock/recipes/robot_recipes.json @@ -40,7 +40,7 @@ "skill_used": "electronics", "skills_required": [ [ "mechanics", 4 ], [ "computer", 5 ] ], "difficulty": 6, - "time": 25000, + "time": "4 m 10 s", "reversible": false, "book_learn": [ [ "recipe_lab_elec", 6 ], [ "textbook_robots", 7 ] ], "tools": [ [ [ "electrohack", 20 ] ] ], diff --git a/data/mods/Aftershock/recipes/uncraft.json b/data/mods/Aftershock/recipes/uncraft.json index 59044a5c2e6ee..4cf1ae741ad95 100644 --- a/data/mods/Aftershock/recipes/uncraft.json +++ b/data/mods/Aftershock/recipes/uncraft.json @@ -14,7 +14,7 @@ "result": "afs_atomic_smartphone", "type": "uncraft", "activity_level": "fake", - "time": 500, + "time": "5 s", "qualities": [ { "id": "SCREW", "level": 1 } ], "components": [ [ [ "plastic_chunk", 1 ] ], @@ -142,7 +142,7 @@ "result": "aza_sword", "type": "uncraft", "activity_level": "fake", - "time": 500, + "time": "5 s", "qualities": [ { "id": "HAMMER", "level": 1 }, { "id": "SAW_M", "level": 1 } ], "components": [ [ [ "afs_material_2", 6 ] ], [ [ "afs_material_3", 4 ] ], [ [ "afs_material_1", 8 ] ] ] }, diff --git a/data/mods/BlazeIndustries/recipes/blaze_construction_recipes.json b/data/mods/BlazeIndustries/recipes/blaze_construction_recipes.json index 6dbab78fce605..4aa1d081a2e3a 100644 --- a/data/mods/BlazeIndustries/recipes/blaze_construction_recipes.json +++ b/data/mods/BlazeIndustries/recipes/blaze_construction_recipes.json @@ -38,7 +38,7 @@ "group": "convert_fridge_power_supply", "category": "FURN", "required_skills": [ [ "fabrication", 3 ], [ "electronics", 4 ], [ "mechanics", 3 ] ], - "time": 30, + "time": "1 s", "qualities": [ { "id": "SCREW", "level": 1 }, { "id": "HAMMER", "level": 3 }, { "id": "SAW_M", "level": 2 } ], "components": [ [ [ "cable", 10 ] ], [ [ "power_supply", 1 ] ], [ [ "plastic_chunk", 2 ] ] ], "pre_note": "Converts a fridge to run off of vehicle power. You can 'e'xamine it afterwards to take it down for mounting.", @@ -51,7 +51,7 @@ "group": "convert_vehicle_fridge_to_freezer", "category": "FURN", "required_skills": [ [ "electronics", 3 ], [ "mechanics", 3 ] ], - "time": 20, + "time": "1 s", "qualities": [ { "id": "SCREW", "level": 1 }, { "id": "HAMMER", "level": 3 }, { "id": "SAW_M", "level": 2 } ], "components": [ [ [ "cable", 10 ] ], [ [ "amplifier", 3 ] ], [ [ "refrigerant_tank", 2 ] ] ], "pre_note": "Further modifies a converted fridge to function as a freezer. You can 'e'xamine it afterwards to take it down for mounting.", @@ -64,7 +64,7 @@ "group": "convert_vehicle_fridge_to_freezer", "category": "FURN", "required_skills": [ [ "electronics", 3 ], [ "mechanics", 3 ] ], - "time": 20, + "time": "1 s", "qualities": [ { "id": "SCREW", "level": 1 }, { "id": "HAMMER", "level": 3 }, { "id": "SAW_M", "level": 2 } ], "components": [ [ [ "cable", 10 ] ], [ [ "amplifier", 3 ] ], [ [ "refrigerant_tank", 2 ] ], [ [ "afs_fridge", 1 ] ] ], "pre_note": "Further modifies a converted fridge to function as a freezer. You can 'e'xamine it afterwards to take it down for mounting.", diff --git a/data/mods/BlazeIndustries/recipes/blaze_other_recipes.json b/data/mods/BlazeIndustries/recipes/blaze_other_recipes.json index 7b8b9712baf18..80c177ebc3ee7 100644 --- a/data/mods/BlazeIndustries/recipes/blaze_other_recipes.json +++ b/data/mods/BlazeIndustries/recipes/blaze_other_recipes.json @@ -121,7 +121,7 @@ "skill_used": "fabrication", "skills_required": [ "electronics", 3 ], "difficulty": 4, - "time": 90000, + "time": "15 m", "decomp_learn": 3, "reversible": true, "book_learn": [ [ "textbook_mechanics", 6 ], [ "textbook_electronics", 8 ], [ "textbook_fabrication", 8 ], [ "welding_book", 5 ] ], @@ -139,7 +139,7 @@ "skill_used": "fabrication", "skills_required": [ "electronics", 3 ], "difficulty": 4, - "time": 90000, + "time": "15 m", "decomp_learn": 3, "reversible": true, "book_learn": [ [ "textbook_fabrication", 3 ], [ "manual_fabrication", 3 ], [ "manual_electronics", 3 ], [ "manual_mechanics", 3 ] ], @@ -170,7 +170,7 @@ "subcategory": "CSC_OTHER_VEHICLE", "skill_used": "electronics", "difficulty": 4, - "time": 60000, + "time": "10 m", "decomp_learn": 3, "reversible": true, "autolearn": true, diff --git a/data/mods/CRT_EXPANSION/items/crt_recipes.json b/data/mods/CRT_EXPANSION/items/crt_recipes.json index aa223e02f4194..114288e8b8835 100644 --- a/data/mods/CRT_EXPANSION/items/crt_recipes.json +++ b/data/mods/CRT_EXPANSION/items/crt_recipes.json @@ -7,7 +7,7 @@ "subcategory": "CSC_OTHER_OTHER", "skill_used": "survival", "difficulty": 0, - "time": 400, + "time": "4 s", "autolearn": true, "components": [ [ [ "withered", 3 ] ] ] }, @@ -15,7 +15,7 @@ "result": "withered_bundle", "type": "uncraft", "activity_level": "fake", - "time": 300, + "time": "3 s", "components": [ [ [ "withered", 3 ] ] ] }, { @@ -26,7 +26,7 @@ "subcategory": "CSC_ARMOR_SUIT", "skill_used": "survival", "difficulty": 1, - "time": 1000, + "time": "10 s", "autolearn": true, "components": [ [ [ "withered_bundle", 20 ] ] ] } diff --git a/data/mods/CrazyCataclysm/crazy_aperturepotato.json b/data/mods/CrazyCataclysm/crazy_aperturepotato.json index ffe41cb1f7440..23c9e8d4235c9 100644 --- a/data/mods/CrazyCataclysm/crazy_aperturepotato.json +++ b/data/mods/CrazyCataclysm/crazy_aperturepotato.json @@ -7,7 +7,7 @@ "subcategory": "CSC_ELECTRONIC_COMPONENTS", "skill_used": "electronics", "difficulty": 8, - "time": 11000, + "time": "110 s", "book_learn": [ [ "textbook_robots", 4 ] ], "qualities": [ { "id": "SCREW", "level": 1 } ], "components": [ diff --git a/data/mods/CrazyCataclysm/crazy_comestibles.json b/data/mods/CrazyCataclysm/crazy_comestibles.json index d33b0273a4b35..cce0a5d910776 100644 --- a/data/mods/CrazyCataclysm/crazy_comestibles.json +++ b/data/mods/CrazyCataclysm/crazy_comestibles.json @@ -26,7 +26,7 @@ "skill_used": "cooking", "difficulty": 1, "autolearn": true, - "time": 1000, + "time": "10 s", "qualities": [ { "id": "COOK", "level": 2 } ], "components": [ [ [ "cookies", 4 ] ], [ [ "marloss_berry", 1 ], [ "marloss_seed", 1 ], [ "mycus_fruit", 1 ] ] ] } diff --git a/data/mods/innawood/recipes/distill.json b/data/mods/innawood/recipes/distill.json index 25d56ac72a2a2..71241abb72f05 100644 --- a/data/mods/innawood/recipes/distill.json +++ b/data/mods/innawood/recipes/distill.json @@ -8,7 +8,7 @@ "subcategory": "CSC_FOOD_BREW", "skill_used": "cooking", "difficulty": 4, - "time": 30000, + "time": "5 m", "batch_time_factors": [ 50, 4 ], "autolearn": true, "qualities": [ { "id": "BOIL", "level": 2 }, { "id": "DISTILL", "level": 2 } ], diff --git a/src/recipe.cpp b/src/recipe.cpp index 2067facada3f0..b42157054d244 100644 --- a/src/recipe.cpp +++ b/src/recipe.cpp @@ -183,10 +183,7 @@ void recipe::load( const JsonObject &jo, const std::string &src ) return; } - if( jo.has_int( "time" ) ) { - // so we can specify moves that is not a multiple of 100 - time = jo.get_int( "time" ); - } else if( jo.has_string( "time" ) ) { + if( jo.has_string( "time" ) ) { time = to_moves( read_from_json_string( jo.get_member( "time" ), time_duration::units ) ); } @@ -370,14 +367,9 @@ void recipe::load( const JsonObject &jo, const std::string &src ) blueprint_reqs = cata::make_value(); const JsonObject jneeds = jo.get_object( "blueprint_needs" ); if( jneeds.has_member( "time" ) ) { - if( jneeds.has_int( "time" ) ) { - // so we can specify moves that is not a multiple of 100 - blueprint_reqs->time = jneeds.get_int( "time" ); - } else { - blueprint_reqs->time = - to_moves( read_from_json_string( - jneeds.get_member( "time" ), time_duration::units ) ); - } + blueprint_reqs->time = + to_moves( read_from_json_string( + jneeds.get_member( "time" ), time_duration::units ) ); } if( jneeds.has_member( "skills" ) ) { std::vector> blueprint_skills; From 2b4018dc1c91c70065fd5f241e3de30862892a7b Mon Sep 17 00:00:00 2001 From: Fris0uman Date: Sat, 9 Jul 2022 15:18:09 +0200 Subject: [PATCH 06/11] Book time is string only --- data/mods/Aftershock/items/books.json | 4 ++-- data/mods/Magiclysm/items/recipe_books.json | 2 +- src/activity_actor.cpp | 18 +++++++++--------- src/avatar.cpp | 15 +++++++-------- src/character.cpp | 10 +++++----- src/character.h | 2 +- src/game_inventory.cpp | 4 ++-- src/item.cpp | 18 +++++++----------- src/item_factory.cpp | 7 +------ src/itype.h | 4 ++-- src/npc.cpp | 8 ++++---- src/npc.h | 2 +- 12 files changed, 42 insertions(+), 52 deletions(-) diff --git a/data/mods/Aftershock/items/books.json b/data/mods/Aftershock/items/books.json index 55e49316d6621..ccf1cf1e19cf8 100644 --- a/data/mods/Aftershock/items/books.json +++ b/data/mods/Aftershock/items/books.json @@ -13,7 +13,7 @@ "symbol": "?", "color": "light_blue", "intelligence": 8, - "time": 20, + "time": "20 m", "chapters": 30, "fun": 6 }, @@ -31,7 +31,7 @@ "symbol": "?", "color": "light_blue", "intelligence": 4, - "time": 20, + "time": "20 m", "chapters": 3, "fun": 2 }, diff --git a/data/mods/Magiclysm/items/recipe_books.json b/data/mods/Magiclysm/items/recipe_books.json index 419e4ded50ed1..fe51b70358fbe 100644 --- a/data/mods/Magiclysm/items/recipe_books.json +++ b/data/mods/Magiclysm/items/recipe_books.json @@ -114,7 +114,7 @@ "symbol": "?", "material": [ "paper" ], "volume": "1250 ml", - "time": 60, + "time": "1 h", "fun": 0, "skill": "fabrication", "price": 30000, diff --git a/src/activity_actor.cpp b/src/activity_actor.cpp index 121b69bff9f7f..5dbeb23eb39d3 100644 --- a/src/activity_actor.cpp +++ b/src/activity_actor.cpp @@ -1313,8 +1313,8 @@ void read_activity_actor::read_book( Character &learner, // Calculate experience gained /** @EFFECT_INT increases reading comprehension */ // Enhanced Memory Banks modestly boosts experience - int min_ex = std::max( 1, islotbook->time / 10 + learner.get_int() / 4 ); - int max_ex = islotbook->time / 5 + learner.get_int() / 2 - originalSkillLevel; + int min_ex = std::max( 1, to_minutes( islotbook->time ) / 10 + learner.get_int() / 4 ); + int max_ex = to_minutes( islotbook->time ) / 5 + learner.get_int() / 2 - originalSkillLevel; min_ex = learner.enchantment_cache->modify_value( enchant_vals::mod::READING_EXP, min_ex ); @@ -1402,8 +1402,8 @@ bool read_activity_actor::player_read( avatar &you ) book->mark_chapter_as_read( *learner ); if( reading_for_skill ) { if( !learner->is_avatar() ) { - const int npc_read_time = you.time_to_read( *book, *reader, learner ); - penalty = static_cast( moves_total ) / npc_read_time; + const time_duration npc_read_time = you.time_to_read( *book, *reader, learner ); + penalty = static_cast( moves_total ) / to_moves( npc_read_time ); } } else { continue; // reading for fun @@ -1637,7 +1637,7 @@ void read_activity_actor::finish( player_activity &act, Character &who ) } if( continuous ) { - int time_taken; + time_duration time_taken; // caller should check if npc can read first if( who.is_npc() ) { @@ -1661,13 +1661,13 @@ void read_activity_actor::finish( player_activity &act, Character &who ) time_taken = who.as_avatar()->time_to_read( *book, *reader ); add_msg_debug( debugmode::DF_ACT_READ, "reading time = %s", - to_string_writable( time_duration::from_moves( time_taken ) ) ); + to_string_writable( time_taken ) ); } // restart the activity - moves_total = time_taken; - act.moves_total = time_taken; - act.moves_left = time_taken; + moves_total = to_moves( time_taken ); + act.moves_total = to_moves( time_taken ); + act.moves_left = to_moves( time_taken ); return; } else { who.add_msg_if_player( m_info, _( "You finish reading." ) ); diff --git a/src/avatar.cpp b/src/avatar.cpp index b276c23499922..70e002d87ef5c 100644 --- a/src/avatar.cpp +++ b/src/avatar.cpp @@ -393,9 +393,9 @@ bool avatar::read( item_location &book, item_location ereader ) } bool continuous = false; - const int time_taken = time_to_read( *book, *reader ); + const time_duration time_taken = time_to_read( *book, *reader ); add_msg_debug( debugmode::DF_ACT_READ, "avatar::read time_taken = %s", - to_string_writable( time_duration::from_moves( time_taken ) ) ); + to_string_writable( time_taken ) ); // If the player hasn't read this book before, skim it to get an idea of what's in it. if( !has_identified( book->typeId() ) ) { @@ -407,7 +407,7 @@ bool avatar::read( item_location &book, item_location ereader ) assign_activity( player_activity( read_activity_actor( - time_taken, + to_moves( time_taken ), book, ereader, false @@ -641,7 +641,7 @@ bool avatar::read( item_location &book, item_location ereader ) assign_activity( player_activity( read_activity_actor( - time_taken, + to_moves( time_taken ), book, ereader, continuous, @@ -742,11 +742,10 @@ void avatar::identify( const item &item ) add_msg( m_info, _( "It would be easier to master if you'd have skill expertise in %s." ), style_to_learn->primary_skill->name() ); add_msg( m_info, _( "A training session with this book takes %s." ), - to_string( time_duration::from_minutes( reading->time ) ) ); + to_string_clipped( reading->time ) ); } else { - add_msg( m_info, n_gettext( "A chapter of this book takes %d minute to read.", - "A chapter of this book takes %d minutes to read.", reading->time ), - reading->time ); + add_msg( m_info, _( "A chapter of this book takes %s to read." ), + to_string_clipped( reading->time ) ); } std::vector crafting_recipes; diff --git a/src/character.cpp b/src/character.cpp index 5dd74907b8d93..b98020fc3ae3e 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -10404,7 +10404,7 @@ const Character *Character::get_book_reader( const item &book, return nullptr; } - int time_taken = INT_MAX; + time_duration time_taken = time_duration::from_minutes( INT_MAX ); auto candidates = get_crafting_helpers(); for( const npc *elem : candidates ) { @@ -10435,7 +10435,7 @@ const Character *Character::get_book_reader( const item &book, } else if( elem->is_blind() ) { reasons.push_back( string_format( _( "%s is blind." ), elem->disp_name() ) ); } else { - int proj_time = time_to_read( book, *elem ); + time_duration proj_time = time_to_read( book, *elem ); if( proj_time < time_taken ) { reader = elem; time_taken = proj_time; @@ -10446,8 +10446,8 @@ const Character *Character::get_book_reader( const item &book, return reader; } -int Character::time_to_read( const item &book, const Character &reader, - const Character *learner ) const +time_duration Character::time_to_read( const item &book, const Character &reader, + const Character *learner ) const { const auto &type = book.type->book; const skill_id &skill = type->skill; @@ -10460,7 +10460,7 @@ int Character::time_to_read( const item &book, const Character &reader, reading_speed = std::max( reading_speed, learner->read_speed() ); } - int retval = type->time * reading_speed; + time_duration retval = type->time * reading_speed; retval *= std::min( fine_detail_vision_mod(), reader.fine_detail_vision_mod() ); const int effective_int = std::min( { get_int(), reader.get_int(), learner ? learner->get_int() : INT_MAX } ); diff --git a/src/character.h b/src/character.h index 7c3f08fcffa36..174efefe31bf5 100644 --- a/src/character.h +++ b/src/character.h @@ -2189,7 +2189,7 @@ class Character : public Creature, public visitable * @param reader the player/NPC who's reading to the caller * @param learner if not nullptr, assume that the caller and reader read at a pace that isn't too fast for him */ - int time_to_read( const item &book, const Character &reader, + time_duration time_to_read( const item &book, const Character &reader, const Character *learner = nullptr ) const; /** Calls Creature::normalize() diff --git a/src/game_inventory.cpp b/src/game_inventory.cpp index 8a4b8a8ed5894..df9c19ab17ee9 100644 --- a/src/game_inventory.cpp +++ b/src/game_inventory.cpp @@ -1386,9 +1386,9 @@ class read_inventory_preset: public pickup_inventory_preset return std::string(); // Just to make sure } // Actual reading time (in turns). Can be penalized. - const int actual_turns = you.time_to_read( *loc, *reader ) / to_moves( 1_turns ); + const int actual_turns = to_moves( you.time_to_read( *loc, *reader ) ); // Theoretical reading time (in turns) based on the reader speed. Free of penalties. - const int normal_turns = get_book( loc ).time * reader->read_speed() / to_moves( 1_turns ); + const int normal_turns = to_moves( get_book( loc ).time ) * reader->read_speed(); const std::string duration = to_string_approx( time_duration::from_turns( actual_turns ), false ); if( actual_turns > normal_turns ) { // Longer - complicated stuff. diff --git a/src/item.cpp b/src/item.cpp index fe1ba0e998002..baab3aef27166 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -23,6 +23,7 @@ #include "bionics.h" #include "bodygraph.h" #include "bodypart.h" +#include "calendar.h" #include "cata_assert.h" #include "cata_utility.h" #include "catacharset.h" @@ -4196,20 +4197,15 @@ void item::book_info( std::vector &info, const iteminfo_query *parts, iteminfo::show_plus, player_character.book_fun_for( *this, player_character ) ); } if( parts->test( iteminfo_parts::BOOK_TIMEPERCHAPTER ) ) { - std::string fmt = n_gettext( - "A chapter of this book takes minute to " - "read.", - "A chapter of this book takes minutes to " - "read.", book.time ); + std::string fmt = string_format( _( "A chapter of this book takes %s to " + "read." ), to_string_clipped( book.time ) ); if( type->use_methods.count( "MA_MANUAL" ) ) { - fmt = n_gettext( - "A training session with this book takes " - " minute.", - "A training session with this book takes " - " minutes.", book.time ); + fmt = string_format( _( + "A training session with this book takes " + "%s." ), to_string_clipped( book.time ) ); } info.emplace_back( "BOOK", "", fmt, - iteminfo::lower_is_better, book.time ); + iteminfo::lower_is_better, to_minutes( book.time ) ); } if( book.chapters > 0 && parts->test( iteminfo_parts::BOOK_NUMUNREADCHAPTERS ) ) { diff --git a/src/item_factory.cpp b/src/item_factory.cpp index fee9dc94d7c47..f2ee3d9aa5ce8 100644 --- a/src/item_factory.cpp +++ b/src/item_factory.cpp @@ -2964,12 +2964,7 @@ void islot_book::load( const JsonObject &jo ) optional( jo, was_loaded, "fun", fun, 0 ); optional( jo, was_loaded, "intelligence", intel, 0 ); - if( jo.has_int( "time" ) ) { - time = jo.get_int( "time" ); - } else if( jo.has_string( "time" ) ) { - time = to_minutes( read_from_json_string( jo.get_member( "time" ), - time_duration::units ) ); - } + optional( jo, was_loaded, "time", time, 0_turns ); optional( jo, was_loaded, "skill", skill, skill_id::NULL_ID() ); optional( jo, was_loaded, "martial_art", martial_art, matype_id::NULL_ID() ); diff --git a/src/itype.h b/src/itype.h index b633cc2cded76..826d63b12bd4e 100644 --- a/src/itype.h +++ b/src/itype.h @@ -518,10 +518,10 @@ struct islot_book { */ int intel = 0; /** - * How long in minutes it takes to read. + * How long it takes to read. * "To read" means getting 1 skill point, not all of them. */ - int time = 0; + time_duration time = 0_turns; /** * Fun books have chapters; after all are read, the book is less fun. */ diff --git a/src/npc.cpp b/src/npc.cpp index 1d2aa4beccc58..b1f377d7ceaef 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -1330,7 +1330,7 @@ bool npc::can_read( const item &book, std::vector &fail_reasons ) return true; } -int npc::time_to_read( const item &book, const Character &reader ) const +time_duration npc::time_to_read( const item &book, const Character &reader ) const { const auto &type = book.type->book; const skill_id &skill = type->skill; @@ -1340,7 +1340,7 @@ int npc::time_to_read( const item &book, const Character &reader ) const reader.get_knowledge_level( skill ) < type->level; int reading_speed = try_understand ? std::max( reader.read_speed(), read_speed() ) : read_speed(); - int retval = type->time * reading_speed; + time_duration retval = type->time * reading_speed; retval *= std::min( fine_detail_vision_mod(), reader.fine_detail_vision_mod() ); if( type->intel > reader.get_int() && !reader.has_trait( trait_PROF_DICEMASTER ) ) { @@ -1374,14 +1374,14 @@ void npc::do_npc_read() add_msg_if_player_sees( pos(), _( "%s starts reading." ), disp_name() ); // NPCs can't read to other NPCs yet - const int time_taken = time_to_read( *book, *this ); + const time_duration time_taken = time_to_read( *book, *this ); item_location ereader = {}; // NPCs read until they gain a level assign_activity( player_activity( read_activity_actor( - time_taken, + to_moves( time_taken ), book, ereader, true, diff --git a/src/npc.h b/src/npc.h index bdd42af1074fa..9b319be092c0e 100644 --- a/src/npc.h +++ b/src/npc.h @@ -910,7 +910,7 @@ class npc : public Character double value( const item &it, double market_price ) const; bool wear_if_wanted( const item &it, std::string &reason ); bool can_read( const item &book, std::vector &fail_reasons ); - int time_to_read( const item &book, const Character &reader ) const; + time_duration time_to_read( const item &book, const Character &reader ) const; void do_npc_read(); void stow_item( item &it ); bool wield( item &it ) override; From 2b1bb1ba388ef6f8c3bc617d11623e1bb0383eec Mon Sep 17 00:00:00 2001 From: Fris0uman Date: Sun, 10 Jul 2022 10:38:07 +0200 Subject: [PATCH 07/11] fix book changes --- src/character.cpp | 14 +++++++------- src/character.h | 6 +++--- src/game_inventory.cpp | 4 ++-- src/item.cpp | 15 ++++++++++----- src/newcharacter.cpp | 2 +- src/npc.cpp | 4 ++-- src/player_display.cpp | 2 +- tests/reading_test.cpp | 8 ++++---- 8 files changed, 30 insertions(+), 25 deletions(-) diff --git a/src/character.cpp b/src/character.cpp index b98020fc3ae3e..c01e8e3a41e05 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -3088,12 +3088,12 @@ std::string Character::enumerate_unmet_requirements( const item &it, const item return enumerate_as_string( unmet_reqs ); } -int Character::read_speed( bool return_stat_effect ) const +int Character::read_speed() const { // Stat window shows stat effects on based on current stat const int intel = get_int(); /** @EFFECT_INT increases reading speed by 3s per level above 8*/ - int ret = to_moves( 1_minutes ) - to_moves( 3_seconds ) * ( intel - 8 ); + time_duration ret = 1_minutes - 3_seconds * ( intel - 8 ); if( has_bionic( afs_bio_linguistic_coprocessor ) ) { // Aftershock ret *= .85; @@ -3101,11 +3101,11 @@ int Character::read_speed( bool return_stat_effect ) const ret *= mutation_value( "reading_speed_multiplier" ); - if( ret < to_moves( 1_seconds ) ) { - ret = to_moves( 1_seconds ); + if( ret < 1_seconds ) { + ret = 1_seconds; } // return_stat_effect actually matters here - return return_stat_effect ? ret : ret * 100 / to_moves( 1_minutes ); + return ret * 100 / 1_minutes; } bool Character::meets_skill_requirements( const std::map &req, @@ -10460,12 +10460,12 @@ time_duration Character::time_to_read( const item &book, const Character &reader reading_speed = std::max( reading_speed, learner->read_speed() ); } - time_duration retval = type->time * reading_speed; + time_duration retval = type->time * reading_speed / 100; retval *= std::min( fine_detail_vision_mod(), reader.fine_detail_vision_mod() ); const int effective_int = std::min( { get_int(), reader.get_int(), learner ? learner->get_int() : INT_MAX } ); if( type->intel > effective_int && !reader.has_trait( trait_PROF_DICEMASTER ) ) { - retval += type->time * ( type->intel - effective_int ) * 100; + retval += type->time * ( type->intel - effective_int ); } if( !has_identified( book.typeId() ) ) { //skimming diff --git a/src/character.h b/src/character.h index 174efefe31bf5..5197b8437980b 100644 --- a/src/character.h +++ b/src/character.h @@ -2116,8 +2116,8 @@ class Character : public Creature, public visitable std::string enumerate_unmet_requirements( const item &it, const item &context = item() ) const; // Mental skills and stats - /** Returns the player's reading speed */ - int read_speed( bool return_stat_effect = true ) const; + /** Returns the player's reading speed as a percentage*/ + int read_speed() const; /** Returns a value used when attempting to convince NPC's of something */ int talk_skill() const; /** Returns a value used when attempting to intimidate NPC's */ @@ -2190,7 +2190,7 @@ class Character : public Creature, public visitable * @param learner if not nullptr, assume that the caller and reader read at a pace that isn't too fast for him */ time_duration time_to_read( const item &book, const Character &reader, - const Character *learner = nullptr ) const; + const Character *learner = nullptr ) const; /** Calls Creature::normalize() * nulls out the player's weapon diff --git a/src/game_inventory.cpp b/src/game_inventory.cpp index df9c19ab17ee9..7f4f226e4e2ae 100644 --- a/src/game_inventory.cpp +++ b/src/game_inventory.cpp @@ -1386,9 +1386,9 @@ class read_inventory_preset: public pickup_inventory_preset return std::string(); // Just to make sure } // Actual reading time (in turns). Can be penalized. - const int actual_turns = to_moves( you.time_to_read( *loc, *reader ) ); + const int actual_turns = to_turns( you.time_to_read( *loc, *reader ) ); // Theoretical reading time (in turns) based on the reader speed. Free of penalties. - const int normal_turns = to_moves( get_book( loc ).time ) * reader->read_speed(); + const int normal_turns = to_turns( get_book( loc ).time ) * reader->read_speed() / 100 ; const std::string duration = to_string_approx( time_duration::from_turns( actual_turns ), false ); if( actual_turns > normal_turns ) { // Longer - complicated stuff. diff --git a/src/item.cpp b/src/item.cpp index baab3aef27166..cfa1d3d0e3aaa 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -4197,12 +4197,17 @@ void item::book_info( std::vector &info, const iteminfo_query *parts, iteminfo::show_plus, player_character.book_fun_for( *this, player_character ) ); } if( parts->test( iteminfo_parts::BOOK_TIMEPERCHAPTER ) ) { - std::string fmt = string_format( _( "A chapter of this book takes %s to " - "read." ), to_string_clipped( book.time ) ); + std::string fmt = n_gettext( + "A chapter of this book takes minute to " + "read.", + "A chapter of this book takes minutes to " + "read.", to_minutes( book.time ) ); if( type->use_methods.count( "MA_MANUAL" ) ) { - fmt = string_format( _( - "A training session with this book takes " - "%s." ), to_string_clipped( book.time ) ); + fmt = n_gettext( + "A training session with this book takes " + " minute.", + "A training session with this book takes " + " minutes.", to_minutes( book.time ) ); } info.emplace_back( "BOOK", "", fmt, iteminfo::lower_is_better, to_minutes( book.time ) ); diff --git a/src/newcharacter.cpp b/src/newcharacter.cpp index 179bed0838bd8..caf7499ae8f43 100644 --- a/src/newcharacter.cpp +++ b/src/newcharacter.cpp @@ -1130,7 +1130,7 @@ tab_direction set_stats( avatar &u, pool_type pool ) mvwprintz( w, point( iSecondColumn, 3 ), c_light_red, _( "Increasing Int further costs 2 points" ) ); } - const int read_spd = u.read_speed( false ); + const int read_spd = u.read_speed(); mvwprintz( w_description, point_zero, ( read_spd == 100 ? COL_STAT_NEUTRAL : ( read_spd < 100 ? COL_STAT_BONUS : COL_STAT_PENALTY ) ), _( "Read times: %d%%" ), read_spd ); diff --git a/src/npc.cpp b/src/npc.cpp index b1f377d7ceaef..5fcc6cca3705c 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -1340,11 +1340,11 @@ time_duration npc::time_to_read( const item &book, const Character &reader ) con reader.get_knowledge_level( skill ) < type->level; int reading_speed = try_understand ? std::max( reader.read_speed(), read_speed() ) : read_speed(); - time_duration retval = type->time * reading_speed; + time_duration retval = type->time * reading_speed / 100; retval *= std::min( fine_detail_vision_mod(), reader.fine_detail_vision_mod() ); if( type->intel > reader.get_int() && !reader.has_trait( trait_PROF_DICEMASTER ) ) { - retval += type->time * ( type->intel - reader.get_int() ) * 100; + retval += type->time * ( type->intel - reader.get_int() ); } return retval; } diff --git a/src/player_display.cpp b/src/player_display.cpp index da4e18e68891b..7fe351e10bfcf 100644 --- a/src/player_display.cpp +++ b/src/player_display.cpp @@ -468,7 +468,7 @@ static void draw_stats_info( const catacurses::window &w_info, const Character & _( "Intelligence is less important in most situations, but it is vital for more complex tasks like " "electronics crafting. It also affects how much skill you can pick up from reading a book." ) ); print_colored_text( w_info, point( 1, 4 ), col_temp, c_light_gray, - string_format( _( "Read times: %d%%" ), you.read_speed( false ) ) ); + string_format( _( "Read times: %d%%" ), you.read_speed() ) ); print_colored_text( w_info, point( 1, 5 ), col_temp, c_light_gray, string_format( _( "Crafting bonus: %d%%" ), you.get_int() ) ); } else if( line == 3 ) { diff --git a/tests/reading_test.cpp b/tests/reading_test.cpp index 58f29f82083f0..33cfe0beca1bc 100644 --- a/tests/reading_test.cpp +++ b/tests/reading_test.cpp @@ -215,9 +215,9 @@ TEST_CASE( "estimated reading time for a book", "[reading][book][time]" ) REQUIRE( alpha->type->book ); // Convert time to read from minutes to moves, for easier comparison later - int moves_child = child->type->book->time * to_moves( 1_minutes ); - int moves_western = western->type->book->time * to_moves( 1_minutes ); - int moves_alpha = alpha->type->book->time * to_moves( 1_minutes ); + time_duration moves_child = child->type->book->time; + time_duration moves_western = western->type->book->time; + time_duration moves_alpha = alpha->type->book->time; GIVEN( "some unidentified books and plenty of light" ) { REQUIRE_FALSE( dummy.has_identified( child->typeId() ) ); @@ -496,7 +496,7 @@ TEST_CASE( "reading a book with an ebook reader", "[reading][book][ereader]" ) dummy.activity = player_activity( read_activity_actor( - dummy.time_to_read( *booklc, dummy ), + to_moves( dummy.time_to_read( *booklc, dummy ) ), booklc, ereader, true From f733d5c5ed84e5ffff230bc082a10786da714000 Mon Sep 17 00:00:00 2001 From: Fris0uman Date: Sun, 10 Jul 2022 13:38:18 +0200 Subject: [PATCH 08/11] more test fix --- tests/reading_test.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/reading_test.cpp b/tests/reading_test.cpp index 33cfe0beca1bc..e9e30eb952d87 100644 --- a/tests/reading_test.cpp +++ b/tests/reading_test.cpp @@ -161,7 +161,7 @@ TEST_CASE( "character reading speed", "[reading][character][speed]" ) REQUIRE( dummy.get_int() == 8 ); THEN( "reading speed is normal" ) { - CHECK( dummy.read_speed() == 6000 ); + CHECK( dummy.read_speed() * 60 == 6000 ); } } @@ -169,13 +169,13 @@ TEST_CASE( "character reading speed", "[reading][character][speed]" ) THEN( "reading speed gets slower as intelligence decreases" ) { dummy.int_max = 7; - CHECK( dummy.read_speed() == 6300 ); + CHECK( dummy.read_speed() * 60 == 6300 ); dummy.int_max = 6; - CHECK( dummy.read_speed() == 6600 ); + CHECK( dummy.read_speed() * 60 == 6600 ); dummy.int_max = 5; - CHECK( dummy.read_speed() == 6900 ); + CHECK( dummy.read_speed() * 60 == 6900 ); dummy.int_max = 4; - CHECK( dummy.read_speed() == 7200 ); + CHECK( dummy.read_speed() * 60 == 7200 ); } } @@ -183,13 +183,13 @@ TEST_CASE( "character reading speed", "[reading][character][speed]" ) THEN( "reading speed gets faster as intelligence increases" ) { dummy.int_max = 9; - CHECK( dummy.read_speed() == 5700 ); + CHECK( dummy.read_speed() * 60 == 5700 ); dummy.int_max = 10; - CHECK( dummy.read_speed() == 5400 ); + CHECK( dummy.read_speed() * 60 == 5400 ); dummy.int_max = 12; - CHECK( dummy.read_speed() == 4800 ); + CHECK( dummy.read_speed() * 60 == 4800 ); dummy.int_max = 14; - CHECK( dummy.read_speed() == 4200 ); + CHECK( dummy.read_speed() * 60 == 4200 ); } } } @@ -249,7 +249,7 @@ TEST_CASE( "estimated reading time for a book", "[reading][book][time]" ) WHEN( "player has average intelligence" ) { dummy.int_max = 8; REQUIRE( dummy.get_int() == 8 ); - REQUIRE( dummy.read_speed() == 6000 ); // 60s, "normal" + REQUIRE( dummy.read_speed() * 60 == 6000 ); // 60s, "normal" THEN( "they can read books at their reading level in the normal amount time" ) { CHECK( dummy.time_to_read( *child, dummy ) == moves_child ); @@ -263,7 +263,7 @@ TEST_CASE( "estimated reading time for a book", "[reading][book][time]" ) WHEN( "player has below average intelligence" ) { dummy.int_max = 6; REQUIRE( dummy.get_int() == 6 ); - REQUIRE( dummy.read_speed() == 6600 ); // 66s + REQUIRE( dummy.read_speed() * 60 == 6600 ); // 66s THEN( "they take longer than average to read any book" ) { CHECK( dummy.time_to_read( *child, dummy ) > moves_child ); @@ -275,7 +275,7 @@ TEST_CASE( "estimated reading time for a book", "[reading][book][time]" ) WHEN( "player has above average intelligence" ) { dummy.int_max = 10; REQUIRE( dummy.get_int() == 10 ); - REQUIRE( dummy.read_speed() == 5400 ); // 54s + REQUIRE( dummy.read_speed() * 60 == 5400 ); // 54s THEN( "they take less time than average to read any book" ) { CHECK( dummy.time_to_read( *child, dummy ) < moves_child ); From 638165d596b954599fa00a18c4cac4d5034175e2 Mon Sep 17 00:00:00 2001 From: Fris0uman <41293484+Fris0uman@users.noreply.github.com> Date: Sun, 10 Jul 2022 15:14:51 +0200 Subject: [PATCH 09/11] Update src/character.cpp Co-authored-by: Anton Burmistrov --- src/character.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/character.cpp b/src/character.cpp index c01e8e3a41e05..88a73465b0f5d 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -3104,7 +3104,6 @@ int Character::read_speed() const if( ret < 1_seconds ) { ret = 1_seconds; } - // return_stat_effect actually matters here return ret * 100 / 1_minutes; } From 6be08c383fcce172c5034e1e6fc67a25568d2c55 Mon Sep 17 00:00:00 2001 From: Fris0uman Date: Mon, 11 Jul 2022 19:45:44 +0200 Subject: [PATCH 10/11] Fix test --- src/character.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/character.cpp b/src/character.cpp index c01e8e3a41e05..34ad856a9c05f 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -10465,7 +10465,7 @@ time_duration Character::time_to_read( const item &book, const Character &reader const int effective_int = std::min( { get_int(), reader.get_int(), learner ? learner->get_int() : INT_MAX } ); if( type->intel > effective_int && !reader.has_trait( trait_PROF_DICEMASTER ) ) { - retval += type->time * ( type->intel - effective_int ); + retval += type->time * ( time_duration::from_seconds( type->intel - effective_int ) / 1_minutes ); } if( !has_identified( book.typeId() ) ) { //skimming From 209dcfffa942ee508f9632f5ee6e7081e12398f8 Mon Sep 17 00:00:00 2001 From: Fris0uman Date: Tue, 12 Jul 2022 08:31:50 +0200 Subject: [PATCH 11/11] fix missing level penalty for NPCs too --- src/npc.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/npc.cpp b/src/npc.cpp index 5fcc6cca3705c..fd3b601556713 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -1344,7 +1344,8 @@ time_duration npc::time_to_read( const item &book, const Character &reader ) con retval *= std::min( fine_detail_vision_mod(), reader.fine_detail_vision_mod() ); if( type->intel > reader.get_int() && !reader.has_trait( trait_PROF_DICEMASTER ) ) { - retval += type->time * ( type->intel - reader.get_int() ); + retval += type->time * ( time_duration::from_seconds( type->intel - reader.get_int() ) / + 1_minutes ); } return retval; }