to also saturate the blood with floor.
Add a basic blood scent effect: all hounds, vampires, and the mosquito get M_BLOOD_SCENT which will let them wake up when blood is spilled in their vicinity. smell_blood() is rather similar to noisy(), so monsters will try to seek the origin of the blood spilled.
Player vampires now get a message if blood is spilled outside their LOS, "You smell fresh blood" with a distance estimate ("near-by", "in the distance") added for vampires that are (near) bloodless. Also, the radius a vampire will be capable of smelling blood will increase the thirstier he is.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3936 c06c8d41-db1a-0410-9941-cceddc491573
C5U3HSOOQ7BKXKXIDS7MLVXUKDTHAWJ5NXNX6YDXTM3GWY5UWX4QC
LEBCZRNPIEYOSGSVK6Y5MUNX4TCL43RK22MG2STL2SPKYKOSPTEQC
PR42BCP5BPRFD2MP5H6CIJP7E57Q6TKL6SOXZWFKMFVR2OZWHT7AC
VX2D7IVDD7OFX55ZVY5NKPITC3XWNJX4WSEBBTYASMXKJY5E7VBAC
F5APHUYFFFBUYWCU3OPCE5535X5FNUHMPZQ2H4M5J2RPIJIXTNRQC
KAOE5HB3THUKVGFZRO5EZESHEB3Q34WUO5DFMLWIKOBF47LZTIYAC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
JESCEQPAFC23D6BUZMBOB4M54XT3GQZJYT7NCJ556LEUCHRER3SQC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
C5VA63WAQRWPENIMXRPUPZLZJMC77PL2B3A77HYFWDCZU5QDG7VQC
NNG27Y5ZQAZX6UD7F7M4F6KEZBEDFXPEEC3LFUSX4ESKT7K6UJQAC
7KWDC7XFNMBLSUO2HISIROBINZBX5T67LJEEXTAORXW2YZ7VWFGAC
X5WLJCJVW55SXZVP7IKP7ADCJIGNKN4PKAXFECVR6TNK7XSMZR7QC
74LQ7JXVLAFSHLI7LCBKFX47CNTYSKGUQSXNX5FCIUIGCC2JTR3QC
TXFN7TLLKYEM2W5HVB2UXKXUH7MTXOU77PXBPMP7NJKXSLVX5PMQC
L254F6ZIU2HWGLFFGPIORTN4C3TDQ3E5JZ7Z7GQA5AEDIKL6PKDAC
WUTE7R6SROKLIWR3QASJSH2IZDJNPAIMWJRUSISQTN4YMKNFTODQC
SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC
QDTVLBRGHDTRUVT7I3O72K6TMOYAUSAJBZUHGOEFU2RKJNUPWZSQC
GTXKQTORYHZ7XB2VIH6372UM5GMWAN7IVRXWY5FGBCHFGBV6D6NAC
OP6CTAKWCAU64JXQ3USQYR5E5IFHQHNCACII5UMVRXUTZXJQOAZAC
RCPQNIRPR3NQXEMVLBAQW6657UJFIP43N54UJVEZHJH22OH4UQIQC
S2LIBA2CLTZ6ZU66AUZ2CCNLCDOBSGWQGTZ6HFAFP2XSWAALGLSQC
AVCMVFA3MKCXHO6H44UK5KJNIHTGQV7UA7GYXM26VI6TXXU5ZN6QC
3WHI3KM43ZCN4ITJLFQQBQBC4OJPRS7QTBPIQ6QBCUVKRSK476SAC
4VK7VHWRVRO66BRSGTBPSYJGGXLRF6AG6G74UDTPHTPXR7ZRNINQC
HH3HFWVXABJ4IRMN22PPJCREMULZSN6DA7VYKOGECGMNUQTZ5QNQC
F6LX36GU6BWJFJLV2JNVM6PWTMQ35R33EOMQNGGQNQY67V2LJVIAC
MJWFTUS66PTCNEYXEJA3CUJFXNWXIKDD6H3V24PW7HK64NSVOFSAC
VK3LNDA3TXEPBMLDWBTEBDOZMPP3YUED3A624XMHWI6FI7LP3HGAC
RBAGQ2PB7V5YAM5KSHSZR2E3MLKDSRVM5XYGI2TIXP5QMVBOQHDQC
B3MFLKPJ34I2USQX7UM3SPDIFVGACB5HXYLEKT3FDULL57QOE2LAC
5K2ANIEXD3CPJM4XNKNPZINP2G4NT7SJBKRN62WNBUKJXFERTILQC
YX2LDGNQNB6AQRKAVXNYQ473X6EVPQEBT5AJKBIIWFIMS3U2BNQQC
E5DMZFW6WCFAKTKKOQPYTQXZ2CGLWMVH64LRXDUI2UIG4VYUHIVQC
RSIUBEQUGNU4LO6KH4PKVROWQS33DAKSY4XFVGN7T3CEKSXABCSAC
KN5WFFRSNGHIGI5IUYRBOA4R4K7XK3AEAAMN6ELDFTSYKPN7QX7AC
static const char* _player_vampire_smells_blood(int dist)
{
// non-hungry vampires get no clear indication of how close the smell is
if (you.hunger_state > HS_HUNGRY)
return "";
if (dist < 16) // 4*4
return " near-by";
if (you.hunger_state <= HS_NEAR_STARVING && dist > 64) // 8*8
return " in the distance";
return "";
}
void blood_smell( int strength, int blood_x, int blood_y )
{
struct monsters *monster = 0; // NULL {dlb}
const int range = strength * strength;
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS,
"blood stain at (%d, %d), range of smell = %d",
blood_x, blood_y, range);
#endif
// of the player species, only vampires can smell blood
if (you.species == SP_VAMPIRE)
{
// whether they actually do so, depends on their hunger state
int vamp_strength = strength - 2 * (you.hunger_state - 1);
if (vamp_strength > 0)
{
int vamp_range = vamp_strength * vamp_strength;
const int player_distance
= distance( you.x_pos, you.y_pos, blood_x, blood_y );
if (player_distance <= vamp_range)
{
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS,
"Player smells blood, pos: (%d, %d), dist = %d)",
you.x_pos, you.y_pos, player_distance);
#endif
you.check_awaken(range - player_distance);
// don't message if you can see the square
if (!see_grid(blood_x, blood_y))
{
mprf("You smell fresh blood%s.",
_player_vampire_smells_blood(player_distance));
}
}
}
}
for (int p = 0; p < MAX_MONSTERS; p++)
{
monster = &menv[p];
if (monster->type < 0)
continue;
if (!mons_class_flag(monster->type, M_BLOOD_SCENT))
continue;
if (distance(monster->x, monster->y, blood_x, blood_y) <= range)
{
// let sleeping hounds lie
if (mons_is_sleeping(monster)
&& mons_species(monster->type) != MONS_VAMPIRE)
{
// 33% chance of sleeping on
// 33% of being disturbed (start BEH_WANDER)
// 33% of being alerted (start BEH_SEEK)
if (!one_chance_in(3))
{
if (coinflip())
{
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "disturbing %s (%d, %d)",
monster->name(DESC_PLAIN).c_str(),
monster->x, monster->y);
#endif
behaviour_event( monster, ME_DISTURB, MHITNOT,
blood_x, blood_y );
}
continue;
}
}
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "alerting %s (%d, %d)",
monster->name(DESC_PLAIN).c_str(), monster->x, monster->y);
#endif
behaviour_event( monster, ME_ALERT, MHITNOT, blood_x, blood_y );
}
}
} // end blood_smell()
bool death_message =
!silent && mons_near(monster) && player_monster_visible(monster);
bool death_message
= !silent && mons_near(monster) && player_monster_visible(monster);
pbolt.smart_monster = (mons_intel(monster->type) == I_HIGH ||
mons_intel(monster->type) == I_NORMAL);
pbolt.smart_monster = (mons_intel(monster->type) == I_HIGH
|| mons_intel(monster->type) == I_NORMAL);
// if the beam is an actual missile or of the MMISSILE type (Earth magic)
// might bleed on the floor
if (!engulfs
&& (beam.flavour == BEAM_MISSILE || beam.flavour == BEAM_MMISSILE))
{
int blood = hurted/2; // assumes DVORP_PIERCING, factor: 0.5
if (blood > you.hp)
blood = you.hp;
bleed_onto_floor(you.x_pos, you.y_pos, -1, blood, true);
}
player_monster_visible(&menv[tid])?
mon->name(DESC_NOCAP_THE).c_str()
: "something");
player_monster_visible(&menv[tid]) ?
mon->name(DESC_NOCAP_THE).c_str() : "something");
// if the beam is an actual missile or of the MMISSILE type (Earth magic)
// might bleed on the floor
if (!engulfs
&& (beam.flavour == BEAM_MISSILE || beam.flavour == BEAM_MMISSILE))
{
// using raw_damage instead of the flavoured one!
int blood = raw_damage/2; // assumes DVORP_PIERCING, factor: 0.5
if (blood > mon->hit_points)
blood = mon->hit_points;
bleed_onto_floor(mon->x, mon->y, mon->type, blood, true);
}