Skip to content

Commit

Permalink
Butchering proficiencies (#76156)
Browse files Browse the repository at this point in the history
* add butchering profs

* Thank you Ferret

Co-authored-by: TheShadowFerret <[email protected]>

* Update data/json/hobbies.json

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* remove prof_butchery_offal, tweak learning of the profs slightly

* Astyle

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Update src/activity_handlers.cpp

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* fix syntax error

* fix whatever gods of github messed up in my PR

* tweak learning time since now leaning is not count as all the time you spend butchering

* change speeds, influence and training as it was discussed

* penalize only time spend on this specific activity

* Update src/activity_handlers.cpp

* use much better code by IdleSol, apply penalties values by HadeanLake

Co-authored-by: IdleSol <[email protected]>
Co-authored-by: HadeanLake <[email protected]>

* Apply suggestions from code review

---------

Co-authored-by: TheShadowFerret <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: IdleSol <[email protected]>
Co-authored-by: HadeanLake <[email protected]>
  • Loading branch information
5 people authored Sep 5, 2024
1 parent 67159f2 commit ab971ba
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 6 deletions.
2 changes: 1 addition & 1 deletion data/json/hobbies.json
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,7 @@
"points": -3,
"traits": [ "ANTIFRUIT", "MEATARIAN" ],
"skills": [ { "level": 2, "name": "survival" }, { "level": 2, "name": "cooking" } ],
"proficiencies": [ "prof_knives_familiar", "prof_knife_skills" ]
"proficiencies": [ "prof_knives_familiar", "prof_knife_skills", "prof_butchering_basic", "prof_skinning_basic" ]
},
{
"type": "profession",
Expand Down
20 changes: 17 additions & 3 deletions data/json/professions.json
Original file line number Diff line number Diff line change
Expand Up @@ -905,7 +905,9 @@
"prof_baking",
"prof_baking_desserts_1",
"prof_frying",
"prof_knives_familiar"
"prof_knives_familiar",
"prof_butchering_basic",
"prof_skinning_basic"
],
"items": {
"both": {
Expand All @@ -931,7 +933,17 @@
"description": "You spent most of your adult life in a butcher shop. Your trusty knife has seen many different creatures and you know how to butcher them.",
"points": 2,
"skills": [ { "name": "cutting", "level": 2 }, { "name": "cooking", "level": 2 }, { "name": "survival", "level": 2 } ],
"proficiencies": [ "prof_food_prep", "prof_knife_skills", "prof_intro_biology", "prof_wp_basic_bird", "prof_knives_familiar" ],
"proficiencies": [
"prof_food_prep",
"prof_knife_skills",
"prof_intro_biology",
"prof_wp_basic_bird",
"prof_knives_familiar",
"prof_butchering_basic",
"prof_butchering_adv",
"prof_skinning_basic",
"prof_skinning_adv"
],
"items": {
"both": {
"entries": [
Expand Down Expand Up @@ -5212,7 +5224,9 @@
"prof_bow_expert",
"prof_fletching",
"prof_carving",
"prof_knives_familiar"
"prof_knives_familiar",
"prof_butchering_basic",
"prof_skinning_basic"
],
"items": {
"both": {
Expand Down
40 changes: 40 additions & 0 deletions data/json/proficiencies/butchering.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
[
{
"type": "proficiency",
"id": "prof_butchering_basic",
"category": "prof_butchering",
"name": { "str": "Principles of Butchering" },
"description": "You know how to pick up most of the meat from the animal body.",
"can_learn": true,
"time_to_learn": "2 h"
},
{
"type": "proficiency",
"id": "prof_butchering_adv",
"category": "prof_butchering",
"name": { "str": "Butchering Expert" },
"description": "There is very little meat left after your skillful knife movements.",
"can_learn": true,
"time_to_learn": "25 h",
"required_proficiencies": [ "prof_butchering_basic" ]
},
{
"type": "proficiency",
"id": "prof_skinning_basic",
"category": "prof_butchering",
"name": { "str": "Principles of Skinning" },
"description": "You stopped making holes in the skin of animals you butcher.",
"can_learn": true,
"time_to_learn": "2 h"
},
{
"type": "proficiency",
"id": "prof_skinning_adv",
"category": "prof_butchering",
"name": { "str": "Skinning Expert" },
"description": "You really know how to skin the animal.",
"can_learn": true,
"time_to_learn": "25 h",
"required_proficiencies": [ "prof_skinning_basic" ]
}
]
6 changes: 6 additions & 0 deletions data/json/proficiencies/proficiency_categories.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
"name": "Food Handling",
"description": "Proficiencies for cooking and food preparation, as well as experience with food handling tools."
},
{
"type": "proficiency_category",
"id": "prof_butchering",
"name": "Butchering",
"description": "Proficiencies for carving and proper dressing of meat and skin of animals."
},
{
"type": "proficiency_category",
"id": "prof_electronic",
Expand Down
123 changes: 121 additions & 2 deletions src/activity_handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,11 @@ static const morale_type morale_feeling_good( "morale_feeling_good" );
static const morale_type morale_game( "morale_game" );
static const morale_type morale_tree_communion( "morale_tree_communion" );

static const proficiency_id proficiency_prof_butchering_adv( "prof_butchering_adv" );
static const proficiency_id proficiency_prof_butchering_basic( "prof_butchering_basic" );
static const proficiency_id proficiency_prof_dissect_humans( "prof_dissect_humans" );
static const proficiency_id proficiency_prof_skinning_adv( "prof_skinning_adv" );
static const proficiency_id proficiency_prof_skinning_basic( "prof_skinning_basic" );

static const quality_id qual_BUTCHER( "BUTCHER" );
static const quality_id qual_CUT_FINE( "CUT_FINE" );
Expand Down Expand Up @@ -803,6 +807,36 @@ int butcher_time_to_cut( Character &you, const item &corpse_item, const butcher_
if( corpse_item.has_flag( flag_QUARTERED ) ) {
time_to_cut /= 4;
}

double butch_basic = you.get_proficiency_practice( proficiency_prof_butchering_basic );
double butch_adv = you.get_proficiency_practice( proficiency_prof_butchering_adv );
double skin_basic = you.get_proficiency_practice( proficiency_prof_skinning_basic );
double penalty_small = 0.5;
double penalty_big = 1.5;

int prof_butch_penalty = penalty_big * ( 1 - butch_basic ) + penalty_small * ( 1 - butch_adv );
int prof_skin_penalty = penalty_small * ( 1 - skin_basic );

// there supposed to be a code for book mitigation, but we don't have any book fitting for this

if( action == butcher_type::FULL ) {
// 40% of butchering and gutting, 40% of skinning, 20% another activities
time_to_cut *= 0.4 * ( 1 + prof_butch_penalty ) + 0.4 * ( 1 + prof_skin_penalty ) + 0.2;
}

if( action == butcher_type::QUICK ) {
// 70% of butchery, 15% skinning, 15% another activities
time_to_cut *= 0.7 * ( 1 + prof_butch_penalty ) + 0.15 * ( 1 + prof_skin_penalty ) + 0.15;
}

if( action == butcher_type::FIELD_DRESS ) {
time_to_cut *= 1 + prof_butch_penalty;
}

if( action == butcher_type::SKIN ) {
time_to_cut *= 1 + prof_skin_penalty;
}

time_to_cut *= ( 1.0f - ( get_player_character().get_num_crafting_helpers( 3 ) / 10.0f ) );
return time_to_cut;
}
Expand Down Expand Up @@ -942,7 +976,7 @@ static std::vector<item> create_charge_items( const itype *drop, int count,

// Returns false if the calling function should abort
static bool butchery_drops_harvest( item *corpse_item, const mtype &mt, Character &you,
butcher_type action )
butcher_type action, int moves_total )
{
const int tool_quality = you.max_quality( action == butcher_type::DISSECT ? qual_CUT_FINE :
qual_BUTCHER, PICKUP_RANGE );
Expand Down Expand Up @@ -1009,6 +1043,7 @@ static bool butchery_drops_harvest( item *corpse_item, const mtype &mt, Characte
}

map &here = get_map();

for( const harvest_entry &entry : ( action == butcher_type::DISSECT &&
!mt.dissect.is_empty() ) ? *mt.dissect : *mt.harvest ) {
const int skill_level = butchery_dissect_skill_level( you, tool_quality, entry.type );
Expand Down Expand Up @@ -1049,6 +1084,21 @@ static bool butchery_drops_harvest( item *corpse_item, const mtype &mt, Characte
roll = 0;
}

const double butch_basic = you.get_proficiency_practice( proficiency_prof_butchering_basic );
const double skin_basic = you.get_proficiency_practice( proficiency_prof_skinning_basic );
const double skin_adv = you.get_proficiency_practice( proficiency_prof_skinning_adv );
const double penalty_small = 0.15;
const double penalty_big = 2;

if( entry.type == harvest_drop_flesh || entry.type == harvest_drop_offal ) {
roll /= 1 + ( penalty_small * ( 1 - butch_basic ) );
}

if( entry.type == harvest_drop_skin ) {
roll /= 1 + ( penalty_big * ( 1 - skin_basic ) );
roll /= 1 + ( penalty_small * ( 1 - skin_adv ) );
}

// QUICK BUTCHERY
if( action == butcher_type::QUICK ) {
if( entry.type == harvest_drop_flesh ) {
Expand Down Expand Up @@ -1259,6 +1309,75 @@ static bool butchery_drops_harvest( item *corpse_item, const mtype &mt, Characte
0 ) + 4 );
}

// handle our prof training
if( action == butcher_type::FULL && ( mt.harvest->has_entry_type( harvest_drop_flesh ) ||
mt.harvest->has_entry_type( harvest_drop_offal ) ) ) {
// 40% of butchering and gutting, 40% of skinning, 20% another activities
if( you.has_proficiency( proficiency_prof_butchering_basic ) ) {
you.practice_proficiency( proficiency_prof_butchering_adv,
time_duration::from_moves<int>( moves_total * 0.4 ) );
} else {
you.practice_proficiency( proficiency_prof_butchering_basic,
time_duration::from_moves<int>( moves_total * 0.4 ) );
}
}

if( action == butcher_type::FULL && mt.harvest->has_entry_type( harvest_drop_skin ) ) {
// 40% of butchering and gutting, 40% of skinning, 20% another activities
if( you.has_proficiency( proficiency_prof_skinning_basic ) ) {
you.practice_proficiency( proficiency_prof_skinning_adv,
time_duration::from_moves<int>( moves_total * 0.4 ) );
} else {
you.practice_proficiency( proficiency_prof_skinning_basic,
time_duration::from_moves<int>( moves_total * 0.4 ) );
}
}

if( action == butcher_type::QUICK && ( mt.harvest->has_entry_type( harvest_drop_flesh ) ||
mt.harvest->has_entry_type( harvest_drop_offal ) ) ) {
// 70% of butchery, 15% skinning, 15% another activities
if( you.has_proficiency( proficiency_prof_butchering_basic ) ) {
you.practice_proficiency( proficiency_prof_butchering_adv,
time_duration::from_moves<int>( moves_total * 0.7 ) );
} else {
you.practice_proficiency( proficiency_prof_butchering_basic,
time_duration::from_moves<int>( moves_total * 0.7 ) );
}
}

if( action == butcher_type::QUICK && mt.harvest->has_entry_type( harvest_drop_skin ) ) {
// 70% of butchery, 15% skinning, 15% another activities
if( you.has_proficiency( proficiency_prof_skinning_basic ) ) {
you.practice_proficiency( proficiency_prof_skinning_adv,
time_duration::from_moves<int>( moves_total * 0.15 ) );
} else {
you.practice_proficiency( proficiency_prof_skinning_basic,
time_duration::from_moves<int>( moves_total * 0.15 ) );
}
}

if( action == butcher_type::FIELD_DRESS && ( mt.harvest->has_entry_type( harvest_drop_flesh ) ||
mt.harvest->has_entry_type( harvest_drop_offal ) ) ) {
if( you.has_proficiency( proficiency_prof_butchering_basic ) ) {
you.practice_proficiency( proficiency_prof_butchering_adv,
time_duration::from_moves<int>( moves_total ) );
} else {
you.practice_proficiency( proficiency_prof_butchering_basic,
time_duration::from_moves<int>( moves_total ) );
}
}

if( action == butcher_type::SKIN && mt.harvest->has_entry_type( harvest_drop_skin ) ) {
// 70% of butchery, 15% skinning, 15% another activities
if( you.has_proficiency( proficiency_prof_skinning_basic ) ) {
you.practice_proficiency( proficiency_prof_skinning_adv,
time_duration::from_moves<int>( moves_total ) );
} else {
you.practice_proficiency( proficiency_prof_skinning_basic,
time_duration::from_moves<int>( moves_total ) );
}
}

// after this point, if there was a liquid handling from the harvest,
// and the liquid handling was interrupted, then the activity was canceled,
// therefore operations on this activity's targets and values may be invalidated.
Expand Down Expand Up @@ -1345,7 +1464,7 @@ void activity_handlers::butcher_finish( player_activity *act, Character *you )
}

// all action types - yields
if( !butchery_drops_harvest( &corpse_item, *corpse, *you, action ) ) {
if( !butchery_drops_harvest( &corpse_item, *corpse, *you, action, act->moves_total ) ) {
// FATAL FAILURE
add_msg( m_warning, SNIPPET.random_from_category( "harvest_drop_default_dissect_failed" ).value_or(
translation() ).translated() );
Expand Down

0 comments on commit ab971ba

Please sign in to comment.