void activity_handlers::butcher_finish( player_activity *act, player *p ) { // corpses can disappear (rezzing!), so check for that if( static_cast<int>(g->m.i_at(p->pos()).size()) <= act->index || !(g->m.i_at(p->pos())[act->index].is_corpse() ) ) { add_msg(m_info, _("There's no corpse to butcher!")); return; } mtype *corpse = g->m.i_at(p->pos())[act->index].get_mtype(); std::vector<item> contents = g->m.i_at(p->pos())[act->index].contents; int age = g->m.i_at(p->pos())[act->index].bday; g->m.i_rem(p->pos(), act->index); int factor = p->butcher_factor(); int pieces = 0, skins = 0, bones = 0, fats = 0, sinews = 0, feathers = 0; bool stomach = false; switch (corpse->size) { case MS_TINY: pieces = 1; skins = 1; bones = 1; fats = 1; sinews = 1; feathers = 2; break; case MS_SMALL: pieces = 2; skins = 2; bones = 4; fats = 2; sinews = 4; feathers = 6; break; case MS_MEDIUM: pieces = 4; skins = 4; bones = 9; fats = 4; sinews = 9; feathers = 11; break; case MS_LARGE: pieces = 8; skins = 8; bones = 14; fats = 8; sinews = 14; feathers = 17; break; case MS_HUGE: pieces = 16; skins = 16; bones = 21; fats = 16; sinews = 21; feathers = 24; break; } int sSkillLevel = p->skillLevel("survival"); auto roll_butchery = [&] () { double skill_shift = 0.; skill_shift += rng_float( 0, sSkillLevel - 3 ); skill_shift += rng_float( 0, p->dex_cur - 8 ) / 4.0; if( p->str_cur < 4 ) { skill_shift -= rng_float( 0, 5 * ( 4 - p->str_cur ) ) / 4.0; } if( factor < 0 ) { skill_shift -= rng_float( 0, -factor / 5.0 ); } return static_cast<int>( skill_shift ); }; int practice = std::max( 0, 4 + pieces + roll_butchery()); p->practice("survival", practice); // Lose some meat, skins, etc if the rolls are low pieces += std::min( 0, roll_butchery() ); skins += std::min( 0, roll_butchery() - 4 ); bones += std::min( 0, roll_butchery() - 2 ); fats += std::min( 0, roll_butchery() - 4 ); sinews += std::min( 0, roll_butchery() - 8 ); feathers += std::min( 0, roll_butchery() - 1 ); stomach = (roll_butchery() >= 0); if( bones > 0 ) { if( corpse->has_material("veggy") ) { g->m.spawn_item(p->pos(), "plant_sac", bones, 0, age); add_msg(m_good, _("You harvest some fluid bladders!")); } else if( corpse->has_flag(MF_BONES) && corpse->has_flag(MF_POISON) ) { g->m.spawn_item(p->pos(), "bone_tainted", bones / 2, 0, age); add_msg(m_good, _("You harvest some salvageable bones!")); } else if( corpse->has_flag(MF_BONES) && corpse->has_flag(MF_HUMAN) ) { g->m.spawn_item(p->pos(), "bone_human", bones, 0, age); add_msg(m_good, _("You harvest some salvageable bones!")); } else if( corpse->has_flag(MF_BONES) ) { g->m.spawn_item(p->pos(), "bone", bones, 0, age); add_msg(m_good, _("You harvest some usable bones!")); } } if( sinews > 0 ) { if( corpse->has_flag(MF_BONES) && !corpse->has_flag(MF_POISON) ) { g->m.spawn_item(p->pos(), "sinew", sinews, 0, age); add_msg(m_good, _("You harvest some usable sinews!")); } else if( corpse->has_material("veggy") ) { g->m.spawn_item(p->pos(), "plant_fibre", sinews, 0, age); add_msg(m_good, _("You harvest some plant fibers!")); } } if( stomach ) { const itype_id meat = corpse->get_meat_itype(); if( meat == "meat" ) { if( corpse->size == MS_SMALL || corpse->size == MS_MEDIUM ) { g->m.spawn_item(p->pos(), "stomach", 1, 0, age); add_msg(m_good, _("You harvest the stomach!")); } else if( corpse->size == MS_LARGE || corpse->size == MS_HUGE ) { g->m.spawn_item(p->pos(), "stomach_large", 1, 0, age); add_msg(m_good, _("You harvest the stomach!")); } } } if( (corpse->has_flag(MF_FUR) || corpse->has_flag(MF_LEATHER) || corpse->has_flag(MF_CHITIN)) && skins > 0 ) { add_msg(m_good, _("You manage to skin the %s!"), corpse->nname().c_str()); int fur = 0; int leather = 0; int chitin = 0; while (skins > 0 ) { if( corpse->has_flag(MF_CHITIN) ) { chitin = rng(0, skins); skins -= chitin; skins = std::max(skins, 0); } if( corpse->has_flag(MF_FUR) ) { fur = rng(0, skins); skins -= fur; skins = std::max(skins, 0); } if( corpse->has_flag(MF_LEATHER) ) { leather = rng(0, skins); skins -= leather; skins = std::max(skins, 0); } } if( chitin ) { g->m.spawn_item(p->pos(), "chitin_piece", chitin, 0, age); } if( fur ) { g->m.spawn_item(p->pos(), "raw_fur", fur, 0, age); } if( leather ) { g->m.spawn_item(p->pos(), "raw_leather", leather, 0, age); } } if( feathers > 0 ) { if( corpse->has_flag(MF_FEATHER) ) { g->m.spawn_item(p->pos(), "feather", feathers, 0, age); add_msg(m_good, _("You harvest some feathers!")); } } if( fats > 0 ) { if( corpse->has_flag(MF_FAT) && corpse->has_flag(MF_POISON) ) { g->m.spawn_item(p->pos(), "fat_tainted", fats, 0, age); add_msg(m_good, _("You harvest some gooey fat!")); } else if( corpse->has_flag(MF_FAT) ) { g->m.spawn_item(p->pos(), "fat", fats, 0, age); add_msg(m_good, _("You harvest some fat!")); } } //Add a chance of CBM recovery. For shocker and cyborg corpses. //As long as the factor is above -4 (the sinew cutoff), you will be able to extract cbms bool any_cbm = false; bool cbm = false; if( corpse->has_flag(MF_CBM_CIV) ) { if( roll_butchery() >= 0 ) { any_cbm = true; cbm = butcher_cbm_item( "bio_power_storage", p->pos3(), age ) || cbm; } if( roll_butchery() >= 0 ) { any_cbm = true; cbm = butcher_cbm_group( "bionics_common", p->pos3(), age ) || cbm; } } // Zombie scientist bionics if( corpse->has_flag(MF_CBM_SCI) ) { if( roll_butchery() >= 0 ) { any_cbm = true; cbm = butcher_cbm_item( "bio_power_storage", p->pos3(), age ) || cbm; } if( roll_butchery() >= 0 ) { any_cbm = true; cbm = butcher_cbm_group( "bionics_sci", p->pos3(), age ) || cbm; } } // Zombie technician bionics if( corpse->has_flag(MF_CBM_TECH) ) { if( roll_butchery() >= 0 ) { any_cbm = true; cbm = butcher_cbm_item( "bio_power_storage", p->pos3(), age ) || cbm; } if( roll_butchery() >= 0 ) { any_cbm = true; cbm = butcher_cbm_group( "bionics_tech", p->pos3(), age ) || cbm; } } // Substation mini-boss bionics if( corpse->has_flag(MF_CBM_SUBS) ) { if( roll_butchery() >= 0 ) { any_cbm = true; cbm = butcher_cbm_item( "bio_power_storage", p->pos3(), age ) || cbm; } if( roll_butchery() >= 0 ) { any_cbm = true; cbm = butcher_cbm_group( "bionics_subs", p->pos3(), age ) || cbm; } if( roll_butchery() >= 0 ) { any_cbm = true; cbm = butcher_cbm_group( "bionics_subs", p->pos3(), age ) || cbm; } } // Payoff for butchering the zombie bio-op if( corpse->has_flag(MF_CBM_OP) ) { if( roll_butchery() >= 0 ) { any_cbm = true; cbm = butcher_cbm_item( "bio_power_storage_mkII", p->pos3(), age ) || cbm; } if( roll_butchery() >= 0 ) { any_cbm = true; cbm = butcher_cbm_group( "bionics_op", p->pos3(), age ) || cbm; } } if( cbm ) { add_msg( m_good, _("You discover a CBM in the %s!"), corpse->nname().c_str() ); } else if( any_cbm ) { add_msg( m_good, _("You discover a fused lump of bio-circuitry in the %s!"), corpse->nname().c_str() ); } //Add a chance of CBM power storage recovery. if( corpse->has_flag(MF_CBM_POWER) ) { //As long as the factor is above -4 (the sinew cutoff), you will be able to extract cbms if( roll_butchery() >= 0 ) { //To see if it spawns a battery if( one_in(3) ) { //The battery works 33% of the time. add_msg(m_good, _("You discover a power storage in the %s!"), corpse->nname().c_str()); g->m.spawn_item( p->pos3(), "bio_power_storage", 1, 0, age); } else { //There is a burnt out CBM add_msg(m_good, _("You discover a fused lump of bio-circuitry in the %s!"), corpse->nname().c_str()); g->m.spawn_item( p->pos3(), "burnt_out_bionic", 1, 0, age); } } } // Recover hidden items for( auto &content : contents ) { if( ( roll_butchery() + 10 ) * 5 > rng( 0, 100 ) ) { add_msg( m_good, _( "You discover a %s in the %s!" ), content.tname().c_str(), corpse->nname().c_str() ); g->m.add_item_or_charges( p->pos(), content ); } else if( content.is_bionic() ) { g->m.spawn_item(p->pos(), "burnt_out_bionic", 1, 0, age); } } if( pieces <= 0 ) { add_msg(m_bad, _("Your clumsy butchering destroys the meat!")); } else { add_msg(m_good, _("You butcher the corpse.")); const itype_id meat = corpse->get_meat_itype(); if( meat == "null" ) { return; } item tmpitem(meat, age); tmpitem.set_mtype( corpse ); while ( pieces > 0 ) { pieces--; g->m.add_item_or_charges(p->pos(), tmpitem); } } }
void Menu::createCommandsMenu(MenuItem *menu) { Common::String string(_gui->_engine->_world->_commandsMenu); Common::String item; for (uint i = 0; i < string.size(); i++) { while(i < string.size() && string[i] != ';') // Read token item += string[i++]; if (item == "(-") { menu->subitems.push_back(new MenuSubItem(NULL, 0)); } else { bool enabled = true; int style = 0; char shortcut = 0; const char *shortPtr = strrchr(item.c_str(), '/'); if (shortPtr != NULL) { if (strlen(shortPtr) >= 2) { shortcut = shortPtr[1]; item.deleteChar(shortPtr - item.c_str()); item.deleteChar(shortPtr - item.c_str()); } else { error("Unexpected shortcut: '%s', item '%s' in menu '%s'", shortPtr, item.c_str(), string.c_str()); } } while (item.size() >= 2 && item[item.size() - 2] == '<') { char c = item.lastChar(); if (c == 'B') { style |= kFontStyleBold; } else if (c == 'I') { style |= kFontStyleItalic; } else if (c == 'U') { style |= kFontStyleUnderline; } else if (c == 'O') { style |= kFontStyleOutline; } else if (c == 'S') { style |= kFontStyleShadow; } else if (c == 'C') { style |= kFontStyleCondensed; } else if (c == 'E') { style |= kFontStyleExtended; } item.deleteLastChar(); item.deleteLastChar(); } Common::String tmpitem(item); tmpitem.trim(); if (tmpitem[0] == '(') { enabled = false; for (uint j = 0; j < item.size(); j++) if (item[j] == '(') { item.deleteChar(j); break; } } menu->subitems.push_back(new MenuSubItem(item.c_str(), kMenuActionCommand, style, shortcut, enabled)); } item.clear(); } }
void player::activate_mutation( const trait_id &mut ) { const mutation_branch &mdata = mut.obj(); auto &tdata = my_mutations[mut]; int cost = mdata.cost; // You can take yourself halfway to Near Death levels of hunger/thirst. // Fatigue can go to Exhausted. if ((mdata.hunger && get_hunger() >= 700) || (mdata.thirst && get_thirst() >= 260) || (mdata.fatigue && get_fatigue() >= EXHAUSTED)) { // Insufficient Foo to *maintain* operation is handled in player::suffer add_msg_if_player(m_warning, _("You feel like using your %s would kill you!"), mdata.name.c_str()); return; } if (tdata.powered && tdata.charge > 0) { // Already-on units just lose a bit of charge tdata.charge--; } 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.hunger){ mod_hunger(cost); } if (mdata.thirst){ mod_thirst(cost); } if (mdata.fatigue){ mod_fatigue(cost); } tdata.powered = true; // Handle stat changes from activation apply_mods(mut, true); recalc_sight_limits(); } if( mut == trait_WEB_WEAVER ) { g->m.add_field( pos(), fd_web, 1 ); add_msg_if_player(_("You start spinning web with your spinnerets!")); } else if (mut == "BURROW"){ if( is_underwater() ) { add_msg_if_player(m_info, _("You can't do that while underwater.")); tdata.powered = false; return; } tripoint dirp; if (!choose_adjacent(_("Burrow where?"), dirp)) { tdata.powered = false; return; } if( dirp == pos() ) { add_msg_if_player(_("You've got places to go and critters to beat.")); add_msg_if_player(_("Let the lesser folks eat their hearts out.")); tdata.powered = false; return; } time_duration time_to_do = 0_turns; if (g->m.is_bashable(dirp) && g->m.has_flag("SUPPORTS_ROOF", dirp) && g->m.ter(dirp) != t_tree) { // Being better-adapted to the task means that skillful Survivors can do it almost twice as fast. time_to_do = 30_minutes; } else if (g->m.move_cost(dirp) == 2 && g->get_levz() == 0 && g->m.ter(dirp) != t_dirt && g->m.ter(dirp) != t_grass) { time_to_do = 10_minutes; } else { add_msg_if_player(m_info, _("You can't burrow there.")); tdata.powered = false; return; } assign_activity( activity_id( "ACT_BURROW" ), to_moves<int>( time_to_do ), -1, 0 ); activity.placement = dirp; add_msg_if_player(_("You tear into the %s with your teeth and claws."), g->m.tername(dirp).c_str()); tdata.powered = false; return; // handled when the activity finishes } else if( mut == trait_SLIMESPAWNER ) { std::vector<tripoint> valid; for( const tripoint &dest : g->m.points_in_radius( pos(), 1 ) ) { if (g->is_empty(dest)) { valid.push_back( dest ); } } // Oops, no room to divide! if( valid.empty() ) { add_msg_if_player(m_bad, _("You focus, but are too hemmed in to birth a new slimespring!")); tdata.powered = false; return; } add_msg_if_player(m_good, _("You focus, and with a pleasant splitting feeling, birth a new slimespring!")); int numslime = 1; for (int i = 0; i < numslime && !valid.empty(); i++) { const tripoint target = random_entry_removed( valid ); if( monster * const slime = g->summon_mon( mtype_id( "mon_player_blob" ), target ) ) { slime->friendly = -1; } } if (one_in(3)) { //~ Usual enthusiastic slimespring small voices! :D add_msg_if_player(m_good, _("wow! you look just like me! we should look out for each other!")); } else if (one_in(2)) { //~ Usual enthusiastic slimespring small voices! :D add_msg_if_player(m_good, _("come on, big me, let's go!")); } else { //~ Usual enthusiastic slimespring small voices! :D add_msg_if_player(m_good, _("we're a team, we've got this!")); } tdata.powered = false; return; } else if( mut == trait_NAUSEA || mut == trait_VOMITOUS ) { vomit(); tdata.powered = false; return; } else if( mut == trait_M_FERTILE ) { spores(); tdata.powered = false; return; } else if( mut == trait_M_BLOOM ) { blossoms(); tdata.powered = false; return; } else if( mut == trait_SELFAWARE ) { print_health(); tdata.powered = false; return; } else if( !mdata.spawn_item.empty() ) { item tmpitem( mdata.spawn_item ); i_add_or_drop( tmpitem ); add_msg_if_player( _( mdata.spawn_item_message.c_str() ) ); tdata.powered = false; return; } }
void activity_handlers::butcher_finish( player_activity *act, player *p ) { // Corpses can disappear (rezzing!), so check for that auto items_here = g->m.i_at( p->pos() ); if( static_cast<int>( items_here.size() ) <= act->index || !( items_here[act->index].is_corpse() ) ) { add_msg(m_info, _("There's no corpse to butcher!")); return; } item &corpse_item = items_here[act->index]; const mtype *corpse = corpse_item.get_mtype(); std::vector<item> contents = corpse_item.contents; const int age = corpse_item.bday; g->m.i_rem( p->pos(), act->index ); const int factor = p->butcher_factor(); int pieces = 0; int skins = 0; int bones = 0; int fats = 0; int sinews = 0; int feathers = 0; int wool = 0; bool stomach = false; switch (corpse->size) { case MS_TINY: pieces = 1; skins = 1; bones = 1; fats = 1; sinews = 1; feathers = 2; wool = 1; break; case MS_SMALL: pieces = 2; skins = 2; bones = 4; fats = 2; sinews = 4; feathers = 6; wool = 2; break; case MS_MEDIUM: pieces = 4; skins = 4; bones = 9; fats = 4; sinews = 9; feathers = 11; wool = 4; break; case MS_LARGE: pieces = 8; skins = 8; bones = 14; fats = 8; sinews = 14; feathers = 17; wool = 8; break; case MS_HUGE: pieces = 16; skins = 16; bones = 21; fats = 16; sinews = 21; feathers = 24; wool = 16; break; } const int skill_level = p->skillLevel( skill_survival ); auto roll_butchery = [&] () { double skill_shift = 0.0; ///\xrefitem Skill_Effects_Survival "" "" Survival above 3 randomly increases Butcher rolls, below 3 decreases skill_shift += rng_float( 0, skill_level - 3 ); ///\xrefitem Stat_Effects_Dexterity "" "" Dexterity above 8 randomly increases Butcher rolls, slightly, below 8 decreases skill_shift += rng_float( 0, p->dex_cur - 8 ) / 4.0; ///\xrefitem Stat_Effects_Strength "" "" Strength below 4 randomly decreases Butcher rolls, slightly if( p->str_cur < 4 ) { skill_shift -= rng_float( 0, 5 * ( 4 - p->str_cur ) ) / 4.0; } if( factor < 0 ) { skill_shift -= rng_float( 0, -factor / 5.0 ); } return static_cast<int>( round( skill_shift ) ); }; int practice = std::max( 0, 4 + pieces + roll_butchery()); p->practice( skill_survival, practice ); // Lose some meat, skins, etc if the rolls are low pieces += std::min( 0, roll_butchery() ); skins += std::min( 0, roll_butchery() - 4 ); bones += std::min( 0, roll_butchery() - 2 ); fats += std::min( 0, roll_butchery() - 4 ); sinews += std::min( 0, roll_butchery() - 8 ); feathers += std::min( 0, roll_butchery() - 1 ); wool += std::min( 0, roll_butchery() ); stomach = roll_butchery() >= 0; if( bones > 0 ) { if( corpse->has_material("veggy") ) { g->m.spawn_item(p->pos(), "plant_sac", bones, 0, age); add_msg(m_good, _("You harvest some fluid bladders!")); } else if( corpse->has_flag(MF_BONES) && corpse->has_flag(MF_POISON) ) { g->m.spawn_item(p->pos(), "bone_tainted", bones / 2, 0, age); add_msg(m_good, _("You harvest some salvageable bones!")); } else if( corpse->has_flag(MF_BONES) && corpse->has_flag(MF_HUMAN) ) { g->m.spawn_item(p->pos(), "bone_human", bones, 0, age); add_msg(m_good, _("You harvest some salvageable bones!")); } else if( corpse->has_flag(MF_BONES) ) { g->m.spawn_item(p->pos(), "bone", bones, 0, age); add_msg(m_good, _("You harvest some usable bones!")); } } if( sinews > 0 ) { if( corpse->has_flag(MF_BONES) && !corpse->has_flag(MF_POISON) ) { g->m.spawn_item(p->pos(), "sinew", sinews, 0, age); add_msg(m_good, _("You harvest some usable sinews!")); } else if( corpse->has_material("veggy") ) { g->m.spawn_item(p->pos(), "plant_fibre", sinews, 0, age); add_msg(m_good, _("You harvest some plant fibers!")); } } if( stomach ) { const itype_id meat = corpse->get_meat_itype(); if( meat == "meat" ) { if( corpse->size == MS_SMALL || corpse->size == MS_MEDIUM ) { g->m.spawn_item(p->pos(), "stomach", 1, 0, age); add_msg(m_good, _("You harvest the stomach!")); } else if( corpse->size == MS_LARGE || corpse->size == MS_HUGE ) { g->m.spawn_item(p->pos(), "stomach_large", 1, 0, age); add_msg(m_good, _("You harvest the stomach!")); } } else if( meat == "human_flesh" ) { if( corpse->size == MS_SMALL || corpse->size == MS_MEDIUM ) { g->m.spawn_item(p->pos(), "hstomach", 1, 0, age); add_msg(m_good, _("You harvest the stomach!")); } else if( corpse->size == MS_LARGE || corpse->size == MS_HUGE ) { g->m.spawn_item(p->pos(), "hstomach_large", 1, 0, age); add_msg(m_good, _("You harvest the stomach!")); } } } if( (corpse->has_flag(MF_FUR) || corpse->has_flag(MF_LEATHER) || corpse->has_flag(MF_CHITIN)) && skins > 0 ) { add_msg(m_good, _("You manage to skin the %s!"), corpse->nname().c_str()); int fur = 0; int leather = 0; int human_leather = 0; int chitin = 0; while (skins > 0 ) { if( corpse->has_flag(MF_CHITIN) ) { chitin = rng(0, skins); skins -= chitin; skins = std::max(skins, 0); } if( corpse->has_flag(MF_FUR) ) { fur = rng(0, skins); skins -= fur; skins = std::max(skins, 0); } if( corpse->has_flag(MF_LEATHER) ) { if( corpse->has_flag(MF_HUMAN) ) { human_leather = rng(0, skins); skins -= human_leather; } else { leather = rng(0, skins); skins -= leather; } skins = std::max(skins, 0); } } if( chitin > 0 ) { g->m.spawn_item(p->pos(), "chitin_piece", chitin, 0, age); } if( fur > 0 ) { g->m.spawn_item(p->pos(), "raw_fur", fur, 0, age); } if( leather > 0 ) { g->m.spawn_item(p->pos(), "raw_leather", leather, 0, age); } if( human_leather ) { g->m.spawn_item(p->pos(), "raw_hleather", leather, 0, age); } } if( feathers > 0 ) { if( corpse->has_flag(MF_FEATHER) ) { g->m.spawn_item(p->pos(), "feather", feathers, 0, age); add_msg(m_good, _("You harvest some feathers!")); } } if( wool > 0 ) { if( corpse->has_flag(MF_WOOL) ) { g->m.spawn_item(p->pos(), "wool_staple", wool, 0, age); add_msg(m_good, _("You harvest some wool staples!")); } } if( fats > 0 ) { if( corpse->has_flag(MF_FAT) && corpse->has_flag(MF_POISON) ) { g->m.spawn_item(p->pos(), "fat_tainted", fats, 0, age); add_msg(m_good, _("You harvest some gooey fat!")); } else if( corpse->has_flag(MF_FAT) ) { g->m.spawn_item(p->pos(), "fat", fats, 0, age); add_msg(m_good, _("You harvest some fat!")); } } //Add a chance of CBM recovery. For shocker and cyborg corpses. //As long as the factor is above -4 (the sinew cutoff), you will be able to extract cbms if( corpse->has_flag(MF_CBM_CIV) ) { butcher_cbm_item( "bio_power_storage", p->pos(), age, roll_butchery() ); butcher_cbm_group( "bionics_common", p->pos(), age, roll_butchery() ); } // Zombie scientist bionics if( corpse->has_flag(MF_CBM_SCI) ) { butcher_cbm_item( "bio_power_storage", p->pos(), age, roll_butchery() ); butcher_cbm_group( "bionics_sci", p->pos(), age, roll_butchery() ); } // Zombie technician bionics if( corpse->has_flag(MF_CBM_TECH) ) { butcher_cbm_item( "bio_power_storage", p->pos(), age, roll_butchery() ); butcher_cbm_group( "bionics_tech", p->pos(), age, roll_butchery() ); } // Substation mini-boss bionics if( corpse->has_flag(MF_CBM_SUBS) ) { butcher_cbm_item( "bio_power_storage", p->pos(), age, roll_butchery() ); butcher_cbm_group( "bionics_subs", p->pos(), age, roll_butchery() ); butcher_cbm_group( "bionics_subs", p->pos(), age, roll_butchery() ); } // Payoff for butchering the zombie bio-op if( corpse->has_flag(MF_CBM_OP) ) { butcher_cbm_item( "bio_power_storage_mkII", p->pos(), age, roll_butchery() ); butcher_cbm_group( "bionics_op", p->pos(), age, roll_butchery() ); } //Add a chance of CBM power storage recovery. if( corpse->has_flag(MF_CBM_POWER) ) { butcher_cbm_item( "bio_power_storage", p->pos(), age, roll_butchery() ); } // Recover hidden items for( auto &content : contents ) { if( ( roll_butchery() + 10 ) * 5 > rng( 0, 100 ) ) { //~ %1$s - item name, %2$s - monster name add_msg( m_good, _( "You discover a %1$s in the %2$s!" ), content.tname().c_str(), corpse->nname().c_str() ); g->m.add_item_or_charges( p->pos(), content ); } else if( content.is_bionic() ) { g->m.spawn_item(p->pos(), "burnt_out_bionic", 1, 0, age); } } if( pieces <= 0 ) { add_msg(m_bad, _("Your clumsy butchering destroys the meat!")); } else { add_msg(m_good, _("You butcher the corpse.")); const itype_id meat = corpse->get_meat_itype(); if( meat == "null" ) { return; } item tmpitem(meat, age); tmpitem.set_mtype( corpse ); while ( pieces > 0 ) { pieces--; g->m.add_item_or_charges(p->pos(), tmpitem); } } }