Example #1
0
bool item::is_weap()
{
 if (is_gun() || is_food() || is_ammo() || is_food_container() || is_armor() ||
     is_book() || is_tool())
  return false;
 return (type->melee_dam > 7 || type->melee_cut > 5);
}
Example #2
0
nc_color item::color(player *u)
{
 nc_color ret = c_ltgray;

 if (active) // Active items show up as yellow
  ret = c_yellow;
 else if (is_gun()) { // Guns are green if you are carrying ammo for them
  ammotype amtype = ammo_type();
  if (u->has_ammo(amtype).size() > 0)
   ret = c_green;
 } else if (is_ammo()) { // Likewise, ammo is green if you have guns that use it
  ammotype amtype = ammo_type();
  if (u->weapon.is_gun() && u->weapon.ammo_type() == amtype)
   ret = c_green;
  else {
   for (int i = 0; i < u->inv.size(); i++) {
    if (u->inv[i].is_gun() && u->inv[i].ammo_type() == amtype) {
     i = u->inv.size();
     ret = c_green;
    }
   }
  }
 } else if (is_book()) {
  it_book* tmp = dynamic_cast<it_book*>(type);
  if (tmp->type !=sk_null && tmp->intel <= u->int_cur + u->sklevel[tmp->type] &&
      (tmp->intel == 0 || !u->has_trait(PF_ILLITERATE)) &&
      tmp->req <= u->sklevel[tmp->type] && tmp->level > u->sklevel[tmp->type])
   ret = c_ltblue;
 }
 return ret;
}
Example #3
0
ammotype item::ammo_type()
{
 if (is_gun()) {
  it_gun* gun = dynamic_cast<it_gun*>(type);
  ammotype ret = gun->ammo;
  for (int i = 0; i < contents.size(); i++) {
   if (contents[i].is_gunmod() && !contents[i].has_flag(IF_MODE_AUX)) {
    it_gunmod* mod = dynamic_cast<it_gunmod*>(contents[i].type);
    if (mod->newtype != AT_NULL)
     ret = mod->newtype;
   }
  }
  return ret;
 } else if (is_tool()) {
  it_tool* tool = dynamic_cast<it_tool*>(type);
  return tool->ammo;
 } else if (is_ammo()) {
  it_ammo* amm = dynamic_cast<it_ammo*>(type);
  return amm->type;
 } else if (is_gunmod()) {
  it_gunmod* mod = dynamic_cast<it_gunmod*>(type);
  return mod->newtype;
 }
 return AT_NULL;
}
Example #4
0
int item::weight()
{
 if (type->id == itm_corpse) {
  int ret;
  switch (corpse->size) {
   case MS_TINY:   ret =    5;	break;
   case MS_SMALL:  ret =   60;	break;
   case MS_MEDIUM: ret =  520;	break;
   case MS_LARGE:  ret = 2000;	break;
   case MS_HUGE:   ret = 4000;	break;
  }
  if (made_of(VEGGY))
   ret /= 10;
  else if (made_of(IRON) || made_of(STEEL) || made_of(STONE))
   ret *= 5;
  return ret;
 }
 int ret = type->weight;
 if (is_ammo()) { 
  ret *= charges;
  ret /= 100;
 }
 for (int i = 0; i < contents.size(); i++)
  ret += contents[i].weight();
 return ret;
}
Example #5
0
/* Proper usage includes:
 * 1.  Initializing the slot during character generation or a
 *     restore.
 * 2.  Setting the slot due to a player's actions.
 * 3.  If one of the objects in the slot are split off, these
 *     functions can be used to put the remainder back in the slot.
 * 4.  Putting an item that was thrown and returned back into the slot.
 * 5.  Emptying the slot, by passing a null object.  NEVER pass
 *     zeroobj!
 *
 * If the item is being moved from another slot, it is the caller's
 * responsibility to handle that.  It's also the caller's responsibility
 * to print the appropriate messages.
 */
