valuation is shopping.cc. It currently only reflects missiles that are blocked with the shield. They could also reflect the brand effects of blocked melee weapons, but I'm not sure if that's a good idea.
drop_item and the item to be dropped have been moved from fire_beam()'s parameters into the bolt structure, along with the beam's remaining range. Seems to work fine, but it might still lead to some buggyness.
The game now distinguishes between killing yourself by hitting yourself with a beam bounced off a wall versus other forms of self targeting.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7705 c06c8d41-db1a-0410-9941-cceddc491573
CDFS7Z74W5HKPQIHQICOG442KQFXUSBGGLDDQLE3MG74T44YU6AQC
ZUKTDWZ4R5VZLWO22E3RWAGTUF4HZ6DUXY65VLWQZVAFYJZGZP4QC
3USQPDXQMQUTNA3EZJUQ4NJMNPNF3IA7GVMOVG56P2XSVBWDHLXAC
TO74NQE4DXNBFQ3OOVHUSWKUCDSEUWLXVUAZF3XJU5TU7BDRPNUAC
QZM4EDMUKU7QWQKWXHTRINNWH3GQQ6RSAX7WIX6PQAEM5V2Y2BQQC
VVVOUK7QZU3NNYAI6SJNWM5ZK7362HIXXSQI5BKVMHHL2CXMYXMQC
5FHWTG7M6FW4B3I33YI7QSM3OZIB6ZGC6TI6JISSLY5Y43HI56VAC
BYURAML2EPTULHH22Q5RPXYGDEYAJYESR6C72UMNPPYHTCJZUPFAC
JDIK6Y6PQBNY4C7XGSTUDWNDHP3KUEV54SGWOBLVUHNE4H674TEQC
SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
3DQXSE4YGFBBDUWK4YEOFWW4UPWILWELFSLP37SL6BERGAZJC5YAC
5BJPWUPLJFS34FUTFJVKA4A52YMIGV6EWDXLNSDCWBJWBGVSQFGQC
Y2NYY7HWFZ2LQDK3ACSLGS37F2J2IJ5LRGCIMZYXLEOSVPD3A4DAC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
FA2V3G4NYTWJWUT7EWH75L3YOUX6YVOZ5LNRSFLO2XF273JKSUTAC
AMAPVOFKH3YS5VCVOG2YNHXNDAZATMXFUL6ODZUIOF5OYYKBVKGAC
W74555HMPXUQ72AGKBXC5P3STMMX5DZAW6ZESUDLNVJBCAG43PLAC
TQLWCGVXVZ75H7MDBJD3DJDUFNW62WOAEDJUVKCHQTAXKBP47CSAC
32PXX2XJVV7YSLLYNAVS7RYKYRAOQ565TZMTITSEPSSXOYPB5M2AC
DS2GZKISEP2DM2VU6EJ525Q7W3WVOKJXG5PY2OY4VNFCLBHVVOTAC
GDMMLW5HKFUFEVA7BKREZGIAHV3KAXN2I7DY55RQFHXS5NVAAZZQC
SIDH2P7NBIG5KEOE27XHD3ZT2NQ2OJZFN6VZXWNWYFFY5YVXSSVQC
DGF6PWWASI5CEJBNZ3S5IU2PTM5CSKUUQXQPZ6A26XFPZIHKGJ5AC
NVSFIV2ZKP44XHCSCXG6OZVGL67OIFINC34J2EMKTA4KULCERUEAC
Q3DNEB5OOJ34P5ML4CMK3L6SCP7RLW7DDOZEG24KZBX3C7BJRQDAC
MDAJYB6STTZPNHRQ2X66MMMSONMKXTESLHJSFPGN7H3D3TOVBAVAC
SRQJVKQVUY7QGCEBA2VQTWEJ7ADIUSY7L46HJQSQNM5DXYRRH5KAC
RR2J4VLJCZSAKY3HNS334KI4YUAPOMSETO2HGCGEEIUCUJAYAGSQC
H7BW6SEIQ57X6V4BM2RX54W42W6BH5XJBAS6FYCYKLQQG43ZMU4QC
3KAINFIXO7WNWGUGZB43EUNFRS2ZPBLQZDTY456QACMRHYIJ7WDAC
KAL42YT6OQXFPMKKKHE2NQM47W5KMLSRI6KWFRTJFAO4WKP4MMLAC
VNHFP63ZLLZU3A3PLXP4BITX57DUIYDHFOHQYK3BOBHV3S64G26QC
2SNCC2NXKFVBYTWH7THU2QELHONTOBRNCWH6FWYORKKCWZAXTTVAC
TX3LTXGB7TJ2QHLW2TEW6XTCTOW5A3KTZGBPBRTDTUYOZFFT3NLAC
PR42BCP5BPRFD2MP5H6CIJP7E57Q6TKL6SOXZWFKMFVR2OZWHT7AC
PONOTAV3NEDNVGEJNPMLC5AY2BPV5E3ZHWDLNQCKCEBVKPBIY7QQC
5DMO2DEV7IK3MJG274EUNZBGQ7EBZWC2WTSKAEGPDMILX7BXYG3AC
FUEEIUKGHHFPIRZCN3N753GONWAZTWQ2ZWR53IBJAAZ6FZUNGOMAC
FLAGBNUNSIQNFDN53CDWABJRTTFWDL4PG34AI474ZKPXDEPYHOAQC
2TZT4GURBCNHSVOXO5ZMN7XEIO3K4GWJCDPVSYUCMVZ6UFDL4DIQC
GT7BSR54BVJKHUCLEBTELGBMNBFFDQW52EVC4XKVEMUVG2UGZMDAC
TGJZXTUIAKCFZQJ54ZQEBGFBVZSJCAX6AWDRSH3TP7UJRLGUM5SAC
OFH2B2UZBK43QLFQBZ54FOCFLFNE54BZVDNCEUGDTBCUGNVZULIQC
QNKMXCJSGRBEPE6ZNPEXU5EQIOME6EI4DECVC56GLOBCMGWWE6MQC
25CH7HH4LKXFIZ75YNMXS3TSXO6O27DYSOPLOD45K4OCNFWLS4LQC
AIVXE6QBRVCZAASKQRZO6LBDGTYEYSSD2DZCWRX4VLSKE3GCNIDAC
SUWIERONPDATHPDMZRYO6GYIXSW6XIS5V5MK5IV23DWQH2LL7VIAC
AS2IQQJNNCEQNXXKTGYHLB7RO3ZKCF4F7GK6FJH66BOOKDDRGNIQC
OHJE4HQ2B3HVV4BOPBRFKO6HBRTLZEI74P5PLJF5GLSRD2MFWXHQC
JJULXW764V5C2HJKZNWQAEWB6QM5YZADD7ZCE35LYTBFEM6PMYCAC
GVCGKTH5IJ4VSQEIN4CRC7ZFVZW26JPIYNCPTO7GY66CSZZEW3ZQC
FCPBRFLI4FHMB3Q4AFIYPG22ALFOLIYFBODHNCW5O6PVMMD65YDQC
7YUGK5Q64KG5O7GJGTUBRRLHAHBCJ5YOE23YUPT6UBKUSB67CYAQC
PI5BATR2SER3RFE76IUGHM2AGXVFOUM3PLU7WC2K2Q2BA5K2E73QC
UAJN2CFA2QHYDHW2UFAVPPHDQFCD54RKM6V2UC4AMEDJUBBLNWIQC
ZGUJWUFJ4NFFJ6PGXLFGQWCWBCZHPWGWI44NJHJEVPRG5L36PADQC
O7S3ILRELHICJXXTDGMF7KPPZWYHPYCNDPV2I77FZXXH4I454B4QC
4UXFU3FZOCBSLDQ4S7MJKAE2H7VUHCNRDQMIY6NJ3PHYXWNGISDQC
GSJA56E3ORVIBCBA6T6WU2HE4DCLJ6NZPW76O7L54N4CYPKLJOWQC
5K2ANIEXD3CPJM4XNKNPZINP2G4NT7SJBKRN62WNBUKJXFERTILQC
RWCCZ64BG3HSOTM54ANIGENC3F3AIR42LJFRYSAKMCPCIUSOZY5QC
K33CV7EYR37TTSEXQWQ6QPHSEUFO545AIPUZOA2C47QTUCUWFPAAC
YX2LDGNQNB6AQRKAVXNYQ473X6EVPQEBT5AJKBIIWFIMS3U2BNQQC
UZ5623MOLKBTGBSRBJ4OBOEI4IEZSPV3NCV2DRMUZ3CHHJQVHIIAC
NRMSQFTORG3GC7HQBIN5DHB5GLWXM6IQO6PTXD4C7LBQWJIHYIGAC
YMLVBQ6M27MECUVMU3BQP3WSGR7GW4XJMQIHLGHHWMVXHMMIXOYAC
bool is_shield(const item_def &item);
bool is_shield_incompatible(const item_def &weapon,
const item_def *shield = NULL);
// Only works for armour/weapons/missiles
needs_damage = true;
break;
case KILLED_BY_REFLECTION:
needs_damage = true;
if (terse)
desc += "reflected bolt";
else
{
desc += "Killed by a reflected ";
if (auxkilldata.empty())
desc += "bolt";
else
desc += auxkilldata;
if (!death_source_name.empty() && !oneline && !semiverbose)
{
desc += "\n";
desc += " ";
desc += "... reflected by ";
desc += death_source_name;
needs_damage = false;
}
}
break;
case KILLED_BY_BOUNCE:
if (terse)
desc += "bounced beam";
else
{
desc += "Killed themselves with a bounced ";
if (auxkilldata.empty())
desc += "beam";
else
desc += auxkilldata;
}
int affect(bolt &beam, const coord_def& p, item_def *item = NULL,
bool affect_items = true);
void beam_drop_object( bolt &beam, item_def *item, const coord_def& where );
int affect(bolt &beam, const coord_def& p = coord_def(),
item_def *item = NULL, bool affect_items = true);
void beam_drop_object( bolt &beam, item_def *item = NULL,
const coord_def& where = coord_def() );
* 6. Decrease remaining range appropriately
* 7. Check for early out due to aimed_at_feet
* 8. Draw the beam
* 9. Drop an object where the beam 'landed'
*10. Beams explode where the beam 'landed'
*11. If no message generated yet, send "nothing happens" (enchantments only)
* 6. If the beam was reflected during affect() then return, since
* a recursive call to fire_beam() took care of the rest.
* 7. Decrease remaining range appropriately
* 8. Check for early out due to aimed_at_feet
* 9. Draw the beam
*10. Drop an object where the beam 'landed'
*11. Beams explode where the beam 'landed'
*12. If no message generated yet, send "nothing happens" (enchantments only)
const int reflections = pbolt.reflections;
if (reflections == 0)
{
// We aren't being recursively called.
beam_message_cache.clear();
pbolt.range_used = 0;
}
ASSERT(pbolt.range >= 0 && pbolt.range_used >=0);
ASSERT(pbolt.range_used <= pbolt.range);
ASSERT(!pbolt.drop_item || pbolt.item);
ASSERT(!pbolt.dropped_item);
if (pbolt.range == pbolt.range_used && pbolt.range > 0)
{
#ifdef DEBUG
mprf(MSGCH_DIAGNOSTICS, "fire_beam() called on already done beam "
"'%s' (item = '%s')", pbolt.name.c_str(),
pbolt.item ? pbolt.item->name(DESC_PLAIN).c_str() : "none");
#endif
return;
}
if (!pbolt.is_tracer && reflections == 0 && YOU_KILL(pbolt.thrower))
{
switch(pbolt.flavour)
{
case BEAM_HELLFIRE:
case BEAM_HELLFROST:
did_god_conduct(DID_UNHOLY, 2 + random2(3), pbolt.effect_known);
break;
default:
break;
}
}
// Conditions: beam is missile and not tracer.
#ifdef DEBUG
if (!beam.drop_item)
mprf(MSGCH_DIAGNOSTICS, "beam_drop_object() called when beam.drop_item "
"is false (beam = %s, item = %s)", beam.name.c_str(),
item->name(DESC_PLAIN).c_str());
#endif
if (beam.dropped_item)
{
#ifdef DEBUG
mprf(MSGCH_DIAGNOSTICS, "beam_drop_object() called after object "
"already dropped (beam = %s, item = %s)", beam.name.c_str(),
item->name(DESC_PLAIN).c_str());
#endif
return;
}
coord_def p = _p;
if (!in_bounds(p))
p = beam.pos;
// Conditions: beam is missile and not tracer.
copy_item_to_grid( *item, p, 1 );
if (copy_item_to_grid( *item, p, 1 ))
beam.dropped_item = true;
else
{
#ifdef DEBUG
mprf(MSGCH_DIAGNOSTICS, "beam_drop_object() unable to drop "
"object (beam = %s, item = %s)", beam.name.c_str(),
item->name(DESC_PLAIN).c_str());
#endif
}
ouch(dam, NON_MONSTER, KILLED_BY_TARGETTING);
{
if (beam.reflections > 0)
ouch(dam, beam.reflector, KILLED_BY_REFLECTION,
beam.name.c_str());
else if (beam.bounces > 0)
ouch(dam, NON_MONSTER, KILLED_BY_BOUNCE,
beam.name.c_str());
else
ouch(dam, NON_MONSTER, KILLED_BY_TARGETTING);
}
}
static bool _beam_is_reflectable( const bolt &beam, const item_def *item )
{
if (beam.range_used >= beam.range)
return (false);
return (item && is_shield(*item) && shield_reflects(*item));
}
static void _ident_reflector(item_def *item)
{
if (!is_artefact(*item))
set_ident_flags(*item, ISFLAG_KNOW_TYPE);
beam.source = beam.pos;
// Reset bounce_pos, so that if we somehow reflect again before reaching
// the wall that we won't keep heading towards the wall.
beam.bounce_pos.set(0, 0);
if (beam.pos == you.pos())
beam.reflector = NON_MONSTER;
else if (mgrd(beam.pos) != NON_MONSTER)
beam.reflector = mgrd(beam.pos);
else
{
beam.reflector = -1;
#ifdef DEBUG
mprf(MSGCH_DIAGNOSTICS, "Bolt reflected by neither player nor "
"monster (bolt = %s, item = %s)", beam.name.c_str(),
beam.item ? beam.item->name(DESC_PLAIN).c_str() : "none");
#endif
}
fire_beam(beam);
}
mprf( "You block the %s.", beam.name.c_str() );
if (_beam_is_reflectable(beam, you.shield()))
{
mprf( "Your %s reflects the %s!",
you.shield()->name(DESC_PLAIN).c_str(),
beam.name.c_str() );
_ident_reflector(you.shield());
_reflect_beam(beam);
}
else
mprf( "You block the %s.", beam.name.c_str() );
mprf("%s blocks the %s.",
mon->name(DESC_CAP_THE).c_str(),
beam.name.c_str());
item_def *shield = mon->mslot_item(MSLOT_SHIELD);
if (_beam_is_reflectable(beam, shield))
{
if (you.can_see(mon))
{
mprf("%s reflects the %s off %s %s!",
mon->name(DESC_CAP_THE).c_str(),
beam.name.c_str(),
mon->pronoun(PRONOUN_NOCAP_POSSESSIVE).c_str(),
shield->name(DESC_PLAIN).c_str());
_ident_reflector(shield);
}
else if (see_grid(beam.pos))
mprf("The %s bounces off of thin air!",
beam.name.c_str());
_reflect_beam(beam);
}
else
mprf("%s blocks the %s.",
mon->name(DESC_CAP_THE).c_str(),
beam.name.c_str());
aimed_at_spot(false),
aux_source(), affects_nothing(false), obvious_effect(false),
effect_known(true), fr_count(0), foe_count(0), fr_power(0),
foe_power(0), fr_hurt(0), foe_hurt(0), fr_helped(0),
foe_helped(0), is_tracer(false), aimed_at_feet(false),
aimed_at_spot(false), aux_source(), affects_nothing(false),
effect_known(true), obvious_effect(false), fr_count(0),
foe_count(0), fr_power(0), foe_power(0), fr_hurt(0),
foe_hurt(0), fr_helped(0), foe_helped(0),
dropped_item(false), item_pos(), item_index(NON_ITEM),
range_used(0), is_tracer(false), aimed_at_feet(false),