Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Butchering proficiencies #76156

Merged
merged 15 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -888,7 +888,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 @@ -914,7 +916,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 @@ -5195,7 +5207,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
133 changes: 131 additions & 2 deletions src/activity_handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,11 @@
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 @@ -811,6 +815,45 @@
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.25;
double penalty_big = 0.75;
int prof_penalty = 0;
GuardianDll marked this conversation as resolved.
Show resolved Hide resolved

if( action == butcher_type::FULL ) {
// 40% of butchering and gutting, 40% of skinning, 20% another activities
prof_penalty += ( time_to_cut * 0.4 ) * penalty_small * ( 1 - butch_adv );
prof_penalty += ( time_to_cut * 0.4 ) * penalty_big * ( 1 - butch_basic );
prof_penalty += ( time_to_cut * 0.4 ) * penalty_small * ( 1 - skin_basic );

time_to_cut += prof_penalty;
}

if( action == butcher_type::QUICK ) {
// 70% of butchery, 15% skinning, 15% another activities
prof_penalty += ( time_to_cut * 0.7 ) * penalty_small * ( 1 - butch_adv );
prof_penalty += ( time_to_cut * 0.7 ) * penalty_big * ( 1 - butch_basic );
prof_penalty += ( time_to_cut * 0.15 ) * penalty_small * ( 1 - skin_basic );

time_to_cut += prof_penalty;
}

if( action == butcher_type::FIELD_DRESS ) {
prof_penalty += time_to_cut * penalty_small * ( 1 - butch_adv );
prof_penalty += time_to_cut * penalty_big * ( 1 - butch_basic );

time_to_cut += prof_penalty;
}

if( action == butcher_type::SKIN ) {
prof_penalty += time_to_cut * penalty_small * ( 1 - skin_basic );

time_to_cut += prof_penalty;
}

time_to_cut *= ( 1.0f - ( get_player_character().get_num_crafting_helpers( 3 ) / 10.0f ) );
return time_to_cut;
}
Expand Down Expand Up @@ -950,7 +993,7 @@

// 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 @@ -1017,6 +1060,7 @@
}

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 @@ -1057,6 +1101,22 @@
roll = 0;
}

const double butch_basic = you.get_proficiency_practice( proficiency_prof_butchering_basic );
const double butch_adv = you.get_proficiency_practice( proficiency_prof_butchering_basic );

Check failure on line 1105 in src/activity_handlers.cpp

View workflow job for this annotation

GitHub Actions / build (src)

Value stored to 'butch_adv' during its initialization is never read [clang-analyzer-deadcode.DeadStores,-warnings-as-errors]

Check failure on line 1105 in src/activity_handlers.cpp

View workflow job for this annotation

GitHub Actions / build (src)

unused variable 'butch_adv' [clang-diagnostic-unused-variable,-warnings-as-errors]

Check failure on line 1105 in src/activity_handlers.cpp

View workflow job for this annotation

GitHub Actions / Basic Build and Test (Clang 10, Ubuntu, Curses)

unused variable 'butch_adv' [-Werror,-Wunused-variable]
GuardianDll marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -1267,6 +1327,75 @@
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 @@ -1353,7 +1482,7 @@
}

// 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
Loading