void setuwep(struct obj *obj)
{
	struct obj *olduwep = uwep;

	if (obj == uwep) return; /* necessary to not set unweapon */
	/* This message isn't printed in the caller because it happens
	 * *whenever* Sunsword is unwielded, from whatever cause.
	 */
	setworn(obj, W_WEP);
	if (uwep == obj && artifact_light(olduwep) && olduwep->lamplit) {
	    end_burn(olduwep, FALSE);
	    if (!Blind) pline("%s glowing.", Tobjnam(olduwep, "stop"));
	}
	/* Note: Explicitly wielding a pick-axe will not give a "bashing"
	 * message.  Wielding one via 'a'pplying it will.
	 * 3.2.2:  Wielding arbitrary objects will give bashing message too.
	 */
	if (obj) {
		unweapon = (obj->oclass == WEAPON_CLASS) ?
				is_launcher(obj) || is_ammo(obj) ||
				is_missile(obj) || (is_pole(obj)
				&& !u.usteed) : !is_weptool(obj);
	} else
		unweapon = TRUE;	/* for "bare hands" message */
	update_inventory();
}
Example #6
0
/* release the objects the creature is carrying */
void
relobj(struct monst *mtmp, int show, boolean is_pet)
{       /* If true, pet should keep wielded/worn items */
    struct obj *otmp;
    int omx = mtmp->mx, omy = mtmp->my;
    struct obj *keepobj = 0;
    struct obj *wep = MON_WEP(mtmp), *hwep = attacktype(mtmp->data, AT_WEAP)
        ? select_hwep(mtmp) : (struct obj *)0, *proj =
        attacktype(mtmp->data, AT_WEAP)
        ? select_rwep(mtmp) : (struct obj *)0, *rwep;
    boolean item1 = FALSE, item2 = FALSE;

    rwep = attacktype(mtmp->data, AT_WEAP) ? propellor : &zeroobj;


    if (!is_pet || mindless(mtmp->data) || is_animal(mtmp->data))
        item1 = item2 = TRUE;
    if (!tunnels(mtmp->data) || !needspick(mtmp->data))
        item1 = TRUE;

    while ((otmp = mtmp->minvent) != 0) {
        obj_extract_self(otmp);
        /* special case: pick-axe and unicorn horn are non-worn */
        /* items that we also want pets to keep 1 of */
        /* (It is a coincidence that these can also be wielded.) */
        if (otmp->owornmask || otmp == wep || otmp == hwep || otmp == rwep ||
            otmp == proj ||
            would_prefer_hwep(mtmp, otmp) ||  /* cursed item in hand? */
            would_prefer_rwep(mtmp, otmp) || could_use_item(mtmp, otmp) ||
            ((!rwep || rwep == &zeroobj) &&
             (is_ammo(otmp) || is_launcher(otmp))) ||
            (rwep && rwep != &zeroobj && ammo_and_launcher(otmp, rwep)) ||
            ((!item1 && otmp->otyp == PICK_AXE) ||
             (!item2 && otmp->otyp == UNICORN_HORN && !otmp->cursed))) {
            if (is_pet) {       /* dont drop worn/wielded item */
                if (otmp->otyp == PICK_AXE)
                    item1 = TRUE;
                if (otmp->otyp == UNICORN_HORN && !otmp->cursed)
                    item2 = TRUE;
                otmp->nobj = keepobj;
                keepobj = otmp;
                continue;
            }
        }
        if (otmp == wep)
            setmnotwielded(mtmp, otmp);
        mdrop_obj(mtmp, otmp, is_pet && flags.verbose);
    }

    /* put kept objects back */
    while ((otmp = keepobj) != NULL) {
        keepobj = otmp->nobj;
        add_to_minv(mtmp, otmp);
    }

    if (show & cansee(omx, omy))
        newsym(omx, omy);
}
Example #7
0
bool item::is_other()
{
 if( is_null() )
  return false;

 return (!is_gun() && !is_ammo() && !is_armor() && !is_food() &&
         !is_food_container() && !is_tool() && !is_gunmod() && !is_bionic() &&
         !is_book() && !is_weap());
}
Example #8
0
bool item::count_by_charges()
{
 if (is_ammo())
  return true;
 if (is_food()) {
  it_comest* food = dynamic_cast<it_comest*>(type);
  return (food->charges > 1);
 }
 return false;
}
Example #9
0
bool item::is_food(player *u)
{
 if (u == NULL)
  return is_food();

 if (type->is_food())
  return true;

 if (u->has_bionic(bio_batteries) && is_ammo() &&
     (dynamic_cast<it_ammo*>(type))->type == AT_BATT)
  return true;
 if (u->has_bionic(bio_furnace) && is_flammable(type->m1) &&
     is_flammable(type->m2) && type->id != itm_corpse)
  return true;
 return false;
}
Example #10
0
void vehicle::turret_reload( vehicle_part &pt )
{
    item &gun = pt.base;
    if( !gun.is_gun() || gun.ammo_type() == "NULL" ) {
        return;
    }

    // try to reload using stored fuel from onboard vehicle tanks
    for( const auto &e : fuels_left() ) {
        const itype *fuel = item::find_type( e.first );
        if( !fuel->ammo || e.second < gun.ammo_required() ) {
            continue;
        }

        if( ( gun.ammo_current() == "null" && fuel->ammo->type == gun.ammo_type() ) ||
            ( gun.ammo_current() == e.first ) ) {

            int qty = gun.ammo_remaining();
            gun.ammo_set( e.first, e.second );

            drain( e.first, gun.ammo_remaining() - qty );

            return;
        }
    }

    // otherwise try to reload from turret cargo space
    for( auto it = pt.items.begin(); it != pt.items.end(); ++it ) {
        if( it->is_ammo() &&
            ( ( gun.ammo_current() == "null" && it->ammo_type() == gun.ammo_type() ) ||
              ( gun.ammo_current() == it->typeId() ) ) ) {

            int qty = gun.ammo_remaining();
            gun.ammo_set( it->typeId(), it->charges );

            it->charges -= gun.ammo_remaining() - qty;

            if( it->charges <= 0 ) {
                pt.items.erase( it );
            }

            return;
        }
    }
}
Example #11
0
bool item::is_food(player *u) const
{
 if (!u)
  return is_food();

 if( is_null() )
  return false;

 if (type->is_food())
  return true;

 if (u->has_bionic("bio_batteries") && is_ammo() &&
     (dynamic_cast<it_ammo*>(type))->type == AT_BATT)
  return true;
 if (u->has_bionic("bio_furnace") && is_flammable(type->m1) &&
     is_flammable(type->m2) && typeId() != "corpse")
  return true;
 return false;
}
Example #12
0
static struct obj *
DROPPABLES(struct monst *mon)
{
    struct obj *obj;
    struct obj *wep = MON_WEP(mon), *hwep = attacktype(mon->data, AT_WEAP)
        ? select_hwep(mon) : (struct obj *)0, *proj =
        attacktype(mon->data, AT_WEAP)
        ? select_rwep(mon) : (struct obj *)0, *rwep;
    boolean item1 = FALSE, item2 = FALSE;

    rwep = attacktype(mon->data, AT_WEAP) ? propellor : &zeroobj;

    if (is_animal(mon->data) || mindless(mon->data))
        item1 = item2 = TRUE;
    if (!tunnels(mon->data) || !needspick(mon->data))
        item1 = TRUE;
    for (obj = mon->minvent; obj; obj = obj->nobj) {
        if (!item1 && is_pick(obj) &&
            (obj->otyp != DWARVISH_MATTOCK || !which_armor(mon, W_ARMS))) {
            item1 = TRUE;
            continue;
        }
        if (!item2 && obj->otyp == UNICORN_HORN && !obj->cursed) {
            item2 = TRUE;
            continue;
        }
        if (!obj->owornmask && obj != wep && obj != rwep &&
            obj != proj && obj != hwep &&
            !would_prefer_hwep(mon, obj)  /* cursed item in hand?  */
            && !would_prefer_rwep(mon, obj)
            && ((rwep != &zeroobj) || (!is_ammo(obj) && !is_launcher(obj)))
            && (rwep == &zeroobj || !ammo_and_launcher(obj, rwep))
            && !could_use_item(mon, obj))
            return obj;
    }
    return NULL;
}
Example #13
0
std::string item::info(bool showtext)
{
 std::stringstream dump;
 if( !is_null() )
 {
  dump << " Volume: " << volume() << "    Weight: " << weight() << "\n" <<
          " Bash: " << int(type->melee_dam) <<
          (has_flag(IF_SPEAR) ? "  Pierce: " : "  Cut: ") <<
          int(type->melee_cut) << "  To-hit bonus: " <<
          (type->m_to_hit > 0 ? "+" : "" ) << int(type->m_to_hit) << "\n" <<
          " Moves per attack: " << attack_time() << "\n";
 }

 if (is_food()) {

  it_comest* food = dynamic_cast<it_comest*>(type);
  dump << " Nutrition: " << int(food->nutr) << "\n Quench: " <<
          int(food->quench) << "\n Enjoyability: " << int(food->fun);

 } else if (is_food_container()) {

 // added charge display for debugging
 
  it_comest* food = dynamic_cast<it_comest*>(contents[0].type);
  dump << " Nutrition: " << int(food->nutr) << "\n Quench: " <<
          int(food->quench) << "\n Enjoyability: " << int(food->fun)
          << "\n Charges: " << int(contents[0].charges);

 } else if (is_ammo()) {
 
  // added charge display for debugging

  it_ammo* ammo = dynamic_cast<it_ammo*>(type);
  dump << " Type: " << ammo_name(ammo->type) << "\n Damage: " <<
           int(ammo->damage) << "\n Armor-pierce: " << int(ammo->pierce) <<
           "\n Range: " << int(ammo->range) << "\n Accuracy: " <<
           int(100 - ammo->accuracy) << "\n Recoil: " << int(ammo->recoil)
           << "\n Count: " << int(ammo->count);

 } else if (is_ammo_container()) {

  it_ammo* ammo = dynamic_cast<it_ammo*>(contents[0].type);
  dump << " Type: " << ammo_name(ammo->type) << "\n Damage: " <<
           int(ammo->damage) << "\n Armor-pierce: " << int(ammo->pierce) <<
           "\n Range: " << int(ammo->range) << "\n Accuracy: " <<
           int(100 - ammo->accuracy) << "\n Recoil: " << int(ammo->recoil)
           << "\n Count: " << int(contents[0].charges); 
           
 } else if (is_gun()) {

  it_gun* gun = dynamic_cast<it_gun*>(type);
  int ammo_dam = 0, ammo_recoil = 0;
  bool has_ammo = (curammo != NULL && charges > 0);
  if (has_ammo) {
   ammo_dam = curammo->damage;
   ammo_recoil = curammo->recoil;
  }
   
  dump << " Skill used: " << skill_name(gun->skill_used) << "\n Ammunition: " <<
          clip_size() << " rounds of " << ammo_name(ammo_type());

  dump << "\n Damage: ";
  if (has_ammo)
   dump << ammo_dam;
  dump << (gun_damage(false) >= 0 ? "+" : "" ) << gun_damage(false);
  if (has_ammo)
   dump << " = " << gun_damage();

  dump << "\n Accuracy: " << int(100 - accuracy());

  dump << "\n Recoil: ";
  if (has_ammo)
   dump << ammo_recoil;
  dump << (recoil(false) >= 0 ? "+" : "" ) << recoil(false);
  if (has_ammo)
   dump << " = " << recoil();

  dump << "\n Reload time: " << int(gun->reload_time);
  if (has_flag(IF_RELOAD_ONE))
   dump << " per round";

  if (burst_size() == 0) {
   if (gun->skill_used == sk_pistol && has_flag(IF_RELOAD_ONE))
    dump << "\n Revolver.";
   else
    dump << "\n Semi-automatic.";
  } else
   dump << "\n Burst size: " << burst_size();
  if (contents.size() > 0)
   dump << "\n";
  for (int i = 0; i < contents.size(); i++)
   dump << "\n+" << contents[i].tname();

 } else if (is_gunmod()) {

  it_gunmod* mod = dynamic_cast<it_gunmod*>(type);
  if (mod->accuracy != 0)
   dump << " Accuracy: " << (mod->accuracy > 0 ? "+" : "") <<
           int(mod->accuracy);
  if (mod->damage != 0)
   dump << "\n Damage: " << (mod->damage > 0 ? "+" : "") << int(mod->damage);
  if (mod->clip != 0)
   dump << "\n Magazine: " << (mod->clip > 0 ? "+" : "") << int(mod->damage) << "%";
  if (mod->recoil != 0)
   dump << "\n Recoil: " << int(mod->recoil);
  if (mod->burst != 0)
   dump << "\n Burst: " << (mod->clip > 0 ? "+" : "") << int(mod->clip);
  if (mod->newtype != AT_NULL)
   dump << "\n " << ammo_name(mod->newtype);
  dump << "\n Used on: ";
  if (mod->used_on_pistol)
   dump << "Pistols.  ";
  if (mod->used_on_shotgun)
   dump << "Shotguns.  ";
  if (mod->used_on_smg)
   dump << "SMGs.  ";
  if (mod->used_on_rifle)
   dump << "Rifles.";

 } else if (is_armor()) {

  it_armor* armor = dynamic_cast<it_armor*>(type);
  dump << " Covers: ";
  if (armor->covers & mfb(bp_head))
   dump << "The head. ";
  if (armor->covers & mfb(bp_eyes))
   dump << "The eyes. ";
  if (armor->covers & mfb(bp_mouth))
   dump << "The mouth. ";
  if (armor->covers & mfb(bp_torso))
   dump << "The torso. ";
  if (armor->covers & mfb(bp_arms))
   dump << "The arms. ";   
  if (armor->covers & mfb(bp_hands))
   dump << "The hands. ";
  if (armor->covers & mfb(bp_legs))
   dump << "The legs. ";
  if (armor->covers & mfb(bp_feet))
   dump << "The feet. ";
  dump << "\n Encumberment: "			<< int(armor->encumber) <<
          "\n Bashing protection: "		<< int(armor->dmg_resist) <<
          "\n Cut protection: "			<< int(armor->cut_resist) <<
          "\n Environmental protection: "	<< int(armor->env_resist) <<
          "\n Warmth: "				<< int(armor->warmth) <<
          "\n Storage: "			<< int(armor->storage);

} else if (is_book()) {

  it_book* book = dynamic_cast<it_book*>(type);
  if (book->type == sk_null)
   dump << " Just for fun.\n";
  else {
   dump << " Can bring your " << skill_name(book->type) << " skill to " <<
           int(book->level) << std::endl;
   if (book->req == 0)
    dump << " It can be understood by beginners.\n";
   else
    dump << " Requires " << skill_name(book->type) << " level " <<
            int(book->req) << " to understand.\n";
  }
  dump << " Requires intelligence of " << int(book->intel) << " to easily read." << std::endl;
  if (book->fun != 0)
   dump << " Reading this book affects your morale by " <<
           (book->fun > 0 ? "+" : "") << int(book->fun) << std::endl;
  dump << " This book takes " << int(book->time) << " minutes to read.";

 } else if (is_tool()) {

  it_tool* tool = dynamic_cast<it_tool*>(type);
  dump << " Maximum " << tool->max_charges << " charges";
  if (tool->ammo == AT_NULL)
   dump << ".";
  else
   dump << " of " << ammo_name(tool->ammo) << ".";

 } else if (is_style()) {

  dump << "\n";
  it_style* style = dynamic_cast<it_style*>(type);
  for (int i = 0; i < style->moves.size(); i++) {
   dump << default_technique_name(style->moves[i].tech) <<
           ". Requires Unarmed Skill of " << style->moves[i].level << "\n";
  }

 } else if (!is_null() && type->techniques != 0) {

  dump << "\n";
  for (int i = 1; i < NUM_TECHNIQUES; i++) {
   if (type->techniques & mfb(i))
    dump << default_technique_name( technique_id(i) ) << "; ";
  }

 }

 if ( showtext && !is_null() ) {
  dump << "\n\n" << type->description << "\n";
  if (contents.size() > 0) {
   if (is_gun()) {
    for (int i = 0; i < contents.size(); i++)
     dump << "\n " << contents[i].type->description;
   } else
    dump << "\n " << contents[0].type->description;
   dump << "\n";
  }
 }
 return dump.str();
}
Example #14
0
bool item::destroyed_at_zero_charges()
{
 return (is_ammo() || is_food());
}
Example #15
0
std::string item::info(bool showtext, std::vector<iteminfo> *dump)
{
 std::stringstream temp1, temp2;

 if( !is_null() )
 {
  dump->push_back(iteminfo("BASE", " Volume: ", "", int(volume()), "", false, true));
  dump->push_back(iteminfo("BASE", "    Weight: ", "", int(weight()), "", true, true));
  dump->push_back(iteminfo("BASE", " Bash: ", "", int(type->melee_dam), "", false));
  dump->push_back(iteminfo("BASE", (has_flag(IF_SPEAR) ? "  Pierce: " : "  Cut: "), "", int(type->melee_cut), "", false));
  dump->push_back(iteminfo("BASE", "  To-hit bonus: ", ((type->m_to_hit > 0) ? "+" : ""), int(type->m_to_hit), ""));
  dump->push_back(iteminfo("BASE", " Moves per attack: ", "", int(attack_time()), "", true, true));

 if (type->techniques != 0)
  for (int i = 1; i < NUM_TECHNIQUES; i++)
   if (type->techniques & mfb(i))
    dump->push_back(iteminfo("TECHNIQUE", " +",default_technique_name( technique_id(i) )));
 }

 if (is_food()) {
  it_comest* food = dynamic_cast<it_comest*>(type);

  dump->push_back(iteminfo("FOOD", " Nutrition: ", "", int(food->nutr)));
  dump->push_back(iteminfo("FOOD", " Quench: ", "", int(food->quench)));
  dump->push_back(iteminfo("FOOD", " Enjoyability: ", "", int(food->fun)));

 } else if (is_food_container()) {
 // added charge display for debugging
  it_comest* food = dynamic_cast<it_comest*>(contents[0].type);

  dump->push_back(iteminfo("FOOD", " Nutrition: ", "", int(food->nutr)));
  dump->push_back(iteminfo("FOOD", " Quench: ", "", int(food->quench)));
  dump->push_back(iteminfo("FOOD", " Enjoyability: ", "", int(food->fun)));
  dump->push_back(iteminfo("FOOD", " Portions: ", "", abs(int(contents[0].charges))));

 } else if (is_ammo()) {
  // added charge display for debugging
  it_ammo* ammo = dynamic_cast<it_ammo*>(type);

  dump->push_back(iteminfo("AMMO", " Type: ", ammo_name(ammo->type)));
  dump->push_back(iteminfo("AMMO", " Damage: ", "", int(ammo->damage)));
  dump->push_back(iteminfo("AMMO", " Armor-pierce: ", "", int(ammo->pierce)));
  dump->push_back(iteminfo("AMMO", " Range: ", "", int(ammo->range)));
  dump->push_back(iteminfo("AMMO", " Accuracy: ", "", int(100 - ammo->accuracy)));
  dump->push_back(iteminfo("AMMO", " Recoil: ", "", int(ammo->recoil), "", true, true));
  dump->push_back(iteminfo("AMMO", " Count: ", "", int(ammo->count)));

 } else if (is_ammo_container()) {
  it_ammo* ammo = dynamic_cast<it_ammo*>(contents[0].type);

  dump->push_back(iteminfo("AMMO", " Type: ", ammo_name(ammo->type)));
  dump->push_back(iteminfo("AMMO", " Damage: ", "", int(ammo->damage)));
  dump->push_back(iteminfo("AMMO", " Armor-pierce: ", "", int(ammo->pierce)));
  dump->push_back(iteminfo("AMMO", " Range: ", "", int(ammo->range)));
  dump->push_back(iteminfo("AMMO", " Accuracy: ", "", int(100 - ammo->accuracy)));
  dump->push_back(iteminfo("AMMO", " Recoil: ", "", int(ammo->recoil), "", true, true));
  dump->push_back(iteminfo("AMMO", " Count: ", "", int(contents[0].charges)));

 } else if (is_gun()) {
  it_gun* gun = dynamic_cast<it_gun*>(type);
  int ammo_dam = 0, ammo_recoil = 0;
  bool has_ammo = (curammo != NULL && charges > 0);
  if (has_ammo) {
   ammo_dam = curammo->damage;
   ammo_recoil = curammo->recoil;
  }

  dump->push_back(iteminfo("GUN", " Skill used: ", gun->skill_used->name()));
  dump->push_back(iteminfo("GUN", " Ammunition: ", "", int(clip_size()), " rounds of " + ammo_name(ammo_type())));

  temp1.str("");
  if (has_ammo)
   temp1 << ammo_dam;

  temp1 << (gun_damage(false) >= 0 ? "+" : "" );

  temp2.str("");
  if (has_ammo)
   temp2 << " = " << gun_damage();

  dump->push_back(iteminfo("GUN", " Damage: ", temp1.str(), int(gun_damage(false)), temp2.str()));
  dump->push_back(iteminfo("GUN", " Accuracy: ", "", int(100 - accuracy())));

  temp1.str("");
  if (has_ammo)
   temp1 << ammo_recoil;

  temp1 << (recoil(false) >= 0 ? "+" : "" );

  temp2.str("");
  if (has_ammo)
   temp2 << " = " << recoil();

  dump->push_back(iteminfo("GUN"," Recoil: ", temp1.str(), int(recoil(false)), temp2.str(), true, true));

  dump->push_back(iteminfo("GUN", " Reload time: ", "", int(gun->reload_time), ((has_flag(IF_RELOAD_ONE)) ? " per round" : ""), true, true));

  if (burst_size() == 0) {
   if (gun->skill_used == Skill::skill("pistol") && has_flag(IF_RELOAD_ONE))
    dump->push_back(iteminfo("GUN", " Revolver."));
   else
    dump->push_back(iteminfo("GUN", " Semi-automatic."));
  } else
   dump->push_back(iteminfo("GUN", " Burst size: ", "", int(burst_size())));

  if (contents.size() > 0)
   dump->push_back(iteminfo("GUN", "\n"));

  temp1.str("");
  for (int i = 0; i < contents.size(); i++)
   temp1 << "\n+" << contents[i].tname();

  dump->push_back(iteminfo("GUN", temp1.str()));

 } else if (is_gunmod()) {
  it_gunmod* mod = dynamic_cast<it_gunmod*>(type);

  if (mod->accuracy != 0)
   dump->push_back(iteminfo("GUNMOD", " Accuracy: ", ((mod->accuracy > 0) ? "+" : ""), int(mod->accuracy)));
  if (mod->damage != 0)
   dump->push_back(iteminfo("GUNMOD", " Damage: ", ((mod->damage > 0) ? "+" : ""), int(mod->damage)));
  if (mod->clip != 0)
   dump->push_back(iteminfo("GUNMOD", " Magazine: ", ((mod->clip > 0) ? "+" : ""), int(mod->clip), "%"));
  if (mod->recoil != 0)
   dump->push_back(iteminfo("GUNMOD", " Recoil: ", ((mod->recoil > 0) ? "+" : ""), int(mod->recoil), "", true, true));
  if (mod->burst != 0)
   dump->push_back(iteminfo("GUNMOD", " Burst: ", (mod->burst > 0 ? "+" : ""), int(mod->burst)));

  if (mod->newtype != AT_NULL)
   dump->push_back(iteminfo("GUNMOD", " " + ammo_name(mod->newtype)));

  temp1.str("");
  temp1 << " Used on: ";
  if (mod->used_on_pistol)
   temp1 << "Pistols.  ";
  if (mod->used_on_shotgun)
   temp1 << "Shotguns.  ";
  if (mod->used_on_smg)
   temp1 << "SMGs.  ";
  if (mod->used_on_rifle)
   temp1 << "Rifles.";

  dump->push_back(iteminfo("GUNMOD", temp1.str()));

 } else if (is_armor()) {
  it_armor* armor = dynamic_cast<it_armor*>(type);
  
  temp1.str("");
  temp1 << " Covers: ";
  if (armor->covers & mfb(bp_head))
   temp1 << "The head. ";
  if (armor->covers & mfb(bp_eyes))
   temp1 << "The eyes. ";
  if (armor->covers & mfb(bp_mouth))
   temp1 << "The mouth. ";
  if (armor->covers & mfb(bp_torso))
   temp1 << "The torso. ";
  if (armor->covers & mfb(bp_arms))
   temp1 << "The arms. ";
  if (armor->covers & mfb(bp_hands))
   temp1 << "The hands. ";
  if (armor->covers & mfb(bp_legs))
   temp1 << "The legs. ";
  if (armor->covers & mfb(bp_feet))
   temp1 << "The feet. ";

  dump->push_back(iteminfo("ARMOR", temp1.str()));

    if (has_flag(IF_FIT))
    {
        dump->push_back(iteminfo("ARMOR", " Encumberment: ", "", int(armor->encumber) - 1, " (fits)", true, true));
    }
    else
    {
        dump->push_back(iteminfo("ARMOR", " Encumberment: ", "", int(armor->encumber), "", true, true));
    }

  dump->push_back(iteminfo("ARMOR", " Bashing protection: ", "", int(armor->dmg_resist)));
  dump->push_back(iteminfo("ARMOR", " Cut protection: ", "", int(armor->cut_resist)));
  dump->push_back(iteminfo("ARMOR", " Environmental protection: ", "", int(armor->env_resist)));
  dump->push_back(iteminfo("ARMOR", " Warmth: ", "", int(armor->warmth)));
  dump->push_back(iteminfo("ARMOR", " Storage: ", "", int(armor->storage)));

} else if (is_book()) {

  it_book* book = dynamic_cast<it_book*>(type);
  if (!book->type)
   dump->push_back(iteminfo("BOOK", " Just for fun."));
  else {
    dump->push_back(iteminfo("BOOK", " Can bring your ", book->type->name() + " skill to ", int(book->level)));

   if (book->req == 0)
    dump->push_back(iteminfo("BOOK", " It can be understood by beginners."));
   else
    dump->push_back(iteminfo("BOOK", " Requires ", book->type->name() + " level ", int(book->req), " to understand.", true, true));
  }

  dump->push_back(iteminfo("BOOK", " Requires intelligence of ", "", int(book->intel), " to easily read.", true, true));
  if (book->fun != 0)
   dump->push_back(iteminfo("BOOK", " Reading this book affects your morale by ", (book->fun > 0 ? "+" : ""), int(book->fun)));

  dump->push_back(iteminfo("BOOK", " This book takes ", "", int(book->time), " minutes to read.", true, true));

 } else if (is_tool()) {
  it_tool* tool = dynamic_cast<it_tool*>(type);

  if ((tool->max_charges)!=0)
   dump->push_back(iteminfo("TOOL", " Maximum ", "", int(tool->max_charges), " charges" + ((tool->ammo == AT_NULL) ? "" : (" of " + ammo_name(tool->ammo))) + "."));

 } else if (is_style()) {
  it_style* style = dynamic_cast<it_style*>(type);

  for (int i = 0; i < style->moves.size(); i++) {
   dump->push_back(iteminfo("STYLE", default_technique_name(style->moves[i].tech), ". Requires Unarmed Skill of ", int(style->moves[i].level)));
  }

 }

 if ( showtext && !is_null() ) {
  dump->push_back(iteminfo("DESCRIPTION", type->description));
    if (is_armor() && has_flag(IF_FIT))
    {
        dump->push_back(iteminfo("DESCRIPTION", "\n\n"));
        dump->push_back(iteminfo("DESCRIPTION", "This piece of clothing fits you perfectly."));
    }  
  if (contents.size() > 0) {
   if (is_gun()) {
    for (int i = 0; i < contents.size(); i++)
     dump->push_back(iteminfo("DESCRIPTION", contents[i].type->description));
   } else
    dump->push_back(iteminfo("DESCRIPTION", contents[0].type->description));
  }
 }

 temp1.str("");
 std::vector<iteminfo>& vecData = *dump; // vector is not copied here
 for (int i = 0; i < vecData.size(); i++) {
  if (vecData[i].sType == "DESCRIPTION")
   temp1 << "\n";

  temp1 << vecData[i].sName;
  temp1 << vecData[i].sPre;

  if (vecData[i].iValue != -999)
   temp1 << vecData[i].iValue;

  temp1 << vecData[i].sPost;
  temp1 << ((vecData[i].bNewLine) ? "\n" : "");
 }

 return temp1.str();
}
Example #16
0
void
m_throw(struct monst *mon, int x, int y, int dx, int dy, int range,
        struct obj *obj, boolean verbose)
{
    struct monst *mtmp;
    struct obj *singleobj;
    struct tmp_sym *tsym = 0;
    int hitu, blindinc = 0;

