Permalink
Cannot retrieve contributors at this time
Join GitHub today
GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.
Sign up
Fetching contributors…
| #include "iuse.h" | |
| #include "game.h" | |
| #include "mapdata.h" | |
| #include "keypress.h" | |
| #include "output.h" | |
| #include "rng.h" | |
| #include "line.h" | |
| #include "mutation.h" | |
| #include "player.h" | |
| #include "vehicle.h" | |
| #include <sstream> | |
| #include <algorithm> | |
| #define RADIO_PER_TURN 25 // how many characters per turn of radio | |
| // mfb(n) converts a flag to its appropriate position in covers's bitfield | |
| #ifndef mfb | |
| #define mfb(n) long(1 << (n)) | |
| #endif | |
| static void add_or_drop_item(game *g, player *p, item *it) | |
| { | |
| item replacement(g->itypes[it->type->id], int(g->turn), g->nextinv); | |
| bool drop = false; | |
| int iter = 0; | |
| // Should this vary based on how many charges get consumed by default? | |
| if (replacement.charges >= 0) | |
| { | |
| replacement.charges = 1; | |
| } | |
| if( replacement.is_drink() ) { | |
| it->charges++; | |
| return; | |
| } | |
| while (p->has_item(replacement.invlet)) { | |
| replacement.invlet = g->nextinv; | |
| g->advance_nextinv(); | |
| iter++; | |
| } | |
| if (!drop && (iter == inv_chars.size() || p->volume_carried() >= p->volume_capacity())) | |
| drop = true; | |
| if (drop) | |
| g->m.add_item_or_charges(p->posx, p->posy, replacement); | |
| else | |
| p->i_add(replacement, g); | |
| } | |
| static bool use_fire(game *g, player *p, item *it) | |
| { | |
| if (!p->use_charges_if_avail("fire", 1)) | |
| { | |
| add_or_drop_item(g, p, it); | |
| g->add_msg_if_player(p, _("You need a lighter!")); | |
| return false; | |
| } | |
| return true; | |
| } | |
| // Returns false if the inscription failed or if the player canceled the action. Otherwise, returns true. | |
| static bool inscribe_item( game *g, player *p, std::string verb, std::string gerund, bool carveable ) | |
| { | |
| //Note: this part still strongly relies on English grammar. | |
| //Although it can be easily worked around in language like Chinese, | |
| //but might need to be reworked for some European languages that have more verb forms | |
| char ch = g->inv(string_format(_("%s on what?"), verb.c_str())); | |
| item* cut = &(p->i_at(ch)); | |
| if (cut->type->id == "null") | |
| { | |
| g->add_msg(_("You do not have that item!")); | |
| return false; | |
| } | |
| if (!cut->made_of(SOLID)) | |
| { | |
| std::string lower_verb = verb; | |
| std::transform(lower_verb.begin(), lower_verb.end(), lower_verb.begin(), ::tolower); | |
| g->add_msg(_("You can't %s an item that's not solid!"), lower_verb.c_str()); | |
| return false; | |
| } | |
| if(carveable && !(cut->made_of("wood") || cut->made_of("plastic") || cut->made_of("glass") || | |
| cut->made_of("chitin") || cut->made_of("iron") || cut->made_of("steel") || | |
| cut->made_of("silver"))) { | |
| std::string lower_verb = verb; | |
| std::transform(lower_verb.begin(), lower_verb.end(), lower_verb.begin(), ::tolower); | |
| std::string mat = cut->get_material(1); | |
| material_type* mt = material_type::find_material(mat); | |
| std::string mtname = "null"; | |
| if(mt!=NULL) { | |
| mtname = mt->name(); | |
| } | |
| std::transform(mtname.begin(), mtname.end(), mtname.begin(), ::tolower); | |
| g->add_msg(_("You can't %1$s an item made of %2$s!"), | |
| lower_verb.c_str(), mtname.c_str()); | |
| return false; | |
| } | |
| std::map<std::string, std::string>::iterator ent = cut->item_vars.find("item_note"); | |
| std::string message = string_format(_("%1$s on this %2$s is a note saying: "), gerund.c_str(), cut->type->name.c_str()); | |
| message = string_input_popup(string_format(_("%s what?"), verb.c_str()), 64, (ent != cut->item_vars.end() ? | |
| cut->item_vars["item_note"] : message )); | |
| if( message.size() > 0 ) { cut->item_vars["item_note"] = message; } | |
| return true; | |
| } | |
| void iuse::none(game *g, player *p, item *it, bool t) | |
| { | |
| g->add_msg(_("You can't do anything interesting with your %s."), | |
| it->tname(g).c_str()); | |
| } | |
| /* To mark an item as "removed from inventory", set its invlet to 0 | |
| This is useful for traps (placed on ground), inactive bots, etc | |
| */ | |
| void iuse::sewage(game *g, player *p, item *it, bool t) | |
| { | |
| p->vomit(g); | |
| if (one_in(4)) | |
| p->mutate(g); | |
| } | |
| void iuse::honeycomb(game *g, player *p, item *it, bool t) | |
| { | |
| g->m.spawn_item(p->posx, p->posy, "wax",0, 2); | |
| } | |
| void iuse::royal_jelly(game *g, player *p, item *it, bool t) | |
| { | |
| // TODO: Add other diseases here; royal jelly is a cure-all! | |
| p->pkill += 5; | |
| std::string message; | |
| if (p->has_disease("fungus")) { | |
| message = _("You feel cleansed inside!"); | |
| p->rem_disease("fungus"); | |
| } | |
| if (p->has_disease("blind")) { | |
| message = _("Your sight returns!"); | |
| p->rem_disease("blind"); | |
| } | |
| if (p->has_disease("poison") || p->has_disease("foodpoison") || | |
| p->has_disease("badpoison")) { | |
| message = _("You feel much better!"); | |
| p->rem_disease("poison"); | |
| p->rem_disease("badpoison"); | |
| p->rem_disease("foodpoison"); | |
| } | |
| if (p->has_disease("asthma")) { | |
| message = _("Your breathing clears up!"); | |
| p->rem_disease("asthma"); | |
| } | |
| if (p->has_disease("common_cold") || p->has_disease("flu")) { | |
| message = _("You feel healthier!"); | |
| p->rem_disease("common_cold"); | |
| p->rem_disease("flu"); | |
| } | |
| g->add_msg_if_player(p,message.c_str()); | |
| } | |
| // returns true if we want to use the special action | |
| bool use_healing_item(game *g, player *p, item *it, int normal_power, int head_power, | |
| int torso_power, std::string item_name, std::string special_action) | |
| { | |
| int bonus = p->skillLevel("firstaid"); | |
| hp_part healed; | |
| if (p->is_npc()) { // NPCs heal whichever has sustained the most damage | |
| int highest_damage = 0; | |
| for (int i = 0; i < num_hp_parts; i++) { | |
| int damage = p->hp_max[i] - p->hp_cur[i]; | |
| if (i == hp_head) | |
| damage *= 1.5; | |
| if (i == hp_torso) | |
| damage *= 1.2; | |
| if (damage > highest_damage) { | |
| highest_damage = damage; | |
| healed = hp_part(i); | |
| } | |
| } | |
| } else { // Player--present a menu | |
| WINDOW* hp_window = newwin(11, 22, (TERMY-10)/2, (TERMX-22)/2); | |
| wborder(hp_window, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX, | |
| LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX ); | |
| mvwprintz(hp_window, 1, 1, c_ltred, _("Use %s:"), item_name.c_str()); | |
| if(p->hp_cur[hp_head] < p->hp_max[hp_head]) | |
| { | |
| mvwprintz(hp_window, 2, 1, c_ltgray, _("1: Head")); | |
| } | |
| if(p->hp_cur[hp_torso] < p->hp_max[hp_torso]) | |
| { | |
| mvwprintz(hp_window, 3, 1, c_ltgray, _("2: Torso")); | |
| } | |
| if(p->hp_cur[hp_arm_l] < p->hp_max[hp_arm_l]) | |
| { | |
| mvwprintz(hp_window, 4, 1, c_ltgray, _("3: Left Arm")); | |
| } | |
| if(p->hp_cur[hp_arm_r] < p->hp_max[hp_arm_r]) | |
| { | |
| mvwprintz(hp_window, 5, 1, c_ltgray, _("4: Right Arm")); | |
| } | |
| if(p->hp_cur[hp_leg_l] < p->hp_max[hp_leg_l]) | |
| { | |
| mvwprintz(hp_window, 6, 1, c_ltgray, _("5: Left Leg")); | |
| } | |
| if(p->hp_cur[hp_leg_r] < p->hp_max[hp_leg_r]) | |
| { | |
| mvwprintz(hp_window, 7, 1, c_ltgray, _("6: Right Leg")); | |
| } | |
| if(special_action != "") | |
| { | |
| mvwprintz(hp_window, 8, 1, c_ltgray, _("7: %s"), special_action.c_str()); | |
| } | |
| mvwprintz(hp_window, 9, 1, c_ltgray, _("8: Exit")); | |
| nc_color color; | |
| std::string asterisks = ""; | |
| for (int i = 0; i < num_hp_parts; i++) | |
| { | |
| if (p->hp_cur[i] < p->hp_max[i]) | |
| { | |
| int current_hp = p->hp_cur[i]; | |
| int temporary_bonus = bonus; | |
| if (current_hp != 0) | |
| { | |
| switch (hp_part(i)) { | |
| case hp_head: | |
| current_hp += head_power; | |
| temporary_bonus *= .8; | |
| break; | |
| case hp_torso: | |
| current_hp += torso_power; | |
| temporary_bonus *= 1.5; | |
| break; | |
| default: | |
| current_hp += normal_power; | |
| break; | |
| } | |
| current_hp += temporary_bonus; | |
| if (current_hp > p->hp_max[i]) | |
| { | |
| current_hp = p->hp_max[i]; | |
| } | |
| if (current_hp == p->hp_max[i]) | |
| { | |
| color = c_green; | |
| asterisks = "***"; | |
| } | |
| else if (current_hp > p->hp_max[i] * .8) | |
| { | |
| color = c_ltgreen; | |
| asterisks = "***"; | |
| } | |
| else if (current_hp > p->hp_max[i] * .5) | |
| { | |
| color = c_yellow; | |
| asterisks = "** "; | |
| } | |
| else if (current_hp > p->hp_max[i] * .3) | |
| { | |
| color = c_ltred; | |
| asterisks = "** "; | |
| } | |
| else | |
| { | |
| color = c_red; | |
| asterisks = "* "; | |
| } | |
| if (p->has_trait(PF_SELFAWARE)) | |
| { | |
| if (current_hp >= 100) | |
| { | |
| mvwprintz(hp_window, i + 2, 16, color, "%d", current_hp); | |
| } | |
| else if (current_hp >= 10) | |
| { | |
| mvwprintz(hp_window, i + 2, 17, color, "%d", current_hp); | |
| } | |
| else | |
| { | |
| mvwprintz(hp_window, i + 2, 19, color, "%d", current_hp); | |
| } | |
| } | |
| else | |
| { | |
| mvwprintz(hp_window, i + 2, 16, color, asterisks.c_str()); | |
| } | |
| } | |
| else | |
| { | |
| // curhp is 0; requires surgical attention | |
| mvwprintz(hp_window, i + 2, 16, c_dkgray, "---"); | |
| } | |
| } | |
| } | |
| wrefresh(hp_window); | |
| char ch; | |
| do { | |
| ch = getch(); | |
| if (ch == '1'){ | |
| healed = hp_head; | |
| } else if (ch == '2'){ | |
| healed = hp_torso; | |
| } else if (ch == '3') { | |
| if (p->hp_cur[hp_arm_l] == 0) { | |
| g->add_msg_if_player(p,_("That arm is broken. It needs surgical attention.")); | |
| add_or_drop_item(g, p, it); | |
| return false; | |
| } else { | |
| healed = hp_arm_l; | |
| } | |
| } else if (ch == '4') { | |
| if (p->hp_cur[hp_arm_r] == 0) { | |
| g->add_msg_if_player(p,_("That arm is broken. It needs surgical attention.")); | |
| add_or_drop_item(g, p, it); | |
| return false; | |
| } else { | |
| healed = hp_arm_r; | |
| } | |
| } else if (ch == '5') { | |
| if (p->hp_cur[hp_leg_l] == 0) { | |
| g->add_msg_if_player(p,_("That leg is broken. It needs surgical attention.")); | |
| add_or_drop_item(g, p, it); | |
| return false; | |
| } else { | |
| healed = hp_leg_l; | |
| } | |
| } else if (ch == '6') { | |
| if (p->hp_cur[hp_leg_r] == 0) { | |
| g->add_msg_if_player(p,_("That leg is broken. It needs surgical attention.")); | |
| add_or_drop_item(g, p, it); | |
| return false; | |
| } else { | |
| healed = hp_leg_r; | |
| } | |
| } else if (ch == '8' || special_action == "") { | |
| g->add_msg_if_player(p,_("Never mind.")); | |
| add_or_drop_item(g, p, it); | |
| return false; | |
| } else if (ch == '7') { | |
| return true; | |
| } | |
| } while (ch < '1' || ch > '8'); | |
| werase(hp_window); | |
| wrefresh(hp_window); | |
| delwin(hp_window); | |
| refresh(); | |
| } | |
| p->practice(g->turn, "firstaid", 8); | |
| int dam = 0; | |
| if (healed == hp_head){ | |
| dam = head_power + bonus * .8; | |
| } else if (healed == hp_torso){ | |
| dam = torso_power + bonus * 1.5; | |
| } else { | |
| dam = normal_power + bonus; | |
| } | |
| p->heal(healed, dam); | |
| return false; | |
| } | |
| void iuse::bandage(game *g, player *p, item *it, bool t) | |
| { | |
| if (use_healing_item(g, p, it, 3, 1, 4, _("Bandage"), p->has_disease("bleed") ? _("Stop Bleeding") : "")) | |
| { | |
| g->add_msg_if_player(p,_("You stopped the bleeding.")); | |
| p->rem_disease("bleed"); | |
| } | |
| } | |
| void iuse::firstaid(game *g, player *p, item *it, bool t) | |
| { | |
| if (use_healing_item(g, p, it, 14, 10, 18, _("First Aid"), p->has_disease("bite") ? _("Clean Wound") : "")) | |
| { | |
| g->add_msg_if_player(p,_("You clean the bite wound.")); | |
| p->rem_disease("bite"); | |
| } | |
| } | |
| void iuse::disinfectant(game *g, player *p, item *it, bool t) | |
| { | |
| if (use_healing_item(g, p, it, 6, 5, 9, _("Disinfectant"), p->has_disease("bite") ? _("Clean Wound") : "")) | |
| { | |
| g->add_msg_if_player(p,_("You disinfect the bite wound.")); | |
| p->rem_disease("bite"); | |
| } | |
| } | |
| void iuse::pkill(game *g, player *p, item *it, bool t) | |
| { | |
| // Aspirin | |
| if (it->has_flag("PKILL_1")) { | |
| g->add_msg_if_player(p,_("You take some %s."), it->tname().c_str()); | |
| if (!p->has_disease("pkill1")) { | |
| p->add_disease("pkill1", 120); | |
| } else { | |
| for (int i = 0; i < p->illness.size(); i++) { | |
| if (p->illness[i].type == "pkill1") { | |
| p->illness[i].duration = 120; | |
| i = p->illness.size(); | |
| } | |
| } | |
| } | |
| // Codeine | |
| } else if (it->has_flag("PKILL_2")) { | |
| g->add_msg_if_player(p,_("You take some %s."), it->tname().c_str()); | |
| p->add_disease("pkill2", 180); | |
| } else if (it->has_flag("PKILL_3")) { | |
| g->add_msg_if_player(p,_("You take some %s."), it->tname().c_str()); | |
| p->add_disease("pkill3", 20); | |
| p->add_disease("pkill2", 200); | |
| } else if (it->has_flag("PKILL_4")) { | |
| g->add_msg_if_player(p,_("You shoot up.")); | |
| p->add_disease("pkill3", 80); | |
| p->add_disease("pkill2", 200); | |
| } else if (it->has_flag("PKILL_L")) { | |
| g->add_msg_if_player(p,_("You take some %s."), it->tname().c_str()); | |
| p->add_disease("pkill_l", rng(12, 18) * 300); | |
| } | |
| } | |
| void iuse::xanax(game *g, player *p, item *it, bool t) | |
| { | |
| g->add_msg_if_player(p,_("You take some %s."), it->tname().c_str()); | |
| if (!p->has_disease("took_xanax")) | |
| p->add_disease("took_xanax", 900); | |
| else | |
| p->add_disease("took_xanax", 200); | |
| } | |
| void iuse::caff(game *g, player *p, item *it, bool t) | |
| { | |
| it_comest *food = dynamic_cast<it_comest*> (it->type); | |
| p->fatigue -= food->stim * 3; | |
| } | |
| void iuse::alcohol(game *g, player *p, item *it, bool t) | |
| { | |
| int duration = 680 - (10 * p->str_max); // Weaker characters are cheap drunks | |
| if (p->has_trait(PF_LIGHTWEIGHT)) | |
| duration += 300; | |
| p->pkill += 8; | |
| p->add_disease("drunk", duration); | |
| } | |
| void iuse::alcohol_weak(game *g, player *p, item *it, bool t) | |
| { | |
| int duration = 340 - (6 * p->str_max); | |
| if (p->has_trait(PF_LIGHTWEIGHT)) | |
| duration += 120; | |
| p->pkill += 4; | |
| p->add_disease("drunk", duration); | |
| } | |
| void iuse::cig(game *g, player *p, item *it, bool t) | |
| { | |
| if (!use_fire(g, p, it)) return; | |
| if (it->type->id == "cig") | |
| g->add_msg_if_player(p,_("You light a cigarette and smoke it.")); | |
| else //cigar | |
| g->add_msg_if_player(p,_("You take a few puffs from your cigar.")); | |
| p->add_disease("cig", 200); | |
| for (int i = 0; i < p->illness.size(); i++) { | |
| if (p->illness[i].type == "cig" && p->illness[i].duration > 600) | |
| g->add_msg_if_player(p,_("Ugh, too much smoke... you feel gross.")); | |
| } | |
| } | |
| void iuse::antibiotic(game *g, player *p, item *it, bool t) | |
| { | |
| if (p->has_disease("infected")){ | |
| g->add_msg_if_player(p,_("You took some antibiotics.")); | |
| p->rem_disease("infected"); | |
| p->add_disease("recover", 1200); | |
| } | |
| else { | |
| g->add_msg_if_player(p,_("You took some antibiotics.")); | |
| } | |
| } | |
| void iuse::weed(game *g, player *p, item *it, bool t) | |
| { | |
| if (!use_fire(g, p, it)) return; | |
| g->add_msg_if_player(p,_("Good stuff, man!")); | |
| int duration = 60; | |
| if (p->has_trait(PF_LIGHTWEIGHT)) | |
| duration = 90; | |
| p->hunger += 8; | |
| if (p->pkill < 15) | |
| p->pkill += 5; | |
| p->add_disease("high", duration); | |
| } | |
| void iuse::coke(game *g, player *p, item *it, bool t) | |
| { | |
| g->add_msg_if_player(p,_("You snort a bump.")); | |
| int duration = 21 - p->str_cur; | |
| if (p->has_trait(PF_LIGHTWEIGHT)) | |
| duration += 20; | |
| p->hunger -= 8; | |
| p->add_disease("high", duration); | |
| } | |
| void iuse::crack(game *g, player *p, item *it, bool t) | |
| { | |
| // Crack requires a fire source AND a pipe. | |
| if (!use_fire(g, p, it)) return; | |
| g->add_msg_if_player(p,_("You smoke some rocks.")); | |
| int duration = 10; | |
| if (p->has_trait(PF_LIGHTWEIGHT)) | |
| { | |
| duration += 10; | |
| } | |
| p->hunger -= 8; | |
| p->add_disease("high", duration); | |
| } | |
| void iuse::grack(game *g, player *p, item *it, bool t) | |
| { | |
| // Grack requires a fire source AND a pipe. | |
| if (!use_fire(g, p, it)) return; | |
| g->add_msg_if_player(p,_("You smoke some Grack Cocaine. Time seems to stop.")); | |
| int duration = 1000; | |
| if (p->has_trait(PF_LIGHTWEIGHT)) | |
| duration += 10; | |
| p->hunger -= 8; | |
| p->add_disease("grack", duration); | |
| } | |
| void iuse::meth(game *g, player *p, item *it, bool t) | |
| { | |
| int duration = 10 * (40 - p->str_cur); | |
| if (p->has_amount("apparatus", 1) && | |
| p->use_charges_if_avail("fire", 1)) | |
| { | |
| g->add_msg_if_player(p,_("You smoke some crystals.")); | |
| duration *= 1.5; | |
| } | |
| else | |
| { | |
| g->add_msg_if_player(p,_("You snort some crystals.")); | |
| } | |
| if (!p->has_disease("meth")) {duration += 600;} | |
| if (duration > 0) | |
| { | |
| int hungerpen = (p->str_cur < 10 ? 20 : 30 - p->str_cur); | |
| p->hunger -= hungerpen; | |
| p->add_disease("meth", duration); | |
| } | |
| } | |
| void iuse::vitamins(game *g, player *p, item *it, bool t) | |
| { | |
| g->add_msg_if_player(p,_("You take some vitamins.")); | |
| if (p->health >= 10) | |
| { | |
| return; | |
| } | |
| else if (p->health >= 0) | |
| { | |
| p->health = 10; | |
| } | |
| else | |
| { | |
| p->health += 10; | |
| } | |
| } | |
| void iuse::vaccine(game *g, player *p, item *it, bool t) | |
| { | |
| g->add_msg_if_player(p,_("You inject the vaccine, and feel much healthier.")); | |
| if (p->health >= 100) | |
| { | |
| return; | |
| } | |
| else if (p->health >= 0) | |
| { | |
| p->health = 100; | |
| } | |
| else | |
| { | |
| p->health += 100; | |
| } | |
| } | |
| void iuse::poison(game *g, player *p, item *it, bool t) | |
| { | |
| p->add_disease("poison", 600); | |
| p->add_disease("foodpoison", 1800); | |
| } | |
| void iuse::hallu(game *g, player *p, item *it, bool t) | |
| { | |
| p->add_disease("hallu", 2400); | |
| } | |
| void iuse::thorazine(game *g, player *p, item *it, bool t) | |
| { | |
| p->fatigue += 15; | |
| p->rem_disease("hallu"); | |
| p->rem_disease("visuals"); | |
| p->rem_disease("high"); | |
| if (!p->has_disease("dermatik")) | |
| p->rem_disease("formication"); | |
| g->add_msg_if_player(p,_("You feel somewhat sedated.")); | |
| } | |
| void iuse::prozac(game *g, player *p, item *it, bool t) | |
| { | |
| if (!p->has_disease("took_prozac") && p->morale_level() < 0) | |
| p->add_disease("took_prozac", 7200); | |
| else | |
| p->stim += 3; | |
| } | |
| void iuse::sleep(game *g, player *p, item *it, bool t) | |
| { | |
| p->fatigue += 40; | |
| g->add_msg_if_player(p,_("You feel very sleepy...")); | |
| } | |
| void iuse::iodine(game *g, player *p, item *it, bool t) | |
| { | |
| p->add_disease("iodine", 1200); | |
| g->add_msg_if_player(p,_("You take an iodine tablet.")); | |
| } | |
| void iuse::flumed(game *g, player *p, item *it, bool t) | |
| { | |
| p->add_disease("took_flumed", 6000); | |
| g->add_msg_if_player(p,_("You take some %s"), it->tname().c_str()); | |
| } | |
| void iuse::flusleep(game *g, player *p, item *it, bool t) | |
| { | |
| p->add_disease("took_flumed", 7200); | |
| p->fatigue += 30; | |
| g->add_msg_if_player(p,_("You feel very sleepy...")); | |
| } | |
| void iuse::inhaler(game *g, player *p, item *it, bool t) | |
| { | |
| p->rem_disease("asthma"); | |
| g->add_msg_if_player(p,_("You take a puff from your inhaler.")); | |
| } | |
| void iuse::blech(game *g, player *p, item *it, bool t) | |
| { | |
| // TODO: Add more effects? | |
| g->add_msg_if_player(p,_("Blech, that burns your throat!")); | |
| p->vomit(g); | |
| } | |
| void iuse::mutagen(game *g, player *p, item *it, bool t) | |
| { | |
| if( it->has_flag("MUTAGEN_STRONG") ) | |
| { | |
| p->mutate(g); | |
| if (!one_in(3)) | |
| p->mutate(g); | |
| if (one_in(2)) | |
| p->mutate(g); | |
| } | |
| else if( it->has_flag("MUTAGEN_PLANT") ) | |
| { | |
| g->add_msg_if_player(p, _("You feel much closer to nature.")); | |
| p->mutate_category(g, MUTCAT_PLANT); | |
| } | |
| else if( it->has_flag("MUTAGEN_INSECT") ) | |
| { | |
| g->add_msg_if_player(p, _("You hear buzzing, and feel your body harden.")); | |
| p->mutate_category(g, MUTCAT_INSECT); | |
| } | |
| else if( it->has_flag("MUTAGEN_SPIDER") ) | |
| { | |
| g->add_msg_if_player(p, _("You feel insidious.")); | |
| p->mutate_category(g, MUTCAT_SPIDER); | |
| } | |
| else if( it->has_flag("MUTAGEN_SLIME") ) | |
| { | |
| g->add_msg_if_player(p, _("Your body loses all rigidity for a moment.")); | |
| p->mutate_category(g, MUTCAT_SLIME); | |
| } | |
| else if( it->has_flag("MUTAGEN_FISH") ) | |
| { | |
| g->add_msg_if_player(p, _("You are overcome by an overwhelming longing for the ocean.")); | |
| p->mutate_category(g, MUTCAT_FISH); | |
| } | |
| else if( it->has_flag("MUTAGEN_RAT") ) | |
| { | |
| g->add_msg_if_player(p, _("You feel a momentary nausea.")); | |
| p->mutate_category(g, MUTCAT_RAT); | |
| } | |
| else if( it->has_flag("MUTAGEN_BEAST") ) | |
| { | |
| g->add_msg_if_player(p, _("Your heart races and you see blood for a moment.")); | |
| p->mutate_category(g, MUTCAT_BEAST); | |
| } | |
| else if( it->has_flag("MUTAGEN_CATTLE") ) | |
| { | |
| g->add_msg_if_player(p, _("Your mind and body slow down. You feel peaceful.")); | |
| p->mutate_category(g, MUTCAT_CATTLE); | |
| } | |
| else if( it->has_flag("MUTAGEN_CEPHALOPOD") ) | |
| { | |
| g->add_msg_if_player(p, _("Your mind is overcome by images of eldritch horrors...and then they pass.")); | |
| p->mutate_category(g, MUTCAT_CEPHALOPOD); | |
| } | |
| else if( it->has_flag("MUTAGEN_BIRD") ) | |
| { | |
| g->add_msg_if_player(p, _("Your body lightens and you long for the sky.")); | |
| p->mutate_category(g, MUTCAT_BIRD); | |
| } | |
| else if( it->has_flag("MUTAGEN_LIZARD") ) | |
| { | |
| g->add_msg_if_player(p, _("For a heartbeat, your body cools down.")); | |
| p->mutate_category(g, MUTCAT_LIZARD); | |
| } | |
| else if( it->has_flag("MUTAGEN_TROGLOBITE") ) | |
| { | |
| g->add_msg_if_player(p, _("You yearn for a cool, dark place to hide.")); | |
| p->mutate_category(g, MUTCAT_TROGLO); | |
| } | |
| else | |
| { | |
| if (!one_in(3)) | |
| { | |
| p->mutate(g); | |
| } | |
| } | |
| } | |
| void iuse::purifier(game *g, player *p, item *it, bool t) | |
| { | |
| std::vector<int> valid; // Which flags the player has | |
| for (int i = PF_NULL+1; i < PF_MAX2; i++) { | |
| if (p->has_trait(pl_flag(i)) && !p->has_base_trait(pl_flag(i))) //Looks for active mutation | |
| valid.push_back(i); | |
| } | |
| if (valid.size() == 0) { | |
| g->add_msg_if_player(p,_("You feel cleansed.")); | |
| return; | |
| } | |
| int num_cured = rng(1, valid.size()); | |
| if (num_cured > 4) | |
| num_cured = 4; | |
| for (int i = 0; i < num_cured && valid.size() > 0; i++) { | |
| int index = rng(0, valid.size() - 1); | |
| p->remove_mutation(g, pl_flag(valid[index]) ); | |
| valid.erase(valid.begin() + index); | |
| } | |
| } | |
| void iuse::marloss(game *g, player *p, item *it, bool t) | |
| { | |
| if (p->is_npc()) | |
| return; | |
| // If we have the marloss in our veins, we are a "breeder" and will spread | |
| // alien lifeforms. | |
| if (p->has_trait(PF_MARLOSS)) { | |
| g->add_msg_if_player(p,_("As you eat the berry, you have a near-religious experience, feeling at one with your surroundings...")); | |
| p->add_morale(MORALE_MARLOSS, 100, 1000); | |
| p->hunger = -100; | |
| monster goo(g->mtypes[mon_blob]); | |
| goo.friendly = -1; | |
| int goo_spawned = 0; | |
| for (int x = p->posx - 4; x <= p->posx + 4; x++) { | |
| for (int y = p->posy - 4; y <= p->posy + 4; y++) { | |
| if (rng(0, 10) > trig_dist(x, y, p->posx, p->posy) && | |
| rng(0, 10) > trig_dist(x, y, p->posx, p->posy) ) | |
| g->m.marlossify(x, y); | |
| if (one_in(10 + 5 * trig_dist(x, y, p->posx, p->posy)) && | |
| (goo_spawned == 0 || one_in(goo_spawned * 2))) { | |
| goo.spawn(x, y); | |
| g->z.push_back(goo); | |
| goo_spawned++; | |
| } | |
| } | |
| } | |
| return; | |
| } | |
| /* If we're not already carriers of Marloss, roll for a random effect: | |
| * 1 - Mutate | |
| * 2 - Mutate | |
| * 3 - Mutate | |
| * 4 - Purify | |
| * 5 - Purify | |
| * 6 - Cleanse radiation + Purify | |
| * 7 - Fully satiate | |
| * 8 - Vomit | |
| * 9 - Give Marloss mutation | |
| */ | |
| int effect = rng(1, 9); | |
| if (effect <= 3) { | |
| g->add_msg_if_player(p,_("This berry tastes extremely strange!")); | |
| p->mutate(g); | |
| } else if (effect <= 6) { // Radiation cleanse is below | |
| g->add_msg_if_player(p,_("This berry makes you feel better all over.")); | |
| p->pkill += 30; | |
| this->purifier(g, p, it, t); | |
| } else if (effect == 7) { | |
| g->add_msg_if_player(p,_("This berry is delicious, and very filling!")); | |
| p->hunger = -100; | |
| } else if (effect == 8) { | |
| g->add_msg_if_player(p,_("You take one bite, and immediately vomit!")); | |
| p->vomit(g); | |
| } else if (!p->has_trait(PF_MARLOSS)) { | |
| g->add_msg_if_player(p,_("You feel a strange warmth spreading throughout your body...")); | |
| p->toggle_mutation(PF_MARLOSS); | |
| } | |
| if (effect == 6) | |
| p->radiation = 0; | |
| } | |
| void iuse::dogfood(game *g, player *p, item *it, bool t) | |
| { | |
| int dirx, diry; | |
| if(!g->choose_adjacent(_("Put the dog food"),dirx,diry)) | |
| return; | |
| p->moves -= 15; | |
| int mon_dex = g->mon_at(dirx,diry); | |
| if (mon_dex != -1) { | |
| if (g->z[mon_dex].type->id == mon_dog) { | |
| g->add_msg_if_player(p,_("The dog seems to like you!")); | |
| g->z[mon_dex].friendly = -1; | |
| } else | |
| g->add_msg_if_player(p,_("The %s seems quite unimpressed!"),g->z[mon_dex].type->name.c_str()); | |
| } else | |
| g->add_msg_if_player(p,_("You spill the dogfood all over the ground.")); | |
| } | |
| // TOOLS below this point! | |
| bool prep_firestarter_use(game *g, player *p, item *it, int &posx, int &posy) | |
| { | |
| if (!g->choose_adjacent(_("Light"),posx,posy)) | |
| { | |
| it->charges++; | |
| return false; | |
| } | |
| if (posx == p->posx && posy == p->posy) | |
| { | |
| g->add_msg_if_player(p, _("You would set yourself on fire.")); | |
| g->add_msg_if_player(p, _("But you're already smokin' hot.")); | |
| it->charges++; | |
| return false; | |
| } | |
| if (!(g->m.flammable_items_at(posx, posy) || g->m.has_flag(flammable, posx, posy) || g->m.has_flag(flammable2, posx, posy))) | |
| { | |
| g->add_msg_if_player(p,_("There's nothing to light there.")); | |
| it->charges++; | |
| return false; | |
| } | |
| else | |
| { | |
| return true; | |
| } | |
| } | |
| void resolve_firestarter_use(game *g, player *p, item *it, int posx, int posy) | |
| { | |
| // this should have already been checked, but double-check to make sure | |
| if (g->m.flammable_items_at(posx, posy) || g->m.has_flag(flammable, posx, posy) || g->m.has_flag(flammable2, posx, posy)) | |
| { | |
| if (g->m.add_field(g, posx, posy, fd_fire, 1)) | |
| { | |
| field ¤t_field = g->m.field_at(posx, posy); | |
| current_field.findField(fd_fire)->setFieldAge(current_field.findField(fd_fire)->getFieldAge() + 100); | |
| g->add_msg_if_player(p, _("You successfully light a fire.")); | |
| } | |
| } | |
| else | |
| { | |
| debugmsg(_("Flammable items disappeared while lighting a fire!")); | |
| } | |
| } | |
| void iuse::lighter(game *g, player *p, item *it, bool t) | |
| { | |
| int dirx, diry; | |
| if (prep_firestarter_use(g, p, it, dirx, diry)) | |
| { | |
| p->moves -= 15; | |
| resolve_firestarter_use(g, p, it, dirx, diry); | |
| } | |
| } | |
| void iuse::primitive_fire(game *g, player *p, item *it, bool t) | |
| { | |
| int posx, posy; | |
| if (prep_firestarter_use(g, p, it, posx, posy)) | |
| { | |
| p->moves -= 500; | |
| const int skillLevel = p->skillLevel("survival"); | |
| const int sides = 10; | |
| const int base_dice = 3; | |
| // aiming for ~50% success at skill level 3, and possible but unheard of at level 0 | |
| const int difficulty = (base_dice + 3) * sides / 2; | |
| if (dice(skillLevel+base_dice, 10) >= difficulty) | |
| { | |
| resolve_firestarter_use(g, p, it, posx, posy); | |
| } | |
| else | |
| { | |
| g->add_msg_if_player(p, _("You try to light a fire, but fail.")); | |
| } | |
| p->practice(g->turn, "survival", 10); | |
| } | |
| } | |
| void iuse::sew(game *g, player *p, item *it, bool t) | |
| { | |
| if(p->fine_detail_vision_mod(g) > 2.5) | |
| { | |
| g->add_msg(_("You can't see to sew!")); | |
| it->charges++; | |
| return; | |
| } | |
| char ch = g->inv_type(_("Repair what?"), IC_ARMOR); | |
| item* fix = &(p->i_at(ch)); | |
| if (fix == NULL || fix->is_null()) | |
| { | |
| g->add_msg_if_player(p,_("You do not have that item!")); | |
| it->charges++; | |
| return; | |
| } | |
| if (!fix->is_armor()) | |
| { | |
| g->add_msg_if_player(p,_("That isn't clothing!")); | |
| it->charges++; | |
| return; | |
| } | |
| //some items are made from more than one material. we should try to use both items if one type of repair item is missing | |
| itype_id repair_item = "none"; | |
| std::vector<std::string> plurals; | |
| std::vector<itype_id> repair_items; | |
| std::string plural = ""; | |
| //translation note: add <plural> tag to keep them unique | |
| if (fix->made_of("cotton") || fix->made_of("wool")) | |
| { | |
| repair_items.push_back("rag"); | |
| plurals.push_back(_("<plural>rags")); | |
| } | |
| if (fix->made_of("leather")) | |
| { | |
| repair_items.push_back("leather"); | |
| plurals.push_back(rm_prefix(_("<plural>leather"))); | |
| } | |
| if (fix->made_of("fur")) | |
| { | |
| repair_items.push_back("fur"); | |
| plurals.push_back(rm_prefix(_("<plural>fur"))); | |
| } | |
| if(repair_items.empty()) | |
| { | |
| g->add_msg_if_player(p,_("Your %s is not made of cotton, wool, leather or fur."), fix->tname().c_str()); | |
| it->charges++; | |
| return; | |
| } | |
| int items_needed=(fix->damage>2||fix->damage==0)?1:0; | |
| // this will cause issues if/when NPCs start being able to sew. | |
| // but, then again, it'll cause issues when they start crafting, too. | |
| inventory crafting_inv = g->crafting_inventory(p); | |
| bool bFound = false; | |
| //go through all discovered repair items and see if we have any of them available | |
| for(unsigned int i = 0; i< repair_items.size(); i++) | |
| { | |
| if (crafting_inv.has_amount(repair_items[i], items_needed)) | |
| { | |
| //we've found enough of a material, use this one | |
| repair_item = repair_items[i]; | |
| bFound = true; | |
| } | |
| } | |
| if (!bFound) | |
| { | |
| for(unsigned int i = 0; i< repair_items.size(); i++) | |
| { | |
| g->add_msg_if_player(p,_("You don't have enough %s to do that."), plurals[i].c_str()); | |
| } | |
| it->charges++; | |
| return; | |
| } | |
| if (fix->damage < 0) | |
| { | |
| g->add_msg_if_player(p,_("Your %s is already enhanced."), fix->tname().c_str()); | |
| it->charges++; | |
| return; | |
| } | |
| std::vector<component> comps; | |
| comps.push_back(component(repair_item, items_needed)); | |
| comps.back().available = true; | |
| if (fix->damage == 0) | |
| { | |
| p->moves -= 500 * p->fine_detail_vision_mod(g); | |
| p->practice(g->turn, "tailor", 10); | |
| int rn = dice(4, 2 + p->skillLevel("tailor")); | |
| if (p->dex_cur < 8 && one_in(p->dex_cur)) | |
| {rn -= rng(2, 6);} | |
| if (p->dex_cur >= 16 || (p->dex_cur > 8 && one_in(16 - p->dex_cur))) | |
| {rn += rng(2, 6);} | |
| if (p->dex_cur > 16) | |
| {rn += rng(0, p->dex_cur - 16);} | |
| if (rn <= 4) | |
| { | |
| g->add_msg_if_player(p,_("You damage your %s!"), fix->tname().c_str()); | |
| fix->damage++; | |
| } | |
| else if (rn >= 12 && p->i_at(ch).has_flag("VARSIZE") && !p->i_at(ch).has_flag("FIT")) | |
| { | |
| g->add_msg_if_player(p,_("You take your %s in, improving the fit."), fix->tname().c_str()); | |
| (p->i_at(ch).item_tags.insert("FIT")); | |
| } | |
| else if (rn >= 12 && (p->i_at(ch).has_flag("FIT") || !p->i_at(ch).has_flag("VARSIZE"))) | |
| { | |
| g->add_msg_if_player(p, _("You make your %s extra sturdy."), fix->tname().c_str()); | |
| fix->damage--; | |
| g->consume_items(p, comps); | |
| } | |
| else | |
| { | |
| g->add_msg_if_player(p,_("You practice your sewing.")); | |
| } | |
| } | |
| else | |
| { | |
| p->moves -= 500 * p->fine_detail_vision_mod(g); | |
| p->practice(g->turn, "tailor", 8); | |
| int rn = dice(4, 2 + p->skillLevel("tailor")); | |
| rn -= rng(fix->damage, fix->damage * 2); | |
| if (p->dex_cur < 8 && one_in(p->dex_cur)) | |
| {rn -= rng(2, 6);} | |
| if (p->dex_cur >= 8 && (p->dex_cur >= 16 || one_in(16 - p->dex_cur))) | |
| {rn += rng(2, 6);} | |
| if (p->dex_cur > 16) | |
| {rn += rng(0, p->dex_cur - 16);} | |
| if (rn <= 4) | |
| { | |
| g->add_msg_if_player(p,_("You damage your %s further!"), fix->tname().c_str()); | |
| fix->damage++; | |
| if (fix->damage >= 5) | |
| { | |
| g->add_msg_if_player(p,_("You destroy it!")); | |
| p->i_rem(ch); | |
| } | |
| } | |
| else if (rn <= 6) | |
| { | |
| g->add_msg_if_player(p,_("You don't repair your %s, but you waste lots of thread."), fix->tname().c_str()); | |
| int waste = rng(1, 8); | |
| if (waste > it->charges) | |
| {it->charges = 1;} | |
| else | |
| {it->charges -= waste;} | |
| } | |
| else if (rn <= 8) | |
| { | |
| g->add_msg_if_player(p,_("You repair your %s, but waste lots of thread."), fix->tname().c_str()); | |
| if (fix->damage>=3) {g->consume_items(p, comps);} | |
| fix->damage--; | |
| int waste = rng(1, 8); | |
| if (waste > it->charges) | |
| {it->charges = 1;} | |
| else | |
| {it->charges -= waste;} | |
| } | |
| else if (rn <= 16) | |
| { | |
| g->add_msg_if_player(p,_("You repair your %s!"), fix->tname().c_str()); | |
| if (fix->damage>=3) {g->consume_items(p, comps);} | |
| fix->damage--; | |
| } | |
| else | |
| { | |
| g->add_msg_if_player(p,_("You repair your %s completely!"), fix->tname().c_str()); | |
| if (fix->damage>=3) {g->consume_items(p, comps);} | |
| fix->damage = 0; | |
| } | |
| } | |
| //iuse::sew uses up 1 charge when called, if less than 1, set to 1, and use that one up. | |
| if (it->charges < 1) | |
| {it->charges = 1;} | |
| } | |
| void iuse::extra_battery(game *g, player *p, item *it, bool t) | |
| { | |
| char ch = g->inv_type(_("Modify what?"), IC_TOOL); | |
| item* modded = &(p->i_at(ch)); | |
| if (modded == NULL || modded->is_null()) | |
| { | |
| g->add_msg_if_player(p,_("You do not have that item!")); | |
| return; | |
| } | |
| if (!modded->is_tool()) | |
| { | |
| g->add_msg_if_player(p,_("You can only mod tools with this battery mod.")); | |
| return; | |
| } | |
| it_tool *tool = dynamic_cast<it_tool*>(modded->type); | |
| if (tool->ammo != "battery") | |
| { | |
| g->add_msg_if_player(p,_("That item does not use batteries!")); | |
| return; | |
| } | |
| if (modded->has_flag("DOUBLE_AMMO")) | |
| { | |
| g->add_msg_if_player(p,_("That item has already had its battery capacity doubled.")); | |
| return; | |
| } | |
| modded->item_tags.insert("DOUBLE_AMMO"); | |
| g->add_msg_if_player(p,_("You double the battery capacity of your %s!"), tool->name.c_str()); | |
| it->invlet = 0; | |
| } | |
| void iuse::scissors(game *g, player *p, item *it, bool t) | |
| { | |
| char ch = g->inv(_("Chop up what?")); | |
| item* cut = &(p->i_at(ch)); | |
| if (cut->type->id == "null") | |
| { | |
| g->add_msg_if_player(p,_("You do not have that item!")); | |
| return; | |
| } | |
| if (cut->type->id == "string_6" || cut->type->id == "string_36" || cut->type->id == "rope_30" || cut->type->id == "rope_6") | |
| { | |
| g->add_msg(_("You cannot cut that, you must disassemble it using the disassemble key")); | |
| return; | |
| } | |
| if (cut->type->id == "rag" || cut->type->id == "rag_bloody" || cut->type->id == "leather") | |
| { | |
| g->add_msg_if_player(p, _("There's no point in cutting a %s."), cut->type->name.c_str()); | |
| return; | |
| } | |
| if (!cut->made_of("cotton") && !cut->made_of("leather")) | |
| { | |
| g->add_msg(_("You can only slice items made of cotton or leather.")); | |
| return; | |
| } | |
| p->moves -= 25 * cut->volume(); | |
| int count = cut->volume(); | |
| if (p->skillLevel("tailor") == 0) | |
| { | |
| count = rng(0, count); | |
| } | |
| else if (p->skillLevel("tailor") == 1 && count >= 2) | |
| { | |
| count -= rng(0, 2); | |
| } | |
| if (dice(3, 3) > p->dex_cur) | |
| { | |
| count -= rng(1, 3); | |
| } | |
| if (cut->damage>2 || cut->damage<0) | |
| { | |
| count-= cut->damage; | |
| } | |
| //scrap_text is result string of worthless scraps | |
| //sliced_text is result on a success | |
| std::string scrap_text, sliced_text, type; | |
| if (cut->made_of("cotton")) | |
| { | |
| scrap_text = _("You clumsily cut the %s into useless ribbons."); | |
| sliced_text = ngettext("You slice the %s into a rag.", "You slice the %1$s into %2$d rags.", count); | |
| type = "rag"; | |
| } | |
| else | |
| { | |
| scrap_text = _("You clumsily cut the %s into useless scraps."); | |
| sliced_text = ngettext("You slice the %s into a piece of leather.", "You slice the %1$s into %2$d pieces of leather.", count); | |
| type = "leather"; | |
| } | |
| if (count <= 0) | |
| { | |
| g->add_msg_if_player(p, scrap_text.c_str(), cut->tname().c_str()); | |
| p->i_rem(ch); | |
| return; | |
| } | |
| g->add_msg_if_player(p, sliced_text.c_str(), cut->tname().c_str(), count); | |
| item result(g->itypes[type], int(g->turn), g->nextinv); | |
| p->i_rem(ch); | |
| bool drop = false; | |
| for (int i = 0; i < count; i++) | |
| { | |
| int iter = 0; | |
| while (p->has_item(result.invlet) && iter < inv_chars.size()) | |
| { | |
| result.invlet = g->nextinv; | |
| g->advance_nextinv(); | |
| iter++; | |
| } | |
| if (!drop && (iter == inv_chars.size() || p->volume_carried() >= p->volume_capacity())) | |
| drop = true; | |
| if (drop) | |
| g->m.add_item_or_charges(p->posx, p->posy, result); | |
| else | |
| p->i_add(result, g); | |
| } | |
| return; | |
| } | |
| void iuse::extinguisher(game *g, player *p, item *it, bool t) | |
| { | |
| g->draw(); | |
| int x, y; | |
| // If anyone other than the player wants to use one of these, | |
| // they're going to need to figure out how to aim it. | |
| if (!g->choose_adjacent("Spray", x, y)) | |
| return; | |
| p->moves -= 140; | |
| field ¤t_field = g->m.field_at(x, y); | |
| if (current_field.findField(fd_fire)) { | |
| current_field.findField(fd_fire)->setFieldDensity(current_field.findField(fd_fire)->getFieldDensity() - rng(2, 3)); | |
| if (current_field.findField(fd_fire)->getFieldDensity() <= 0) { | |
| //g->m.field_at(x, y).density = 1; | |
| g->m.remove_field(x, y, fd_fire); | |
| } | |
| } | |
| int mondex = g->mon_at(x, y); | |
| if (mondex != -1) { | |
| g->z[mondex].moves -= 150; | |
| if (g->u_see(&(g->z[mondex]))) | |
| g->add_msg_if_player(p,_("The %s is sprayed!"), g->z[mondex].name().c_str()); | |
| if (g->z[mondex].made_of(LIQUID)) { | |
| if (g->u_see(&(g->z[mondex]))) | |
| g->add_msg_if_player(p,_("The %s is frozen!"), g->z[mondex].name().c_str()); | |
| if (g->z[mondex].hurt(rng(20, 60))) | |
| g->kill_mon(mondex, (p == &(g->u))); | |
| else | |
| g->z[mondex].speed /= 2; | |
| } | |
| } | |
| if (g->m.move_cost(x, y) != 0) { | |
| x += (x - p->posx); | |
| y += (y - p->posy); | |
| if (current_field.findField(fd_fire)) { | |
| current_field.findField(fd_fire)->setFieldDensity(current_field.findField(fd_fire)->getFieldDensity() - rng(0, 1) + rng(0, 1)); | |
| if (current_field.findField(fd_fire)->getFieldDensity() <= 0) { | |
| //g->m.field_at(x, y).density = 1; | |
| g->m.remove_field(x, y,fd_fire); | |
| } | |
| } | |
| } | |
| } | |
| void iuse::hammer(game *g, player *p, item *it, bool t) | |
| { | |
| g->draw(); | |
| int x, y; | |
| // If anyone other than the player wants to use one of these, | |
| // they're going to need to figure out how to aim it. | |
| if (!g->choose_adjacent(_("Pry"), x, y)) | |
| return; | |
| if (x == p->posx && y == p->posy) | |
| { | |
| g->add_msg_if_player(p, _("You try to hit yourself with the hammer.")); | |
| g->add_msg_if_player(p, _("But you can't touch this.")); | |
| return; | |
| } | |
| int nails = 0, boards = 0; | |
| ter_id newter; | |
| switch (g->m.ter(x, y)) | |
| { | |
| case t_fence_h: | |
| case t_fence_v: | |
| nails = 6; | |
| boards = 3; | |
| newter = t_fence_post; | |
| break; | |
| case t_window_boarded: | |
| nails = 8; | |
| boards = 4; | |
| newter = t_window_empty; | |
| break; | |
| case t_door_boarded: | |
| nails = 12; | |
| boards = 4; | |
| newter = t_door_b; | |
| break; | |
| default: | |
| g->add_msg_if_player(p,_("Hammers can only remove boards from windows, doors and fences.")); | |
| g->add_msg_if_player(p,_("To board up a window or door, press *")); | |
| return; | |
| } | |
| p->moves -= 500; | |
| g->m.spawn_item(p->posx, p->posy, "nail", 0, 0, nails); | |
| g->m.spawn_item(p->posx, p->posy, "2x4", 0, boards); | |
| g->m.ter_set(x, y, newter); | |
| } | |
| void iuse::gasoline_lantern_off(game *g, player *p, item *it, bool t) | |
| { | |
| if (it->charges == 0) | |
| { | |
| g->add_msg_if_player(p,_("The lantern is empty.")); | |
| } | |
| else if(!p->use_charges_if_avail("fire", 1)) | |
| { | |
| g->add_msg_if_player(p,_("You need a lighter!")); | |
| } | |
| else | |
| { | |
| g->add_msg_if_player(p,_("You turn the lantern on.")); | |
| it->make(g->itypes["gasoline_lantern_on"]); | |
| it->active = true; | |
| it->charges --; | |
| } | |
| } | |
| void iuse::gasoline_lantern_on(game *g, player *p, item *it, bool t) | |
| { | |
| if (t) // Normal use | |
| { | |
| // Do nothing... player::active_light and the lightmap::generate deal with this | |
| } | |
| else // Turning it off | |
| { | |
| g->add_msg_if_player(p,_("The lantern is extinguished.")); | |
| it->make(g->itypes["gasoline_lantern"]); | |
| it->active = false; | |
| } | |
| } | |
| void iuse::light_off(game *g, player *p, item *it, bool t) | |
| { | |
| if (it->charges == 0) | |
| g->add_msg_if_player(p,_("The flashlight's batteries are dead.")); | |
| else { | |
| g->add_msg_if_player(p,_("You turn the flashlight on.")); | |
| it->make(g->itypes["flashlight_on"]); | |
| it->active = true; | |
| it->charges --; | |
| } | |
| } | |
| void iuse::light_on(game *g, player *p, item *it, bool t) | |
| { | |
| if (t) { // Normal use | |
| // Do nothing... player::active_light and the lightmap::generate deal with this | |
| } else { // Turning it off | |
| g->add_msg_if_player(p,_("The flashlight flicks off.")); | |
| it->make(g->itypes["flashlight"]); | |
| it->active = false; | |
| } | |
| } | |
| // this function only exists because we need to set it->active = true | |
| // otherwise crafting would just give you the active version directly | |
| void iuse::lightstrip(game *g, player *p, item *it, bool t) | |
| { | |
| g->add_msg_if_player(p,_("You irreversibly activate the lightstrip.")); | |
| it->make(g->itypes["lightstrip"]); | |
| it->active = true; | |
| } | |
| void iuse::lightstrip_active(game *g, player *p, item *it, bool t) | |
| { | |
| if (t) | |
| { // Normal use | |
| // Do nothing... player::active_light and the lightmap::generate deal with this | |
| } | |
| else | |
| { // Turning it off | |
| g->add_msg_if_player(p,_("The lightstrip dies.")); | |
| it->make(g->itypes["lightstrip_dead"]); | |
| it->active = false; | |
| } | |
| } | |
| void iuse::glowstick(game *g, player *p, item *it, bool t) | |
| { | |
| g->add_msg_if_player(p,_("You activate the glowstick.")); | |
| it->make(g->itypes["glowstick_lit"]); | |
| it->active = true; | |
| } | |
| void iuse::glowstick_active(game *g, player *p, item *it, bool t) | |
| { | |
| if (t) | |
| { // Normal use | |
| // Do nothing... player::active_light and the lightmap::generate deal with this | |
| } | |
| else | |
| { | |
| if (it->charges > 0) | |
| { | |
| g->add_msg_if_player(p,_("You can't turn off a glowstick.")); | |
| } | |
| else | |
| { | |
| g->add_msg_if_player(p,_("The glowstick fades out.")); | |
| it->active = false; | |
| } | |
| } | |
| } | |
| void iuse::cauterize_elec(game *g, player *p, item *it, bool t) | |
| { | |
| if (it->charges == 0) | |
| g->add_msg_if_player(p,_("You need batteries to cauterize wounds.")); | |
| else if (!p->has_disease("bite") && !p->has_disease("bleed")) | |
| g->add_msg_if_player(p,_("You are not bleeding or bitten, there is no need to cauterize yourself.")); | |
| else if (p->is_npc() || query_yn(_("Cauterize any open wounds?"))) | |
| { | |
| it->charges -= 1; | |
| p->cauterize(g); | |
| } | |
| } | |
| void iuse::solder_weld(game *g, player *p, item *it, bool t) | |
| { | |
| it->charges += (dynamic_cast<it_tool*>(it->type))->charges_per_use; | |
| int choice = menu(true, | |
| _("Using soldering item:"), _("Cauterize wound"), _("Repair plastic/metal/kevlar item"), _("Cancel"), NULL); | |
| switch (choice) | |
| { | |
| case 1: | |
| { | |
| iuse::cauterize_elec(g, p, it, t); | |
| } | |
| break; | |
| case 2: | |
| { | |
| if(it->charges <= 0) | |
| { | |
| g->add_msg_if_player(p,_("You don't have enough batteries!")); | |
| return; | |
| } | |
| char ch = g->inv_type(_("Repair what?"), IC_ARMOR); | |
| item* fix = &(p->i_at(ch)); | |
| if (fix == NULL || fix->is_null()) | |
| { | |
| g->add_msg_if_player(p,_("You do not have that item!")); | |
| return; | |
| } | |
| if (!fix->is_armor()) | |
| { | |
| g->add_msg_if_player(p,_("That isn't clothing!")); | |
| return; | |
| } | |
| itype_id repair_item = "none"; | |
| std::vector<std::string> repairitem_names; | |
| std::vector<itype_id> repair_items; | |
| if (fix->made_of("kevlar")) | |
| { | |
| repair_items.push_back("kevlar_plate"); | |
| repairitem_names.push_back(_("kevlar plates")); | |
| } | |
| if (fix->made_of("plastic")) | |
| { | |
| repair_items.push_back("plastic_chunk"); | |
| repairitem_names.push_back(_("plastic chunks")); | |
| } | |
| if (fix->made_of("iron") || fix->made_of("steel")) | |
| { | |
| repair_items.push_back("scrap"); | |
| repairitem_names.push_back(_("scrap metal")); | |
| } | |
| if(repair_items.empty()) | |
| { | |
| g->add_msg_if_player(p,_("Your %s is not made of kevlar, plastic or metal."), fix->tname().c_str()); | |
| return; | |
| } | |
| //repairing or modifying items requires at least 1 repair item, otherwise number is related to size of item | |
| int items_needed=ceil( fix->volume() * 0.25); | |
| // this will cause issues if/when NPCs start being able to sew. | |
| // but, then again, it'll cause issues when they start crafting, too. | |
| inventory crafting_inv = g->crafting_inventory(p); | |
| bool bFound = false; | |
| //go through all discovered repair items and see if we have any of them available | |
| for(unsigned int i = 0; i< repair_items.size(); i++) | |
| { | |
| if (crafting_inv.has_amount(repair_items[i], items_needed)) | |
| { | |
| //we've found enough of a material, use this one | |
| repair_item = repair_items[i]; | |
| bFound = true; | |
| } | |
| } | |
| if (!bFound) | |
| { | |
| for(unsigned int i = 0; i< repair_items.size(); i++) | |
| { | |
| g->add_msg_if_player(p,_("You don't have enough %s to do that."), repairitem_names[i].c_str()); | |
| } | |
| return; | |
| } | |
| if (fix->damage < 0) | |
| { | |
| g->add_msg_if_player(p,_("Your %s is already enhanced."), fix->tname().c_str()); | |
| return; | |
| } | |
| std::vector<component> comps; | |
| comps.push_back(component(repair_item, items_needed)); | |
| comps.back().available = true; | |
| if (fix->damage == 0) | |
| { | |
| p->moves -= 500 * p->fine_detail_vision_mod(g); | |
| p->practice(g->turn, "mechanics", 10); | |
| int rn = dice(4, 2 + p->skillLevel("mechanics")); | |
| if (p->dex_cur < 8 && one_in(p->dex_cur)) | |
| {rn -= rng(2, 6);} | |
| if (p->dex_cur >= 16 || (p->dex_cur > 8 && one_in(16 - p->dex_cur))) | |
| {rn += rng(2, 6);} | |
| if (p->dex_cur > 16) | |
| {rn += rng(0, p->dex_cur - 16);} | |
| if (rn <= 4) | |
| { | |
| g->add_msg_if_player(p,_("You damage your %s!"), fix->tname().c_str()); | |
| fix->damage++; | |
| } | |
| else if (rn >= 12 && p->i_at(ch).has_flag("VARSIZE") && !p->i_at(ch).has_flag("FIT")) | |
| { | |
| g->add_msg_if_player(p,_("You take your %s in, improving the fit."), fix->tname().c_str()); | |
| (p->i_at(ch).item_tags.insert("FIT")); | |
| } | |
| else if (rn >= 12 && (p->i_at(ch).has_flag("FIT") || !p->i_at(ch).has_flag("VARSIZE"))) | |
| { | |
| g->add_msg_if_player(p, _("You make your %s extra sturdy."), fix->tname().c_str()); | |
| fix->damage--; | |
| g->consume_items(p, comps); | |
| } | |
| else | |
| { | |
| g->add_msg_if_player(p,_("You practice your soldering.")); | |
| } | |
| } | |
| else | |
| { | |
| p->moves -= 500 * p->fine_detail_vision_mod(g); | |
| p->practice(g->turn, "mechanics", 8); | |
| int rn = dice(4, 2 + p->skillLevel("mechanics")); | |
| rn -= rng(fix->damage, fix->damage * 2); | |
| if (p->dex_cur < 8 && one_in(p->dex_cur)) | |
| {rn -= rng(2, 6);} | |
| if (p->dex_cur >= 8 && (p->dex_cur >= 16 || one_in(16 - p->dex_cur))) | |
| {rn += rng(2, 6);} | |
| if (p->dex_cur > 16) | |
| {rn += rng(0, p->dex_cur - 16);} | |
| if (rn <= 4) | |
| { | |
| g->add_msg_if_player(p,_("You damage your %s further!"), fix->tname().c_str()); | |
| fix->damage++; | |
| if (fix->damage >= 5) | |
| { | |
| g->add_msg_if_player(p,_("You destroy it!")); | |
| p->i_rem(ch); | |
| } | |
| } | |
| else if (rn <= 6) | |
| { | |
| g->add_msg_if_player(p,_("You don't repair your %s, and you waste lots of charge."), fix->tname().c_str()); | |
| int waste = rng(1, 8); | |
| if (waste > it->charges) | |
| {it->charges = 1;} | |
| else | |
| {it->charges -= waste;} | |
| } | |
| else if (rn <= 8) | |
| { | |
| g->add_msg_if_player(p,_("You repair your %s, but you waste lots of charge."), fix->tname().c_str()); | |
| if (fix->damage>=3) {g->consume_items(p, comps);} | |
| fix->damage--; | |
| int waste = rng(1, 8); | |
| if (waste > it->charges) | |
| {it->charges = 1;} | |
| else | |
| {it->charges -= waste;} | |
| } | |
| else if (rn <= 16) | |
| { | |
| g->add_msg_if_player(p,_("You repair your %s!"), fix->tname().c_str()); | |
| if (fix->damage>=3) {g->consume_items(p, comps);} | |
| fix->damage--; | |
| } | |
| else | |
| { | |
| g->add_msg_if_player(p,_("You repair your %s completely!"), fix->tname().c_str()); | |
| if (fix->damage>=3) {g->consume_items(p, comps);} | |
| fix->damage = 0; | |
| } | |
| } | |
| it->charges -= 1; | |
| } | |
| break; | |
| case 3: | |
| { | |
| } | |
| break; | |
| default: | |
| break; | |
| }; | |
| } | |
| void iuse::water_purifier(game *g, player *p, item *it, bool t) | |
| { | |
| it->charges++; | |
| char ch = g->inv_type(_("Purify what?"), IC_COMESTIBLE); | |
| if (!p->has_item(ch)) { | |
| g->add_msg_if_player(p,_("You do not have that item!")); | |
| return; | |
| } | |
| if (p->i_at(ch).contents.size() == 0) { | |
| g->add_msg_if_player(p,_("You can only purify water.")); | |
| return; | |
| } | |
| item *pure = &(p->i_at(ch).contents[0]); | |
| if (pure->type->id != "water" && pure->type->id != "salt_water") { | |
| g->add_msg_if_player(p,_("You can only purify water.")); | |
| return; | |
| } | |
| if (pure->charges > it->charges) | |
| { | |
| g->add_msg_if_player(p,_("You don't have enough battery power to purify all the water.")); | |
| return; | |
| } | |
| it->charges -= pure->charges; | |
| p->moves -= 150; | |
| pure->make(g->itypes["water_clean"]); | |
| pure->poison = 0; | |
| } | |
| void iuse::two_way_radio(game *g, player *p, item *it, bool t) | |
| { | |
| WINDOW* w = newwin(6, 36, (TERMY-6)/2, (TERMX-36)/2); | |
| wborder(w, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX, | |
| LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX ); | |
| // TODO: More options here. Thoughts... | |
| // > Respond to the SOS of an NPC | |
| // > Report something to a faction | |
| // > Call another player | |
| fold_and_print(w, 1, 1, 999, c_white, | |
| _( | |
| "1: Radio a faction for help...\n" | |
| "2: Call Acquaintance...\n" | |
| "3: General S.O.S.\n" | |
| "0: Cancel")); | |
| wrefresh(w); | |
| char ch = getch(); | |
| if (ch == '1') { | |
| p->moves -= 300; | |
| faction* fac = g->list_factions(_("Call for help...")); | |
| if (fac == NULL) { | |
| it->charges++; | |
| return; | |
| } | |
| int bonus = 0; | |
| if (fac->goal == FACGOAL_CIVILIZATION) | |
| bonus += 2; | |
| if (fac->has_job(FACJOB_MERCENARIES)) | |
| bonus += 4; | |
| if (fac->has_job(FACJOB_DOCTORS)) | |
| bonus += 2; | |
| if (fac->has_value(FACVAL_CHARITABLE)) | |
| bonus += 3; | |
| if (fac->has_value(FACVAL_LONERS)) | |
| bonus -= 3; | |
| if (fac->has_value(FACVAL_TREACHERY)) | |
| bonus -= rng(0, 8); | |
| bonus += fac->respects_u + 3 * fac->likes_u; | |
| if (bonus >= 25) { | |
| popup(_("They reply, \"Help is on the way!\"")); | |
| g->add_event(EVENT_HELP, int(g->turn) + fac->response_time(g), fac->id, -1, -1); | |
| fac->respects_u -= rng(0, 8); | |
| fac->likes_u -= rng(3, 5); | |
| } else if (bonus >= -5) { | |
| popup(_("They reply, \"Sorry, you're on your own!\"")); | |
| fac->respects_u -= rng(0, 5); | |
| } else { | |
| popup(_("They reply, \"Hah! We hope you die!\"")); | |
| fac->respects_u -= rng(1, 8); | |
| } | |
| } else if (ch == '2') { // Call Acquaitance | |
| // TODO: Implement me! | |
| } else if (ch == '3') { // General S.O.S. | |
| p->moves -= 150; | |
| std::vector<npc*> in_range; | |
| for (int i = 0; i < g->cur_om->npcs.size(); i++) { | |
| if (g->cur_om->npcs[i]->op_of_u.value >= 4 && | |
| rl_dist(g->levx, g->levy, g->cur_om->npcs[i]->mapx, | |
| g->cur_om->npcs[i]->mapy) <= 30) | |
| in_range.push_back((g->cur_om->npcs[i])); | |
| } | |
| if (in_range.size() > 0) { | |
| npc* coming = in_range[rng(0, in_range.size() - 1)]; | |
| popup(_("A reply! %s says, \"I'm on my way; give me %d minutes!\""), | |
| coming->name.c_str(), coming->minutes_to_u(g)); | |
| coming->mission = NPC_MISSION_RESCUE_U; | |
| } else | |
| popup(_("No-one seems to reply...")); | |
| } else | |
| it->charges++; // Canceled the call, get our charge back | |
| werase(w); | |
| wrefresh(w); | |
| delwin(w); | |
| refresh(); | |
| } | |
| void iuse::radio_off(game *g, player *p, item *it, bool t) | |
| { | |
| if (it->charges == 0) | |
| g->add_msg_if_player(p,_("It's dead.")); | |
| else { | |
| g->add_msg_if_player(p,_("You turn the radio on.")); | |
| it->make(g->itypes["radio_on"]); | |
| it->active = true; | |
| } | |
| } | |
| static radio_tower *find_radio_station( game *g, int frequency ) | |
| { | |
| radio_tower *tower = NULL; | |
| for (int k = 0; k < g->cur_om->radios.size(); k++) | |
| { | |
| tower = &g->cur_om->radios[k]; | |
| if( 0 < tower->strength - rl_dist(tower->x, tower->y, g->levx, g->levy) && | |
| tower->frequency == frequency ) | |
| { | |
| return tower; | |
| } | |
| } | |
| return NULL; | |
| } | |
| void iuse::directional_antenna(game *g, player *p, item *it, bool t) | |
| { | |
| // Find out if we have an active radio | |
| item radio = p->i_of_type("radio_on"); | |
| if( radio.typeId() != "radio_on" ) | |
| { | |
| g->add_msg( _("Must have an active radio to check for signal sirection.") ); | |
| return; | |
| } | |
| // Find the radio station its tuned to (if any) | |
| radio_tower *tower = find_radio_station( g, radio.frequency ); | |
| if( tower == NULL ) | |
| { | |
| g->add_msg( _("You can't find the direction if your radio isn't tuned.") ); | |
| return; | |
| } | |
| // Report direction. | |
| direction angle = direction_from( g->levx, g->levy, tower->x, tower->y ); | |
| g->add_msg( _("The signal seems strongest to the %s."), direction_name(angle).c_str()); | |
| } | |
| void iuse::radio_on(game *g, player *p, item *it, bool t) | |
| { | |
| if (t) | |
| { // Normal use | |
| std::string message = _("Radio: Kssssssssssssh."); | |
| radio_tower *selected_tower = find_radio_station( g, it->frequency ); | |
| if( selected_tower != NULL ) | |
| { | |
| if( selected_tower->type == MESSAGE_BROADCAST ) | |
| { | |
| message = selected_tower->message; | |
| } | |
| else if (selected_tower->type == WEATHER_RADIO) | |
| { | |
| message = weather_forecast(g, *selected_tower); | |
| } | |
| int signal_strength = selected_tower->strength - | |
| rl_dist(selected_tower->x, selected_tower->y, g->levx, g->levy); | |
| for (int j = 0; j < message.length(); j++) | |
| { | |
| if (dice(10, 100) > dice(10, signal_strength * 3)) | |
| { | |
| if (!one_in(10)) | |
| { | |
| message[j] = '#'; | |
| } | |
| else | |
| { | |
| message[j] = char(rng('a', 'z')); | |
| } | |
| } | |
| } | |
| std::vector<std::string> segments = foldstring(message, RADIO_PER_TURN); | |
| int index = g->turn % (segments.size()); | |
| std::stringstream messtream; | |
| messtream << _("radio: ") << segments[index]; | |
| message = messtream.str(); | |
| } | |
| point pos = g->find_item(it); | |
| g->sound(pos.x, pos.y, 6, message.c_str()); | |
| } else { // Activated | |
| int ch = menu( true, _("Radio:"), _("Scan"), _("Turn off"), NULL ); | |
| switch (ch) | |
| { | |
| case 1: | |
| { | |
| int old_frequency = it->frequency; | |
| radio_tower *tower = NULL; | |
| radio_tower *lowest_tower = NULL; | |
| radio_tower *lowest_larger_tower = NULL; | |
| for (int k = 0; k < g->cur_om->radios.size(); k++) | |
| { | |
| tower = &g->cur_om->radios[k]; | |
| if( 0 < tower->strength - rl_dist(tower->x, tower->y, g->levx, g->levy) && | |
| tower->frequency != old_frequency ) | |
| { | |
| if( tower->frequency > old_frequency && | |
| (lowest_larger_tower == NULL || | |
| tower->frequency < lowest_larger_tower->frequency) ) | |
| { | |
| lowest_larger_tower = tower; | |
| } | |
| else if( lowest_tower == NULL || | |
| tower->frequency < lowest_tower->frequency ) | |
| { | |
| lowest_tower = tower; | |
| } | |
| } | |
| } | |
| if( lowest_larger_tower != NULL ) | |
| { | |
| it->frequency = lowest_larger_tower->frequency; | |
| } | |
| else if( lowest_tower != NULL ) | |
| { | |
| it->frequency = lowest_tower->frequency; | |
| } | |
| } | |
| break; | |
| case 2: | |
| g->add_msg_if_player(p,_("The radio dies.")); | |
| it->make(g->itypes["radio"]); | |
| it->active = false; | |
| break; | |
| case 3: break; | |
| } | |
| } | |
| } | |
| void iuse::noise_emitter_off(game *g, player *p, item *it, bool t) | |
| { | |
| if (it->charges == 0) | |
| { | |
| g->add_msg_if_player(p,_("It's dead.")); | |
| } | |
| else | |
| { | |
| g->add_msg_if_player(p,_("You turn the noise emitter on.")); | |
| it->make(g->itypes["noise_emitter_on"]); | |
| it->active = true; | |
| } | |
| } | |
| void iuse::noise_emitter_on(game *g, player *p, item *it, bool t) | |
| { | |
| if (t) // Normal use | |
| { | |
| point pos = g->find_item(it); | |
| g->sound(pos.x, pos.y, 30, _("KXSHHHHRRCRKLKKK!")); | |
| } | |
| else // Turning it off | |
| { | |
| g->add_msg_if_player(p,_("The infernal racket dies as you turn off the noise emitter.")); | |
| it->make(g->itypes["noise_emitter"]); | |
| it->active = false; | |
| } | |
| } | |
| void iuse::roadmap(game *g, player *p, item *it, bool t) | |
| { | |
| if (it->charges < 1) { | |
| g->add_msg_if_player(p, _("There isn't anything new on the map.")); | |
| return; | |
| } | |
| // Show roads | |
| roadmap_targets(g, p, it, t, (int)ot_hiway_ns, 2, 0, 0); | |
| roadmap_targets(g, p, it, t, (int)ot_road_ns, 12, 0, 0); | |
| roadmap_targets(g, p, it, t, (int)ot_bridge_ns, 2, 0, 0); | |
| // Show evac shelters | |
| roadmap_targets(g, p, it, t, (int)ot_shelter, 1, 0, 0); | |
| // Show hospital(s) | |
| roadmap_targets(g, p, it, t, (int)ot_hospital_entrance, 2, 0, 0); | |
| // Show megastores | |
| roadmap_targets(g, p, it, t, (int)ot_megastore_entrance, 2, 0, 0); | |
| // Show police stations | |
| roadmap_targets(g, p, it, t, (int)ot_police_north, 4, 0, 0); | |
| // Show pharmacies | |
| roadmap_targets(g, p, it, t, (int)ot_s_pharm_north, 4, 0, 0); | |
| g->add_msg_if_player(p, _("You add roads and points of interest to your map.")); | |
| it->charges = 0; | |
| } | |
| void iuse::roadmap_a_target(game *g, player *p, item *it, bool t, int target) | |
| { | |
| int dist = 0; | |
| oter_t oter_target = oterlist[target]; | |
| point place = g->cur_om->find_closest(g->om_location(), (oter_id)target, 1, dist, | |
| false); | |
| int pomx = (g->levx + int(MAPSIZE / 2)) / 2; //overmap loc | |
| int pomy = (g->levy + int(MAPSIZE / 2)) / 2; //overmap loc | |
| if (g->debugmon) debugmsg("Map: %s at %d,%d found! You @ %d %d",oter_target.name.c_str(), place.x, place.y, pomx,pomy); | |
| if (place.x >= 0 && place.y >= 0) { | |
| for (int x = place.x - 3; x <= place.x + 3; x++) { | |
| for (int y = place.y - 3; y <= place.y + 3; y++) | |
| g->cur_om->seen(x, y, g->levz) = true; | |
| } | |
| direction to_hospital = direction_from(pomx,pomy, place.x, place.y); | |
| int distance = trig_dist(pomx,pomy, place.x, place.y); | |
| g->add_msg_if_player(p, _("You add a %s location to your map."), oterlist[target].name.c_str()); | |
| g->add_msg_if_player(p, _("It's %d squares to the %s"), distance, direction_name(to_hospital).c_str()); | |
| } else { | |
| g->add_msg_if_player(p, _("You can't find a hospital near your location.")); | |
| } | |
| } | |
| void iuse::roadmap_targets(game *g, player *p, item *it, bool t, int target, int target_range, int distance, int reveal_distance) | |
| { | |
| oter_t oter_target = oterlist[target]; | |
| point place; | |
| point origin = g->om_location(); | |
| std::vector<point> places = g->cur_om->find_all(tripoint(origin.x, origin.y, g->levz), | |
| (oter_id)target, target_range, distance, false); | |
| for (std::vector<point>::iterator iter = places.begin(); iter != places.end(); ++iter) { | |
| place = *iter; | |
| if (place.x >= 0 && place.y >= 0) { | |
| if (reveal_distance == 0) { | |
| g->cur_om->seen(place.x,place.y,g->levz) = true; | |
| } else { | |
| for (int x = place.x - reveal_distance; x <= place.x + reveal_distance; x++) { | |
| for (int y = place.y - reveal_distance; y <= place.y + reveal_distance; y++) | |
| g->cur_om->seen(x, y,g->levz) = true; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| void iuse::picklock(game *g, player *p, item *it, bool t) | |
| { | |
| int dirx, diry; | |
| if(!g->choose_adjacent(_("Use your pick lock"), dirx, diry)) | |
| return; | |
| if (dirx == p->posx && diry == p->posy) { | |
| g->add_msg_if_player(p, _("You pick your nose and your sinuses swing open.")); | |
| return; | |
| } | |
| ter_id type = g->m.ter(dirx, diry); | |
| int npcdex = g->npc_at(dirx, diry); | |
| if (npcdex != -1) { | |
| g->add_msg_if_player(p, _("You can pick your friends, and you can\npick your nose, but you can't pick\nyour friend's nose")); | |
| return; | |
| } | |
| int pick_quality = 1; | |
| if( it->typeId() == "picklock" ) { | |
| pick_quality = 5; | |
| } | |
| else if( it->typeId() == "crude_picklock" ) { | |
| pick_quality = 3; | |
| } | |
| std::string door_name; | |
| ter_id new_type; | |
| if (type == t_chaingate_l) { | |
| door_name = rm_prefix(_("<door_name>gate")); | |
| new_type = t_chaingate_c; | |
| } else if (type == t_door_locked || type == t_door_locked_alarm || type == t_door_locked_interior) { | |
| door_name = rm_prefix(_("<door_name>door")); | |
| new_type = t_door_c; | |
| } else if (type == t_door_bar_locked) { | |
| door_name = rm_prefix(_("<door_name>door")); | |
| new_type = t_door_bar_o; | |
| g->add_msg_if_player(p, _("The door swings open...")); | |
| } else { | |
| g->add_msg(_("That cannot be picked.")); | |
| return; | |
| } | |
| p->practice(g->turn, "mechanics", 1); | |
| p->moves -= (1000 - (pick_quality * 100)) - (p->dex_cur + p->skillLevel("mechanics")) * 5; | |
| int pick_roll = (dice(2, p->skillLevel("mechanics")) + dice(2, p->dex_cur) - it->damage / 2) * pick_quality; | |
| int door_roll = dice(4, 30); | |
| if (pick_roll >= door_roll) { | |
| p->practice(g->turn, "mechanics", 1); | |
| g->add_msg_if_player(p,_("With a satisfying click, the lock on the %s opens."), door_name.c_str()); | |
| g->m.ter_set(dirx, diry, new_type); | |
| } else if (door_roll > (1.5 * pick_roll) && it->damage < 100) { | |
| it->damage++; | |
| std::string sStatus = rm_prefix(_("<door_status>damage")); | |
| if (it->damage >= 5) { | |
| sStatus = rm_prefix(_("<door_status>destroy")); | |
| it->invlet = 0; // no copy to inventory in player.cpp:4472 -> | |
| } | |
| g->add_msg_if_player(p,"The lock stumps your efforts to pick it, and you %s your tool.", sStatus.c_str()); | |
| } else { | |
| g->add_msg_if_player(p,_("The lock stumps your efforts to pick it.")); | |
| } | |
| if ( type == t_door_locked_alarm && (door_roll + dice(1, 30)) > pick_roll && | |
| it->damage < 100) { | |
| g->sound(p->posx, p->posy, 40, _("An alarm sounds!")); | |
| if (!g->event_queued(EVENT_WANTED)) { | |
| g->add_event(EVENT_WANTED, int(g->turn) + 300, 0, g->levx, g->levy); | |
| } | |
| } | |
| } | |
| void iuse::crowbar(game *g, player *p, item *it, bool t) | |
| { | |
| int dirx, diry; | |
| if(!g->choose_adjacent(_("Pry"), dirx,diry)) | |
| return; | |
| if (dirx == p->posx && diry == p->posy) { | |
| g->add_msg_if_player(p, _("You attempt to pry open your wallet")); | |
| g->add_msg_if_player(p, _("but alas. You are just too miserly.")); | |
| return; | |
| } | |
| ter_id type = g->m.ter(dirx, diry); | |
| const char *succ_action; | |
| const char *fail_action; | |
| ter_id new_type; | |
| bool noisy; | |
| int difficulty; | |
| if (type == t_door_c || type == t_door_locked || type == t_door_locked_alarm || type == t_door_locked_interior) { | |
| succ_action = _("You pry open the door."); | |
| fail_action = _("You pry, but cannot pry open the door."); | |
| new_type = t_door_o; | |
| noisy = true; | |
| difficulty = 6; | |
| } else if (type == t_door_bar_locked) { | |
| succ_action = _("You pry open the door."); | |
| fail_action = _("You pry, but cannot pry open the door."); | |
| new_type = t_door_bar_o; | |
| noisy = false; | |
| difficulty = 10; | |
| } else if (type == t_manhole_cover) { | |
| succ_action = _("You lift the manhole cover."); | |
| fail_action = _("You pry, but cannot lift the manhole cover."); | |
| new_type = t_manhole; | |
| noisy = false; | |
| difficulty = 12; | |
| } else if (g->m.furn(dirx, diry) == f_crate_c) { | |
| succ_action = _("You pop open the crate."); | |
| fail_action = _("You pry, but cannot pop open the crate."); | |
| noisy = true; | |
| difficulty = 6; | |
| } else if (type == t_window_domestic || type == t_curtains) { | |
| succ_action = _("You pry open the window."); | |
| fail_action = _("You pry, but cannot pry open the window."); | |
| new_type = t_window_open; | |
| noisy = true; | |
| difficulty = 6; | |
| } else { | |
| int nails = 0, boards = 0; | |
| ter_id newter; | |
| switch (g->m.ter(dirx, diry)) { | |
| case t_window_boarded: | |
| nails = 8; | |
| boards = 4; | |
| newter = t_window_empty; | |
| break; | |
| case t_door_boarded: | |
| nails = 12; | |
| boards = 4; | |
| newter = t_door_b; | |
| break; | |
| case t_fence_h: | |
| nails = 6; | |
| boards = 3; | |
| newter = t_fence_post; | |
| break; | |
| case t_fence_v: | |
| nails = 6; | |
| boards = 3; | |
| newter = t_fence_post; | |
| break; | |
| default: | |
| g->add_msg_if_player(p,_("There's nothing to pry there.")); | |
| return; | |
| } | |
| if(p->skillLevel("carpentry") < 1) | |
| p->practice(g->turn, "carpentry", 1); | |
| p->moves -= 500; | |
| g->m.spawn_item(p->posx, p->posy, "nail", 0, 0, nails); | |
| g->m.spawn_item(p->posx, p->posy, "2x4", 0, boards); | |
| g->m.ter_set(dirx, diry, newter); | |
| return; | |
| } | |
| p->practice(g->turn, "mechanics", 1); | |
| p->moves -= (difficulty * 25) - ((p->str_cur + p->skillLevel("mechanics")) * 5); | |
| if (dice(4, difficulty) < dice(2, p->skillLevel("mechanics")) + dice(2, p->str_cur)) { | |
| p->practice(g->turn, "mechanics", 1); | |
| g->add_msg_if_player(p, succ_action); | |
| if (g->m.furn(dirx, diry) == f_crate_c) | |
| g->m.furn_set(dirx, diry, f_crate_o); | |
| else | |
| g->m.ter_set(dirx, diry, new_type); | |
| if (noisy) | |
| g->sound(dirx, diry, 12, _("crunch!")); | |
| if ( type == t_door_locked_alarm ) { | |
| g->sound(p->posx, p->posy, 40, _("An alarm sounds!")); | |
| if (!g->event_queued(EVENT_WANTED)) { | |
| g->add_event(EVENT_WANTED, int(g->turn) + 300, 0, g->levx, g->levy); | |
| } | |
| } | |
| } else { | |
| if (type == t_window_domestic || type == t_curtains) { | |
| //chance of breaking the glass if pry attempt fails | |
| if (dice(4, difficulty) > dice(2, p->skillLevel("mechanics")) + dice(2, p->str_cur)) { | |
| g->add_msg_if_player(p,_("You break the glass.")); | |
| g->sound(dirx, diry, 24, _("glass breaking!")); | |
| g->m.ter_set(dirx, diry, t_window_frame); | |
| g->m.spawn_item(dirx, diry, "sheet", 0, 2); | |
| g->m.spawn_item(dirx, diry, "stick", 0); | |
| g->m.spawn_item(dirx, diry, "string_36", 0); | |
| return; | |
| } | |
| } | |
| g->add_msg_if_player(p, fail_action); | |
| } | |
| } | |
| void iuse::makemound(game *g, player *p, item *it, bool t) | |
| { | |
| if (g->m.has_flag(diggable, p->posx, p->posy)) { | |
| g->add_msg_if_player(p,_("You churn up the earth here.")); | |
| p->moves = -300; | |
| g->m.ter_set(p->posx, p->posy, t_dirtmound); | |
| } else | |
| g->add_msg_if_player(p,_("You can't churn up this ground.")); | |
| } | |
| //TODO remove this? | |
| void iuse::dig(game *g, player *p, item *it, bool t) | |
| { | |
| g->add_msg_if_player(p,_("You can dig a pit via the construction menu--hit *")); | |
| } | |
| void iuse::siphon(game *g, player *p, item *it, bool t) | |
| { | |
| int posx = 0; | |
| int posy = 0; | |
| if(!g->choose_adjacent(_("Siphon from"), posx, posy)) | |
| return; | |
| vehicle* veh = g->m.veh_at(posx, posy); | |
| if (veh == NULL) | |
| { | |
| g->add_msg_if_player(p,_("There's no vehicle there.")); | |
| return; | |
| } | |
| if (veh->fuel_left("gasoline") == 0) | |
| { | |
| g->add_msg_if_player(p, _("That vehicle has no fuel to siphon.")); | |
| return; | |
| } | |
| p->siphon(g, veh, "gasoline"); | |
| p->moves -= 200; | |
| return; | |
| } | |
| void iuse::chainsaw_off(game *g, player *p, item *it, bool t) | |
| { | |
| p->moves -= 80; | |
| if (rng(0, 10) - it->damage > 5 && it->charges > 0) { | |
| g->sound(p->posx, p->posy, 20, | |
| _("With a roar, the chainsaw leaps to life!")); | |
| it->make(g->itypes["chainsaw_on"]); | |
| it->active = true; | |
| } else | |
| g->add_msg_if_player(p,_("You yank the cord, but nothing happens.")); | |
| } | |
| void iuse::chainsaw_on(game *g, player *p, item *it, bool t) | |
| { | |
| if (t) { // Effects while simply on | |
| if (one_in(15)) | |
| g->sound(p->posx, p->posy, 12, _("Your chainsaw rumbles.")); | |
| } else { // Toggling | |
| g->add_msg_if_player(p,_("Your chainsaw dies.")); | |
| it->make(g->itypes["chainsaw_off"]); | |
| it->active = false; | |
| } | |
| } | |
| void iuse::jackhammer(game *g, player *p, item *it, bool t) | |
| { | |
| int dirx, diry; | |
| if(!g->choose_adjacent(_("Drill"),dirx,diry)) | |
| return; | |
| if (dirx == p->posx && diry == p->posy) { | |
| g->add_msg_if_player(p,_("My god! Let's talk it over OK?")); | |
| g->add_msg_if_player(p,_("Don't do anything rash..")); | |
| return; | |
| } | |
| if (g->m.is_destructable(dirx, diry) && g->m.has_flag(supports_roof, dirx, diry) && | |
| g->m.ter(dirx, diry) != t_tree) { | |
| g->m.destroy(g, dirx, diry, false); | |
| p->moves -= 500; | |
| g->sound(dirx, diry, 45, _("TATATATATATATAT!")); | |
| } else if (g->m.move_cost(dirx, diry) == 2 && g->levz != -1 && | |
| g->m.ter(dirx, diry) != t_dirt && g->m.ter(dirx, diry) != t_grass) { | |
| g->m.destroy(g, dirx, diry, false); | |
| p->moves -= 500; | |
| g->sound(dirx, diry, 45, _("TATATATATATATAT!")); | |
| } else { | |
| g->add_msg_if_player(p,_("You can't drill there.")); | |
| it->charges += (dynamic_cast<it_tool*>(it->type))->charges_per_use; | |
| } | |
| } | |
| void iuse::jacqueshammer(game *g, player *p, item *it, bool t) | |
| { | |
| int dirx, diry; | |
| g->draw(); | |
| mvprintw(0, 0, _("Percer dans quelle direction?")); | |
| get_direction(g, dirx, diry, input()); | |
| if (dirx == -2) { | |
| g->add_msg_if_player(p,_("Direction invalide")); | |
| return; | |
| } | |
| if (dirx == 0 && diry == 0) { | |
| g->add_msg_if_player(p,_("Mon dieu! Nous allons en parler OK?")); | |
| g->add_msg_if_player(p,_("Ne pas faire eruption rien..")); | |
| return; | |
| } | |
| dirx += p->posx; | |
| diry += p->posy; | |
| if (g->m.is_destructable(dirx, diry) && g->m.has_flag(supports_roof, dirx, diry) && | |
| g->m.ter(dirx, diry) != t_tree) { | |
| g->m.destroy(g, dirx, diry, false); | |
| p->moves -= 500; | |
| g->sound(dirx, diry, 45, _("OHOHOHOHOHOHOHOHO!")); | |
| } else if (g->m.move_cost(dirx, diry) == 2 && g->levz != -1 && | |
| g->m.ter(dirx, diry) != t_dirt && g->m.ter(dirx, diry) != t_grass) { | |
| g->m.destroy(g, dirx, diry, false); | |
| p->moves -= 500; | |
| g->sound(dirx, diry, 45, _("OHOHOHOHOHOHOHOHO!")); | |
| } else { | |
| g->add_msg_if_player(p,_("Vous ne pouvez pas percer la-bas..")); | |
| it->charges += (dynamic_cast<it_tool*>(it->type))->charges_per_use; | |
| } | |
| } | |
| void iuse::pickaxe(game *g, player *p, item *it, bool t) | |
| { | |
| g->add_msg_if_player(p,_("Whoa buddy! You can't go cheating in items and")); | |
| g->add_msg_if_player(p,_("just expect them to work! Now put the pickaxe")); | |
| g->add_msg_if_player(p,_("down and go play the game.")); | |
| } | |
| void iuse::set_trap(game *g, player *p, item *it, bool t) | |
| { | |
| int dirx, diry; | |
| if(!g->choose_adjacent(_("Place trap"),dirx,diry)) | |
| return; | |
| if (dirx == p->posx && diry == p->posy) { | |
| g->add_msg_if_player(p,_("Yeah. Place the %s at your feet."), it->tname().c_str()); | |
| g->add_msg_if_player(p,_("Real damn smart move.")); | |
| return; | |
| } | |
| int posx = dirx; | |
| int posy = diry; | |
| if (g->m.move_cost(posx, posy) != 2) { | |
| g->add_msg_if_player(p,_("You can't place a %s there."), it->tname().c_str()); | |
| return; | |
| } | |
| if (g->m.tr_at(posx, posy) != tr_null) { | |
| g->add_msg_if_player(p, _("You can't place a %s there. It contains a trap already."), it->tname().c_str()); | |
| return; | |
| } | |
| trap_id type = tr_null; | |
| ter_id ter; | |
| bool buried = false; | |
| bool set = false; | |
| std::stringstream message; | |
| int practice; | |
| if(it->type->id == "cot"){ | |
| message << _("You unfold the cot and place it on the ground."); | |
| type = tr_cot; | |
| practice = 0; | |
| } else if(it->type->id == "rollmat"){ | |
| message << _("You unroll the mat and lay it on the ground."); | |
| type = tr_rollmat; | |
| practice = 0; | |
| } else if(it->type->id == "brazier"){ | |
| message << _("You place the brazier securely."); | |
| type = tr_brazier; | |
| practice = 0; | |
| } else if(it->type->id == "boobytrap"){ | |
| message << _("You set the boobytrap up and activate the grenade."); | |
| type = tr_boobytrap; | |
| practice = 4; | |
| } else if(it->type->id == "bubblewrap"){ | |
| message << _("You set the bubblewrap on the ground, ready to be popped."); | |
| type = tr_bubblewrap; | |
| practice = 2; | |
| } else if(it->type->id == "beartrap"){ | |
| buried = (p->has_amount("shovel", 1) && | |
| g->m.has_flag(diggable, posx, posy) && | |
| query_yn(_("Bury the beartrap?"))); | |
| type = (buried ? tr_beartrap_buried : tr_beartrap); | |
| message << (buried ? _("You bury the beartrap.") : _("You set the beartrap.")) ; | |
| practice = (buried ? 7 : 4); | |
| } else if(it->type->id == "board_trap"){ | |
| message << string_format("You set the board trap on the %s, nails facing up.", g->m.tername(posx, posy).c_str()); | |
| type = tr_nailboard; | |
| practice = 2; | |
| } else if(it->type->id == "funnel"){ | |
| message << _("You place the funnel, waiting to collect rain."); | |
| type = tr_funnel; | |
| practice = 0; | |
| } else if(it->type->id == "tripwire"){ | |
| // Must have a connection between solid squares. | |
| if ((g->m.move_cost(posx , posy - 1) != 2 && | |
| g->m.move_cost(posx , posy + 1) != 2 ) || | |
| (g->m.move_cost(posx + 1, posy ) != 2 && | |
| g->m.move_cost(posx - 1, posy ) != 2 ) || | |
| (g->m.move_cost(posx - 1, posy - 1) != 2 && | |
| g->m.move_cost(posx + 1, posy + 1) != 2 ) || | |
| (g->m.move_cost(posx + 1, posy - 1) != 2 && | |
| g->m.move_cost(posx - 1, posy + 1) != 2 )) { | |
| message << _("You string up the tripwire."); | |
| type= tr_tripwire; | |
| practice = 3; | |
| } else { | |
| g->add_msg_if_player(p,_("You must place the tripwire between two solid tiles.")); | |
| return; | |
| } | |
| } else if(it->type->id == "crossbow_trap"){ | |
| message << _("You set the crossbow trap."); | |
| type = tr_crossbow; | |
| practice = 4; | |
| } else if(it->type->id == "shotgun_trap"){ | |
| message << _("You set the shotgun trap."); | |
| type = tr_shotgun_2; | |
| practice = 5; | |
| } else if(it->type->id == "blade_trap"){ | |
| posx = (dirx - p->posx)*2 + p->posx; //math correction for blade trap | |
| posy = (diry - p->posy)*2 + p->posy; | |
| for (int i = -1; i <= 1; i++) { | |
| for (int j = -1; j <= 1; j++) { | |
| if (g->m.move_cost(posx + i, posy + j) != 2) { | |
| g->add_msg_if_player(p,_("That trap needs a 3x3 space to be clear, centered two tiles from you.")); | |
| return; | |
| } | |
| } | |
| } | |
| message << _("You set the blade trap two squares away."); | |
| type = tr_engine; | |
| practice = 12; | |
| } else if(it->type->id == "light_snare_kit"){ | |
| for(int i = -1; i <= 1; i++) { | |
| for(int j = -1; j <= 1; j++){ | |
| ter = g->m.ter(posx+j, posy+i); | |
| if(ter == t_tree_young && !set) { | |
| message << _("You set the snare trap."); | |
| type = tr_light_snare; | |
| practice = 2; | |
| set = true; | |
| } | |
| } | |
| } | |
| if(!set) { | |
| g->add_msg_if_player(p, _("Invalid Placement.")); | |
| return; | |
| } | |
| } else if(it->type->id == "heavy_snare_kit"){ | |
| for(int i = -1; i <= 1; i++) { | |
| for(int j = -1; j <= 1; j++){ | |
| ter = g->m.ter(posx+j, posy+i); | |
| if(ter == t_tree && !set) { | |
| message << _("You set the snare trap."); | |
| type = tr_heavy_snare; | |
| practice = 4; | |
| set = true; | |
| } | |
| } | |
| } | |
| if(!set) { | |
| g->add_msg_if_player(p, _("Invalid Placement.")); | |
| return; | |
| } | |
| } else if(it->type->id == "landmine"){ | |
| buried = (p->has_amount("shovel", 1) && | |
| g->m.has_flag(diggable, posx, posy) && | |
| query_yn(_("Bury the landmine?"))); | |
| type = (buried ? tr_landmine_buried : tr_landmine); | |
| message << (buried ? _("You bury the landmine.") : _("You set the landmine.")); | |
| practice = (buried ? 7 : 4); | |
| } else { | |
| g->add_msg_if_player(p,_("Tried to set a trap. But got confused! %s"), it->tname().c_str()); | |
| } | |
| if (buried) { | |
| if (!p->has_amount("shovel", 1)) { | |
| g->add_msg_if_player(p,_("You need a shovel.")); | |
| return; | |
| } else if (!g->m.has_flag(diggable, posx, posy)) { | |
| g->add_msg_if_player(p,_("You can't dig in that %s"), g->m.tername(posx, posy).c_str()); | |
| return; | |
| } | |
| } | |
| g->add_msg_if_player(p,message.str().c_str()); | |
| p->practice(g->turn, "traps", practice); | |
| g->m.add_trap(posx, posy, type); | |
| p->moves -= 100 + practice * 25; | |
| if (type == tr_engine) { | |
| for (int i = -1; i <= 1; i++) { | |
| for (int j = -1; j <= 1; j++) { | |
| if (i != 0 || j != 0) | |
| g->m.add_trap(posx + i, posy + j, tr_blade); | |
| } | |
| } | |
| } | |
| it->invlet = 0; // Remove the trap from the player's inv | |
| } | |
| void iuse::geiger(game *g, player *p, item *it, bool t) | |
| { | |
| if (t) { // Every-turn use when it's on | |
| int rads = g->m.radiation(p->posx, p->posy); | |
| if (rads == 0) | |
| return; | |
| g->sound(p->posx, p->posy, 6, ""); | |
| if (rads > 50) | |
| g->add_msg(_("The geiger counter buzzes intensely.")); | |
| else if (rads > 35) | |
| g->add_msg(_("The geiger counter clicks wildly.")); | |
| else if (rads > 25) | |
| g->add_msg(_("The geiger counter clicks rapidly.")); | |
| else if (rads > 15) | |
| g->add_msg(_("The geiger counter clicks steadily.")); | |
| else if (rads > 8) | |
| g->add_msg(_("The geiger counter clicks slowly.")); | |
| else if (rads > 4) | |
| g->add_msg(_("The geiger counter clicks intermittantly.")); | |
| else | |
| g->add_msg(_("The geiger counter clicks once.")); | |
| return; | |
| } | |
| // Otherwise, we're activating the geiger counter | |
| it_tool *type = dynamic_cast<it_tool*>(it->type); | |
| bool is_on = (type->id == "geiger_on"); | |
| if (is_on) { | |
| g->add_msg(_("The geiger counter's SCANNING LED flicks off.")); | |
| it->make(g->itypes["geiger_off"]); | |
| it->active = false; | |
| return; | |
| } | |
| std::string toggle_text = is_on ? _("Turn continuous scan off") : _("Turn continuous scan on"); | |
| int ch = menu(true, _("Geiger counter:"), _("Scan yourself"), _("Scan the ground"), | |
| toggle_text.c_str(), _("Cancel"), NULL); | |
| switch (ch) { | |
| case 1: g->add_msg_if_player(p,_("Your radiation level: %d"), p->radiation); break; | |
| case 2: g->add_msg_if_player(p,_("The ground's radiation level: %d"), | |
| g->m.radiation(p->posx, p->posy)); break; | |
| case 3: | |
| g->add_msg_if_player(p,_("The geiger counter's scan LED flicks on.")); | |
| it->make(g->itypes["geiger_on"]); | |
| it->active = true; | |
| break; | |
| case 4: | |
| it->charges++; | |
| break; | |
| } | |
| } | |
| void iuse::teleport(game *g, player *p, item *it, bool t) | |
| { | |
| p->moves -= 100; | |
| g->teleport(p); | |
| } | |
| void iuse::can_goo(game *g, player *p, item *it, bool t) | |
| { | |
| it->make(g->itypes["canister_empty"]); | |
| int tries = 0, goox, gooy; | |
| do { | |
| goox = p->posx + rng(-2, 2); | |
| gooy = p->posy + rng(-2, 2); | |
| tries++; | |
| } while (g->m.move_cost(goox, gooy) == 0 && tries < 10); | |
| if (tries == 10) | |
| return; | |
| int mondex = g->mon_at(goox, gooy); | |
| if (mondex != -1) { | |
| if (g->u_see(goox, gooy)) | |
| g->add_msg(_("Black goo emerges from the canister and envelopes a %s!"), | |
| g->z[mondex].name().c_str()); | |
| g->z[mondex].poly(g->mtypes[mon_blob]); | |
| g->z[mondex].speed -= rng(5, 25); | |
| g->z[mondex].hp = g->z[mondex].speed; | |
| } else { | |
| if (g->u_see(goox, gooy)) | |
| g->add_msg(_("Living black goo emerges from the canister!")); | |
| monster goo(g->mtypes[mon_blob]); | |
| goo.friendly = -1; | |
| goo.spawn(goox, gooy); | |
| g->z.push_back(goo); | |
| } | |
| tries = 0; | |
| while (!one_in(4) && tries < 10) { | |
| tries = 0; | |
| do { | |
| goox = p->posx + rng(-2, 2); | |
| gooy = p->posy + rng(-2, 2); | |
| tries++; | |
| } while (g->m.move_cost(goox, gooy) == 0 && | |
| g->m.tr_at(goox, gooy) == tr_null && tries < 10); | |
| if (tries < 10) { | |
| if (g->u_see(goox, gooy)) | |
| g->add_msg(_("A nearby splatter of goo forms into a goo pit.")); | |
| g->m.tr_at(goox, gooy) = tr_goo; | |
| } | |
| } | |
| } | |
| void iuse::pipebomb(game *g, player *p, item *it, bool t) | |
| { | |
| if (!p->use_charges_if_avail("fire", 1)) { | |
| g->add_msg_if_player(p,_("You need a lighter!")); | |
| return; | |
| } | |
| g->add_msg_if_player(p,_("You light the fuse on the pipe bomb.")); | |
| it->make(g->itypes["pipebomb_act"]); | |
| it->charges = 3; | |
| it->active = true; | |
| } | |
| void iuse::pipebomb_act(game *g, player *p, item *it, bool t) | |
| { | |
| point pos = g->find_item(it); | |
| if (pos.x == -999 || pos.y == -999) | |
| return; | |
| if (t) // Simple timer effects | |
| g->sound(pos.x, pos.y, 0, _("Ssssss")); // Vol 0 = only heard if you hold it | |
| else { // The timer has run down | |
| if (one_in(10) && g->u_see(pos.x, pos.y)) | |
| g->add_msg(_("The pipe bomb fizzles out.")); | |
| else | |
| g->explosion(pos.x, pos.y, rng(6, 14), rng(0, 4), false); | |
| } | |
| } | |
| void iuse::grenade(game *g, player *p, item *it, bool t) | |
| { | |
| g->add_msg_if_player(p,_("You pull the pin on the grenade.")); | |
| it->make(g->itypes["grenade_act"]); | |
| it->charges = 5; | |
| it->active = true; | |
| } | |
| void iuse::grenade_act(game *g, player *p, item *it, bool t) | |
| { | |
| point pos = g->find_item(it); | |
| if (pos.x == -999 || pos.y == -999) | |
| return; | |
| if (t) // Simple timer effects | |
| g->sound(pos.x, pos.y, 0, _("Tick.")); // Vol 0 = only heard if you hold it | |
| else // When that timer runs down... | |
| g->explosion(pos.x, pos.y, 12, 28, false); | |
| } | |
| void iuse::flashbang(game *g, player *p, item *it, bool t) | |
| { | |
| g->add_msg_if_player(p,_("You pull the pin on the flashbang.")); | |
| it->make(g->itypes["flashbang_act"]); | |
| it->charges = 5; | |
| it->active = true; | |
| } | |
| void iuse::flashbang_act(game *g, player *p, item *it, bool t) | |
| { | |
| point pos = g->find_item(it); | |
| if (pos.x == -999 || pos.y == -999) | |
| return; | |
| if (t) // Simple timer effects | |
| g->sound(pos.x, pos.y, 0, _("Tick.")); // Vol 0 = only heard if you hold it | |
| else // When that timer runs down... | |
| g->flashbang(pos.x, pos.y); | |
| } | |
| void iuse::c4(game *g, player *p, item *it, bool t) | |
| { | |
| int time = query_int(_("Set the timer to (0 to cancel)?")); | |
| if (time == 0) { | |
| g->add_msg_if_player(p,"Never mind."); | |
| return; | |
| } | |
| g->add_msg_if_player(p,_("You set the timer to %d."), time); | |
| it->make(g->itypes["c4armed"]); | |
| it->charges = time; | |
| it->active = true; | |
| } | |
| void iuse::c4armed(game *g, player *p, item *it, bool t) | |
| { | |
| point pos = g->find_item(it); | |
| if (pos.x == -999 || pos.y == -999) | |
| return; | |
| if (t) // Simple timer effects | |
| g->sound(pos.x, pos.y, 0, _("Tick.")); // Vol 0 = only heard if you hold it | |
| else // When that timer runs down... | |
| g->explosion(pos.x, pos.y, 40, 3, false); | |
| } | |
| void iuse::EMPbomb(game *g, player *p, item *it, bool t) | |
| { | |
| g->add_msg_if_player(p,_("You pull the pin on the EMP grenade.")); | |
| it->make(g->itypes["EMPbomb_act"]); | |
| it->charges = 3; | |
| it->active = true; | |
| } | |
| void iuse::EMPbomb_act(game *g, player *p, item *it, bool t) | |
| { | |
| point pos = g->find_item(it); | |
| if (pos.x == -999 || pos.y == -999) | |
| return; | |
| if (t) // Simple timer effects | |
| g->sound(pos.x, pos.y, 0, _("Tick.")); // Vol 0 = only heard if you hold it | |
| else { // When that timer runs down... | |
| for (int x = pos.x - 4; x <= pos.x + 4; x++) { | |
| for (int y = pos.y - 4; y <= pos.y + 4; y++) | |
| g->emp_blast(x, y); | |
| } | |
| } | |
| } | |
| void iuse::scrambler(game *g, player *p, item *it, bool t) | |
| { | |
| g->add_msg_if_player(p,_("You pull the pin on the scrambler grenade.")); | |
| it->make(g->itypes["scrambler_act"]); | |
| it->charges = 3; | |
| it->active = true; | |
| } | |
| void iuse::scrambler_act(game *g, player *p, item *it, bool t) | |
| { | |
| point pos = g->find_item(it); | |
| if (pos.x == -999 || pos.y == -999) | |
| return; | |
| if (t) // Simple timer effects | |
| g->sound(pos.x, pos.y, 0, _("Tick.")); // Vol 0 = only heard if you hold it | |
| else { // When that timer runs down... | |
| for (int x = pos.x - 4; x <= pos.x + 4; x++) { | |
| for (int y = pos.y - 4; y <= pos.y + 4; y++) | |
| g->scrambler_blast(x, y); | |
| } | |
| } | |
| } | |
| void iuse::gasbomb(game *g, player *p, item *it, bool t) | |
| { | |
| g->add_msg_if_player(p,_("You pull the pin on the teargas canister.")); | |
| it->make(g->itypes["gasbomb_act"]); | |
| it->charges = 20; | |
| it->active = true; | |
| } | |
| void iuse::gasbomb_act(game *g, player *p, item *it, bool t) | |
| { | |
| point pos = g->find_item(it); | |
| if (pos.x == -999 || pos.y == -999) | |
| return; | |
| if (t) { | |
| if (it->charges > 15) | |
| g->sound(pos.x, pos.y, 0, _("Tick.")); // Vol 0 = only heard if you hold it | |
| else { | |
| int junk; | |
| for (int i = -2; i <= 2; i++) { | |
| for (int j = -2; j <= 2; j++) { | |
| if (g->m.sees(pos.x, pos.y, pos.x + i, pos.y + j, 3, junk) && | |
| g->m.move_cost(pos.x + i, pos.y + j) > 0) | |
| g->m.add_field(g, pos.x + i, pos.y + j, fd_tear_gas, 3); | |
| } | |
| } | |
| } | |
| } else | |
| it->make(g->itypes["canister_empty"]); | |
| } | |
| void iuse::smokebomb(game *g, player *p, item *it, bool t) | |
| { | |
| g->add_msg_if_player(p,_("You pull the pin on the smoke bomb.")); | |
| it->make(g->itypes["smokebomb_act"]); | |
| it->charges = 20; | |
| it->active = true; | |
| } | |
| void iuse::smokebomb_act(game *g, player *p, item *it, bool t) | |
| { | |
| point pos = g->find_item(it); | |
| if (pos.x == -999 || pos.y == -999) | |
| return; | |
| if (t) { | |
| if (it->charges > 17) | |
| g->sound(pos.x, pos.y, 0, _("Tick.")); // Vol 0 = only heard if you hold it | |
| else { | |
| int junk; | |
| for (int i = -2; i <= 2; i++) { | |
| for (int j = -2; j <= 2; j++) { | |
| if (g->m.sees(pos.x, pos.y, pos.x + i, pos.y + j, 3, junk) && | |
| g->m.move_cost(pos.x + i, pos.y + j) > 0) | |
| g->m.add_field(g, pos.x + i, pos.y + j, fd_smoke, rng(1, 2) + rng(0, 1)); | |
| } | |
| } | |
| } | |
| } else | |
| it->make(g->itypes["canister_empty"]); | |
| } | |
| void iuse::acidbomb(game *g, player *p, item *it, bool t) | |
| { | |
| g->add_msg_if_player(p,_("You remove the divider, and the chemicals mix.")); | |
| p->moves -= 150; | |
| it->make(g->itypes["acidbomb_act"]); | |
| it->charges = 1; | |
| it->bday = int(g->turn); | |
| it->active = true; | |
| } | |
| void iuse::acidbomb_act(game *g, player *p, item *it, bool t) | |
| { | |
| if (!p->has_item(it)) { | |
| point pos = g->find_item(it); | |
| if (pos.x == -999) | |
| pos = point(p->posx, p->posy); | |
| it->charges = 0; | |
| for (int x = pos.x - 1; x <= pos.x + 1; x++) { | |
| for (int y = pos.y - 1; y <= pos.y + 1; y++) | |
| g->m.add_field(g, x, y, fd_acid, 3); | |
| } | |
| } | |
| } | |
| void iuse::arrow_flamable(game *g, player *p, item *it, bool t) | |
| { | |
| if (!p->use_charges_if_avail("fire", 1)) | |
| { | |
| g->add_msg_if_player(p,_("You need a lighter!")); | |
| return; | |
| } | |
| g->add_msg_if_player(p,_("You light the arrow!.")); | |
| p->moves -= 150; | |
| it->make(g->itypes["arrow_flamming"]); | |
| } | |
| void iuse::molotov(game *g, player *p, item *it, bool t) | |
| { | |
| if (!p->use_charges_if_avail("fire", 1)) | |
| { | |
| g->add_msg_if_player(p,_("You need a lighter!")); | |
| return; | |
| } | |
| g->add_msg_if_player(p,_("You light the molotov cocktail.")); | |
| p->moves -= 150; | |
| it->make(g->itypes["molotov_lit"]); | |
| it->charges = 1; | |
| it->bday = int(g->turn); | |
| it->active = true; | |
| } | |
| void iuse::molotov_lit(game *g, player *p, item *it, bool t) | |
| { | |
| int age = int(g->turn) - it->bday; | |
| if (!p->has_item(it)) { | |
| point pos = g->find_item(it); | |
| it->charges = -1; | |
| g->explosion(pos.x, pos.y, 8, 0, true); | |
| } else if (age >= 5) { // More than 5 turns old = chance of going out | |
| if (rng(1, 50) < age) { | |
| g->add_msg_if_player(p,_("Your lit molotov goes out.")); | |
| it->make(g->itypes["molotov"]); | |
| it->charges = 0; | |
| it->active = false; | |
| } | |
| } | |
| } | |
| void iuse::dynamite(game *g, player *p, item *it, bool t) | |
| { | |
| if (!p->use_charges_if_avail("fire", 1)) | |
| { | |
| it->charges++; | |
| g->add_msg_if_player(p,_("You need a lighter!")); | |
| return; | |
| } | |
| g->add_msg_if_player(p,_("You light the dynamite.")); | |
| it->make(g->itypes["dynamite_act"]); | |
| it->charges = 20; | |
| it->active = true; | |
| } | |
| void iuse::dynamite_act(game *g, player *p, item *it, bool t) | |
| { | |
| point pos = g->find_item(it); | |
| if (pos.x == -999 || pos.y == -999) | |
| return; | |
| if (t) // Simple timer effects | |
| g->sound(pos.x, pos.y, 0, _("ssss...")); | |
| else // When that timer runs down... | |
| g->explosion(pos.x, pos.y, 60, 0, false); | |
| } | |
| void iuse::firecracker_pack(game *g, player *p, item *it, bool t) | |
| { | |
| if (!p->use_charges_if_avail("fire", 1)) | |
| { | |
| g->add_msg_if_player(p,_("You need a lighter!")); | |
| return; | |
| } | |
| WINDOW* w = newwin(5, 41, (TERMY-5)/2, (TERMX-41)/2); | |
| wborder(w, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX, | |
| LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX ); | |
| int mid_x = getmaxx(w) / 2; | |
| int tmpx = 5; | |
| mvwprintz(w, 1, 2, c_white, _("How many do you want to light? (1-%d)"), it->charges); | |
| mvwprintz(w, 2, mid_x, c_white, "1"); | |
| tmpx += shortcut_print(w, 3, tmpx, c_white, c_ltred, _("<I>ncrease"))+1; | |
| tmpx += shortcut_print(w, 3, tmpx, c_white, c_ltred, _("<D>ecrease"))+1; | |
| tmpx += shortcut_print(w, 3, tmpx, c_white, c_ltred, _("<A>ccept"))+1; | |
| tmpx += shortcut_print(w, 3, tmpx, c_white, c_ltred, _("<C>ancel"))+1; | |
| wrefresh(w); | |
| bool close = false; | |
| int charges = 1; | |
| char ch = getch(); | |
| while(!close) { | |
| if(ch == 'I') { | |
| charges++; | |
| if(charges > it->charges) { | |
| charges = it->charges; | |
| } | |
| mvwprintz(w, 2, mid_x, c_white, "%d", charges); | |
| wrefresh(w); | |
| } else if(ch == 'D') { | |
| charges--; | |
| if(charges < 1) { | |
| charges = 1; | |
| } | |
| mvwprintz(w, 2, mid_x, c_white, "%d ", charges); //Trailing space clears the second digit when decreasing from 10 to 9 | |
| wrefresh(w); | |
| } else if(ch == 'A') { | |
| if(charges == it->charges) { | |
| g->add_msg_if_player(p,_("You light the pack of firecrackers.")); | |
| it->make(g->itypes["firecracker_pack_act"]); | |
| it->charges = charges; | |
| it->bday = g->turn; | |
| it->active = true; | |
| } else { | |
| if(charges == 1) { | |
| g->add_msg_if_player(p,_("You light one firecracker.")); | |
| item new_it = item(g->itypes["firecracker_act"], int(g->turn)); | |
| new_it.charges = 2; | |
| new_it.active = true; | |
| p->i_add(new_it, g); | |
| it->charges -= 1; | |
| } else { | |
| g->add_msg_if_player(p,_("You light a string of %d firecrackers."), charges); | |
| item new_it = item(g->itypes["firecracker_pack_act"], int(g->turn)); | |
| new_it.charges = charges; | |
| new_it.bday = g->turn; | |
| new_it.active = true; | |
| p->i_add(new_it, g); | |
| it->charges -= charges; | |
| } | |
| if(it->charges == 1) { | |
| it->make(g->itypes["firecracker"]); | |
| } | |
| } | |
| close = true; | |
| } else if(ch == 'C') { | |
| close = true; | |
| } | |
| if(!close) { | |
| ch = getch(); | |
| } | |
| } | |
| } | |
| void iuse::firecracker_pack_act(game *g, player *p, item *it, bool t) | |
| { | |
| point pos = g->find_item(it); | |
| int current_turn = g->turn; | |
| int timer = current_turn - it->bday; | |
| if(timer < 2) { | |
| g->sound(pos.x, pos.y, 0, _("ssss...")); | |
| it->damage += 1; | |
| } else if(it->charges > 0) { | |
| int ex = rng(3,5); | |
| int i = 0; | |
| if(ex > it->charges) { | |
| ex = it->charges; | |
| } | |
| for(i = 0; i < ex; i++) { | |
| g->sound(pos.x, pos.y, 20, _("Bang!")); | |
| } | |
| it->charges -= ex; | |
| } | |
| } | |
| void iuse::firecracker(game *g, player *p, item *it, bool t) | |
| { | |
| if (!p->use_charges_if_avail("fire", 1)) | |
| { | |
| g->add_msg_if_player(p,_("You need a lighter!")); | |
| return; | |
| } | |
| g->add_msg_if_player(p,_("You light the firecracker.")); | |
| it->make(g->itypes["firecracker_act"]); | |
| it->charges = 2; | |
| it->active = true; | |
| } | |
| void iuse::firecracker_act(game *g, player *p, item *it, bool t) | |
| { | |
| point pos = g->find_item(it); | |
| if (pos.x == -999 || pos.y == -999) | |
| return; | |
| if (t) {// Simple timer effects | |
| g->sound(pos.x, pos.y, 0, _("ssss...")); | |
| } else { // When that timer runs down... | |
| g->sound(pos.x, pos.y, 20, _("Bang!")); | |
| } | |
| } | |
| void iuse::mininuke(game *g, player *p, item *it, bool t) | |
| { | |
| g->add_msg_if_player(p,_("You activate the mininuke.")); | |
| it->make(g->itypes["mininuke_act"]); | |
| it->charges = 10; | |
| it->active = true; | |
| } | |
| void iuse::mininuke_act(game *g, player *p, item *it, bool t) | |
| { | |
| point pos = g->find_item(it); | |
| if (pos.x == -999 || pos.y == -999) | |
| return; | |
| if (t) // Simple timer effects | |
| g->sound(pos.x, pos.y, 2, _("Tick.")); | |
| else { // When that timer runs down... | |
| g->explosion(pos.x, pos.y, 200, 0, false); | |
| int junk; | |
| for (int i = -4; i <= 4; i++) { | |
| for (int j = -4; j <= 4; j++) { | |
| if (g->m.sees(pos.x, pos.y, pos.x + i, pos.y + j, 3, junk) && | |
| g->m.move_cost(pos.x + i, pos.y + j) > 0) | |
| g->m.add_field(g, pos.x + i, pos.y + j, fd_nuke_gas, 3); | |
| } | |
| } | |
| } | |
| } | |
| void iuse::pheromone(game *g, player *p, item *it, bool t) | |
| { | |
| point pos(p->posx, p->posy); | |
| if (pos.x == -999 || pos.y == -999) | |
| return; | |
| g->add_msg_player_or_npc( p, _("You squeeze the pheremone ball.."), | |
| _("<npcname> squeezes the pheremone ball...") ); | |
| p->moves -= 15; | |
| int converts = 0; | |
| for (int x = pos.x - 4; x <= pos.x + 4; x++) { | |
| for (int y = pos.y - 4; y <= pos.y + 4; y++) { | |
| int mondex = g->mon_at(x, y); | |
| if (mondex != -1 && g->z[mondex].symbol() == 'Z' && | |
| g->z[mondex].friendly == 0 && rng(0, 500) > g->z[mondex].hp) { | |
| converts++; | |
| g->z[mondex].make_friendly(); | |
| } | |
| } | |
| } | |
| if (g->u_see(p)) { | |
| if (converts == 0) | |
| g->add_msg(_("...but nothing happens.")); | |
| else if (converts == 1) | |
| g->add_msg(_("...and a nearby zombie turns friendly!")); | |
| else | |
| g->add_msg(_("...and several nearby zombies turn friendly!")); | |
| } | |
| } | |
| void iuse::portal(game *g, player *p, item *it, bool t) | |
| { | |
| g->m.add_trap(p->posx + rng(-2, 2), p->posy + rng(-2, 2), tr_portal); | |
| } | |
| void iuse::manhack(game *g, player *p, item *it, bool t) | |
| { | |
| std::vector<point> valid; // Valid spawn locations | |
| for (int x = p->posx - 1; x <= p->posx + 1; x++) { | |
| for (int y = p->posy - 1; y <= p->posy + 1; y++) { | |
| if (g->is_empty(x, y)) | |
| valid.push_back(point(x, y)); | |
| } | |
| } | |
| if (valid.size() == 0) { // No valid points! | |
| g->add_msg_if_player(p,_("There is no adjacent square to release the manhack in!")); | |
| return; | |
| } | |
| int index = rng(0, valid.size() - 1); | |
| p->moves -= 60; | |
| it->invlet = 0; // Remove the manhack from the player's inv | |
| monster m_manhack(g->mtypes[mon_manhack], valid[index].x, valid[index].y); | |
| if (rng(0, p->int_cur / 2) + p->skillLevel("electronics") / 2 + | |
| p->skillLevel("computer") < rng(0, 4)) | |
| g->add_msg_if_player(p,_("You misprogram the manhack; it's hostile!")); | |
| else | |
| m_manhack.friendly = -1; | |
| g->z.push_back(m_manhack); | |
| } | |
| void iuse::turret(game *g, player *p, item *it, bool t) | |
| { | |
| int dirx, diry; | |
| if(!g->choose_adjacent(_("Place the turret"), dirx, diry)) | |
| return; | |
| if (!g->is_empty(dirx, diry)) { | |
| g->add_msg_if_player(p,_("You cannot place a turret there.")); | |
| return; | |
| } | |
| p->moves -= 100; | |
| it->invlet = 0; // Remove the turret from the player's inv | |
| monster mturret(g->mtypes[mon_turret], dirx, diry); | |
| if (rng(0, p->int_cur / 2) + p->skillLevel("electronics") / 2 + | |
| p->skillLevel("computer") < rng(0, 6)) | |
| g->add_msg_if_player(p,_("You misprogram the turret; it's hostile!")); | |
| else | |
| mturret.friendly = -1; | |
| g->z.push_back(mturret); | |
| } | |
| void iuse::UPS_off(game *g, player *p, item *it, bool t) | |
| { | |
| if (it->charges == 0) | |
| g->add_msg_if_player(p,_("The power supply's batteries are dead.")); | |
| else { | |
| g->add_msg_if_player(p,_("You turn the power supply on.")); | |
| if (p->is_wearing("goggles_nv")) | |
| g->add_msg_if_player(p,_("Your light amp goggles power on.")); | |
| if (p->worn.size() && p->worn[0].type->is_power_armor()) | |
| g->add_msg_if_player(p, _("Your power armor engages.")); | |
| it->make(g->itypes["UPS_on"]); | |
| it->active = true; | |
| } | |
| } | |
| void iuse::UPS_on(game *g, player *p, item *it, bool t) | |
| { | |
| if (t) { // Normal use | |
| if (p->worn.size() && p->worn[0].type->is_power_armor()) { | |
| it->charges -= 4; | |
| if (it->charges < 0) { | |
| it->charges = 0; | |
| } | |
| } | |
| } else { // Turning it off | |
| g->add_msg_if_player(p,_("The UPS powers off with a soft hum.")); | |
| if (p->worn.size() && p->worn[0].type->is_power_armor()) | |
| g->add_msg_if_player(p, _("Your power armor disengages.")); | |
| it->make(g->itypes["UPS_off"]); | |
| it->active = false; | |
| } | |
| } | |
| void iuse::adv_UPS_off(game *g, player *p, item *it, bool t) | |
| { | |
| if (it->charges == 0) | |
| g->add_msg_if_player(p,_("The power supply has depleted the plutonium.")); | |
| else { | |
| g->add_msg_if_player(p,_("You turn the power supply on.")); | |
| if (p->is_wearing("goggles_nv")) | |
| g->add_msg_if_player(p,_("Your light amp goggles power on.")); | |
| if (p->worn.size() && p->worn[0].type->is_power_armor()) | |
| g->add_msg_if_player(p, _("Your power armor engages.")); | |
| it->make(g->itypes["adv_UPS_on"]); | |
| it->active = true; | |
| } | |
| } | |
| void iuse::adv_UPS_on(game *g, player *p, item *it, bool t) | |
| { | |
| if (t) { // Normal use | |
| if (p->worn.size() && p->worn[0].type->is_power_armor()) { | |
| it->charges -= 2; | |
| if (it->charges < 0) { | |
| it->charges = 0; | |
| } | |
| } | |
| } else { // Turning it off | |
| g->add_msg_if_player(p,_("The advanced UPS powers off with a soft hum.")); | |
| if (p->worn.size() && p->worn[0].type->is_power_armor()) | |
| g->add_msg_if_player(p, _("Your power armor disengages.")); | |
| it->make(g->itypes["adv_UPS_off"]); | |
| it->active = false; | |
| } | |
| } | |
| void iuse::tazer(game *g, player *p, item *it, bool t) | |
| { | |
| int dirx, diry; | |
| if(!g->choose_adjacent(_("Shock"),dirx,diry)){ | |
| it->charges += (dynamic_cast<it_tool*>(it->type))->charges_per_use; | |
| return; | |
| } | |
| if (dirx == p->posx && diry == p->posy) { | |
| g->add_msg_if_player(p,_("Umm. No.")); | |
| it->charges += (dynamic_cast<it_tool*>(it->type))->charges_per_use; | |
| return; | |
| } | |
| int mondex = g->mon_at(dirx, diry); | |
| int npcdex = g->npc_at(dirx, diry); | |
| if (mondex == -1 && npcdex == -1) { | |
| g->add_msg_if_player(p,_("Your tazer crackles in the air.")); | |
| return; | |
| } | |
| int numdice = 3 + (p->dex_cur / 2.5) + p->skillLevel("melee") * 2; | |
| p->moves -= 100; | |
| if (mondex != -1) { | |
| monster *z = &(g->z[mondex]); | |
| switch (z->type->size) { | |
| case MS_TINY: numdice -= 2; break; | |
| case MS_SMALL: numdice -= 1; break; | |
| case MS_LARGE: numdice += 2; break; | |
| case MS_HUGE: numdice += 4; break; | |
| } | |
| int mondice = z->dodge(); | |
| if (dice(numdice, 10) < dice(mondice, 10)) { // A miss! | |
| g->add_msg_if_player(p,_("You attempt to shock the %s, but miss."), z->name().c_str()); | |
| return; | |
| } | |
| g->add_msg_if_player(p,_("You shock the %s!"), z->name().c_str()); | |
| int shock = rng(5, 25); | |
| z->moves -= shock * 100; | |
| if (z->hurt(shock)) | |
| g->kill_mon(mondex, (p == &(g->u))); | |
| return; | |
| } | |
| if (npcdex != -1) { | |
| npc *foe = g->active_npc[npcdex]; | |
| if (foe->attitude != NPCATT_FLEE) | |
| foe->attitude = NPCATT_KILL; | |
| if (foe->str_max >= 17) | |
| numdice++; // Minor bonus against huge people | |
| else if (foe->str_max <= 5) | |
| numdice--; // Minor penalty against tiny people | |
| if (dice(numdice, 10) <= dice(foe->dodge(g), 6)) { | |
| g->add_msg_if_player(p,_("You attempt to shock %s, but miss."), foe->name.c_str()); | |
| return; | |
| } | |
| g->add_msg_if_player(p,_("You shock %s!"), foe->name.c_str()); | |
| int shock = rng(5, 20); | |
| foe->moves -= shock * 100; | |
| foe->hurtall(shock); | |
| if (foe->hp_cur[hp_head] <= 0 || foe->hp_cur[hp_torso] <= 0) { | |
| foe->die(g, true); | |
| g->active_npc.erase(g->active_npc.begin() + npcdex); | |
| } | |
| } | |
| } | |
| void iuse::mp3(game *g, player *p, item *it, bool t) | |
| { | |
| if (it->charges == 0) | |
| g->add_msg_if_player(p,_("The mp3 player's batteries are dead.")); | |
| else if (p->has_active_item("mp3_on")) | |
| g->add_msg_if_player(p,_("You are already listening to an mp3 player!")); | |
| else { | |
| g->add_msg_if_player(p,_("You put in the earbuds and start listening to music.")); | |
| it->make(g->itypes["mp3_on"]); | |
| it->active = true; | |
| } | |
| } | |
| void iuse::mp3_on(game *g, player *p, item *it, bool t) | |
| { | |
| if (t) { // Normal use | |
| if (!p->has_item(it) || p->has_disease("deaf") ) | |
| return; // We're not carrying it, or we're deaf. | |
| p->add_morale(MORALE_MUSIC, 1, 50); | |
| if (int(g->turn) % 10 == 0) { // Every 10 turns, describe the music | |
| std::string sound = ""; | |
| if (one_in(50)) | |
| sound = _("some bass-heavy post-glam speed polka"); | |
| switch (rng(1, 10)) { | |
| case 1: sound = _("a sweet guitar solo!"); p->stim++; break; | |
| case 2: sound = _("a funky bassline."); break; | |
| case 3: sound = _("some amazing vocals."); break; | |
| case 4: sound = _("some pumping bass."); break; | |
| case 5: sound = _("dramatic classical music."); | |
| if (p->int_cur >= 10) | |
| p->add_morale(MORALE_MUSIC, 1, 100); break; | |
| } | |
| if (sound.length() > 0) | |
| g->add_msg_if_player(p,_("You listen to %s"), sound.c_str()); | |
| } | |
| } else { // Turning it off | |
| g->add_msg_if_player(p,_("The mp3 player turns off.")); | |
| it->make(g->itypes["mp3"]); | |
| it->active = false; | |
| } | |
| } | |
| void iuse::vortex(game *g, player *p, item *it, bool t) | |
| { | |
| std::vector<point> spawn; | |
| for (int i = -3; i <= 3; i++) { | |
| if (g->is_empty(p->posx - 3, p->posy + i)) | |
| spawn.push_back( point(p->posx - 3, p->posy + i) ); | |
| if (g->is_empty(p->posx + 3, p->posy + i)) | |
| spawn.push_back( point(p->posx + 3, p->posy + i) ); | |
| if (g->is_empty(p->posx + i, p->posy - 3)) | |
| spawn.push_back( point(p->posx + i, p->posy - 3) ); | |
| if (g->is_empty(p->posx + i, p->posy + 3)) | |
| spawn.push_back( point(p->posx + i, p->posy + 3) ); | |
| } | |
| if (spawn.empty()) { | |
| g->add_msg_if_player(p,_("Air swirls around you for a moment.")); | |
| it->make(g->itypes["spiral_stone"]); | |
| return; | |
| } | |
| g->add_msg_if_player(p,_("Air swirls all over...")); | |
| int index = rng(0, spawn.size() - 1); | |
| p->moves -= 100; | |
| it->make(g->itypes["spiral_stone"]); | |
| monster mvortex(g->mtypes[mon_vortex], spawn[index].x, spawn[index].y); | |
| mvortex.friendly = -1; | |
| g->z.push_back(mvortex); | |
| } | |
| void iuse::dog_whistle(game *g, player *p, item *it, bool t) | |
| { | |
| g->add_msg_if_player(p,_("You blow your dog whistle.")); | |
| for (int i = 0; i < g->z.size(); i++) { | |
| if (g->z[i].friendly != 0 && g->z[i].type->id == mon_dog) { | |
| bool u_see = g->u_see(&(g->z[i])); | |
| if (g->z[i].has_effect(ME_DOCILE)) { | |
| if (u_see) | |
| g->add_msg_if_player(p,_("Your %s looks ready to attack."), g->z[i].name().c_str()); | |
| g->z[i].rem_effect(ME_DOCILE); | |
| } else { | |
| if (u_see) | |
| g->add_msg_if_player(p,_("Your %s goes docile."), g->z[i].name().c_str()); | |
| g->z[i].add_effect(ME_DOCILE, -1); | |
| } | |
| } | |
| } | |
| } | |
| void iuse::vacutainer(game *g, player *p, item *it, bool t) | |
| { | |
| if (p->is_npc()) | |
| return; // No NPCs for now! | |
| if (!it->contents.empty()) { | |
| g->add_msg_if_player(p,_("That %s is full!"), it->tname().c_str()); | |
| return; | |
| } | |
| item blood(g->itypes["blood"], g->turn); | |
| bool drew_blood = false; | |
| for (int i = 0; i < g->m.i_at(p->posx, p->posy).size() && !drew_blood; i++) { | |
| item *map_it = &(g->m.i_at(p->posx, p->posy)[i]); | |
| if (map_it->type->id == "corpse" && | |
| query_yn(_("Draw blood from %s?"), map_it->tname().c_str())) { | |
| blood.corpse = map_it->corpse; | |
| drew_blood = true; | |
| } | |
| } | |
| if (!drew_blood && query_yn(_("Draw your own blood?"))) | |
| drew_blood = true; | |
| if (!drew_blood) | |
| return; | |
| it->put_in(blood); | |
| } | |
| void iuse::knife(game *g, player *p, item *it, bool t) | |
| { | |
| int choice = menu(true, | |
| _("Using knife:"), _("Cut up fabric"), _("Cut up plastic/kevlar"), _("Carve wood"), _("Cauterize"), _("Carve writing on item"), _("Cancel"), NULL); | |
| switch (choice) | |
| { | |
| if (choice == 5) | |
| break; | |
| case 1: | |
| { | |
| iuse::scissors(g, p, it, t); | |
| } | |
| break; | |
| case 2: | |
| { | |
| char ch = g->inv(_("Chop up what?")); | |
| item* cut = &(p->i_at(ch)); | |
| int amount = 0; | |
| if (cut->type->id == "null") | |
| { | |
| g->add_msg(_("You do not have that item!")); | |
| return; | |
| } | |
| if(cut->made_of("plastic")) | |
| { | |
| //if we're going to cut up a bottle, make sure it isn't full of liquid | |
| amount = cut->volume(); | |
| if(cut->is_container()) | |
| { | |
| if(cut->is_food_container()) | |
| { | |
| g->add_msg(_("That container has liquid in it!")); | |
| break; | |
| } | |
| } | |
| if(amount == 0) | |
| { | |
| g->add_msg(_("This object is too small to salvage a meaningful quantity of plastic from!")); | |
| break; | |
| } | |
| g->add_msg(ngettext("You cut the %1$s into one %2$i chunk.","You cut the %1$s into %2$i plastic chunks.", amount), cut->tname().c_str(), amount); | |
| int count = amount; | |
| item result(g->itypes["plastic_chunk"], int(g->turn), g->nextinv); | |
| p->i_rem(ch); | |
| bool drop = false; | |
| for (int i = 0; i < count; i++) | |
| { | |
| int iter = 0; | |
| while (p->has_item(result.invlet) && iter < inv_chars.size()) | |
| { | |
| result.invlet = g->nextinv; | |
| g->advance_nextinv(); | |
| iter++; | |
| } | |
| if (!drop && (iter == inv_chars.size() || p->volume_carried() >= p->volume_capacity())) | |
| drop = true; | |
| if (drop) | |
| g->m.add_item_or_charges(p->posx, p->posy, result); | |
| else | |
| p->i_add(result); | |
| } | |
| } | |
| else if(cut->made_of("kevlar")) | |
| { | |
| amount = cut->volume(); | |
| if(amount == 0) | |
| { | |
| g->add_msg(_("This object is too small to salvage a meaningful quantity of kevlar from!")); | |
| break; | |
| } | |
| g->add_msg(ngettext("You cut the %1$s into one %2$i chunk.","You cut the %1$s into %2$i plastic chunks.", amount), cut->tname().c_str(), amount); | |
| int count = amount; | |
| item result(g->itypes["kevlar_plate"], int(g->turn), g->nextinv); | |
| p->i_rem(ch); | |
| bool drop = false; | |
| for (int i = 0; i < count; i++) | |
| { | |
| int iter = 0; | |
| while (p->has_item(result.invlet) && iter < inv_chars.size()) | |
| { | |
| result.invlet = g->nextinv; | |
| g->advance_nextinv(); | |
| iter++; | |
| } | |
| if (!drop && (iter == inv_chars.size() || p->volume_carried() >= p->volume_capacity())) | |
| drop = true; | |
| if (drop) | |
| g->m.add_item_or_charges(p->posx, p->posy, result); | |
| else | |
| p->i_add(result); | |
| } | |
| } | |
| else | |
| { | |
| g->add_msg(_("You can't carve that up!")); | |
| } | |
| } | |
| break; | |
| case 3: | |
| { | |
| char ch = g->inv(_("Chop up what?")); | |
| item* cut = &(p->i_at(ch)); | |
| if (cut->type->id == "null") | |
| { | |
| g->add_msg(_("You do not have that item!")); | |
| return; | |
| } | |
| if (cut->type->id == "stick" || cut->type->id == "2x4") | |
| { | |
| g->add_msg(_("You carve several skewers from the %s."), cut->tname().c_str()); | |
| int count = 12; | |
| item skewer(g->itypes["skewer"], int(g->turn), g->nextinv); | |
| p->i_rem(ch); | |
| bool drop = false; | |
| for (int i = 0; i < count; i++) | |
| { | |
| int iter = 0; | |
| while (p->has_item(skewer.invlet) && iter < inv_chars.size()) | |
| { | |
| skewer.invlet = g->nextinv; | |
| g->advance_nextinv(); | |
| iter++; | |
| } | |
| if (!drop && (iter == inv_chars.size() || p->volume_carried() >= p->volume_capacity())) | |
| drop = true; | |
| if (drop) | |
| g->m.add_item_or_charges(p->posx, p->posy, skewer); | |
| else | |
| p->i_add(skewer); | |
| } | |
| } | |
| else | |
| { | |
| g->add_msg(_("You can't carve that up!")); | |
| } | |
| } | |
| break; | |
| case 4: | |
| { | |
| if (!p->has_disease("bite") && !p->has_disease("bleed")) | |
| g->add_msg_if_player(p,_("You are not bleeding or bitten, there is no need to cauterize yourself.")); | |
| else if (!p->use_charges_if_avail("fire", 4)) | |
| g->add_msg_if_player(p,_("You need a lighter with 4 charges before you can cauterize yourself.")); | |
| else | |
| p->cauterize(g); | |
| break; | |
| } | |
| case 5: | |
| { | |
| inscribe_item( g, p, _("Carve"), _("Carved"), true ); | |
| break; | |
| } | |
| } | |
| } | |
| void iuse::cut_log_into_planks(game *g, player *p, item *it) | |
| { | |
| p->moves -= 300; | |
| g->add_msg(_("You cut the log into planks.")); | |
| item plank(g->itypes["2x4"], int(g->turn), g->nextinv); | |
| item scrap(g->itypes["splinter"], int(g->turn), g->nextinv); | |
| bool drop = false; | |
| int planks = (rng(1, 3) + (p->skillLevel("carpentry") * 2)); | |
| int scraps = 12 - planks; | |
| if (planks >= 12) { | |
| planks = 12; | |
| } | |
| if (scraps >= planks) { | |
| g->add_msg(_("You waste a lot of the wood.")); | |
| } | |
| for (int i = 0; i < planks; i++) { | |
| int iter = 0; | |
| while (p->has_item(plank.invlet)) { | |
| plank.invlet = g->nextinv; | |
| g->advance_nextinv(); | |
| iter++; | |
| } | |
| if (!drop && (iter == inv_chars.size() || p->volume_carried() >= p->volume_capacity())) { | |
| drop = true; | |
| } | |
| if (drop) { | |
| g->m.add_item_or_charges(p->posx, p->posy, plank); | |
| } else { | |
| p->i_add(plank); | |
| } | |
| } | |
| for (int i = 0; i < scraps; i++) { | |
| int iter = 0; | |
| while (p->has_item(scrap.invlet)) { | |
| scrap.invlet = g->nextinv; | |
| g->advance_nextinv(); | |
| iter++; | |
| } | |
| if (!drop && (iter == inv_chars.size() || p->volume_carried() >= p->volume_capacity())) | |
| drop = true; | |
| if (drop) | |
| g->m.add_item_or_charges(p->posx, p->posy, scrap); | |
| else | |
| p->i_add(scrap); | |
| } | |
| } | |
| void iuse::lumber(game *g, player *p, item *it, bool t) | |
| { | |
| char ch = g->inv(_("Cut up what?")); | |
| item* cut = &(p->i_at(ch)); | |
| if (cut->type->id == "null") { | |
| g->add_msg(_("You do not have that item!")); | |
| return; | |
| } | |
| if (cut->type->id == "log") { | |
| p->i_rem(ch); | |
| cut_log_into_planks(g, p, it); | |
| return; | |
| } else { | |
| g->add_msg(_("You can't cut that up!")); | |
| } return; | |
| } | |
| void iuse::hacksaw(game *g, player *p, item *it, bool t) | |
| { | |
| int dirx, diry; | |
| if(!g->choose_adjacent(_("Cut up metal"), dirx, diry)) | |
| return; | |
| if (dirx == p->posx && diry == p->posy) { | |
| g->add_msg(_("Why would you do that?")); | |
| g->add_msg(_("You're not even chained to a boiler.")); | |
| return; | |
| } | |
| if (g->m.ter(dirx, diry) == t_chainfence_v || g->m.ter(dirx, diry) == t_chainfence_h || g->m.ter(dirx, diry) == t_chaingate_c) { | |
| p->moves -= 500; | |
| g->m.ter_set(dirx, diry, t_dirt); | |
| g->sound(dirx, diry, 15,_("grnd grnd grnd")); | |
| g->m.spawn_item(dirx, diry, "pipe", 0, 6); | |
| g->m.spawn_item(dirx, diry, "wire", 0, 20); | |
| if (g->m.ter(dirx, diry) == t_chainfence_posts) { | |
| p->moves -= 500; | |
| g->m.ter_set(dirx, diry, t_dirt); | |
| g->sound(dirx, diry, 15,_("grnd grnd grnd")); | |
| g->m.spawn_item(dirx, diry, "pipe", 0, 6); | |
| } else if (g->m.furn(dirx, diry) == f_rack) { | |
| p->moves -= 500; | |
| g->m.furn_set(dirx, diry, f_null); | |
| g->sound(dirx, diry, 15,_("grnd grnd grnd")); | |
| g->m.spawn_item(p->posx, p->posy, "pipe", 0, rng(1, 3)); | |
| g->m.spawn_item(p->posx, p->posy, "steel_chunk", 0); | |
| } else if (g->m.ter(dirx, diry) == t_bars && | |
| (g->m.ter(dirx + 1, diry) == t_sewage || g->m.ter(dirx, diry + 1) == t_sewage || | |
| g->m.ter(dirx - 1, diry) == t_sewage || g->m.ter(dirx, diry - 1) == t_sewage)) { | |
| g->m.ter_set(dirx, diry, t_sewage); | |
| p->moves -= 1000; | |
| g->sound(dirx, diry, 15,_("grnd grnd grnd")); | |
| g->m.spawn_item(p->posx, p->posy, "pipe", 0, 3); | |
| } else if (g->m.ter(dirx, diry) == t_bars && g->m.ter(p->posx, p->posy)) { | |
| g->m.ter_set(dirx, diry, t_floor); | |
| p->moves -= 500; | |
| g->sound(dirx, diry, 15,_("grnd grnd grnd")); | |
| g->m.spawn_item(p->posx, p->posy, "pipe", 0, 3); | |
| } else { | |
| g->add_msg(_("You can't cut that.")); | |
| } | |
| } | |
| } | |
| void iuse::tent(game *g, player *p, item *it, bool t) | |
| { | |
| int dirx, diry; | |
| if(!g->choose_adjacent(_("Pitch the tent"), dirx, diry)) | |
| return; | |
| //must place the center of the tent two spaces away from player | |
| //dirx and diry will be integratined with the player's position | |
| int posx = dirx - p->posx; | |
| int posy = diry - p->posy; | |
| if(posx == 0 && posy == 0){ | |
| g->add_msg_if_player(p,_("Invalid Direction")); | |
| return; | |
| } | |
| posx = posx*2 + p->posx; | |
| posy = posy*2 + p->posy; | |
| for (int i = -1; i <= 1; i++) | |
| for (int j = -1; j <= 1; j++) | |
| if (!g->m.has_flag(flat, posx + i, posy + j) || | |
| g->m.has_furn(posx + i, posy + j)) { | |
| g->add_msg(_("You need a 3x3 flat space to place a tent")); | |
| return; | |
| } | |
| for (int i = -1; i <= 1; i++) | |
| for (int j = -1; j <= 1; j++) | |
| g->m.furn_set(posx + i, posy + j, f_canvas_wall); | |
| g->m.furn_set(posx, posy, f_groundsheet); | |
| g->m.furn_set(posx - (dirx - p->posx), posy - (diry - p->posy), f_canvas_door); | |
| it->invlet = 0; | |
| } | |
| void iuse::shelter(game *g, player *p, item *it, bool t) | |
| { | |
| int dirx, diry; | |
| if(!g->choose_adjacent(_("Put up the shelter"), dirx, diry)) | |
| return; | |
| //must place the center of the tent two spaces away from player | |
| //dirx and diry will be integratined with the player's position | |
| int posx = dirx - p->posx; | |
| int posy = diry - p->posy; | |
| if(posx == 0 && posy == 0){ | |
| g->add_msg_if_player(p,_("Invalid Direction")); | |
| return; | |
| } | |
| posx = posx*2 + p->posx; | |
| posy = posy*2 + p->posy; | |
| for (int i = -1; i <= 1; i++) | |
| for (int j = -1; j <= 1; j++) | |
| if (!g->m.has_flag(flat, posx + i, posy + j) || | |
| g->m.has_furn(posx + i, posy + j)) { | |
| g->add_msg(_("You need a 3x3 flat space to place a shelter")); | |
| return; | |
| } | |
| for (int i = -1; i <= 1; i++) | |
| for (int j = -1; j <= 1; j++) | |
| g->m.furn_set(posx + i, posy + j, f_skin_wall); | |
| g->m.furn_set(posx, posy, f_skin_groundsheet); | |
| g->m.furn_set(posx - (dirx - p->posx), posy - (diry - p->posy), f_skin_door); | |
| it->invlet = 0; | |
| } | |
| void iuse::torch(game *g, player *p, item *it, bool t) | |
| { | |
| if (!p->use_charges_if_avail("fire", 1)) | |
| { | |
| g->add_msg_if_player(p,_("You need a lighter or fire to light this.")); | |
| } | |
| else | |
| { | |
| g->add_msg_if_player(p,_("You light the torch.")); | |
| it->make(g->itypes["torch_lit"]); | |
| it->active = true; | |
| } | |
| } | |
| void iuse::torch_lit(game *g, player *p, item *it, bool t) | |
| { | |
| if (t) { // Normal use | |
| // Do nothing... player::active_light and the lightmap::generate deal with this | |
| } else { // Turning it off | |
| g->add_msg_if_player(p,_("The torch is extinguished")); | |
| it->charges -= 1; | |
| it->make(g->itypes["torch"]); | |
| it->active = false; | |
| } | |
| } | |
| void iuse::candle(game *g, player *p, item *it, bool t) | |
| { | |
| if (!p->use_charges_if_avail("fire", 1)) | |
| { | |
| g->add_msg_if_player(p, _("You need a lighter to light this.")); | |
| } | |
| else | |
| { | |
| g->add_msg_if_player(p, _("You light the candle.")); | |
| it->make(g->itypes["candle_lit"]); | |
| it->active = true; | |
| } | |
| } | |
| void iuse::candle_lit(game *g, player *p, item *it, bool t) | |
| { | |
| if (t) { // Normal use | |
| // Do nothing... player::active_light and the lightmap::generate deal with this | |
| } else { // Turning it off | |
| g->add_msg_if_player(p,_("The candle winks out")); | |
| it->make(g->itypes["candle"]); | |
| it->active = false; | |
| } | |
| } | |
| void iuse::bullet_puller(game *g, player *p, item *it, bool t) | |
| { | |
| char ch = g->inv(_("Disassemble what?")); | |
| item* pull = &(p->i_at(ch)); | |
| if (pull->type->id == "null") { | |
| g->add_msg(_("You do not have that item!")); | |
| return; | |
| } | |
| if (p->skillLevel("gun") < 2) { | |
| g->add_msg(_("You need to be at least level 2 in the firearms skill before you\ | |
| can disassemble ammunition.")); | |
| return;} | |
| int multiply = pull->charges; | |
| if (multiply > 20) | |
| multiply = 20; | |
| item casing; | |
| item primer; | |
| item gunpowder; | |
| item lead; | |
| if (pull->type->id == "556_incendiary" || pull->type->id == "3006_incendiary" || | |
| pull->type->id == "762_51_incendiary") | |
| lead.make(g->itypes["incendiary"]); | |
| else | |
| lead.make(g->itypes["lead"]); | |
| if (pull->type->id == "shot_bird") { | |
| casing.make(g->itypes["shot_hull"]); | |
| primer.make(g->itypes["shotgun_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 12*multiply; | |
| lead.charges = 16*multiply; | |
| } | |
| else if (pull->type->id == "shot_00" || pull->type->id == "shot_slug") { | |
| casing.make(g->itypes["shot_hull"]); | |
| primer.make(g->itypes["shotgun_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 20*multiply; | |
| lead.charges = 16*multiply; | |
| } | |
| else if (pull->type->id == "22_lr" || pull->type->id == "22_ratshot") { | |
| casing.make(g->itypes["22_casing"]); | |
| primer.make(g->itypes["smrifle_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 2*multiply; | |
| lead.charges = 2*multiply; | |
| } | |
| else if (pull->type->id == "22_cb") { | |
| casing.make(g->itypes["22_casing"]); | |
| primer.make(g->itypes["smrifle_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 1*multiply; | |
| lead.charges = 2*multiply; | |
| } | |
| else if (pull->type->id == "9mm") { | |
| casing.make(g->itypes["9mm_casing"]); | |
| primer.make(g->itypes["smpistol_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 4*multiply; | |
| lead.charges = 4*multiply; | |
| } | |
| else if (pull->type->id == "9mmP") { | |
| casing.make(g->itypes["9mm_casing"]); | |
| primer.make(g->itypes["smpistol_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 5*multiply; | |
| lead.charges = 4*multiply; | |
| } | |
| else if (pull->type->id == "9mmP2") { | |
| casing.make(g->itypes["9mm_casing"]); | |
| primer.make(g->itypes["smpistol_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 6*multiply; | |
| lead.charges = 4*multiply; | |
| } | |
| else if (pull->type->id == "38_special") { | |
| casing.make(g->itypes["38_casing"]); | |
| primer.make(g->itypes["smpistol_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 5*multiply; | |
| lead.charges = 5*multiply; | |
| } | |
| else if (pull->type->id == "38_super") { | |
| casing.make(g->itypes["38_casing"]); | |
| primer.make(g->itypes["smpistol_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 7*multiply; | |
| lead.charges = 5*multiply; | |
| } | |
| else if (pull->type->id == "10mm") { | |
| casing.make(g->itypes["40_casing"]); | |
| primer.make(g->itypes["lgpistol_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 8*multiply; | |
| lead.charges = 8*multiply; | |
| } | |
| else if (pull->type->id == "40sw") { | |
| casing.make(g->itypes["40_casing"]); | |
| primer.make(g->itypes["smpistol_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 6*multiply; | |
| lead.charges = 6*multiply; | |
| } | |
| else if (pull->type->id == "44magnum") { | |
| casing.make(g->itypes["44_casing"]); | |
| primer.make(g->itypes["lgpistol_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 10*multiply; | |
| lead.charges = 10*multiply; | |
| } | |
| else if (pull->type->id == "45_acp" || | |
| pull->type->id == "45_jhp") { | |
| casing.make(g->itypes["45_casing"]); | |
| primer.make(g->itypes["lgpistol_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 10*multiply; | |
| lead.charges = 8*multiply; | |
| } | |
| else if (pull->type->id == "45_super") { | |
| casing.make(g->itypes["45_casing"]); | |
| primer.make(g->itypes["lgpistol_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 12*multiply; | |
| lead.charges = 10*multiply; | |
| } | |
| else if (pull->type->id == "454_Casull") { | |
| casing.make(g->itypes["454_casing"]); | |
| primer.make(g->itypes["smrifle_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 20*multiply; | |
| lead.charges = 20*multiply; | |
| } | |
| else if (pull->type->id == "500_Magnum") { | |
| casing.make(g->itypes["500_casing"]); | |
| primer.make(g->itypes["lgpistol_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 24*multiply; | |
| lead.charges = 24*multiply; | |
| } | |
| else if (pull->type->id == "57mm") { | |
| casing.make(g->itypes["57mm_casing"]); | |
| primer.make(g->itypes["smrifle_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 4*multiply; | |
| lead.charges = 2*multiply; | |
| } | |
| else if (pull->type->id == "46mm") { | |
| casing.make(g->itypes["46mm_casing"]); | |
| primer.make(g->itypes["smpistol_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 4*multiply; | |
| lead.charges = 2*multiply; | |
| } | |
| else if (pull->type->id == "762_m43") { | |
| casing.make(g->itypes["762_casing"]); | |
| primer.make(g->itypes["lgrifle_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 7*multiply; | |
| lead.charges = 5*multiply; | |
| } | |
| else if (pull->type->id == "762_m87") { | |
| casing.make(g->itypes["762_casing"]); | |
| primer.make(g->itypes["lgrifle_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 8*multiply; | |
| lead.charges = 5*multiply; | |
| } | |
| else if (pull->type->id == "223") { | |
| casing.make(g->itypes["223_casing"]); | |
| primer.make(g->itypes["smrifle_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 4*multiply; | |
| lead.charges = 2*multiply; | |
| } | |
| else if (pull->type->id == "556" || pull->type->id == "556_incendiary") { | |
| casing.make(g->itypes["223_casing"]); | |
| primer.make(g->itypes["smrifle_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 6*multiply; | |
| lead.charges = 2*multiply; | |
| } | |
| else if (pull->type->id == "270") { | |
| casing.make(g->itypes["3006_casing"]); | |
| primer.make(g->itypes["lgrifle_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 10*multiply; | |
| lead.charges = 5*multiply; | |
| } | |
| else if (pull->type->id == "3006" || pull->type->id == "3006_incendiary") { | |
| casing.make(g->itypes["3006_casing"]); | |
| primer.make(g->itypes["lgrifle_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 8*multiply; | |
| lead.charges = 6*multiply; | |
| } | |
| else if (pull->type->id == "308") { | |
| casing.make(g->itypes["308_casing"]); | |
| primer.make(g->itypes["lgrifle_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 10*multiply; | |
| lead.charges = 6*multiply; | |
| } | |
| else if (pull->type->id == "762_51" || pull->type->id == "762_51_incendiary") { | |
| casing.make(g->itypes["308_casing"]); | |
| primer.make(g->itypes["lgrifle_primer"]); | |
| gunpowder.make(g->itypes["gunpowder"]); | |
| gunpowder.charges = 10*multiply; | |
| lead.charges = 6*multiply; | |
| } | |
| else { | |
| g->add_msg(_("You cannot disassemble that.")); | |
| return; | |
| } | |
| pull->charges = pull->charges - multiply; | |
| if (pull->charges == 0) | |
| p->i_rem(ch); | |
| g->add_msg(_("You take apart the ammunition.")); | |
| p->moves -= 500; | |
| if (casing.type->id != "null"){ | |
| casing.charges = multiply; | |
| int iter = 0; | |
| while ((casing.invlet == 0 || p->has_item(casing.invlet)) && iter < inv_chars.size()) { | |
| casing.invlet = g->nextinv; | |
| g->advance_nextinv(); | |
| iter++;} | |
| if (p->weight_carried() + casing.weight() < p->weight_capacity() && | |
| p->volume_carried() + casing.volume() < p->volume_capacity() && iter < inv_chars.size()) { | |
| p->i_add(casing);} | |
| else | |
| g->m.add_item_or_charges(p->posx, p->posy, casing);} | |
| if (primer.type->id != "null"){ | |
| primer.charges = multiply; | |
| int iter = 0; | |
| while ((primer.invlet == 0 || p->has_item(primer.invlet)) && iter < inv_chars.size()) { | |
| primer.invlet = g->nextinv; | |
| g->advance_nextinv(); | |
| iter++;} | |
| if (p->weight_carried() + primer.weight() < p->weight_capacity() && | |
| p->volume_carried() + primer.volume() < p->volume_capacity() && iter < inv_chars.size()) { | |
| p->i_add(primer);} | |
| else | |
| g->m.add_item_or_charges(p->posx, p->posy, primer);} | |
| int iter = 0; | |
| while ((gunpowder.invlet == 0 || p->has_item(gunpowder.invlet)) && iter < inv_chars.size()) { | |
| gunpowder.invlet = g->nextinv; | |
| g->advance_nextinv(); | |
| iter++;} | |
| if (p->weight_carried() + gunpowder.weight() < p->weight_capacity() && | |
| p->volume_carried() + gunpowder.volume() < p->volume_capacity() && iter < inv_chars.size()) { | |
| p->i_add(gunpowder);} | |
| else | |
| g->m.add_item_or_charges(p->posx, p->posy, gunpowder); | |
| iter = 0; | |
| while ((lead.invlet == 0 || p->has_item(lead.invlet)) && iter < inv_chars.size()) { | |
| lead.invlet = g->nextinv; | |
| g->advance_nextinv(); | |
| iter++;} | |
| if (p->weight_carried() + lead.weight() < p->weight_capacity() && | |
| p->volume_carried() + lead.volume() < p->volume_capacity() && iter < inv_chars.size()) { | |
| p->i_add(lead);} | |
| else | |
| g->m.add_item_or_charges(p->posx, p->posy, lead); | |
| p->practice(g->turn, "gun", rng(1, multiply / 5 + 1)); | |
| } | |
| void iuse::boltcutters(game *g, player *p, item *it, bool t) | |
| { | |
| int dirx, diry; | |
| if(!g->choose_adjacent(_("Cut up metal"),dirx,diry)) | |
| return; | |
| if (dirx == p->posx && diry == p->posy) { | |
| g->add_msg_if_player(p, _("You neatly sever all of the veins\nand arteries in your body. Oh wait,\nNever mind.")); | |
| return; | |
| } | |
| if (g->m.ter(dirx, diry) == t_chaingate_l) { | |
| p->moves -= 100; | |
| g->m.ter_set(dirx, diry, t_chaingate_c); | |
| g->sound(dirx, diry, 5, _("Gachunk!")); | |
| g->m.spawn_item(p->posx, p->posy, "scrap", 0, 3); | |
| } else if (g->m.ter(dirx, diry) == t_chainfence_v || g->m.ter(dirx, diry) == t_chainfence_h) { | |
| p->moves -= 500; | |
| g->m.ter_set(dirx, diry, t_chainfence_posts); | |
| g->sound(dirx, diry, 5,_("Snick, snick, gachunk!")); | |
| g->m.spawn_item(dirx, diry, "wire", 0, 20); | |
| } else { | |
| g->add_msg(_("You can't cut that.")); | |
| } | |
| } | |
| void iuse::mop(game *g, player *p, item *it, bool t) | |
| { | |
| int dirx, diry; | |
| if(!g->choose_adjacent("Mop",dirx,diry)) | |
| return; | |
| if (dirx == p->posx && diry == p->posy) { | |
| g->add_msg_if_player(p,_("You mop yourself up.")); | |
| g->add_msg_if_player(p,_("The universe implodes and reforms around you.")); | |
| return; | |
| } | |
| if (g->m.moppable_items_at(dirx, diry)) { | |
| g->m.mop_spills(dirx, diry); | |
| g->add_msg(_("You mop up the spill")); | |
| p->moves -= 15; | |
| } else { | |
| g->add_msg_if_player(p,_("There's nothing to mop there.")); | |
| } | |
| } | |
| void iuse::rag(game *g, player *p, item *it, bool t) | |
| { | |
| if (p->has_disease("bleed")){ | |
| if (one_in(2)){ | |
| g->add_msg_if_player(p,_("You managed to stop the bleeding.")); | |
| p->rem_disease("bleed"); | |
| } else { | |
| g->add_msg_if_player(p,_("You couldn't stop the bleeding.")); | |
| } | |
| p->use_charges("rag", 1); | |
| it->make(g->itypes["rag_bloody"]); | |
| } else { | |
| g->add_msg_if_player(p,_("You're not bleeding enough to need your %s."), it->type->name.c_str()); | |
| } | |
| } | |
| void iuse::pda(game *g, player *p, item *it, bool t) | |
| { | |
| if (it->charges == 0) | |
| g->add_msg_if_player(p,_("The PDA's batteries are dead.")); | |
| else { | |
| g->add_msg_if_player(p,_("You activate the flashlight app.")); | |
| it->make(g->itypes["pda_flashlight"]); | |
| it->active = true; | |
| it->charges --; | |
| } | |
| } | |
| void iuse::pda_flashlight(game *g, player *p, item *it, bool t) | |
| { | |
| if (t) { // Normal use | |
| // Do nothing... player::active_light and the lightmap::generate deal with this | |
| } else { // Turning it off | |
| g->add_msg_if_player(p,_("The PDA screen goes blank.")); | |
| it->make(g->itypes["pda"]); | |
| it->active = false; | |
| } | |
| } | |
| void iuse::LAW(game *g, player *p, item *it, bool t) | |
| { | |
| g->add_msg_if_player(p,_("You pull the activating lever, readying the LAW to fire.")); | |
| it->make(g->itypes["LAW"]); | |
| it->charges++; | |
| // When converting a tool to a gun, you need to set the current ammo type, this is usually done when a gun is reloaded. | |
| it->curammo = dynamic_cast<it_ammo*>(g->itypes["66mm_HEAT"]); | |
| } | |
| /* MACGUFFIN FUNCTIONS | |
| * These functions should refer to it->associated_mission for the particulars | |
| */ | |
| void iuse::mcg_note(game *g, player *p, item *it, bool t) | |
| { | |
| std::stringstream message; | |
| message << "Dear " << it->name << ":\n"; | |
| /* | |
| faction* fac = NULL; | |
| direction dir = NORTH; | |
| // Pick an associated faction | |
| switch (it->associated_mission) { | |
| case MISSION_FIND_FAMILY_FACTION: | |
| fac = &(g->factions[rng(0, g->factions.size() - 1)]); | |
| break; | |
| case MISSION_FIND_FAMILY_KIDNAPPER: | |
| fac = g->random_evil_faction(); | |
| break; | |
| } | |
| // Calculate where that faction is | |
| if (fac != NULL) { | |
| int omx = g->cur_om->posx, omy = g->cur_om->posy; | |
| if (fac->omx != g->cur_om->posx || fac->omx != g->cur_om->posy) | |
| dir = direction_from(omx, omy, fac->omx, fac->omy); | |
| else | |
| dir = direction_from(g->levx, g->levy, fac->mapx, fac->mapy); | |
| } | |
| // Produce the note and generate the next mission | |
| switch (it->associated_mission) { | |
| case MISSION_FIND_FAMILY_FACTION: | |
| if (fac->name == "The army") | |
| message << "\ | |
| I've been rescued by an army patrol. They're taking me\n\ | |
| to their outpost to the " << direction_name(dir) << ".\n\ | |
| Please meet me there. I need to know you're alright."; | |
| else | |
| message << "\ | |
| This group came through, looking for survivors. They\n\ | |
| said they were members of this group calling itself\n" << fac->name << ".\n\ | |
| They've got a settlement to the " << direction_name(dir) << ", so\n\ | |
| I guess I'm heading there. Meet me there as soon as\n\ | |
| you can, I need to know you're alright."; | |
| break; | |
| popup(message.str().c_str()); | |
| */ | |
| } | |
| void iuse::artifact(game *g, player *p, item *it, bool t) | |
| { | |
| if (!it->is_artifact()) { | |
| debugmsg("iuse::artifact called on a non-artifact item! %s", | |
| it->tname().c_str()); | |
| return; | |
| } else if (!it->is_tool()) { | |
| debugmsg("iuse::artifact called on a non-tool artifact! %s", | |
| it->tname().c_str()); | |
| return; | |
| } | |
| it_artifact_tool *art = dynamic_cast<it_artifact_tool*>(it->type); | |
| int num_used = rng(1, art->effects_activated.size()); | |
| if (num_used < art->effects_activated.size()) | |
| num_used += rng(1, art->effects_activated.size() - num_used); | |
| std::vector<art_effect_active> effects = art->effects_activated; | |
| for (int i = 0; i < num_used; i++) { | |
| int index = rng(0, effects.size() - 1); | |
| art_effect_active used = effects[index]; | |
| effects.erase(effects.begin() + index); | |
| switch (used) { | |
| case AEA_STORM: { | |
| g->sound(p->posx, p->posy, 10, _("Ka-BOOM!")); | |
| int num_bolts = rng(2, 4); | |
| for (int j = 0; j < num_bolts; j++) { | |
| int xdir = 0, ydir = 0; | |
| while (xdir == 0 && ydir == 0) { | |
| xdir = rng(-1, 1); | |
| ydir = rng(-1, 1); | |
| } | |
| int dist = rng(4, 12); | |
| int boltx = p->posx, bolty = p->posy; | |
| for (int n = 0; n < dist; n++) { | |
| boltx += xdir; | |
| bolty += ydir; | |
| g->m.add_field(g, boltx, bolty, fd_electricity, rng(2, 3)); | |
| if (one_in(4)) { | |
| if (xdir == 0) | |
| xdir = rng(0, 1) * 2 - 1; | |
| else | |
| xdir = 0; | |
| } | |
| if (one_in(4)) { | |
| if (ydir == 0) | |
| ydir = rng(0, 1) * 2 - 1; | |
| else | |
| ydir = 0; | |
| } | |
| } | |
| } | |
| } break; | |
| case AEA_FIREBALL: { | |
| point fireball = g->look_around(); | |
| if (fireball.x != -1 && fireball.y != -1) | |
| g->explosion(fireball.x, fireball.y, 8, 0, true); | |
| } break; | |
| case AEA_ADRENALINE: | |
| g->add_msg_if_player(p,_("You're filled with a roaring energy!")); | |
| p->add_disease("adrenaline", rng(200, 250)); | |
| break; | |
| case AEA_MAP: { | |
| bool new_map = false; | |
| for (int x = int(g->levx / 2) - 20; x <= int(g->levx / 2) + 20; x++) { | |
| for (int y = int(g->levy / 2) - 20; y <= int(g->levy / 2) + 20; y++) { | |
| if (!g->cur_om->seen(x, y, g->levz)) { | |
| new_map = true; | |
| g->cur_om->seen(x, y, g->levz) = true; | |
| } | |
| } | |
| } | |
| if (new_map) { | |
| g->add_msg_if_player(p,_("You have a vision of the surrounding area...")); | |
| p->moves -= 100; | |
| } | |
| } break; | |
| case AEA_BLOOD: { | |
| bool blood = false; | |
| for (int x = p->posx - 4; x <= p->posx + 4; x++) { | |
| for (int y = p->posy - 4; y <= p->posy + 4; y++) { | |
| if (!one_in(4) && g->m.add_field(g, x, y, fd_blood, 3) && | |
| (blood || g->u_see(x, y))) | |
| blood = true; | |
| } | |
| } | |
| if (blood) | |
| g->add_msg_if_player(p,_("Blood soaks out of the ground and walls.")); | |
| } break; | |
| case AEA_FATIGUE: { | |
| g->add_msg_if_player(p,_("The fabric of space seems to decay.")); | |
| int x = rng(p->posx - 3, p->posx + 3), y = rng(p->posy - 3, p->posy + 3); | |
| g->m.add_field(g, x, y, fd_fatigue, rng(1, 2)); | |
| } break; | |
| case AEA_ACIDBALL: { | |
| point acidball = g->look_around(); | |
| if (acidball.x != -1 && acidball.y != -1) { | |
| for (int x = acidball.x - 1; x <= acidball.x + 1; x++) { | |
| for (int y = acidball.y - 1; y <= acidball.y + 1; y++) { | |
| g->m.add_field(g, x, y, fd_acid, rng(2, 3)); | |
| } | |
| } | |
| } | |
| } break; | |
| case AEA_PULSE: | |
| g->sound(p->posx, p->posy, 30, _("The earth shakes!")); | |
| for (int x = p->posx - 2; x <= p->posx + 2; x++) { | |
| for (int y = p->posy - 2; y <= p->posy + 2; y++) { | |
| std::string junk; | |
| g->m.bash(x, y, 40, junk); | |
| g->m.bash(x, y, 40, junk); // Multibash effect, so that doors &c will fall | |
| g->m.bash(x, y, 40, junk); | |
| if (g->m.is_destructable(x, y) && rng(1, 10) >= 3) | |
| g->m.ter_set(x, y, t_rubble); | |
| } | |
| } | |
| break; | |
| case AEA_HEAL: | |
| g->add_msg_if_player(p,_("You feel healed.")); | |
| p->healall(2); | |
| break; | |
| case AEA_CONFUSED: | |
| for (int x = p->posx - 8; x <= p->posx + 8; x++) { | |
| for (int y = p->posy - 8; y <= p->posy + 8; y++) { | |
| int mondex = g->mon_at(x, y); | |
| if (mondex != -1) | |
| g->z[mondex].add_effect(ME_STUNNED, rng(5, 15)); | |
| } | |
| } | |
| case AEA_ENTRANCE: | |
| for (int x = p->posx - 8; x <= p->posx + 8; x++) { | |
| for (int y = p->posy - 8; y <= p->posy + 8; y++) { | |
| int mondex = g->mon_at(x, y); | |
| if (mondex != -1 && g->z[mondex].friendly == 0 && | |
| rng(0, 600) > g->z[mondex].hp) | |
| g->z[mondex].make_friendly(); | |
| } | |
| } | |
| break; | |
| case AEA_BUGS: { | |
| int roll = rng(1, 10); | |
| mon_id bug = mon_null; | |
| int num = 0; | |
| std::vector<point> empty; | |
| for (int x = p->posx - 1; x <= p->posx + 1; x++) { | |
| for (int y = p->posy - 1; y <= p->posy + 1; y++) { | |
| if (g->is_empty(x, y)) | |
| empty.push_back( point(x, y) ); | |
| } | |
| } | |
| if (empty.empty() || roll <= 4) | |
| g->add_msg_if_player(p,_("Flies buzz around you.")); | |
| else if (roll <= 7) { | |
| g->add_msg_if_player(p,_("Giant flies appear!")); | |
| bug = mon_fly; | |
| num = rng(2, 4); | |
| } else if (roll <= 9) { | |
| g->add_msg_if_player(p,_("Giant bees appear!")); | |
| bug = mon_bee; | |
| num = rng(1, 3); | |
| } else { | |
| g->add_msg_if_player(p,_("Giant wasps appear!")); | |
| bug = mon_wasp; | |
| num = rng(1, 2); | |
| } | |
| if (bug != mon_null) { | |
| monster spawned(g->mtypes[bug]); | |
| spawned.friendly = -1; | |
| for (int j = 0; j < num && !empty.empty(); j++) { | |
| int index_inner = rng(0, empty.size() - 1); | |
| point spawnp = empty[index_inner]; | |
| empty.erase(empty.begin() + index_inner); | |
| spawned.spawn(spawnp.x, spawnp.y); | |
| g->z.push_back(spawned); | |
| } | |
| } | |
| } break; | |
| case AEA_TELEPORT: | |
| g->teleport(p); | |
| break; | |
| case AEA_LIGHT: | |
| g->add_msg_if_player(p,_("The %s glows brightly!"), it->tname().c_str()); | |
| g->add_event(EVENT_ARTIFACT_LIGHT, int(g->turn) + 30); | |
| break; | |
| case AEA_GROWTH: { | |
| monster tmptriffid(g->mtypes[0], p->posx, p->posy); | |
| mattack tmpattack; | |
| tmpattack.growplants(g, &tmptriffid); | |
| } break; | |
| case AEA_HURTALL: | |
| for (int j = 0; j < g->z.size(); j++) | |
| g->z[j].hurt(rng(0, 5)); | |
| break; | |
| case AEA_RADIATION: | |
| g->add_msg(_("Horrible gasses are emitted!")); | |
| for (int x = p->posx - 1; x <= p->posx + 1; x++) { | |
| for (int y = p->posy - 1; y <= p->posy + 1; y++) | |
| g->m.add_field(g, x, y, fd_nuke_gas, rng(2, 3)); | |
| } | |
| break; | |
| case AEA_PAIN: | |
| g->add_msg_if_player(p,_("You're wracked with pain!")); | |
| p->pain += rng(5, 15); | |
| break; | |
| case AEA_MUTATE: | |
| if (!one_in(3)) | |
| p->mutate(g); | |
| break; | |
| case AEA_PARALYZE: | |
| g->add_msg_if_player(p,_("You're paralyzed!")); | |
| p->moves -= rng(50, 200); | |
| break; | |
| case AEA_FIRESTORM: | |
| g->add_msg_if_player(p,_("Fire rains down around you!")); | |
| for (int x = p->posx - 3; x <= p->posx + 3; x++) { | |
| for (int y = p->posy - 3; y <= p->posy + 3; y++) { | |
| if (!one_in(3)) { | |
| if (g->m.add_field(g, x, y, fd_fire, 1 + rng(0, 1) * rng(0, 1))) | |
| g->m.field_at(x, y).findField(fd_fire)->setFieldAge(g->m.field_at(x, y).findField(fd_fire)->getFieldAge() + 30); | |
| } | |
| } | |
| } | |
| break; | |
| case AEA_ATTENTION: | |
| g->add_msg_if_player(p,_("You feel like your action has attracted attention.")); | |
| p->add_disease("attention", 600 * rng(1, 3)); | |
| break; | |
| case AEA_TELEGLOW: | |
| g->add_msg_if_player(p,_("You feel unhinged.")); | |
| p->add_disease("teleglow", 100 * rng(3, 12)); | |
| break; | |
| case AEA_NOISE: | |
| g->add_msg_if_player(p,_("Your %s emits a deafening boom!"), it->tname().c_str()); | |
| g->sound(p->posx, p->posy, 100, ""); | |
| break; | |
| case AEA_SCREAM: | |
| g->add_msg_if_player(p,_("Your %s screams disturbingly."), it->tname().c_str()); | |
| g->sound(p->posx, p->posy, 40, ""); | |
| p->add_morale(MORALE_SCREAM, -10, 0, 300, 5); | |
| break; | |
| case AEA_DIM: | |
| g->add_msg_if_player(p,_("The sky starts to dim.")); | |
| g->add_event(EVENT_DIM, int(g->turn) + 50); | |
| break; | |
| case AEA_FLASH: | |
| g->add_msg_if_player(p,_("The %s flashes brightly!"), it->tname().c_str()); | |
| g->flashbang(p->posx, p->posy); | |
| break; | |
| case AEA_VOMIT: | |
| g->add_msg_if_player(p,_("A wave of nausea passes through you!")); | |
| p->vomit(g); | |
| break; | |
| case AEA_SHADOWS: { | |
| int num_shadows = rng(4, 8); | |
| monster spawned(g->mtypes[mon_shadow]); | |
| int num_spawned = 0; | |
| for (int j = 0; j < num_shadows; j++) { | |
| int tries = 0, monx, mony, junk; | |
| do { | |
| if (one_in(2)) { | |
| monx = rng(p->posx - 5, p->posx + 5); | |
| mony = (one_in(2) ? p->posy - 5 : p->posy + 5); | |
| } else { | |
| monx = (one_in(2) ? p->posx - 5 : p->posx + 5); | |
| mony = rng(p->posy - 5, p->posy + 5); | |
| } | |
| } while (tries < 5 && !g->is_empty(monx, mony) && | |
| !g->m.sees(monx, mony, p->posx, p->posy, 10, junk)); | |
| if (tries < 5) { | |
| num_spawned++; | |
| spawned.sp_timeout = rng(8, 20); | |
| spawned.spawn(monx, mony); | |
| g->z.push_back(spawned); | |
| } | |
| } | |
| if (num_spawned > 1) | |
| g->add_msg_if_player(p,_("Shadows form around you.")); | |
| else if (num_spawned == 1) | |
| g->add_msg_if_player(p,_("A shadow forms nearby.")); | |
| } break; | |
| } | |
| } | |
| } | |
| void iuse::spray_can(game *g, player *p, item *it, bool t) | |
| { | |
| // We have to access the actual it_tool class to figure out how many charges this thing uses. | |
| // Because the charges have already been removed in player::use, we will have to refund the charges if the user cancels. | |
| // This is a stupid hack, but it's the only way short of rewriting all of the iuse:: functions to draw their own charges as needed. | |
| it_tool *tool = dynamic_cast<it_tool*>(it->type); | |
| int charges_per_use = tool->charges_per_use; | |
| if ( it->type->id == _("permanent_marker") ) | |
| { | |
| int ret=menu(true, _("Write on what?"), _("The ground"), _("An item"), _("Cancel"), NULL ); | |
| if (ret == 2 ) | |
| { | |
| // inscribe_item returns false if the action fails or is canceled somehow. | |
| bool canceled_inscription = !inscribe_item( g, p, _("Write"), _("Written"), false ); | |
| if( canceled_inscription ) | |
| { | |
| //Refund the charges, because the inscription was never made. | |
| it->charges += charges_per_use; | |
| } | |
| return; | |
| } | |
| else if ( ret != 1) // User chose cancel or some other undefined key. | |
| { | |
| //Refund the charges, because the player canceled the action. | |
| it->charges += charges_per_use; | |
| return; | |
| } | |
| } | |
| bool ismarker = (it->type->id=="permanent_marker"); | |
| std::string message = string_input_popup(ismarker?_("Write what?"):_("Spray what?")); | |
| if(message.empty()) | |
| { | |
| //Refund the charges, because the player canceled the action. | |
| it->charges += charges_per_use; | |
| } | |
| else | |
| { | |
| if(g->m.add_graffiti(g, p->posx, p->posy, message)) | |
| { | |
| g->add_msg( | |
| ismarker? | |
| _("You write a message on the ground.") : | |
| _("You spray a message on the ground.") | |
| ); | |
| } | |
| else | |
| { | |
| g->add_msg( | |
| ismarker? | |
| _("You fail to write a message here.") : | |
| _("You fail to spray a message here.") | |
| ); | |
| // Refuned the charges, because the grafitti failed. | |
| it->charges += charges_per_use; | |
| } | |
| } | |
| } | |
| void iuse::heatpack(game *g, player *p, item *it, bool t) | |
| { | |
| char ch = g->inv(_("Heat up what?")); | |
| item* heat = &(p->i_at(ch)); | |
| if (heat->type->id == "null") { | |
| g->add_msg(_("You do not have that item!")); | |
| return; | |
| } | |
| if (heat->type->is_food()) { | |
| p->moves -= 300; | |
| g->add_msg(_("You heat up the food.")); | |
| heat->item_tags.insert("HOT"); | |
| heat->active = true; | |
| heat->item_counter = 600; // sets the hot food flag for 60 minutes | |
| it->make(g->itypes["heatpack_used"]); | |
| return; | |
| } else if (heat->is_food_container()) { | |
| p->moves -= 300; | |
| g->add_msg(_("You heat up the food.")); | |
| heat->contents[0].item_tags.insert("HOT"); | |
| heat->contents[0].active = true; | |
| heat->contents[0].item_counter = 600; // sets the hot food flag for 60 minutes | |
| it->make(g->itypes["heatpack_used"]); | |
| return; | |
| } | |
| { g->add_msg(_("You can't heat that up!")); | |
| } return; | |
| } | |
| void iuse::dejar(game *g, player *p, item *it, bool t) | |
| { | |
| if( (it->type->id).substr(0,4) == "jar_" ) { | |
| g->add_msg_if_player(p,_("You open the jar, exposing it to the atmosphere.")); | |
| } else if( (it->type->id).substr(0,4) == "bag_" ) { | |
| g->add_msg_if_player(p,_("You open the vacuum pack, exposing it to the atmosphere.")); | |
| } else { | |
| // No matching substring, bail out. | |
| return; | |
| } | |
| // Strips off "jar_" or "bag_" from the id to get the content type. | |
| itype_id ujfood = (it->type->id).substr(4); | |
| // temp create item to discover container | |
| item ujitem( g->itypes[ujfood], 0 ); | |
| //discovering container | |
| itype_id ujcont = (dynamic_cast<it_comest*>(ujitem.type))->container; | |
| //turning "sealed jar of xxx" into container for "xxx" | |
| it->make( g->itypes[ujcont] ); | |
| //shoving the "xxx" into the container | |
| it->contents.push_back( item( g->itypes[ujfood], 0 ) ); | |
| it->contents[0].bday = g->turn + 3600 - (g->turn % 3600); | |
| } | |
| void iuse::rad_badge(game *g, player *p, item *it, bool t) | |
| { | |
| g->add_msg_if_player(p,_("You remove the badge from its wrapper, exposing it to ambient radiation.")); | |
| it->make(g->itypes["rad_badge"]); | |
| } | |
| void iuse::boots(game *g, player *p, item *it, bool t) | |
| { | |
| int choice = -1; | |
| if (it->contents.size() == 0) | |
| choice = menu(true, _("Using boots:"), _("Put a knife in the boot"), _("Cancel"), NULL); | |
| else if (it->contents.size() == 1) | |
| choice = menu(true, _("Take what:"), it->contents[0].tname().c_str(), _("Put a knife in the boot"), _("Cancel"), NULL); | |
| else | |
| choice = menu(true, _("Take what:"), it->contents[0].tname().c_str(), it->contents[1].tname().c_str(), _("Cancel"), NULL); | |
| if ((it->contents.size() > 0 && choice == 1) || // Pull 1st | |
| (it->contents.size() > 1 && choice == 2)) { // Pull 2nd | |
| p->moves -= 15; | |
| item knife = it->contents[choice - 1]; | |
| if (!p->is_armed() || p->wield(g, -3)) { | |
| p->i_add(knife); | |
| p->wield(g, knife.invlet); | |
| it->contents.erase(it->contents.begin() + choice - 1); | |
| } | |
| } else if ((it->contents.size() == 0 && choice == 1) || // Put 1st | |
| (it->contents.size() == 1 && choice == 2)) { // Put 2st | |
| char ch = g->inv_type(_("Put what?"), IC_TOOL); | |
| item* put = &(p->i_at(ch)); | |
| if (put == NULL || put->is_null()) { | |
| g->add_msg_if_player(p, _("You do not have that item!")); | |
| return; | |
| } | |
| if (put->type->use != &iuse::knife) { | |
| g->add_msg_if_player(p, _("That isn't knife!")); | |
| return; | |
| } | |
| if (put->type->volume > 5) { | |
| g->add_msg_if_player(p, _("That item does not fit in your boot!")); | |
| return; | |
| } | |
| p->moves -= 30; | |
| g->add_msg_if_player(p, _("You put the %s in your boot."), put->tname().c_str()); | |
| it->put_in(p->i_rem(ch)); | |
| } | |
| } | |
| void iuse::towel(game *g, player *p, item *it, bool t) | |
| { | |
| // check if player is wet | |
| if( abs(p->has_morale(MORALE_WET)) ) | |
| { | |
| p->rem_morale(MORALE_WET); | |
| g->add_msg_if_player(p,_("You use the %s to dry off!"), it->name.c_str()); | |
| } | |
| else | |
| { | |
| g->add_msg_if_player(p,_("You are already dry, %s has no effect"), it->name.c_str()); | |
| } | |
| } | |
| void iuse::unfold_bicycle(game *g, player *p, item *it, bool t) | |
| { | |
| vehicle *bicycle = g->m.add_vehicle( g, veh_bicycle, p->posx, p->posy, 0, 0, 0); | |
| if( bicycle ) { | |
| // Mark the vehicle as foldable. | |
| bicycle->tags.insert("convertible"); | |
| // Restore HP of parts if we stashed them previously. | |
| if( it->item_vars.count("folding_bicycle_parts") ) { | |
| std::istringstream part_hps; | |
| part_hps.str(it->item_vars["folding_bicycle_parts"]); | |
| for (int p = 0; p < bicycle->parts.size(); p++) | |
| { | |
| part_hps >> bicycle->parts[p].hp; | |
| } | |
| } | |
| g->add_msg_if_player(p, _("You painstakingly unfold the bicycle and make it ready to ride.")); | |
| p->moves -= 500; | |
| it->invlet = 0; | |
| } else { | |
| g->add_msg_if_player(p, _("There's no room to unfold the bicycle.")); | |
| } | |
| } |