From be871d682e8087ab38c5e9e054190daf6f81fff2 Mon Sep 17 00:00:00 2001 From: Matthew Cline Date: Fri, 6 Nov 2009 19:26:31 -0800 Subject: Split up debug.cc --- crawl-ref/source/wiz-you.cc | 882 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 882 insertions(+) create mode 100644 crawl-ref/source/wiz-you.cc (limited to 'crawl-ref/source/wiz-you.cc') diff --git a/crawl-ref/source/wiz-you.cc b/crawl-ref/source/wiz-you.cc new file mode 100644 index 0000000000..ad1fb6eb15 --- /dev/null +++ b/crawl-ref/source/wiz-you.cc @@ -0,0 +1,882 @@ +/* + * File: wiz-you.cc + * Summary: Player related debugging functions. + * Written by: Linley Henzell and Jesse Jones + */ + +#include "AppHdr.h" + +#include "wiz-you.h" + +#include "cio.h" +#include "dbg-util.h" +#include "food.h" +#include "message.h" +#include "mutation.h" +#include "newgame.h" +#include "output.h" +#include "player.h" +#include "random.h" +#include "religion.h" +#include "skills.h" +#include "skills2.h" +#include "spl-cast.h" +#include "spl-util.h" +#include "stuff.h" +#include "terrain.h" +#include "xom.h" + +#ifdef WIZARD +void wizard_change_species( void ) +{ + char specs[80]; + int i; + + mpr("What species would you like to be now? " , MSGCH_PROMPT); + get_input_line( specs, sizeof( specs ) ); + + if (specs[0] == '\0') + return; + strlwr(specs); + + species_type sp = SP_UNKNOWN; + + for (i = 0; i < NUM_SPECIES; ++i) + { + const species_type si = static_cast(i); + const std::string sp_name = + lowercase_string(species_name(si, you.experience_level)); + + std::string::size_type pos = sp_name.find(specs); + if (pos != std::string::npos) + { + if (pos == 0 && *specs) + { + // We prefer prefixes over partial matches. + sp = si; + break; + } + else + sp = si; + } + } + + if (sp == SP_UNKNOWN) + { + mpr("That species isn't available."); + return; + } + + // Re-scale skill-points. + for (i = 0; i < NUM_SKILLS; ++i) + { + you.skill_points[i] *= species_skills( i, sp ); + you.skill_points[i] /= species_skills( i, you.species ); + } + + you.species = sp; + you.is_undead = get_undead_state(sp); + + // Change permanent mutations, but preserve non-permanent ones. + unsigned char prev_muts[NUM_MUTATIONS]; + for (i = 0; i < NUM_MUTATIONS; ++i) + { + if (you.demon_pow[i] > 0) + { + if (you.demon_pow[i] > you.mutation[i]) + you.mutation[i] = 0; + else + you.mutation[i] -= you.demon_pow[i]; + + you.demon_pow[i] = 0; + } + prev_muts[i] = you.mutation[i]; + } + give_basic_mutations(sp); + for (i = 0; i < NUM_MUTATIONS; ++i) + { + if (prev_muts[i] > you.demon_pow[i]) + you.demon_pow[i] = 0; + else + you.demon_pow[i] -= prev_muts[i]; + } + + switch (sp) + { + case SP_GREEN_DRACONIAN: + if (you.experience_level >= 7) + perma_mutate(MUT_POISON_RESISTANCE, 1); + break; + + case SP_RED_DRACONIAN: + if (you.experience_level >= 14) + perma_mutate(MUT_HEAT_RESISTANCE, 1); + break; + + case SP_WHITE_DRACONIAN: + if (you.experience_level >= 14) + perma_mutate(MUT_COLD_RESISTANCE, 1); + break; + + + case SP_BLACK_DRACONIAN: + if (you.experience_level >= 18) + perma_mutate(MUT_SHOCK_RESISTANCE, 1); + break; + + case SP_DEMONSPAWN: + { + roll_demonspawn_mutations(); + for (i = 2; i <= you.experience_level; ++i) + { + mutation_type m = you.demon_trait[i-2]; + + if (m == NUM_MUTATIONS) + continue; + + ++you.mutation[m]; + ++you.demon_pow[m]; + } + break; + } + + default: + break; + } + +#ifdef USE_TILE + init_player_doll(); +#endif + redraw_screen(); +} +#endif + +#ifdef WIZARD +// Casts a specific spell by number. +void wizard_cast_spec_spell(void) +{ + int spell = debug_prompt_for_int( "Cast which spell by number? ", true ); + + if (spell == -1) + canned_msg( MSG_OK ); + else if (your_spells( static_cast(spell), 0, false ) + == SPRET_ABORT) + { + crawl_state.cancel_cmd_repeat(); + } +} +#endif + + +#ifdef WIZARD +// Casts a specific spell by name. +void wizard_cast_spec_spell_name(void) +{ + char specs[80]; + + mpr("Cast which spell by name? ", MSGCH_PROMPT); + if (cancelable_get_line_autohist( specs, sizeof( specs ) ) + || specs[0] == '\0') + { + canned_msg( MSG_OK ); + crawl_state.cancel_cmd_repeat(); + return; + } + + spell_type type = spell_by_name(specs, true); + if (type == SPELL_NO_SPELL) + { + mpr((one_chance_in(20)) ? "Maybe you should go back to WIZARD school." + : "I couldn't find that spell."); + crawl_state.cancel_cmd_repeat(); + return; + } + + if (your_spells(type, 0, false) == SPRET_ABORT) + crawl_state.cancel_cmd_repeat(); +} +#endif + +void wizard_heal(bool super_heal) +{ + if (super_heal) + { + // Clear more stuff and give a HP boost. + you.magic_contamination = 0; + you.duration[DUR_LIQUID_FLAMES] = 0; + you.clear_beholders(); + + // If we're repeating then do the HP increase all at once. + int amount = 10; + if (crawl_state.cmd_repeat_goal > 0) + { + amount *= crawl_state.cmd_repeat_goal; + crawl_state.cancel_cmd_repeat(); + } + + inc_hp(amount, true); + } + + // Clear most status ailments. + you.rotting = 0; + you.disease = 0; + you.duration[DUR_CONF] = 0; + you.duration[DUR_POISONING] = 0; + set_hp(you.hp_max, false); + set_mp(you.max_magic_points, false); + set_hunger(10999, true); + you.redraw_hit_points = true; +} + +void wizard_set_hunger_state() +{ + std::string hunger_prompt = + "Set hunger state to s(T)arving, (N)ear starving, (H)ungry"; + if (you.species == SP_GHOUL) + hunger_prompt += " or (S)atiated"; + else + hunger_prompt += ", (S)atiated, (F)ull or (E)ngorged"; + hunger_prompt += "? "; + + mprf(MSGCH_PROMPT, "%s", hunger_prompt.c_str()); + + const int c = tolower(getch()); + + // Values taken from food.cc. + switch (c) + { + case 't': you.hunger = 500; break; + case 'n': you.hunger = 1200; break; + case 'h': you.hunger = 2400; break; + case 's': you.hunger = 5000; break; + case 'f': you.hunger = 8000; break; + case 'e': you.hunger = 12000; break; + default: canned_msg(MSG_OK); break; + } + food_change(); + if (you.species == SP_GHOUL && you.hunger_state >= HS_SATIATED) + mpr("Ghouls can never be full or above!"); +} + +void wizard_gain_piety() +{ + if (you.religion == GOD_NO_GOD) + { + mpr("You are not religious!"); + return; + } + else if (you.religion == GOD_XOM) + { + you.piety = random2(MAX_PIETY+1); // reroll mood + if (one_chance_in(5)) + you.gift_timeout = 0; // 20% chance to make Xom bored. + else + you.gift_timeout = random2(40) + random2(40); // reroll interest + + const std::string new_xom_favour = describe_xom_favour(); + const std::string msg = "You are now " + new_xom_favour; + god_speaks(you.religion, msg.c_str()); + return; + } + + const int old_piety = you.piety; + const int old_penance = you.penance[you.religion]; + if (old_piety >= MAX_PIETY && !old_penance) + { + mprf("Your piety (%d) is already %s maximum.", + old_piety, old_piety == MAX_PIETY ? "at" : "above"); + } + + // Even at maximum, you can still gain gifts. + // Try at least once for maximum, or repeat until something + // happens. Rarely, this might result in several gifts during the + // same round! + do + { + gain_piety(50); + } + while (old_piety < MAX_PIETY && old_piety == you.piety + && old_penance == you.penance[you.religion]); + + if (old_penance) + { + mprf("Congratulations, your penance was decreased from %d to %d!", + old_penance, you.penance[you.religion]); + } + else if (you.piety > old_piety) + { + mprf("Congratulations, your piety went from %d to %d!", + old_piety, you.piety); + } +} + +//--------------------------------------------------------------- +// +// debug_add_skills +// +//--------------------------------------------------------------- +#ifdef WIZARD +void wizard_exercise_skill(void) +{ + int skill = debug_prompt_for_skill( "Which skill (by name)? " ); + + if (skill == -1) + mpr("That skill doesn't seem to exist."); + else + { + mpr("Exercising..."); + exercise(skill, 100); + } +} +#endif + +#ifdef WIZARD +void wizard_set_skill_level(void) +{ + int skill = debug_prompt_for_skill( "Which skill (by name)? " ); + + if (skill == -1) + mpr("That skill doesn't seem to exist."); + else + { + mpr(skill_name(skill)); + int amount = debug_prompt_for_int( "To what level? ", true ); + + if (amount < 0) + canned_msg( MSG_OK ); + else + { + const int old_amount = you.skills[skill]; + const int points = (skill_exp_needed( amount ) + * species_skills( skill, you.species )) / 100; + + you.skill_points[skill] = points + 1; + you.skills[skill] = amount; + + calc_total_skill_points(); + + redraw_skill(you.your_name, player_title()); + + switch (skill) + { + case SK_FIGHTING: + calc_hp(); + break; + + case SK_SPELLCASTING: + case SK_INVOCATIONS: + case SK_EVOCATIONS: + calc_mp(); + break; + + case SK_DODGING: + you.redraw_evasion = true; + break; + + case SK_ARMOUR: + you.redraw_armour_class = true; + you.redraw_evasion = true; + break; + + default: + break; + } + + mprf("%s %s to skill level %d.", + (old_amount < amount ? "Increased" : + old_amount > amount ? "Lowered" + : "Reset"), + skill_name(skill), amount); + + if (skill == SK_STEALTH && amount == 27) + { + mpr("If you set the stealth skill to a value higher than 27, " + "hide mode is activated, and monsters won't notice you."); + } + } + } +} +#endif + + +#ifdef WIZARD +void wizard_set_all_skills(void) +{ + int i; + int amount = + debug_prompt_for_int( "Set all skills to what level? ", true ); + + if (amount < 0) // cancel returns -1 -- bwr + canned_msg( MSG_OK ); + else + { + if (amount > 27) + amount = 27; + + for (i = SK_FIGHTING; i < NUM_SKILLS; ++i) + { + if (is_invalid_skill(i)) + continue; + + const int points = (skill_exp_needed( amount ) + * species_skills( i, you.species )) / 100; + + you.skill_points[i] = points + 1; + you.skills[i] = amount; + } + + redraw_skill(you.your_name, player_title()); + + calc_total_skill_points(); + + calc_hp(); + calc_mp(); + + you.redraw_armour_class = true; + you.redraw_evasion = true; + } +} +#endif + +#ifdef WIZARD +extern mutation_def mutation_defs[]; + +bool wizard_add_mutation() +{ + bool success = false; + char specs[80]; + + if (player_mutation_level(MUT_MUTATION_RESISTANCE) > 0 + && !crawl_state.is_replaying_keys()) + { + const char* msg; + + if (you.mutation[MUT_MUTATION_RESISTANCE] == 3) + msg = "You are immune to mutations, remove immunity?"; + else + msg = "You are resistant to mutations, remove resistance?"; + + if (yesno(msg, true, 'n')) + { + you.mutation[MUT_MUTATION_RESISTANCE] = 0; + crawl_state.cancel_cmd_repeat(); + } + } + + bool force = yesno("Force mutation to happen?", true, 'n'); + + if (player_mutation_level(MUT_MUTATION_RESISTANCE) == 3 && !force) + { + mpr("Can't mutate when immune to mutations without forcing it."); + crawl_state.cancel_cmd_repeat(); + return (false); + } + + bool god_gift = yesno("Treat mutation as god gift?", true, 'n'); + + mpr("Which mutation (name, 'good', 'bad', 'any', 'xom')? ", MSGCH_PROMPT); + get_input_line( specs, sizeof( specs ) ); + + if (specs[0] == '\0') + return (false); + + strlwr(specs); + + mutation_type mutat = NUM_MUTATIONS; + + + if (strcmp(specs, "good") == 0) + mutat = RANDOM_GOOD_MUTATION; + else if (strcmp(specs, "bad") == 0) + mutat = RANDOM_BAD_MUTATION; + else if (strcmp(specs, "any") == 0) + mutat = RANDOM_MUTATION; + else if (strcmp(specs, "xom") == 0) + mutat = RANDOM_XOM_MUTATION; + + if (mutat != NUM_MUTATIONS) + { + int old_resist = player_mutation_level(MUT_MUTATION_RESISTANCE); + + success = mutate(mutat, true, force, god_gift); + + if (old_resist < player_mutation_level(MUT_MUTATION_RESISTANCE) + && !force) + { + crawl_state.cancel_cmd_repeat("Your mutation resistance has " + "increased."); + } + return (success); + } + + std::vector partial_matches; + + for (unsigned i = 0; true; ++i) + { + if (strcmp(specs, mutation_defs[i].wizname) == 0) + { + mutat = mutation_defs[i].mutation; + break; + } + + if (strstr(mutation_defs[i].wizname, specs)) + partial_matches.push_back(mutation_defs[i].mutation); + + // FIXME: hack, but I don't want to export the size + // of the array...this is even worse. + if (mutation_defs[i].mutation + 1 == NUM_MUTATIONS) + break; + } + + // If only one matching mutation, use that. + if (mutat == NUM_MUTATIONS && partial_matches.size() == 1) + mutat = partial_matches[0]; + + if (mutat == NUM_MUTATIONS) + { + crawl_state.cancel_cmd_repeat(); + + if (partial_matches.size() == 0) + mpr("No matching mutation names."); + else + { + std::vector matches; + + for (unsigned int i = 0; i < partial_matches.size(); ++i) + matches.push_back(get_mutation_def(partial_matches[i]).wizname); + + std::string prefix = "No exact match for mutation '" + + std::string(specs) + "', possible matches are: "; + + // Use mpr_comma_separated_list() because the list + // might be *LONG*. + mpr_comma_separated_list(prefix, matches, " and ", ", ", + MSGCH_DIAGNOSTICS); + } + + return (false); + } + else + { + mprf("Found #%d: %s (\"%s\")", (int) mutat, + get_mutation_def(mutat).wizname, + mutation_name(mutat, 1, false).c_str()); + + const int levels = + debug_prompt_for_int("How many levels to increase or decrease? ", + false); + + if (levels == 0) + { + canned_msg(MSG_OK); + success = false; + } + else if (levels > 0) + { + for (int i = 0; i < levels; ++i) + if (mutate(mutat, true, force, god_gift)) + success = true; + } + else + { + for (int i = 0; i < -levels; ++i) + if (delete_mutation(mutat, true, force, god_gift)) + success = true; + } + } + + return (success); +} +#endif + +#ifdef WIZARD +void wizard_get_religion(void) +{ + char specs[80]; + + mpr("Which god (by name)? ", MSGCH_PROMPT); + get_input_line( specs, sizeof( specs ) ); + + if (specs[0] == '\0') + return; + + strlwr(specs); + + god_type god = GOD_NO_GOD; + + for (int i = 1; i < NUM_GODS; ++i) + { + const god_type gi = static_cast(i); + if (lowercase_string(god_name(gi)).find(specs) != std::string::npos) + { + god = gi; + break; + } + } + + if (god == GOD_NO_GOD) + mpr("That god doesn't seem to be taking followers today."); + else + { + dungeon_feature_type feat = + static_cast( DNGN_ALTAR_FIRST_GOD + god - 1 ); + dungeon_terrain_changed(you.pos(), feat, false); + + pray(); + } +} +#endif + +void wizard_set_stats() +{ + char buf[80]; + mprf(MSGCH_PROMPT, "Enter values for Str, Int, Dex (space separated): "); + if (cancelable_get_line_autohist(buf, sizeof buf)) + return; + + int sstr = you.strength, + sdex = you.dex, + sint = you.intel; + + sscanf(buf, "%d %d %d", &sstr, &sint, &sdex); + + you.max_strength = you.strength = debug_cap_stat(sstr); + you.max_dex = you.dex = debug_cap_stat(sdex); + you.max_intel = you.intel = debug_cap_stat(sint); + + you.redraw_strength = true; + you.redraw_dexterity = true; + you.redraw_intelligence = true; + you.redraw_evasion = true; +} + +static const char* dur_names[NUM_DURATIONS] = +{ + "invis", + "conf", + "paralysis", + "slow", + "mesmerised", + "haste", + "might", + "levitation", + "berserker", + "poisoning", + "confusing touch", + "sure blade", + "backlight", + "deaths door", + "fire shield", + "building rage", + "exhausted", + "liquid flames", + "icy armour", + "repel missiles", + "prayer", + "piety pool", + "divine vigour", + "divine stamina", + "divine shield", + "regeneration", + "swiftness", + "stonemail", + "controlled flight", + "teleport", + "control teleport", + "breath weapon", + "transformation", + "death channel", + "deflect missiles", + "phase shift", + "see invisible", + "weapon brand", + "silence", + "condensation shield", + "stoneskin", + "gourmand", + "bargain", + "insulation", + "resist poison", + "resist fire", + "resist cold", + "slaying", + "stealth", + "magic shield", + "sleep", + "sage", + "telepathy", + "petrified", + "lowered mr", + "repel stairs move", + "repel stairs climb" +}; + +void wizard_edit_durations( void ) +{ + std::vector durs; + size_t max_len = 0; + + for (int i = 0; i < NUM_DURATIONS; ++i) + { + if (!you.duration[i]) + continue; + + max_len = std::max(strlen(dur_names[i]), max_len); + durs.push_back(i); + } + + if (durs.size() > 0) + { + for (unsigned int i = 0; i < durs.size(); ++i) + { + int dur = durs[i]; + mprf(MSGCH_PROMPT, "%c) %-*s : %d", 'a' + i, max_len, + dur_names[dur], you.duration[dur]); + } + mpr("", MSGCH_PROMPT); + mpr("Edit which duration (letter or name)? ", MSGCH_PROMPT); + } + else + mpr("Edit which duration (name)? ", MSGCH_PROMPT); + + char buf[80]; + + if (cancelable_get_line_autohist(buf, sizeof buf) || strlen(buf) == 0) + { + canned_msg( MSG_OK ); + return; + } + + strcpy(buf, lowercase_string(trimmed_string(buf)).c_str()); + + if (strlen(buf) == 0) + { + canned_msg( MSG_OK ); + return; + } + + int choice = -1; + + if (strlen(buf) == 1) + { + if (durs.size() == 0) + { + mpr("No existing durations to choose from.", MSGCH_PROMPT); + return; + } + choice = buf[0] - 'a'; + + if (choice < 0 || choice >= (int) durs.size()) + { + mpr("Invalid choice.", MSGCH_PROMPT); + return; + } + choice = durs[choice]; + } + else + { + std::vector matches; + std::vector match_names; + max_len = 0; + + for (int i = 0; i < NUM_DURATIONS; ++i) + { + if (strcmp(dur_names[i], buf) == 0) + { + choice = i; + break; + } + if (strstr(dur_names[i], buf) != NULL) + { + matches.push_back(i); + match_names.push_back(dur_names[i]); + } + } + if (choice != -1) + ; + else if (matches.size() == 1) + choice = matches[0]; + else if (matches.size() == 0) + { + mprf(MSGCH_PROMPT, "No durations matching '%s'.", buf); + return; + } + else + { + std::string prefix = "No exact match for duration '"; + prefix += buf; + prefix += "', possible matches are: "; + + mpr_comma_separated_list(prefix, match_names, " and ", ", ", + MSGCH_DIAGNOSTICS); + return; + } + } + + sprintf(buf, "Set '%s' to: ", dur_names[choice]); + int num = debug_prompt_for_int(buf, false); + + if (num == 0) + { + mpr("Can't set duration directly to 0, setting it to 1 instead.", + MSGCH_PROMPT); + num = 1; + } + you.duration[choice] = num; +} + +static void debug_uptick_xl(int newxl) +{ + while (newxl > you.experience_level) + { + you.experience = 1 + exp_needed( 2 + you.experience_level ); + level_change(true); + } +} + +static void debug_downtick_xl(int newxl) +{ + you.hp = you.hp_max; + while (newxl < you.experience_level) + { + // Each lose_level() subtracts 4 HP, so do this to avoid death + // and/or negative HP when going from a high level to a low level. + you.hp = std::max(5, you.hp); + you.hp_max = std::max(5, you.hp_max); + + lose_level(); + } + + you.hp = std::max(1, you.hp); + you.hp_max = std::max(1, you.hp_max); + + you.base_hp = std::max(5000, you.base_hp); + you.base_hp2 = std::max(5000 + you.hp_max, you.base_hp2); +} + +void wizard_set_xl() +{ + mprf(MSGCH_PROMPT, "Enter new experience level: "); + char buf[30]; + if (cancelable_get_line_autohist(buf, sizeof buf)) + { + canned_msg(MSG_OK); + return; + } + + const int newxl = atoi(buf); + if (newxl < 1 || newxl > 27 || newxl == you.experience_level) + { + canned_msg(MSG_OK); + return; + } + + no_messages mx; + if (newxl < you.experience_level) + debug_downtick_xl(newxl); + else + debug_uptick_xl(newxl); +} + + + -- cgit v1.2.3-54-g00ecf