    bhitpos.x = x;
    bhitpos.y = y;

    if (obj->quan == 1L) {
        /*
         * Remove object from minvent.  This cannot be done later on;
         * what if the player dies before then, leaving the monster
         * with 0 daggers?  (This caused the infamous 2^32-1 orcish
         * dagger bug).
         *
         * VENOM is not in minvent - it should already be OBJ_FREE.
         * The extract below does nothing.
         */

        /* not possibly_unwield, which checks the object's */
        /* location, not its existence */
        if (MON_WEP(mon) == obj) {
            setmnotwielded(mon, obj);
            MON_NOWEP(mon);
        }
        obj_extract_self(obj);
        singleobj = obj;
        obj = NULL;
    } else {
        singleobj = splitobj(obj, 1L);
        obj_extract_self(singleobj);
    }

    singleobj->owornmask = 0;   /* threw one of multiple weapons in hand? */
    singleobj->olev = level;    /* object is on the same level as monster */

    if ((singleobj->cursed || singleobj->greased) && (dx || dy) && !rn2(7)) {
        if (canseemon(mon) && flags.verbose) {
            if (is_ammo(singleobj))
                pline("%s misfires!", Monnam(mon));
            else
                pline("%s as %s throws it!", Tobjnam(singleobj, "slip"),
                      mon_nam(mon));
        }
        dx = rn2(3) - 1;
        dy = rn2(3) - 1;
        /* check validity of new direction */
        if (!dx && !dy) {
            drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
            return;
        }
    }

