Added javelins and sling bullets. Only Urug gets javelins at the moment. No monster gets sling bullets, but they can be randomly generated.
Added deep elf blademasters and master archers to provide Silence-users some entertainment on Elf:7. I've adjusted the non-rogue-layout Elf:7s to use blademasters.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1732 c06c8d41-db1a-0410-9941-cceddc491573
5V47S4NNTHWTSAHV3YLO2VGH7JTUIYJ3GBPDN5ZM4UQALT2ZEXDQC
4DOLKETM4WHB5JUNXNBZJJKMJSMABCQOFPMKREE5VCQHRUEDR3MAC
URJJYXCQMYOXKHYG32UITLRICMPENXYISVWNHTXNGRBH36GJTIHAC
4GGNXCX2CLKWQZIZT543LXFFKFRD4PY5XPJFLGWKW4ACKYZNLVPQC
VNIAJEGE3PYE6F6EAMCQDWMAS52EQTKJUPAFXK7ARCITZ326WTTQC
H3552BCIAVBLKAYKE4DHFLBLFW5RGRMYBMRRYHYEB5IPIJRUVU5QC
QS3ZRS3E6KL3YJHPKYEWCWJYRBJSXD5OOYF6Y25HZVECGPJRDB5QC
2QMDACGXJJYBL2CQIXJLNJ65GL3WJMW4ZRE3BTKK4HRWCBLST5UQC
OYTCBRC7LE44EUVRZVYTOOVKQWJ6P6YE3FXTOGUTNKEMLNWPHKSQC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
QKGDOYIYKE6B36ION5O2DRW65DWWPZMYNWJVH7LJJ7FPGGM2MYAQC
74LQ7JXVLAFSHLI7LCBKFX47CNTYSKGUQSXNX5FCIUIGCC2JTR3QC
FA2V3G4NYTWJWUT7EWH75L3YOUX6YVOZ5LNRSFLO2XF273JKSUTAC
E5DMZFW6WCFAKTKKOQPYTQXZ2CGLWMVH64LRXDUI2UIG4VYUHIVQC
XRZPPYWPWUOM4SFNI6BHKH2UKJQNLKOV6Y7XIEPEZXE5QYRT26PAC
33ZMPQC6OXTESW7SRW765GRNJUEJRSYONRVZVIEUDAUEJ2PPMB4AC
QDTVLBRGHDTRUVT7I3O72K6TMOYAUSAJBZUHGOEFU2RKJNUPWZSQC
Y56C5OMUQ5XF2G6DKDV4R5MED44UOIUPTBBQVWQBUHYIXYA5MOZAC
FUEEIUKGHHFPIRZCN3N753GONWAZTWQ2ZWR53IBJAAZ6FZUNGOMAC
DTO3EUKWHZ5RJNGNCFYXSOVTIPVXPP637F2W7WFGYKJ7JK7VNKNQC
BWAQ3FHBBM6G3K3KYP75CRTR343RDQZJRYX5ZGYUEXYBAC3APDLAC
AVSMB4Y6F6ZMMNNPOAQQZ34OWC6N5JOURTEWFTUKDWMIIMLWWJUAC
WW6THKR7JN447YC23YYHYYNH7ABMCFFSECNUFTIJBZX6JHX6W7TAC
TAVHZJPVNJBZR7CUURAOYNDZPNVQ3AGHTXDEP5K4JGYETBLQJDRQC
VNHFP63ZLLZU3A3PLXP4BITX57DUIYDHFOHQYK3BOBHV3S64G26QC
CIPVRZGLOZHCERK6YPOBV3P2E4IAB4H6D5EHLRQE2O5E4P4VCBUAC
IPB47Q5V3UZIUXP4CHHLYXA5UA4ETTNXJACUBD6YWVIYQDMCZNAAC
ASCTVJSN3NXYQHRVXAORA43CV6H5V2572IMK4UGRHKBAGJOWHC4AC
5KJCHLIUFKRPMIVWUAYT6EOF7SW4PTQF6Y5OPEFWXGLE7DUGYLZAC
2WNUWTZNE66IUUTQ4NW3RN7P2MFUKBXPD265M5CTZCDKC56VQONQC
JVSCP4FTW2G57C6YD5HZOZXTODGZH7TR75JQGFJBEPX3LCZH236QC
R22TTMI6WXWULC7ODKFF3QCB7MOTETQQ6IR4BUCUPOCQKQNCTT5AC
IPQ63XIUPHFMCQOZZAVSGCJOZFDRDWZTUUJSAUMARNDUFLBEMYIAC
WE3JT43OR4L6675GINGU4B3YDBMURJZHDDYY3VLHUJEBAKH2HYEAC
ZJLJGSB2XSBQU42OFQMXL3EG4CXAQGOYAU6YTV2SAWZEJIPFH2CAC
X5WLJCJVW55SXZVP7IKP7ADCJIGNKN4PKAXFECVR6TNK7XSMZR7QC
ZCPJIAG7SEY2TUBAGOFWCEJYXSBT36CZU5VO7BWEGSLJ4K24B4TAC
ZBTD5R4OOQ5D4W6ZRK2XEGLI3AWI37Z2G5X2EQ6IYPXDYKCKWMFAC
HYS3HXTXATFPN7GLN3WBGDCP22UT2D3JBVUS7SP5FE7L54TDCJRQC
X2FMEN4E345XD26Z2X7JMJ7VGHOGCGIELMHQRE2ITLVNQACP3NOQC
YRY2TC3VHOYE47M23UJGUWDGF7H7WGU7WLWI4SUNM4EDNTGUPHGAC
RVST2QHYJ757ZHK4AUJ5NGPDZ44AD6RVFVXYPKQIBJXZBDNUCHXQC
Y3ZCJ2CZJYJAEB76HS4EY4GD64TDPPKANQVNDEH2OJPRDPZWJNYAC
R5Q2OJMXNVK5RPXIKLTHHAOP67XOBB44AZKKZ2TOI3USPL6HACXAC
WQU4ORZR2C52JNRTH5DN4XKNLEC4Q4SUZ7MLO6MBU6SSL2YXLSOAC
GNDVGD7P554FJICPKWYQYXZ46HDMRYKOGZL4XZS2CPF3SNF5UO7QC
int random_choose_weighted(int weight, int first, ...)
{
va_list args;
va_start(args, first);
int chosen = first, cweight = weight, nargs = 100;
while (nargs-- > 0)
{
const int nweight = va_arg(args, int);
if (!nweight)
break;
const int choice = va_arg(args, int);
if (random2(cweight += nweight) < nweight)
chosen = choice;
}
ASSERT(nargs > 0);
va_end(args);
return (chosen);
}
// last updated Jan14,2001 -- gdl
/* ***********************************************************************
* called from: monstuff
* *********************************************************************** */
void throw_type(int lnchClass, int lnchType, int wepClass, int wepType,
bool &launched, bool &thrown);
// decide if something is launched or thrown
// pass -1 for launcher class & 0 for type if no weapon is wielded
void throw_type( int lnchClass, int lnchType, int wepClass, int wepType,
bool &launched, bool &thrown )
{
if (wepClass == OBJ_MISSILES
&& lnchClass == OBJ_WEAPONS
&& is_range_weapon_type(static_cast<weapon_type>(lnchType))
&& wepType == fires_ammo_type(static_cast<weapon_type>(lnchType)))
{
launched = true;
}
if (wepClass == OBJ_WEAPONS)
{
if (wepType == WPN_DAGGER || wepType == WPN_HAND_AXE || wepType == WPN_SPEAR)
{
thrown = true;
}
}
if (wepClass == OBJ_MISSILES)
{
if (wepType == MI_DART || wepType == MI_STONE || wepType == MI_LARGE_ROCK)
{
thrown = true;
}
}
// launched overrides thrown
if (launched == true)
thrown = false;
}
// figure out if we're thrown or launched
throw_type( lnchClass, lnchType, wepClass, wepType, launched, thrown );
if (returning)
{
launched = false;
thrown = true;
}
const launch_retval projected =
is_launched(monster, monster->mslot_item(MSLOT_WEAPON),
mitm[hand_used]);
if (thrown)
// Archers get a boost from their melee attack.
if (mons_class_flag(monster->type, M_ARCHER))
{
const mon_attack_def attk = mons_attack_spec(monster, 0);
if (attk.type == AT_SHOOT)
ammoDamBonus += random2avg(attk.damage, 2);
}
if (projected == LRET_THROWN)
// recent addition {GDL} - monsters won't throw if they can do melee.
// wastes valuable ammo, and most monsters are better at melee anyway.
if (adjacent( beem.target_x, beem.target_y, monster->x, monster->y ))
// Monsters won't shoot in melee range, largely for balance reasons.
// Specialist archers are an exception to this rule.
if (!archer
&& adjacent( beem.target_x, beem.target_y, monster->x, monster->y ))
{
const int weapon = mon->inv[MSLOT_WEAPON];
const int ammo = mon->inv[MSLOT_MISSILE];
if ( weapon != NON_ITEM &&
get_weapon_brand(mitm[weapon]) == SPWPN_RETURNING )
return true;
const int lnchClass = (weapon != NON_ITEM) ? mitm[weapon].base_type : -1;
const int lnchType = (weapon != NON_ITEM) ? mitm[weapon].sub_type : 0;
const int ammoClass = (ammo != NON_ITEM) ? mitm[ammo].base_type : -1;
const int ammoType = (ammo != NON_ITEM) ? mitm[ammo].sub_type : 0;
bool launched = false;
bool thrown = false;
throw_type( lnchClass, lnchType, ammoClass, ammoType, launched, thrown );
// Ugh.
monsters *mnc = const_cast<monsters*>(mon);
const item_def *weapon = mnc->launcher();
const item_def *primary = mnc->mslot_item(MSLOT_WEAPON);
const item_def *missile = mnc->missiles();
MONUSE_WEAPONS_ARMOUR, SIZE_MEDIUM
}
,
{
MONS_DEEP_ELF_BLADEMASTER, 'e', LIGHTCYAN, "deep elf blademaster",
M_WARM_BLOOD | M_FIGHTER,
MR_NO_FLAGS,
450, 10, MONS_ELF, MONS_ELF, MH_NATURAL, -6,
{ {AT_HIT, AF_PLAIN, 25}, {AT_HIT, AF_PLAIN, 25}, {AT_NONE, AF_PLAIN, 0}, {AT_NONE, AF_PLAIN, 0} },
{ 16, 5, 3, 0 },
0, 25, 15, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_HIGH,
MONS_DEEP_ELF_MASTER_ARCHER, 'e', LIGHTMAGENTA, "deep elf master archer",
M_WARM_BLOOD | M_ARCHER,
MR_NO_FLAGS,
450, 10, MONS_ELF, MONS_ELF, MH_NATURAL, -5,
// Attack damage gets rolled into their ranged attacks.
{ {AT_SHOOT, AF_PLAIN, 25}, {AT_HIT, AF_PLAIN, 5}, {AT_NONE, AF_PLAIN, 0}, {AT_NONE, AF_PLAIN, 0} },
{ 15, 4, 2, 0 },
0, 15, 11, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_HIGH,
MONUSE_WEAPONS_ARMOUR, SIZE_MEDIUM
}
,
{
break;
}
case MONS_DEEP_ELF_BLADEMASTER:
{
item_race = MAKE_ITEM_ELVEN;
item.base_type = OBJ_WEAPONS;
// If the blademaster already has a weapon, give him the exact same
// sub_type to match.
const item_def *weap = mon->mslot_item(MSLOT_WEAPON);
if (weap && weap->base_type == OBJ_WEAPONS)
item.sub_type = weap->sub_type;
else
item.sub_type = random_choose_weighted(40, WPN_SABRE,
10, WPN_SHORT_SWORD,
2, WPN_QUICK_BLADE,
0);
break;
}
case MONS_DEEP_ELF_MASTER_ARCHER:
{
item_race = MAKE_ITEM_ELVEN;
item.base_type = OBJ_WEAPONS;
item.sub_type = WPN_LONGBOW;
}
static std::string pow_in_words(int pow)
{
switch (pow)
{
case 0:
return "";
case 3:
return " thousand";
case 6:
return " million";
case 9:
return " billion";
case 12:
default:
return " trillion";
}
}
static std::string tens_in_words(unsigned num)
{
static const char *numbers[] = {
"", "one", "two", "three", "four", "five", "six", "seven",
"eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen",
"fifteen", "sixteen", "seventeen", "eighteen", "nineteen"
};
static const char *tens[] = {
"", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy",
"eighty", "ninety"
};
if (num < 20)
return numbers[num];
int ten = num / 10, digit = num % 10;
return std::string(tens[ten])
+ (digit? std::string("-") + numbers[digit] : "");
static std::string join_strings(const std::string &a, const std::string &b)
{
return !a.empty() && !b.empty()? a + " " + b :
a.empty()? b : a;
}
static std::string hundreds_in_words(unsigned num)
{
unsigned dreds = num / 100, tens = num % 100;
std::string sdreds = dreds? tens_in_words(dreds) + " hundred" : "";
std::string stens = tens? tens_in_words(tens) : "";
return join_strings(sdreds, stens);
}
std::string number_in_words(unsigned num, int pow)
{
if (pow == 12)
return number_in_words(num, 0) + pow_in_words(pow);
unsigned thousands = num % 1000, rest = num / 1000;
if (!rest and !thousands)
return ("zero");
return join_strings((rest? number_in_words(rest, pow + 3) : ""),
(thousands? hundreds_in_words(thousands) + pow_in_words(pow)
: ""));
}
bool is_throwable( const item_def &wpn );
launch_retval is_launched( int being_id, const item_def &ammo, bool msg = false );
const char * ammo_name( missile_type mtyp );
bool is_throwable( const item_def &wpn,
size_type bodysize = SIZE_MEDIUM );
launch_retval is_launched(actor *actor, const item_def *launcher,
const item_def &missile);
{ MI_NEEDLE, "needle", 0, 1, false },
{ MI_STONE, "stone", 4, 2, true },
{ MI_DART, "dart", 5, 3, true },
{ MI_ARROW, "arrow", 6, 5, false },
{ MI_BOLT, "bolt", 8, 5, false },
{ MI_LARGE_ROCK, "large rock", 20, 1000, true },
{ MI_NEEDLE, "needle", 0, 1, false },
{ MI_STONE, "stone", 4, 2, true },
{ MI_DART, "dart", 5, 3, true },
{ MI_ARROW, "arrow", 7, 5, false },
{ MI_BOLT, "bolt", 9, 5, false },
{ MI_LARGE_ROCK, "large rock", 20, 1000, true },
{ MI_SLING_BULLET, "sling bullet", 6, 4, true },
{ MI_JAVELIN, "javelin", 11, 40, true },
}
// decide if something is launched or thrown
launch_retval is_launched(actor *actor, const item_def *launcher,
const item_def &missile)
{
if (missile.base_type == OBJ_MISSILES
&& launcher
&& missile.launched_by(*launcher))
{
return (LRET_LAUNCHED);
}
return (is_throwable(missile, actor->body_size())?
LRET_THROWN : LRET_FUMBLED);
// FIXME
#if 0
// decide if "being" is launching or throwing "ammo"
launch_retval is_launched( int being_id, const item_def &ammo, bool msg )
{
ASSERT( being_id != MHITNOT );
launch_retval ret = LRET_FUMBLED;
const item_def * lnch = 0;
int fit = 0;
if (being_id == MHITYOU)
{
const int wpn = get_inv_wielded();
lnch = (wpn == -1) ? 0 : &you.inv[wpn];
fit = fit_item_throwable_size( ammo, player_size() );
}
else // monster case
{
const int wpn = menv[being_id].inv[MSLOT_WEAPON];
lnch = (wpn == NON_ITEM) ? 0 : &mitm[wpn];
fit = fit_item_throwable_size( ammo, mons_size( menv[being_id].type ) );
}
if (lnch
&& lnch->base_type == OBJ_WEAPONS
&& is_range_weapon( *lnch )
&& ammo.base_type == OBJ_MISSILES
&& ammo.sub_type == fires_ammo_type( *lnch ))
{
ret = LRET_LAUNCHED;
}
else if (is_throwable( ammo ))
{
if (fit == 0)
ret = LRET_THROWN;
else
{
ret = LRET_FUMBLED;
if (being_id == MHITYOU && msg)
{
mpr( MSGCH_WARN, "It's difficult to throw such a%s object.",
(fit > 0) ? " large" : (fit < 0) ? " small" : "n awkward" );
}
}
}
return (ret);
}
#endif
switch (item_typ)
{
case MI_STONE: buff << "stone"; break;
case MI_ARROW: buff << "arrow"; break;
case MI_BOLT: buff << "bolt"; break;
case MI_DART: buff << "dart"; break;
case MI_NEEDLE: buff << "needle"; break;
case MI_LARGE_ROCK: buff << "large rock" ; break;
default: buff << "hysterical raisin"; break;
}
buff << racial_description_string(*this, terse)
<< ammo_name(static_cast<missile_type>(item_typ));
if (you.inv[i].base_type == OBJ_MISSILES &&
you.inv[i].sub_type == sub_type &&
check_warning_inscriptions(you.inv[i], OPER_FIRE))
if (item.base_type == OBJ_MISSILES
&& (item.sub_type == sub_type
|| (sub_type == MI_STONE && item.sub_type == MI_SLING_BULLET))
&& check_warning_inscriptions(you.inv[i], OPER_FIRE))
if (multiplier > 100)
value = value * (100 + random2avg(multiplier - 100, 2)) / 100;
else if (multiplier < 100)
value = value * (100 - random2avg(100 - multiplier, 2)) / 100;
return (value);
}
static int str_adjust_thrown_damage(int dam)
{
return stat_adjust(dam, you.strength, 15, 160, 90);
}
static int dex_adjust_thrown_tohit(int hit)
{
return stat_adjust(hit, you.dex, 13, 160, 90);
}
// give an appropriate 'tohit' & damage
baseHit = 2;
baseDam = property( item, PWPN_DAMAGE );
switch (wepType)
{
case MI_DART:
// give an appropriate 'tohit' & damage
baseHit = 2;
baseDam = property( item, PWPN_DAMAGE );
exHitBonus = you.skills[SK_DARTS] * 2;
exHitBonus += (you.skills[SK_RANGED_COMBAT] * 2) / 3;
exDamBonus = you.skills[SK_DARTS] / 3;
exDamBonus += you.skills[SK_RANGED_COMBAT] / 5;
// exercise skills
exercise(SK_DARTS, 1 + random2avg(3, 2));
break;
case MI_JAVELIN:
// Javelins use polearm and throwing skills.
baseHit = -1;
baseDam = property( item, PWPN_DAMAGE );
exHitBonus += (skill_bump(SK_RANGED_COMBAT) * 3
+ skill_bump(SK_POLEARMS));
exDamBonus += you.skills[SK_RANGED_COMBAT] / 5;
exDamBonus += you.skills[SK_POLEARMS] * 2 / 5;
exHitBonus = you.skills[SK_DARTS] * 2;
exHitBonus += (you.skills[SK_RANGED_COMBAT] * 2) / 3;
exDamBonus = you.skills[SK_DARTS] / 3;
exDamBonus += you.skills[SK_RANGED_COMBAT] / 5;
// Adjust for strength and dex.
exDamBonus = str_adjust_thrown_damage(exDamBonus);
exHitBonus = dex_adjust_thrown_tohit(exHitBonus);
// exercise skills
exercise(SK_DARTS, 1 + random2avg(3, 2));
// High dex helps damage a bit, too (aim for weak spots).
exDamBonus = stat_adjust(exDamBonus, you.dex, 20, 150, 100);
// exercise skills
exercise(SK_POLEARMS, 1 + random2avg(4, 2));
break;
}
fire_order[1] = FIRE_DART; // then only consider darts
fire_order[2] = FIRE_STONE; // and then chuck stones
fire_order[1] = FIRE_JAVELIN;
fire_order[2] = FIRE_DART; // then only consider darts
fire_order[3] = FIRE_STONE; // and then chuck stones
}
static void describe_monster_weapon(monsters *mons)
{
std::string name1, name2;
const item_def *weap = mons->mslot_item(MSLOT_WEAPON),
*alt = mons->mslot_item(MSLOT_ALT_WEAPON);
if (weap)
name1 = weap->name(DESC_NOCAP_A);
if (alt && (!weap || mons_wields_two_weapons(mons)))
name2 = alt->name(DESC_NOCAP_A);
if (name1.empty() && !name2.empty())
name1.swap(name2);
if (name1 == name2 && weap)
{
item_def dup = *weap;
++dup.quantity;
name1 = dup.name(DESC_NOCAP_A, false, false, true, true);
name2.clear();
}
if (name1.empty())
return;
std::ostringstream msg;
msg << mons_pronoun( mons->type, PRONOUN_CAP )
<< " is wielding " << name1;
if (!name2.empty())
msg << " and " << name2;
msg << ".";
mpr(msg.str().c_str());
if (menv[i].type != MONS_DANCING_WEAPON && mon_wep != NON_ITEM)
{
std::ostringstream msg;
msg << mons_pronoun( menv[i].type, PRONOUN_CAP )
<< " is wielding "
<< mitm[mon_wep].name(DESC_NOCAP_A);
// 2-headed ogres can wield 2 weapons
if ((menv[i].type == MONS_TWO_HEADED_OGRE
|| menv[i].type == MONS_ETTIN)
&& menv[i].inv[MSLOT_ALT_WEAPON] != NON_ITEM)
{
msg << " and "
<< mitm[menv[i].inv[MSLOT_ALT_WEAPON]].name(DESC_NOCAP_A);
}
msg << ".";
mpr(msg.str().c_str());
}
if (menv[i].type != MONS_DANCING_WEAPON)
describe_monster_weapon(&menv[i]);
break;
case MI_SLING_BULLET:
description += "A small heavy projectile made of lead. "
"It can be fired with a sling, or thrown by hand.";
break;
case MI_JAVELIN:
description += "A long, light polearm that can be thrown by hand. ";
if (!is_throwable(item, you.body_size()))
description += "Unfortunately, it is too long and awkward "
"for you to use.";
case MONS_DEEP_ELF_SOLDIER:
description << "This one is just a common soldier.";
break;
case MONS_DEEP_ELF_FIGHTER:
description << "This soldier has learned some magic.";
break;
case MONS_DEEP_ELF_KNIGHT:
description << "This one bears the scars of battles past.";
break;
case MONS_DEEP_ELF_MAGE:
description << "Mana crackles between this one's long fingers.";
break;
case MONS_DEEP_ELF_SUMMONER:
description << "This one is a mage specialized in the ancient "
"art of summoning servants of destruction.";
break;
case MONS_DEEP_ELF_CONJURER:
description << "This one is a mage specialized in the ancient "
"art of hurling energies of destruction.";
break;
case MONS_DEEP_ELF_PRIEST:
description << "This one is a servant of the deep elves' god.";
break;
case MONS_DEEP_ELF_HIGH_PRIEST:
description <<
"This one is an exalted servant of the deep elves' god.";
break;
case MONS_DEEP_ELF_DEMONOLOGIST:
description <<
"This mage specialized in demonology, and is marked heavily "
"from long years in contact with unnatural demonic forces.";
break;
case MONS_DEEP_ELF_ANNIHILATOR:
description << "This one likes destructive magics more than most, "
"and is better at them.";
break;
case MONS_DEEP_ELF_SORCERER:
description << "This mighty spellcaster draws power from Hell.";
break;
case MONS_DEEP_ELF_DEATH_MAGE:
description << "A strong negative aura surrounds this one.";
break;
const item_def &weapon = you.inv[ you.equip[EQ_WEAPON] ];
item_buf = weapon.name(DESC_PLAIN, true);
if (is_range_weapon(weapon))
if (you.equip[EQ_WEAPON] != -1)
const int missile =
missile_slot == -1? get_fire_item_index() :
missile_slot;
if (missile < ENDOFPACK)
return item_buf+" with "+you.inv[missile].name(DESC_PLAIN);
const item_def &weapon = you.inv[ you.equip[EQ_WEAPON] ];
item_buf = weapon.name(DESC_PLAIN, true);
if (is_range_weapon(weapon))
{
const int missile =
missile_slot == -1? get_fire_item_index() :
missile_slot;
if (missile < ENDOFPACK)
return item_buf + " with "
+ you.inv[missile].name(DESC_PLAIN);
}
if (you.inv[i].name(DESC_PLAIN).find(weapon) != std::string::npos)
{
if (i != you.equip[EQ_WEAPON])
if (you.inv[i].name(DESC_PLAIN).find(weapon) != std::string::npos)
deep elf blademaster
Once in a very great while, there is a deep elf that scorns magic and
devotes herself to the study of the sword. This is such a champion of
the deep elves, wielding two blades with lethal grace.
%%%%
deep elf master archer
This legendary deep elf archer has devoted her whole life to the
pursuit of archery, dismissing magic as a frivolous distraction.
%%%%
around to get a description of the various dungeon features, and typing
'v' when the cursor is over a monster brings up a short description of
that monster. You can get a map of the whole level (which shows where
you've already been) by typing the 'X' key. On this map, stairs and
known traps are specially colour-coded airs and known traps, even if
something is on top of them.
around to get a description of the various dungeon features, and
typing 'v' when the cursor is over a monster or feature brings up a
short description of that monster. You can get a map of the whole
level (which shows where you've already been) by typing the 'X' key.
On this map, stairs and known traps are specially colour-coded, even
if there's something on top of them.
When you are in a shop, you are given a list of the shopkeeper's stock
from which to choose goods. Unfortunately the shopkeepers all have an
enterprise bargaining agreement with the dungeon teamsters union which
prevents them using non-union labour to obtain stock, so you can't sell
anything in a shop (but what shopkeeper would really buy goods from a
disreputable adventurer like you, anyway?) In shops you have access to
your inventory and to your list of already discovered items. You can
purchase items by pressing the letter of each item in the shop menu; by
pressing 'v' and then the letter, you can get information about the item
you are considering purchasing.
When you visit a shop, you are shown what the shopkeeper has in stock
and can choose what to buy. Unfortunately the shopkeepers all have an
exclusive deal with the Guild of Dungeon Procurers which prevents them
using non-guild labour to obtain stock, so you can't sell anything in
a shop (but what shopkeeper would buy stolen goods from a disreputable
adventurer, anyway?)
You can check your inventory and the items you've identified while
you're shopping, which may help to decide if you really need that
expensive item.
To purchase an item, press the letter of the item in the shop menu;
you can examine stuff before you buy it by pressing 'v' and then the
letter of the item.
If you've lost track of the shops in the dungeon, you can get a list
of all the shops you've found in the dungeon overview (use 'O').
You can also use the stash search: hitting 'Ctrl-F' and searching for
"shop" will list all stores. The stash-search menu allows you travel
quickly to a particular shop; if you just want to know what's in the
shop, you can examine the shop's inventory from the search menu
without having to travel all the way to the shop.
Crawl has an extensive automated travel system: pressing Ctrl-G lets you
chose any dungeon level; the game will then take the shortest path to
reach this destination. You can also use autotravel on the level map
('X'): move the cursor to the place where you want to go and hit Enter.
There are several shortcuts when choosing destinations: try '<' and '>'
to quickly reach the staircases.
Crawl has an extensive automated travel system: pressing Ctrl-G lets
you choose any dungeon level; the game will then take the shortest
path to reach this destination. You can also use autotravel on the
level map ('X'): move the cursor to the place where you want to go and
hit Enter. There are several shortcuts when choosing destinations: try
'<' and '>' to quickly reach the staircases.
When your autotravel gets interrupted, Crawl will remember the previous
destination. Hitting Ctrl-G again and following with Enter puts the
cursor on that square. See Appendix 4 for all commands and shortcuts in
level-map mode.
When your autotravel gets interrupted, Crawl will remember the
previous destination. Hitting Ctrl-G again and following with Enter
puts the cursor on that square. See Appendix 4 for all commands and
shortcuts in level-map mode.
The above assumes that use of the default option 'stash_tracking = all'.
If for some reasons (e.g. to speed up performance) the value has been
changed, you can press Ctrl-S to tell Crawl that a given square is
considered a stash. Ctrl-E will manually erase stashes.
The above assumes that use of the default option 'stash_tracking =
all'. If for some reasons (e.g. to speed up performance) you've
changed the value of the stash_tracking option, you can press Ctrl-S
to tell Crawl that a given square is considered a stash. Ctrl-E will
manually erase stashes.
can be said that race differentiation is still not finished - what sets
the High and Grey Elves really apart? A weak spot of the current skill
system is 'victory dancing', where characters spend the experience
accumulated in a big battle with stupid actions (like casting Magic Dart
at the wall) in order to increase specific skills.
can be said that race differentiation is still not finished - we try to
make differentiation better by going beyond aptitudes alone. A weak spot
of the current skill system is 'victory dancing', where characters spend
the experience accumulated in a big battle with stupid actions (like
casting Magic Dart at the wall) in order to increase specific skills.
While this surely seems dubious, it also allows players to adapt their
characters anytime during play - e.g. to make a transition from a pure
melee fighter to a hybrid using enchantments. For this reason, changing
the experience system is no easy task.
constructed with this in mind: even veteran players will find the Hells
exciting (which themselves are construed such that life endangering
constructed with this in mind: even veteran players will find the Tomb or
the Hells exciting (which are construed such that life endangering
players on their toes. The same can be said of uniques.
players on their toes. The same can be said of uniques. Also, frequent
and early trips to the Abyss are not deficits: there's more than one way
out and possibly doing so should be exciting for all characters.
Mountain Dwarves:
-----------------
Mountain dwarves come from the larger, more civilised communities of
the mountains. They advance slightly more quickly than hill dwarves
and are almost as robust while having similar aptitudes, but are
slightly worse at fighting while being slightly better at more
civilised pursuits.
rather less pleasant Death-God Yredelemnul. Although priests enter the
dungeon with a mace (as well as a priestly robe and a few healing
potions), this is purely the result of an archaic tradition the reason
for which has been lost in the mists of time; Priests are not in any way
rather less pleasant Death-God Yredelemnul. Hill Orcs may choose to
follow the Orc god Beogh instead. Although priests enter the dungeon
with a mace (as well as a priestly robe and a few healing potions),
this is purely the result of an archaic tradition the reason for which
has been lost in the mists of time; Priests are not in any way
Ranged Combat is the basic skill used when throwing or shooting things,
and there are a number of individual weapon skills for missile weapons
as well:
Ranged Combat is the basic skill used when throwing or shooting things.
It affects in particular how effectively poisoned missiles are. There
are a number of individual weapon skills for missile weapons as well:
Interlevel travel menu ('Ctrl-G')
---------------------------------
Interlevel travel allows you to specify a destination far away from your
current place. Crawl will chose the shortest path to move there. Should
you get interrupted, the old destination is saved and can be reused.
Other shortcuts are:
< Travels to the nearest upstairs.
> Travels to the nearest downstairs.