Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
4665 lines (4352 sloc) 143 KB
#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 &current_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 &current_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."));
}
}
You can’t perform that action at this time.