    /* pre-check for doors, walls and boundaries. Also need to pre-check for
       bars regardless of direction; the random chance for small objects
       hitting bars is skipped when reaching them at point blank range */
    if (!isok(bhitpos.x + dx, bhitpos.y + dy)
        || IS_ROCK(level->locations[bhitpos.x + dx][bhitpos.y + dy].typ)
        || closed_door(level, bhitpos.x + dx, bhitpos.y + dy)
        || (level->locations[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS &&
            hits_bars(&singleobj, bhitpos.x, bhitpos.y, 0, 0))) {
        drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
        return;
    }

    /* Note: drop_throw may destroy singleobj.  Since obj must be destroyed
       early to avoid the dagger bug, anyone who modifies this code should be
       careful not to use either one after it's been freed. */
    tsym = tmpsym_initobj(singleobj);

    while (range-- > 0) {      /* Actually the loop is always exited by break */
        bhitpos.x += dx;
        bhitpos.y += dy;
        if ((mtmp = m_at(level, bhitpos.x, bhitpos.y)) != 0) {
            if (ohitmon(mtmp, singleobj, range, verbose))
                break;
        } else if (bhitpos.x == u.ux && bhitpos.y == u.uy) {
            action_interrupted();

            if (singleobj->oclass == GEM_CLASS &&
                singleobj->otyp <= LAST_GEM + 9
                /* 9 glass colors */
                && is_unicorn(youmonst.data) && !u_helpless(hm_all)) {
                if (singleobj->otyp > LAST_GEM) {
                    pline("You catch the %s.", xname(singleobj));
                    pline("You are not interested in %s junk.",
                          s_suffix(mon_nam(mon)));
                    makeknown(singleobj->otyp);
                    dropy(singleobj);
                } else {
                    pline("You accept %s gift in the spirit in which it was "
                          "intended.", s_suffix(mon_nam(mon)));
                    hold_another_object(singleobj, "You catch, but drop, %s.",
                                        xname(singleobj), "You catch:");
                }
                break;
            }
            if (singleobj->oclass == POTION_CLASS) {
                if (!Blind)
                    singleobj->dknown = 1;
                potionhit(&youmonst, singleobj, FALSE);
                break;
            }
            switch (singleobj->otyp) {
                int dam, hitv;

            case EGG:
                if (!touch_petrifies(&mons[singleobj->corpsenm])) {
                    impossible("monster throwing egg type %d",
                               singleobj->corpsenm);
                    hitu = 0;
                    break;
                }
                /* fall through */
            case CREAM_PIE:
            case BLINDING_VENOM:
                hitu = thitu(8, 0, singleobj, NULL);
                break;
            default:
                dam = dmgval(singleobj, &youmonst);
                hitv = 3 - distmin(u.ux, u.uy, mon->mx, mon->my);
                if (hitv < -4)
                    hitv = -4;
                if (is_elf(mon->data) &&
                    objects[singleobj->otyp].oc_skill == P_BOW) {
                    hitv++;
                    if (MON_WEP(mon) && MON_WEP(mon)->otyp == ELVEN_BOW)
                        hitv++;
                    if (singleobj->otyp == ELVEN_ARROW)
                        dam++;
                }
                if (bigmonst(youmonst.data))
                    hitv++;
                hitv += 8 + singleobj->spe;
                if (dam < 1)
                    dam = 1;
                if (objects[singleobj->otyp].oc_class == WEAPON_CLASS ||
                    objects[singleobj->otyp].oc_class == VENOM_CLASS) {
                    hitv += objects[singleobj->otyp].oc_hitbon;
                }
                hitu = thitu(hitv, dam, singleobj, NULL);
            }
            if (hitu && singleobj->opoisoned && is_poisonable(singleobj)) {
                poisoned(xname(singleobj), A_STR,
                         killer_msg_obj(POISONING, singleobj), -10);
            }
            if (hitu &&
                can_blnd(NULL, &youmonst,
                         (uchar) (singleobj->otyp ==
                                  BLINDING_VENOM ? AT_SPIT : AT_WEAP),
                         singleobj)) {
                blindinc = rnd(25);
                if (singleobj->otyp == CREAM_PIE) {
                    if (!Blind)
                        pline("Yecch!  You've been creamed.");
                    else
                        pline("There's something sticky all over your %s.",
                              body_part(FACE));
                } else if (singleobj->otyp == BLINDING_VENOM) {
                    int num_eyes = eyecount(youmonst.data);

                    /* venom in the eyes */
                    if (!Blind)
                        pline("The venom blinds you.");
                    else
                        pline("Your %s sting%s.",
                              (num_eyes ==
                               1) ? body_part(EYE) : makeplural(body_part(EYE)),
                              (num_eyes == 1) ? "s" : "");
                }
            }
            if (hitu && singleobj->otyp == VAMPIRE_BLOOD) {
                if (!Drain_resistance) {
                    losexp("vampire blood", FALSE);
                }
            }
            if (hitu && singleobj->otyp == EGG) {
                if (touched_monster(singleobj->corpsenm))
                    Stoned = 5;
            }
            action_interrupted();
            if (hitu || !range) {
                drop_throw(singleobj, hitu, u.ux, u.uy);
                break;
            }
        } else if (!range       /* reached end of path */
                   /* missile hits edge of screen */
                   || !isok(bhitpos.x + dx, bhitpos.y + dy)
                   /* missile hits the wall */
                   || IS_ROCK(level->
                              locations[bhitpos.x + dx][bhitpos.y + dy].typ)
                   /* missile hit closed door */
                   || closed_door(level, bhitpos.x + dx, bhitpos.y + dy)
                   /* missile might hit iron bars */
                   || (level->locations[bhitpos.x + dx][bhitpos.y + dy].typ ==
                       IRONBARS &&
                       hits_bars(&singleobj, bhitpos.x, bhitpos.y, !rn2(5), 0))
                   /* Thrown objects "sink" */
                   || IS_SINK(level->locations[bhitpos.x][bhitpos.y].typ)) {
            if (singleobj)      /* hits_bars might have destroyed it */
                drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
            break;
        }
        tmpsym_at(tsym, bhitpos.x, bhitpos.y);
        win_delay_output();
    }
    tmpsym_at(tsym, bhitpos.x, bhitpos.y);
    win_delay_output();
    tmpsym_end(tsym);

    if (blindinc) {
        u.ucreamed += blindinc;
        make_blinded(Blinded + (long)blindinc, FALSE);
        if (!Blind)
            pline("Your vision quickly clears.");
        else if (flags.verbose)
            pline("Use the command #wipe to clean your %s.", body_part(FACE));
    }
}