|
|
@@ -40,6 +40,7 @@ |
|
|
|
#include "string_input_popup.h" |
|
|
|
#include "options.h" |
|
|
|
#include "skill.h" |
|
|
|
#include "effect.h" |
|
|
|
|
|
|
|
#include <sstream> |
|
|
|
#include <algorithm> |
|
|
@@ -53,8 +54,10 @@ const skill_id skill_fabrication( "fabrication" ); |
|
|
|
const species_id ZOMBIE( "ZOMBIE" ); |
|
|
|
const species_id HUMAN( "HUMAN" ); |
|
|
|
|
|
|
|
const efftype_id effect_bandaged( "bandaged" ); |
|
|
|
const efftype_id effect_bite( "bite" ); |
|
|
|
const efftype_id effect_bleed( "bleed" ); |
|
|
|
const efftype_id effect_disinfected( "disinfected" ); |
|
|
|
const efftype_id effect_infected( "infected" ); |
|
|
|
const efftype_id effect_music( "music" ); |
|
|
|
const efftype_id effect_playing_instrument( "playing_instrument" ); |
|
|
@@ -497,6 +500,9 @@ void consume_drug_iuse::load( JsonObject &obj ) |
|
|
|
auto hi = vit.size() >= 3 ? vit.get_int( 2 ) : lo; |
|
|
|
vitamins.emplace( vitamin_id( vit.get_string( 0 ) ), std::make_pair( lo, hi ) ); |
|
|
|
} |
|
|
|
|
|
|
|
used_up_item = obj.get_string( "used_up_item", used_up_item ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
void consume_drug_iuse::info( const item &, std::vector<iteminfo> &dump ) const |
|
|
@@ -586,6 +592,12 @@ long consume_drug_iuse::use( player &p, item &it, bool, const tripoint & ) const |
|
|
|
p.use_charges( consumable->first, consumable->second ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if( !used_up_item.empty() ) { |
|
|
|
item used_up( used_up_item, it.birthday() ); |
|
|
|
p.i_add_or_drop( used_up ); |
|
|
|
} |
|
|
|
|
|
|
|
p.moves -= moves; |
|
|
|
return it.type->charges_to_use(); |
|
|
|
} |
|
|
@@ -2769,9 +2781,14 @@ void heal_actor::load( JsonObject &obj ) |
|
|
|
{ |
|
|
|
// Mandatory |
|
|
|
move_cost = obj.get_int( "move_cost" ); |
|
|
|
limb_power = obj.get_float( "limb_power" ); |
|
|
|
limb_power = obj.get_float( "limb_power", 0 ); |
|
|
|
|
|
|
|
// Optional |
|
|
|
bandages_power = obj.get_float( "bandages_power", 0 ); |
|
|
|
bandages_scaling = obj.get_float( "bandages_scaling", 0.25f * bandages_power ); |
|
|
|
disinfectant_power = obj.get_float( "disinfectant_power", 0 ); |
|
|
|
disinfectant_scaling = obj.get_float( "disinfectant_scaling", 0.25f * disinfectant_power ); |
|
|
|
|
|
|
|
head_power = obj.get_float( "head_power", 0.8f * limb_power ); |
|
|
|
torso_power = obj.get_float( "torso_power", 1.5f * limb_power ); |
|
|
|
|
|
|
@@ -2889,9 +2906,29 @@ int heal_actor::get_heal_value( const player &healer, hp_part healed ) const |
|
|
|
return heal_base; |
|
|
|
} |
|
|
|
|
|
|
|
int heal_actor::get_bandaged_level( const player &healer ) const |
|
|
|
{ |
|
|
|
if( bandages_power > 0 ) { |
|
|
|
/** @EFFECT_FIRSTAID increases healing item effects */ |
|
|
|
return bandages_power + bandages_scaling * healer.get_skill_level( skill_firstaid ); |
|
|
|
} |
|
|
|
|
|
|
|
return bandages_power; |
|
|
|
} |
|
|
|
|
|
|
|
int heal_actor::get_disinfected_level( const player &healer ) const |
|
|
|
{ |
|
|
|
if( disinfectant_power > 0 ) { |
|
|
|
/** @EFFECT_FIRSTAID increases healing item effects */ |
|
|
|
return disinfectant_power + disinfectant_scaling * healer.get_skill_level( skill_firstaid ); |
|
|
|
} |
|
|
|
|
|
|
|
return disinfectant_power; |
|
|
|
} |
|
|
|
|
|
|
|
long heal_actor::finish_using( player &healer, player &patient, item &it, hp_part healed ) const |
|
|
|
{ |
|
|
|
float practice_amount = std::max( 9.0f, limb_power * 3.0f ); |
|
|
|
float practice_amount = limb_power * 3.0f; |
|
|
|
const int dam = get_heal_value( healer, healed ); |
|
|
|
|
|
|
|
if( ( patient.hp_cur[healed] >= 1 ) && ( dam > 0 ) ) { // Prevent first-aid from mending limbs |
|
|
@@ -2980,6 +3017,25 @@ long heal_actor::finish_using( player &healer, player &patient, item &it, hp_par |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// apply healing over time effects |
|
|
|
if( bandages_power > 0 ) { |
|
|
|
int bandages_intensity = get_bandaged_level( healer ); |
|
|
|
patient.add_effect( effect_bandaged, 1_turns, bp_healed ); |
|
|
|
effect &e = patient.get_effect( effect_bandaged, bp_healed ); |
|
|
|
e.set_duration( e.get_int_dur_factor() * bandages_intensity ); |
|
|
|
patient.damage_bandaged[healed] = patient.hp_max[healed] - patient.hp_cur[healed]; |
|
|
|
practice_amount += 2 * bandages_intensity; |
|
|
|
} |
|
|
|
if( disinfectant_power > 0 ) { |
|
|
|
int disinfectant_intensity = get_disinfected_level( healer ); |
|
|
|
patient.add_effect( effect_disinfected, 1_turns, bp_healed ); |
|
|
|
effect &e = patient.get_effect( effect_disinfected, bp_healed ); |
|
|
|
e.set_duration( e.get_int_dur_factor() * disinfectant_intensity ); |
|
|
|
patient.damage_disinfected[healed] = patient.hp_max[healed] - patient.hp_cur[healed]; |
|
|
|
practice_amount += 2 * disinfectant_intensity; |
|
|
|
} |
|
|
|
practice_amount = std::max( 9.0f, practice_amount ); |
|
|
|
|
|
|
|
healer.practice( skill_firstaid, ( int )practice_amount ); |
|
|
|
return it.type->charges_to_use(); |
|
|
|
} |
|
|
@@ -2989,7 +3045,7 @@ hp_part pick_part_to_heal( |
|
|
|
const std::string &menu_header, |
|
|
|
int limb_power, int head_bonus, int torso_bonus, |
|
|
|
float bleed_chance, float bite_chance, float infect_chance, |
|
|
|
bool force ) |
|
|
|
bool force, bool is_bandage, bool is_disinfectant ) |
|
|
|
{ |
|
|
|
const bool bleed = bleed_chance > 0.0f; |
|
|
|
const bool bite = bite_chance > 0.0f; |
|
|
@@ -3003,7 +3059,7 @@ hp_part pick_part_to_heal( |
|
|
|
while( true ) { |
|
|
|
hp_part healed_part = patient.body_window( menu_header, force, precise, |
|
|
|
limb_power, head_bonus, torso_bonus, |
|
|
|
bleed, bite, infect ); |
|
|
|
bleed, bite, infect, is_bandage, is_disinfectant ); |
|
|
|
if( healed_part == num_hp_parts ) { |
|
|
|
return num_hp_parts; |
|
|
|
} |
|
|
@@ -3069,9 +3125,11 @@ hp_part heal_actor::use_healing_item( player &healer, player &patient, item &it, |
|
|
|
// Player healing self - let player select |
|
|
|
if( healer.activity.id() != activity_id( "ACT_FIRSTAID" ) ) { |
|
|
|
const std::string menu_header = it.tname(); |
|
|
|
bool is_bandages = bandages_power; |
|
|
|
bool is_disinfectant = disinfectant_power; |
|
|
|
healed = pick_part_to_heal( healer, patient, menu_header, |
|
|
|
limb_power, head_bonus, torso_bonus, |
|
|
|
bleed, bite, infect, force ); |
|
|
|
bleed, bite, infect, force, is_bandages, is_disinfectant ); |
|
|
|
if( healed == num_hp_parts ) { |
|
|
|
return num_hp_parts; // canceled |
|
|
|
} |
|
|
@@ -3088,9 +3146,11 @@ hp_part heal_actor::use_healing_item( player &healer, player &patient, item &it, |
|
|
|
// Player healing NPC |
|
|
|
// TODO: Remove this hack, allow using activities on NPCs |
|
|
|
const std::string menu_header = it.tname(); |
|
|
|
bool is_bandages = bandages_power; |
|
|
|
bool is_disinfectant = disinfectant_power; |
|
|
|
healed = pick_part_to_heal( healer, patient, menu_header, |
|
|
|
limb_power, head_bonus, torso_bonus, |
|
|
|
bleed, bite, infect, force ); |
|
|
|
bleed, bite, infect, force, is_bandages, is_disinfectant ); |
|
|
|
} |
|
|
|
|
|
|
|
if( healed != num_hp_parts ) { |
|
|
@@ -3116,6 +3176,24 @@ void heal_actor::info( const item &, std::vector<iteminfo> &dump ) const |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if( bandages_power > 0 ) { |
|
|
|
dump.emplace_back( "TOOL", _( "<bold>Base bandaging quality:</bold> " ), "", bandages_power, true, |
|
|
|
"", true ); |
|
|
|
if( g != nullptr ) { |
|
|
|
dump.emplace_back( "TOOL", _( "<bold>Actual bandaging quality:</bold> " ), "", |
|
|
|
get_bandaged_level( g->u ), true, "", true ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if( disinfectant_power > 0 ) { |
|
|
|
dump.emplace_back( "TOOL", _( "<bold>Base bandaging quality:</bold> " ), "", disinfectant_power, |
|
|
|
true, "", true ); |
|
|
|
if( g != nullptr ) { |
|
|
|
dump.emplace_back( "TOOL", _( "<bold>Actual bandaging quality:</bold> " ), "", |
|
|
|
get_disinfected_level( g->u ), true, "", true ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if( bleed > 0.0f || bite > 0.0f || infect > 0.0f ) { |
|
|
|
dump.emplace_back( "TOOL", _( "<bold>Chance to heal (percent):</bold> " ), "", -999, true, "", |
|
|
|
true ); |
|
|
|