void player::mutate_towards(std::string mut) { if (has_child_flag(mut)) { remove_child_flag(mut); return; } bool has_prereqs = false; bool prereq1 = false; bool prereq2 = false; std::string canceltrait = ""; std::vector<std::string> prereq = mutation_data[mut].prereqs; std::vector<std::string> prereqs2 = mutation_data[mut].prereqs2; std::vector<std::string> cancel = mutation_data[mut].cancels; for (int i = 0; i < cancel.size(); i++) { if (!has_trait( cancel[i] )) { cancel.erase(cancel.begin() + i); i--; } else if (has_base_trait( cancel[i] )) { //If we have the trait, but it's a base trait, don't allow it to be removed normally canceltrait = cancel[i]; cancel.erase(cancel.begin() + i); i--; } } if (!cancel.empty()) { std::string removed = cancel[ rng(0, cancel.size() - 1) ]; remove_mutation(removed); return; } for (int i = 0; (!prereq1) && i < prereq.size(); i++) { if (has_trait(prereq[i])) { prereq1 = true; } } for (int i = 0; (!prereq2) && i < prereqs2.size(); i++) { if (has_trait(prereqs2[i])) { prereq2 = true; } } if (prereq1 && prereq2) { has_prereqs = true; } if (!has_prereqs && (!prereq.empty() || !prereqs2.empty())) { if (!prereq1 && !prereq.empty()) { std::string devel = prereq[ rng(0, prereq.size() - 1) ]; mutate_towards(devel); return; } else if (!prereq2 && !prereqs2.empty()) { std::string devel = prereqs2[ rng(0, prereqs2.size() - 1) ]; mutate_towards(devel); return; } } // Check for threshhold mutation, if needed bool threshold = mutation_data[mut].threshold; bool has_threshreq = false; std::vector<std::string> threshreq = mutation_data[mut].threshreq; std::vector<std::string> mutcat; mutcat = mutation_data[mut].category; // It shouldn't pick a Threshold anyway (they're supposed to be non-Valid) // but if it does, just reroll if (threshold) { g->add_msg(_("You feel something straining deep inside you, yearning to be free...")); mutate(); return; } for (int i = 0; !has_threshreq && i < threshreq.size(); i++) { if (has_trait(threshreq[i])) { has_threshreq = true; } } // No crossing The Threshold by simply not having it // Reroll mutation, uncategorized (prevents looping) if (!has_threshreq && !threshreq.empty()) { g->add_msg(_("You feel something straining deep inside you, yearning to be free...")); mutate(); return; } // Check if one of the prereqs that we have TURNS INTO this one std::string replacing = ""; prereq = mutation_data[mut].prereqs; // Reset it for (int i = 0; i < prereq.size(); i++) { if (has_trait(prereq[i])) { std::string pre = prereq[i]; for (int j = 0; replacing == "" && j < mutation_data[pre].replacements.size(); j++) { if (mutation_data[pre].replacements[j] == mut) { replacing = pre; } } } } toggle_mutation(mut); if (replacing != "") { g->add_msg(_("Your %1$s mutation turns into %2$s!"), traits[replacing].name.c_str(), traits[mut].name.c_str()); g->u.add_memorial_log(_("'%s' mutation turned into '%s'"), traits[replacing].name.c_str(), traits[mut].name.c_str()); toggle_mutation(replacing); mutation_loss_effect(*this, replacing); mutation_effect(*this, mut); } else if (canceltrait != "") { // If this new mutation cancels a base trait, remove it and add the mutation at the same time g->add_msg(_("Your innate %1$s trait turns into %2$s!"), traits[canceltrait].name.c_str(), traits[mut].name.c_str()); g->u.add_memorial_log(_("'%s' trait turned into '%s'"), traits[canceltrait].name.c_str(), traits[mut].name.c_str()); toggle_mutation(canceltrait); mutation_loss_effect(*this, canceltrait); mutation_effect(*this, mut); } else { g->add_msg(_("You gain a mutation called %s!"), traits[mut].name.c_str()); g->u.add_memorial_log(_("Gained the mutation '%s'."), traits[mut].name.c_str()); mutation_effect(*this, mut); } set_highest_cat_level(); drench_mut_calc(); }
void player::remove_mutation(std::string mut) { // Check for dependant mutations first std::vector<std::string> dependant; for (std::map<std::string, trait>::iterator iter = traits.begin(); iter != traits.end(); ++iter) { for (int i = 0; i < mutation_data[iter->first].prereqs.size(); i++) { if (mutation_data[iter->first].prereqs[i] == iter->first) { dependant.push_back(iter->first); break; } } } if (dependant.size() > 0) { remove_mutation(dependant[rng(0, dependant.size()-1)]); return; } // Check if there's a prereq we should shrink back into std::string replacing = ""; std::vector<std::string> originals = mutation_data[mut].prereqs; for (int i = 0; replacing == "" && i < originals.size(); i++) { std::string pre = originals[i]; for (int j = 0; replacing == "" && j < mutation_data[pre].replacements.size(); j++) { if (mutation_data[pre].replacements[j] == mut) { replacing = pre; } } } std::string replacing2 = ""; std::vector<std::string> originals2 = mutation_data[mut].prereqs2; for (int i = 0; replacing2 == "" && i < originals2.size(); i++) { std::string pre2 = originals2[i]; for (int j = 0; replacing2 == "" && j < mutation_data[pre2].replacements.size(); j++) { if (mutation_data[pre2].replacements[j] == mut) { replacing2 = pre2; } } } // See if this mutation is cancelled by a base trait //Only if there's no prereq to shrink to, thus we're at the bottom of the trait line if (replacing == "") { //Check each mutation until we reach the end or find a trait to revert to for (std::map<std::string, trait>::iterator iter = traits.begin(); replacing == "" && iter != traits.end(); ++iter) { //See if it's in our list of base traits but not active if (has_base_trait(iter->first) && !has_trait(iter->first)) { //See if that base trait cancels the mutation we are using std::vector<std::string> traitcheck = mutation_data[iter->first].cancels; if (!traitcheck.empty()) { for (int j = 0; replacing == "" && j < traitcheck.size(); j++) { if (traitcheck[j] == mut) { replacing = (iter->first); } } } } } } // Duplicated for prereq2 if (replacing2 == "") { //Check each mutation until we reach the end or find a trait to revert to for (std::map<std::string, trait>::iterator iter = traits.begin(); replacing2 == "" && iter != traits.end(); ++iter) { //See if it's in our list of base traits but not active if (has_base_trait(iter->first) && !has_trait(iter->first)) { //See if that base trait cancels the mutation we are using std::vector<std::string> traitcheck = mutation_data[iter->first].cancels; if (!traitcheck.empty()) { for (int j = 0; replacing2 == "" && j < traitcheck.size(); j++) { if (traitcheck[j] == mut) { replacing2 = (iter->first); } } } } } } // This should revert back to a removed base trait rather than simply removing the mutation toggle_mutation(mut); bool mutation_replaced = false; if (replacing != "") { g->add_msg(_("Your %1$s mutation turns into %2$s."), traits[mut].name.c_str(), traits[replacing].name.c_str()); toggle_mutation(replacing); mutation_loss_effect(*this, mut); mutation_effect(*this, replacing); mutation_replaced = true; } if (replacing2 != "") { g->add_msg(_("Your %1$s mutation turns into %2$s."), traits[mut].name.c_str(), traits[replacing2].name.c_str()); toggle_mutation(replacing2); mutation_loss_effect(*this, mut); mutation_effect(*this, replacing2); mutation_replaced = true; } if(!mutation_replaced) { g->add_msg(_("You lose your %s mutation."), traits[mut].name.c_str()); mutation_loss_effect(*this, mut); } set_highest_cat_level(); drench_mut_calc(); }
void player::remove_mutation( const trait_id &mut ) { const auto &mdata = mut.obj(); // Check if there's a prerequisite we should shrink back into trait_id replacing = trait_id::NULL_ID(); std::vector<trait_id> originals = mdata.prereqs; for (size_t i = 0; !replacing && i < originals.size(); i++) { trait_id pre = originals[i]; const auto &p = pre.obj(); for (size_t j = 0; !replacing && j < p.replacements.size(); j++) { if (p.replacements[j] == mut) { replacing = pre; } } } trait_id replacing2 = trait_id::NULL_ID(); std::vector<trait_id> originals2 = mdata.prereqs2; for (size_t i = 0; !replacing2 && i < originals2.size(); i++) { trait_id pre2 = originals2[i]; const auto &p = pre2.obj(); for (size_t j = 0; !replacing2 && j < p.replacements.size(); j++) { if (p.replacements[j] == mut) { replacing2 = pre2; } } } // See if this mutation is canceled by a base trait //Only if there's no prerequisite to shrink to, thus we're at the bottom of the trait line if( !replacing ) { //Check each mutation until we reach the end or find a trait to revert to for( auto &iter : mutation_branch::get_all() ) { //See if it's in our list of base traits but not active if (has_base_trait(iter.first) && !has_trait(iter.first)) { //See if that base trait cancels the mutation we are using std::vector<trait_id> traitcheck = iter.second.cancels; if (!traitcheck.empty()) { for (size_t j = 0; !replacing && j < traitcheck.size(); j++) { if (traitcheck[j] == mut) { replacing = (iter.first); } } } } if( replacing ) { break; } } } // Duplicated for prereq2 if( !replacing2 ) { //Check each mutation until we reach the end or find a trait to revert to for( auto &iter : mutation_branch::get_all() ) { //See if it's in our list of base traits but not active if (has_base_trait(iter.first) && !has_trait(iter.first)) { //See if that base trait cancels the mutation we are using std::vector<trait_id> traitcheck = iter.second.cancels; if (!traitcheck.empty()) { for (size_t j = 0; !replacing2 && j < traitcheck.size(); j++) { if (traitcheck[j] == mut && (iter.first) != replacing) { replacing2 = (iter.first); } } } } if( replacing2 ) { break; } } } // make sure we don't toggle a mutation or trait twice, or it will cancel itself out. if(replacing == replacing2) { replacing2 = trait_id::NULL_ID(); } // This should revert back to a removed base trait rather than simply removing the mutation unset_mutation(mut); bool mutation_replaced = false; game_message_type rating; if( replacing ) { const auto &replace_mdata = replacing.obj(); if(mdata.mixed_effect || replace_mdata.mixed_effect) { rating = m_mixed; } else if(replace_mdata.points - mdata.points > 0) { rating = m_good; } else if(mdata.points - replace_mdata.points > 0) { rating = m_bad; } else { rating = m_neutral; } add_msg_player_or_npc( rating, _("Your %1$s mutation turns into %2$s."), _("<npcname>'s %1$s mutation turns into %2$s."), mdata.name.c_str(), replace_mdata.name.c_str() ); set_mutation(replacing); mutation_loss_effect(mut); mutation_effect(replacing); mutation_replaced = true; } if( replacing2 ) { const auto &replace_mdata = replacing2.obj(); if(mdata.mixed_effect || replace_mdata.mixed_effect) { rating = m_mixed; } else if(replace_mdata.points - mdata.points > 0) { rating = m_good; } else if(mdata.points - replace_mdata.points > 0) { rating = m_bad; } else { rating = m_neutral; } add_msg_player_or_npc( rating, _("Your %1$s mutation turns into %2$s."), _("<npcname>'s %1$s mutation turns into %2$s."), mdata.name.c_str(), replace_mdata.name.c_str() ); set_mutation(replacing2); mutation_loss_effect(mut); mutation_effect(replacing2); mutation_replaced = true; } if(!mutation_replaced) { if(mdata.mixed_effect) { rating = m_mixed; } else if(mdata.points > 0) { rating = m_bad; } else if(mdata.points < 0) { rating = m_good; } else { rating = m_neutral; } add_msg_player_or_npc( rating, _("You lose your %s mutation."), _("<npcname> loses their %s mutation."), mdata.name.c_str() ); mutation_loss_effect(mut); } set_highest_cat_level(); drench_mut_calc(); }
bool player::mutate_towards( const trait_id &mut ) { if (has_child_flag(mut)) { remove_child_flag(mut); return true; } const mutation_branch &mdata = mut.obj(); bool has_prereqs = false; bool prereq1 = false; bool prereq2 = false; std::vector<trait_id> canceltrait; std::vector<trait_id> prereq = mdata.prereqs; std::vector<trait_id> prereqs2 = mdata.prereqs2; std::vector<trait_id> cancel = mdata.cancels; for (size_t i = 0; i < cancel.size(); i++) { if (!has_trait( cancel[i] )) { cancel.erase(cancel.begin() + i); i--; } else if (has_base_trait( cancel[i] )) { //If we have the trait, but it's a base trait, don't allow it to be removed normally canceltrait.push_back( cancel[i]); cancel.erase(cancel.begin() + i); i--; } } for (size_t i = 0; i < cancel.size(); i++) { if (!cancel.empty()) { trait_id removed = cancel[i]; remove_mutation(removed); cancel.erase(cancel.begin() + i); i--; // This checks for cases where one trait knocks out several others // Probably a better way, but gets it Fixed Now--KA101 return mutate_towards(mut); } } for (size_t i = 0; (!prereq1) && i < prereq.size(); i++) { if (has_trait(prereq[i])) { prereq1 = true; } } for (size_t i = 0; (!prereq2) && i < prereqs2.size(); i++) { if (has_trait(prereqs2[i])) { prereq2 = true; } } if (prereq1 && prereq2) { has_prereqs = true; } if (!has_prereqs && (!prereq.empty() || !prereqs2.empty())) { if (!prereq1 && !prereq.empty()) { return mutate_towards( random_entry( prereq ) ); } else if (!prereq2 && !prereqs2.empty()) { return mutate_towards( random_entry( prereqs2 ) ); } } // Check for threshold mutation, if needed bool threshold = mdata.threshold; bool profession = mdata.profession; bool has_threshreq = false; std::vector<trait_id> threshreq = mdata.threshreq; // It shouldn't pick a Threshold anyway--they're supposed to be non-Valid // and aren't categorized. This can happen if someone makes a threshold mutation into a prerequisite. if (threshold) { add_msg_if_player(_("You feel something straining deep inside you, yearning to be free...")); return false; } if (profession) { // Profession picks fail silently return false; } for (size_t i = 0; !has_threshreq && i < threshreq.size(); i++) { if (has_trait(threshreq[i])) { has_threshreq = true; } } // No crossing The Threshold by simply not having it if (!has_threshreq && !threshreq.empty()) { add_msg_if_player(_("You feel something straining deep inside you, yearning to be free...")); return false; } // Check if one of the prerequisites that we have TURNS INTO this one trait_id replacing = trait_id::NULL_ID(); prereq = mdata.prereqs; // Reset it for( auto &elem : prereq ) { if( has_trait( elem ) ) { trait_id pre = elem; const auto &p = pre.obj(); for (size_t j = 0; !replacing && j < p.replacements.size(); j++) { if (p.replacements[j] == mut) { replacing = pre; } } } } // Loop through again for prereqs2 trait_id replacing2 = trait_id::NULL_ID(); prereq = mdata.prereqs2; // Reset it for( auto &elem : prereq ) { if( has_trait( elem ) ) { trait_id pre2 = elem; const auto &p = pre2.obj(); for (size_t j = 0; !replacing2 && j < p.replacements.size(); j++) { if (p.replacements[j] == mut) { replacing2 = pre2; } } } } set_mutation(mut); bool mutation_replaced = false; game_message_type rating; if( replacing ) { const auto &replace_mdata = replacing.obj(); if(mdata.mixed_effect || replace_mdata.mixed_effect) { rating = m_mixed; } else if(replace_mdata.points - mdata.points < 0) { rating = m_good; } else if(mdata.points - replace_mdata.points < 0) { rating = m_bad; } else { rating = m_neutral; } // TODO: Limit this to visible mutations // TODO: In case invisible mutation turns into visible or vice versa // print only the visible mutation appearing/disappearing add_msg_player_or_npc(rating, _("Your %1$s mutation turns into %2$s!"), _("<npcname>'s %1$s mutation turns into %2$s!"), replace_mdata.name.c_str(), mdata.name.c_str() ); add_memorial_log(pgettext("memorial_male", "'%s' mutation turned into '%s'"), pgettext("memorial_female", "'%s' mutation turned into '%s'"), replace_mdata.name.c_str(), mdata.name.c_str()); unset_mutation(replacing); mutation_loss_effect(replacing); mutation_effect(mut); mutation_replaced = true; } if( replacing2 ) { const auto &replace_mdata = replacing2.obj(); if(mdata.mixed_effect || replace_mdata.mixed_effect) { rating = m_mixed; } else if(replace_mdata.points - mdata.points < 0) { rating = m_good; } else if(mdata.points - replace_mdata.points < 0) { rating = m_bad; } else { rating = m_neutral; } add_msg_player_or_npc(rating, _("Your %1$s mutation turns into %2$s!"), _("<npcname>'s %1$s mutation turns into %2$s!"), replace_mdata.name.c_str(), mdata.name.c_str() ); add_memorial_log(pgettext("memorial_male", "'%s' mutation turned into '%s'"), pgettext("memorial_female", "'%s' mutation turned into '%s'"), replace_mdata.name.c_str(), mdata.name.c_str()); unset_mutation(replacing2); mutation_loss_effect(replacing2); mutation_effect(mut); mutation_replaced = true; } for (size_t i = 0; i < canceltrait.size(); i++) { const auto &cancel_mdata = canceltrait[i].obj(); if(mdata.mixed_effect || cancel_mdata.mixed_effect) { rating = m_mixed; } else if(mdata.points < cancel_mdata.points) { rating = m_bad; } else if(mdata.points > cancel_mdata.points) { rating = m_good; } else if(mdata.points == cancel_mdata.points) { rating = m_neutral; } else { rating = m_mixed; } // If this new mutation cancels a base trait, remove it and add the mutation at the same time add_msg_player_or_npc( rating, _("Your innate %1$s trait turns into %2$s!"), _("<npcname>'s innate %1$s trait turns into %2$s!"), cancel_mdata.name.c_str(), mdata.name.c_str() ); add_memorial_log(pgettext("memorial_male", "'%s' mutation turned into '%s'"), pgettext("memorial_female", "'%s' mutation turned into '%s'"), cancel_mdata.name.c_str(), mdata.name.c_str()); unset_mutation(canceltrait[i]); mutation_loss_effect(canceltrait[i]); mutation_effect(mut); mutation_replaced = true; } if (!mutation_replaced) { if(mdata.mixed_effect) { rating = m_mixed; } else if(mdata.points > 0) { rating = m_good; } else if(mdata.points < 0) { rating = m_bad; } else { rating = m_neutral; } // TODO: Limit to visible mutations add_msg_player_or_npc( rating, _("You gain a mutation called %s!"), _("<npcname> gains a mutation called %s!"), mdata.name.c_str() ); add_memorial_log(pgettext("memorial_male", "Gained the mutation '%s'."), pgettext("memorial_female", "Gained the mutation '%s'."), mdata.name.c_str()); mutation_effect(mut); } set_highest_cat_level(); drench_mut_calc(); return true; }
void player::mutate_towards( const std::string &mut ) { if (has_child_flag(mut)) { remove_child_flag(mut); return; } const auto &mdata = mutation_branch::get( mut ); bool has_prereqs = false; bool prereq1 = false; bool prereq2 = false; std::vector<std::string> canceltrait; std::vector<std::string> prereq = mdata.prereqs; std::vector<std::string> prereqs2 = mdata.prereqs2; std::vector<std::string> cancel = mdata.cancels; for (size_t i = 0; i < cancel.size(); i++) { if (!has_trait( cancel[i] )) { cancel.erase(cancel.begin() + i); i--; } else if (has_base_trait( cancel[i] )) { //If we have the trait, but it's a base trait, don't allow it to be removed normally canceltrait.push_back( cancel[i]); cancel.erase(cancel.begin() + i); i--; } } for (size_t i = 0; i < cancel.size(); i++) { if (!cancel.empty()) { std::string removed = cancel[i]; remove_mutation(removed); cancel.erase(cancel.begin() + i); i--; // This checks for cases where one trait knocks out several others // Probably a better way, but gets it Fixed Now--KA101 mutate_towards(mut); return; } } for (size_t i = 0; (!prereq1) && i < prereq.size(); i++) { if (has_trait(prereq[i])) { prereq1 = true; } } for (size_t i = 0; (!prereq2) && i < prereqs2.size(); i++) { if (has_trait(prereqs2[i])) { prereq2 = true; } } if (prereq1 && prereq2) { has_prereqs = true; } if (!has_prereqs && (!prereq.empty() || !prereqs2.empty())) { if (!prereq1 && !prereq.empty()) { mutate_towards( random_entry( prereq ) ); return; } else if (!prereq2 && !prereqs2.empty()) { mutate_towards( random_entry( prereqs2 ) ); return; } } // Check for threshhold mutation, if needed bool threshold = mdata.threshold; bool profession = mdata.profession; bool has_threshreq = false; std::vector<std::string> threshreq = mdata.threshreq; // It shouldn't pick a Threshold anyway--they're supposed to be non-Valid // and aren't categorized--but if it does, just reroll if (threshold) { add_msg(_("You feel something straining deep inside you, yearning to be free...")); mutate(); return; } if (profession) { // Profession picks fail silently mutate(); return; } for (size_t i = 0; !has_threshreq && i < threshreq.size(); i++) { if (has_trait(threshreq[i])) { has_threshreq = true; } } // No crossing The Threshold by simply not having it // Rerolling proved more trouble than it was worth, so deleted if (!has_threshreq && !threshreq.empty()) { add_msg(_("You feel something straining deep inside you, yearning to be free...")); return; } // Check if one of the prereqs that we have TURNS INTO this one std::string replacing = ""; prereq = mdata.prereqs; // Reset it for( auto &elem : prereq ) { if( has_trait( elem ) ) { std::string pre = elem; const auto &p = mutation_branch::get( pre ); for (size_t j = 0; replacing == "" && j < p.replacements.size(); j++) { if (p.replacements[j] == mut) { replacing = pre; } } } } // Loop through again for prereqs2 std::string replacing2 = ""; prereq = mdata.prereqs2; // Reset it for( auto &elem : prereq ) { if( has_trait( elem ) ) { std::string pre2 = elem; const auto &p = mutation_branch::get( pre2 ); for (size_t j = 0; replacing2 == "" && j < p.replacements.size(); j++) { if (p.replacements[j] == mut) { replacing2 = pre2; } } } } set_mutation(mut); bool mutation_replaced = false; game_message_type rating; if (replacing != "") { const auto &replace_mdata = mutation_branch::get( replacing ); if(mdata.mixed_effect || replace_mdata.mixed_effect) { rating = m_mixed; } else if(replace_mdata.points - mdata.points < 0) { rating = m_good; } else if(mdata.points - replace_mdata.points < 0) { rating = m_bad; } else { rating = m_neutral; } add_msg(rating, _("Your %1$s mutation turns into %2$s!"), replace_mdata.name.c_str(), mdata.name.c_str()); add_memorial_log(pgettext("memorial_male", "'%s' mutation turned into '%s'"), pgettext("memorial_female", "'%s' mutation turned into '%s'"), replace_mdata.name.c_str(), mdata.name.c_str()); unset_mutation(replacing); mutation_loss_effect(replacing); mutation_effect(mut); mutation_replaced = true; } if (replacing2 != "") { const auto &replace_mdata = mutation_branch::get( replacing2 ); if(mdata.mixed_effect || replace_mdata.mixed_effect) { rating = m_mixed; } else if(replace_mdata.points - mdata.points < 0) { rating = m_good; } else if(mdata.points - replace_mdata.points < 0) { rating = m_bad; } else { rating = m_neutral; } add_msg(rating, _("Your %1$s mutation turns into %2$s!"), replace_mdata.name.c_str(), mdata.name.c_str()); add_memorial_log(pgettext("memorial_male", "'%s' mutation turned into '%s'"), pgettext("memorial_female", "'%s' mutation turned into '%s'"), replace_mdata.name.c_str(), mdata.name.c_str()); unset_mutation(replacing2); mutation_loss_effect(replacing2); mutation_effect(mut); mutation_replaced = true; } for (size_t i = 0; i < canceltrait.size(); i++) { const auto &cancel_mdata = mutation_branch::get( canceltrait[i] ); if(mdata.mixed_effect || cancel_mdata.mixed_effect) { rating = m_mixed; } else if(mdata.points < cancel_mdata.points) { rating = m_bad; } else if(mdata.points > cancel_mdata.points) { rating = m_good; } else if(mdata.points == cancel_mdata.points) { rating = m_neutral; } else { rating = m_mixed; } // If this new mutation cancels a base trait, remove it and add the mutation at the same time add_msg(rating, _("Your innate %1$s trait turns into %2$s!"), cancel_mdata.name.c_str(), mdata.name.c_str()); add_memorial_log(pgettext("memorial_male", "'%s' mutation turned into '%s'"), pgettext("memorial_female", "'%s' mutation turned into '%s'"), cancel_mdata.name.c_str(), mdata.name.c_str()); unset_mutation(canceltrait[i]); mutation_loss_effect(canceltrait[i]); mutation_effect(mut); mutation_replaced = true; } if (!mutation_replaced) { if(mdata.mixed_effect) { rating = m_mixed; } else if(mdata.points > 0) { rating = m_good; } else if(mdata.points < 0) { rating = m_bad; } else { rating = m_neutral; } add_msg(rating, _("You gain a mutation called %s!"), mdata.name.c_str()); add_memorial_log(pgettext("memorial_male", "Gained the mutation '%s'."), pgettext("memorial_female", "Gained the mutation '%s'."), mdata.name.c_str()); mutation_effect(mut); } set_highest_cat_level(); drench_mut_calc(); }
void player::mutate_towards(game *g, std::string mut) { if (has_child_flag(g, mut)) { remove_child_flag(g, mut); return; } bool has_prereqs = false; std::string canceltrait = ""; std::vector<std::string> prereq = mutation_data[mut].prereqs; std::vector<std::string> cancel = mutation_data[mut].cancels; for (int i = 0; i < cancel.size(); i++) { if (!has_trait( cancel[i] )) { cancel.erase(cancel.begin() + i); i--; } else if (has_base_trait( cancel[i] )) { //If we have the trait, but it's a base trait, don't allow it to be removed normally canceltrait = cancel[i]; cancel.erase(cancel.begin() + i); i--; } } if (!cancel.empty()) { std::string removed = cancel[ rng(0, cancel.size() - 1) ]; remove_mutation(g, removed); return; } for (int i = 0; !has_prereqs && i < prereq.size(); i++) { if (has_trait(prereq[i])) { has_prereqs = true; } } if (!has_prereqs && !prereq.empty()) { std::string devel = prereq[ rng(0, prereq.size() - 1) ]; mutate_towards(g, devel); return; } // Check if one of the prereqs that we have TURNS INTO this one std::string replacing = ""; prereq = mutation_data[mut].prereqs; // Reset it for (int i = 0; i < prereq.size(); i++) { if (has_trait(prereq[i])) { std::string pre = prereq[i]; for (int j = 0; replacing == "" && j < mutation_data[pre].replacements.size(); j++) { if (mutation_data[pre].replacements[j] == mut) { replacing = pre; } } } } toggle_mutation(mut); if (replacing != "") { g->add_msg(_("Your %1$s mutation turns into %2$s!"), traits[replacing].name.c_str(), traits[mut].name.c_str()); g->u.add_memorial_log(_("'%s' mutation turned into '%s'"), traits[replacing].name.c_str(), traits[mut].name.c_str()); toggle_mutation(replacing); mutation_loss_effect(g, *this, replacing); mutation_effect(g, *this, mut); } else if (canceltrait != "") { // If this new mutation cancels a base trait, remove it and add the mutation at the same time g->add_msg(_("Your innate %1$s trait turns into %2$s!"), traits[canceltrait].name.c_str(), traits[mut].name.c_str()); g->u.add_memorial_log(_("'%s' trait turned into '%s'"), traits[canceltrait].name.c_str(), traits[mut].name.c_str()); toggle_mutation(canceltrait); mutation_loss_effect(g, *this, canceltrait); mutation_effect(g, *this, mut); } else { g->add_msg(_("You gain a mutation called %s!"), traits[mut].name.c_str()); g->u.add_memorial_log(_("Gained the mutation '%s'."), traits[mut].name.c_str()); mutation_effect(g, *this, mut); } set_highest_cat_level(); drench_mut_calc(); }
/* * load player from ginormous json blob */ void player::deserialize(JsonIn &jsin) { JsonObject data = jsin.get_object(); JsonArray parray; json_load_common_variables( data ); std::string prof_ident="(null)"; if ( data.read("profession",prof_ident) && profession::exists(prof_ident) ) { prof = profession::prof(prof_ident); } else { debugmsg("Tried to use non-existent profession '%s'", prof_ident.c_str()); } data.read("activity",activity); data.read("backlog",backlog); data.read("driving_recoil",driving_recoil); data.read("in_vehicle",in_vehicle); data.read("controlling_vehicle",controlling_vehicle); data.read("grab_point", grab_point); std::string grab_typestr="OBJECT_NONE"; if( grab_point.x != 0 || grab_point.y != 0 ) { grab_typestr = "OBJECT_VEHICLE"; data.read( "grab_type", grab_typestr); } if ( obj_type_id.find(grab_typestr) != obj_type_id.end() ) { grab_type = (object_type)obj_type_id[grab_typestr]; } data.read( "blocks_left", num_blocks); data.read( "focus_pool", focus_pool); data.read( "style_selected", style_selected ); data.read( "health", health ); data.read( "mutations", my_mutations ); set_highest_cat_level(); drench_mut_calc(); parray = data.get_array("temp_cur"); if ( parray.size() == num_bp ) { for(int i=0; i < num_bp; i++) { temp_cur[i]=parray.get_int(i); } } else { debugmsg("Error, incompatible temp_cur in save file %s",parray.str().c_str()); } parray = data.get_array("temp_conv"); if ( parray.size() == num_bp ) { for(int i=0; i < num_bp; i++) { temp_conv[i]=parray.get_int(i); } } else { debugmsg("Error, incompatible temp_conv in save file %s",parray.str().c_str()); } parray = data.get_array("frostbite_timer"); if ( parray.size() == num_bp ) { for(int i=0; i < num_bp; i++) { frostbite_timer[i]=parray.get_int(i); } } else { debugmsg("Error, incompatible frostbite_timer in save file %s",parray.str().c_str()); } parray = data.get_array("learned_recipes"); if ( !parray.empty() ) { learned_recipes.clear(); std::string pstr=""; while ( parray.has_more() ) { if ( parray.read_next(pstr) ) { learned_recipes[ pstr ] = recipe_by_name( pstr ); } } } data.read("morale", morale); data.read( "active_mission", active_mission ); data.read( "active_missions", active_missions ); data.read( "failed_missions", failed_missions ); data.read( "completed_missions", completed_missions ); stats & pstats = *lifetime_stats(); data.read("player_stats",pstats); inv.clear(); if ( data.has_member("inv") ) { JsonIn* jip = data.get_raw("inv"); inv.json_load_items( *jip ); } if ( data.has_member("invcache") ) { JsonIn* jip = data.get_raw("invcache"); inv.json_load_invcache( *jip ); } worn.clear(); data.read("worn", worn); weapon.contents.clear(); data.read("weapon", weapon); }