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::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(game *g, pl_flag mut) { // Check for dependant mutations first std::vector<pl_flag> dependant; for (int i = 0; i < PF_MAX2; i++) { for (std::vector<pl_flag>::iterator it = g->mutation_data[i].prereqs.begin(); it != g->mutation_data[i].prereqs.end(); it++) { if (*it == i) { dependant.push_back((pl_flag)i); break; } } } if (dependant.size() != 0) { remove_mutation(g,dependant[rng(0,dependant.size())]); return; } // Check if there's a prereq we should shrink back into pl_flag replacing = PF_NULL; std::vector<pl_flag> originals = g->mutation_data[mut].prereqs; for (int i = 0; replacing == PF_NULL && i < originals.size(); i++) { pl_flag pre = originals[i]; for (int j = 0; replacing == PF_NULL && j < g->mutation_data[pre].replacements.size(); j++) { if (g->mutation_data[pre].replacements[j] == mut) replacing = pre; } } // 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 == PF_NULL) { //Check each mutation until we reach the end or find a trait to revert to for (int i = 1; replacing == PF_NULL && i < PF_MAX2; i++) { //See if it's in our list of base traits but not active if (has_base_trait(i) && !has_trait(i)) { //See if that base trait cancels the mutation we are using std::vector<pl_flag> traitcheck = g->mutation_data[i].cancels; if (!traitcheck.empty()) { for (int j = 0; replacing == PF_NULL && j < traitcheck.size(); j++) { if (g->mutation_data[i].cancels[j] == mut) replacing = ((pl_flag)i); } } } } } // This should revert back to a removed base trait rather than simply removing the mutation toggle_mutation(mut); if (replacing != PF_NULL) { g->add_msg("Your %s mutation turns into %s.", traits[mut].name.c_str(), traits[replacing].name.c_str()); toggle_mutation(replacing); mutation_loss_effect(g, *this, mut); mutation_effect(g, *this, replacing); } else { g->add_msg("You lose your %s mutation.", traits[mut].name.c_str()); mutation_loss_effect(g, *this, mut); } }
void player::mutate_towards(game *g, pl_flag mut) { if (has_child_flag(g, mut)) { remove_child_flag(g, mut); return; } bool has_prereqs = false; pl_flag canceltrait = PF_NULL; std::vector<pl_flag> prereq = g->mutation_data[mut].prereqs; std::vector<pl_flag> cancel = g->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 we have the trait, but it's a base trait, don't allow it to be removed normally if (has_base_trait( cancel[i] )) { canceltrait = cancel[i]; cancel.erase(cancel.begin() + i); i--; } } } if (!cancel.empty()) { pl_flag 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()) { pl_flag 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 pl_flag replacing = PF_NULL; prereq = g->mutation_data[mut].prereqs; // Reset it for (int i = 0; i < prereq.size(); i++) { if (has_trait(prereq[i])) { pl_flag pre = prereq[i]; for (int j = 0; replacing == PF_NULL && j < g->mutation_data[pre].replacements.size(); j++) { if (g->mutation_data[pre].replacements[j] == mut) replacing = pre; } } } toggle_mutation(mut); if (replacing != PF_NULL) { g->add_msg("Your %s mutation turns 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 this new mutation cancels a base trait, remove it and add the mutation at the same time if (canceltrait != PF_NULL) { g->add_msg("Your innate %s trait turns 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()); mutation_effect(g, *this, mut); } // Weight us towards any categories that include this mutation for (int i = 0; i < NUM_MUTATION_CATEGORIES; i++) { std::vector<pl_flag> group = mutations_from_category(mutation_category(i)); bool found = false; for (int j = 0; !found && j < group.size(); j++) { if (group[j] == mut) found = true; } if (found) mutation_category_level[i] += 8; else if (mutation_category_level[i] > 0 && !one_in(mutation_category_level[i])) mutation_category_level[i]--; } }
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(); }
void player::remove_mutation(game *g, pl_flag mut) { // Check for dependant mutations first std::vector<pl_flag> dependant; for (int i = 0; i < PF_MAX2; i++) { for (std::vector<pl_flag>::iterator it = g->mutation_data[i].prereqs.begin(); it != g->mutation_data[i].prereqs.end(); it++) { if (*it == i) { dependant.push_back((pl_flag)i); break; } } } if (dependant.size() != 0) { remove_mutation(g,dependant[rng(0,dependant.size())]); return; } // Check if there's a prereq we should shrink back into pl_flag replacing = PF_NULL; std::vector<pl_flag> originals = g->mutation_data[mut].prereqs; for (int i = 0; replacing == PF_NULL && i < originals.size(); i++) { pl_flag pre = originals[i]; for (int j = 0; replacing == PF_NULL && j < g->mutation_data[pre].replacements.size(); j++) { if (g->mutation_data[pre].replacements[j] == mut) replacing = pre; } } // 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 == PF_NULL) { //Check each mutation until we reach the end or find a trait to revert to for (int i = 1; replacing == PF_NULL && i < PF_MAX2; i++) { //See if it's in our list of base traits but not active if (has_base_trait(i) && !has_trait(i)) { //See if that base trait cancels the mutation we are using std::vector<pl_flag> traitcheck = g->mutation_data[i].cancels; if (!traitcheck.empty()) { for (int j = 0; replacing == PF_NULL && j < traitcheck.size(); j++) { if (g->mutation_data[i].cancels[j] == mut) replacing = ((pl_flag)i); } } } } } // This should revert back to a removed base trait rather than simply removing the mutation toggle_mutation(mut); if (replacing != PF_NULL) { 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(g, *this, mut); mutation_effect(g, *this, replacing); } else { g->add_msg(_("You lose your %s mutation."), traits[mut].name.c_str()); mutation_loss_effect(g, *this, mut); } // Reduce the strength of the categories the removed mutation is a part of for (int i = 0; i < NUM_MUTATION_CATEGORIES; i++) { std::vector<pl_flag> group = mutations_from_category(mutation_category(i)); bool found = false; for (int j = 0; !found && j < group.size(); j++) { if (group[j] == mut) found = true; } if (found) { mutation_category_level[i] -= 8; // If the category strength is below 0, set it to 0. We don't want negative category strength. if (mutation_category_level[i] < 0) { mutation_category_level[i] = 0; } } } }