summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authorj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-01-09 14:15:43 +0000
committerj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-01-09 14:15:43 +0000
commit447bc8ac9d8557be01da02c40349e4301f42c089 (patch)
tree70d8049ee1391103b657e1473bda0aa15c3bc491 /crawl-ref
parent88f39cd2d9a9c0c337988e24deca86267da5bb30 (diff)
downloadcrawl-ref-447bc8ac9d8557be01da02c40349e4301f42c089.tar.gz
crawl-ref-447bc8ac9d8557be01da02c40349e4301f42c089.zip
Add gore and splatter to Crawl - in the form of Jarmo's
(strongly modified, I admit) blood patch. Whenever the player or a monster capable of bleeding suffers damage (currently only in melee) or when you dissect a corpse there's a chance (depending on damage/corpse weight) that the square will turn bloody and be coloured red, with a much lower chance of additionally spattering some of the surrounding squares. These chances are probably still a bit too high for later values of possible damage dealt. Also, ranged and some of the magic attacks (earth-based, mostly) should also be able to send blood flying. :p For now, this is flavour only, but it shouldn't be too difficult to introduce relations to Necromancy or evil gods. Also consider dragons to be warm-blooded, like dinosaurs. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3230 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/beam.cc8
-rw-r--r--crawl-ref/source/direct.cc12
-rw-r--r--crawl-ref/source/effects.cc14
-rw-r--r--crawl-ref/source/enum.h3
-rw-r--r--crawl-ref/source/fight.cc29
-rw-r--r--crawl-ref/source/food.cc4
-rw-r--r--crawl-ref/source/misc.cc102
-rw-r--r--crawl-ref/source/misc.h1
-rw-r--r--crawl-ref/source/mon-data.h6
-rw-r--r--crawl-ref/source/mstuff2.cc3
-rw-r--r--crawl-ref/source/religion.cc13
-rw-r--r--crawl-ref/source/traps.cc6
-rw-r--r--crawl-ref/source/view.cc28
-rw-r--r--crawl-ref/source/view.h1
14 files changed, 213 insertions, 17 deletions
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index a09fdbb141..15d3f68a85 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -2669,6 +2669,10 @@ static int affect_wall(bolt &beam, int x, int y)
if (grd[x][y] == DNGN_ROCK_WALL || grd[x][y] == DNGN_CLEAR_ROCK_WALL)
{
grd[x][y] = DNGN_FLOOR;
+
+ // blood does not transfer onto floor
+ if (is_bloodcovered(x,y))
+ env.map[x][y].property = FPROP_NONE;
if (!beam.msg_generated)
{
@@ -2742,6 +2746,10 @@ static int affect_wall(bolt &beam, int x, int y)
{
grd[x][y] = DNGN_FLOOR;
+ // blood does not transfer onto floor
+ if (is_bloodcovered(x,y))
+ env.map[x][y].property = FPROP_NONE;
+
if (!silenced(you.x_pos, you.y_pos))
{
if (!see_grid( x, y ))
diff --git a/crawl-ref/source/direct.cc b/crawl-ref/source/direct.cc
index 36925ca8df..8430d326fb 100644
--- a/crawl-ref/source/direct.cc
+++ b/crawl-ref/source/direct.cc
@@ -2148,6 +2148,9 @@ static void describe_cell(int mx, int my)
if (Options.tutorial_left && tutorial_feat_interesting(grd[mx][my]))
{
feature_desc += " (Press <w>v<lightgray> for more information.)";
+ if (is_bloodcovered(mx, my))
+ feature_desc += EOL "It is spattered with blood.";
+
print_formatted_paragraph(feature_desc, get_number_of_cols());
}
else
@@ -2157,9 +2160,16 @@ static void describe_cell(int mx, int my)
if (interesting_feature(feat))
feature_desc += " (Press 'v' for more information.)";
+ bool bloody = false;
+ if (is_bloodcovered(mx, my))
+ {
+ feature_desc += EOL "It is spattered with blood.";
+ bloody = true;
+ }
+
// Suppress "Floor." if there's something on that square that we've
// already described.
- if ((feat == DNGN_FLOOR || feat == DNGN_FLOOR_SPECIAL)
+ if ((feat == DNGN_FLOOR || feat == DNGN_FLOOR_SPECIAL) && !bloody
&& (monster_described || item_described || cloud_described))
return;
diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc
index fba2ff8e6f..4658ddb393 100644
--- a/crawl-ref/source/effects.cc
+++ b/crawl-ref/source/effects.cc
@@ -2681,6 +2681,20 @@ void update_corpses(double elapsedTime)
grd[cx][cy] =
static_cast<dungeon_feature_type>(
grd[cx][cy] - 1);
+
+ // clean bloody floor
+ if (is_bloodcovered(cx,cy))
+ env.map[cx][cy].property = FPROP_NONE;
+ // chance of cleaning adjacent squares
+ for (int k=-1; k<=1; k++)
+ {
+ for (int l=-1; l<=1; l++)
+ if (is_bloodcovered(cx+k,cy+l)
+ && one_chance_in(5))
+ {
+ env.map[cx+k][cy+l].property = FPROP_NONE;
+ }
+ }
}
}
}
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index e72f69a792..28369c77ac 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -1016,7 +1016,8 @@ enum floor_property_type
{
FPROP_NONE, // 0
FPROP_SANCTUARY_1,
- FPROP_SANCTUARY_2
+ FPROP_SANCTUARY_2,
+ FPROP_BLOODY // bloody floor and sanctuary are exclusive, so that's okay
};
enum duration_type
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index 48dd950bff..09fa35a48f 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -605,6 +605,15 @@ bool melee_attack::player_attack()
// always upset monster regardless of damage
behaviour_event(def, ME_WHACK, MHITYOU);
+ if (damage_done > 0)
+ {
+ int blood = damage_done;
+ if (blood > defender->stat_hp())
+ blood = defender->stat_hp();
+
+ bleed_onto_floor(where.x, where.y, defender->id(), blood, true);
+ }
+
player_hurt_monster();
if (damage_done > 0 || !defender_visible)
@@ -2139,11 +2148,17 @@ bool melee_attack::chop_hydra_head( int dam,
if (def->number < 1)
{
if (defender_visible)
+ {
mprf( "%s %s %s's last head off!",
atk_name(DESC_CAP_THE).c_str(),
attacker->conj_verb(verb).c_str(),
def_name(DESC_NOCAP_THE).c_str() );
+ }
+ coord_def pos = defender->pos();
+ bleed_onto_floor(pos.x, pos.y, defender->id(),
+ def->hit_points, true);
+
defender->hurt(attacker, def->hit_points);
}
else
@@ -3520,10 +3535,22 @@ void melee_attack::mons_perform_attack_rounds()
mons_announce_hit(attk);
check_defender_train_armour();
+ int type = -1; // player
+ if (defender->atype() == ACT_MONSTER)
+ type = defender->id();
+
+ int damage = damage_done;
+ if (damage > defender->stat_hp())
+ damage = defender->stat_hp();
+
+ bleed_onto_floor(pos.x, pos.y, type, damage, true);
+
if (decapitate_hydra(damage_done,
attacker->damage_type(attack_number)))
+ {
continue;
-
+ }
+
special_damage = 0;
special_damage_message.clear();
diff --git a/crawl-ref/source/food.cc b/crawl-ref/source/food.cc
index ff0aef44a9..8507ea7d1a 100644
--- a/crawl-ref/source/food.cc
+++ b/crawl-ref/source/food.cc
@@ -353,6 +353,10 @@ bool butchery()
god_likes_butchery(you.religion))
{
offer_corpse(corpse_id);
+ // ritual sacrifice can also bloodify the ground
+ const int mons_class = mitm[corpse_id].plus;
+ const int max_chunks = mons_weight( mons_class ) / 150;
+ bleed_onto_floor(you.x_pos, you.y_pos, mons_class, max_chunks, true);
destroy_item(corpse_id);
}
else
diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc
index eef3ecc26e..7111bc8881 100644
--- a/crawl-ref/source/misc.cc
+++ b/crawl-ref/source/misc.cc
@@ -84,11 +84,15 @@
// unsigned char chy, unsigned char ch_col)
void turn_corpse_into_chunks( item_def &item )
{
- const int mons_class = item.plus;
- const int max_chunks = mons_weight( mons_class ) / 150;
-
ASSERT( item.base_type == OBJ_CORPSES );
+ const int mons_class = item.plus;
+ const int max_chunks = mons_weight( mons_class ) / 150;
+
+ // only fresh corpses bleed enough to colour the ground
+ if (item.special >= 100)
+ bleed_onto_floor(you.x_pos, you.y_pos, mons_class, max_chunks, true);
+
item.base_type = OBJ_FOOD;
item.sub_type = FOOD_CHUNK;
item.quantity = 1 + random2( max_chunks );
@@ -155,6 +159,98 @@ void turn_corpse_into_chunks( item_def &item )
}
} // end place_chunks()
+// checks whether the player or a monster is capable of bleeding
+static bool victim_can_bleed(int montype)
+{
+ if (montype == -1) // player
+ {
+ if (you.is_undead && (you.species != SP_VAMPIRE
+ || you.hunger_state >= HS_FULL))
+ {
+ return (false);
+ }
+
+ int tran = you.attribute[ATTR_TRANSFORMATION];
+ if (tran == TRAN_STATUE || tran == TRAN_ICE_BEAST
+ || tran == TRAN_AIR || tran == TRAN_LICH
+ || tran == TRAN_SPIDER) // monster spiders don't bleed either
+ {
+ return (false);
+ }
+ return (true);
+ }
+
+ // now check monsters
+ return (mons_class_flag(montype, M_COLD_BLOOD)
+ || mons_class_flag(montype, M_WARM_BLOOD));
+}
+
+static bool allow_bleeding_on_square(int x, int y)
+{
+ // no bleeding onto sanctuary ground, please
+ // also not necessary if already covered in blood
+ if (env.map[x][y].property != FPROP_NONE)
+ return (false);
+
+ // no spattering into lava or water
+ if (grd[x][y] >= DNGN_LAVA && grd[x][y] < DNGN_FLOOR)
+ return (false);
+
+ // the good gods like to keep their altars pristine
+ if (is_good_god(grid_altar_god(grd[x][y])))
+ return (false);
+
+ return (true);
+}
+
+static void maybe_bloodify_square(int x, int y, int amount, bool spatter = false)
+{
+ if (amount < 1)
+ return;
+
+ if (!spatter && !allow_bleeding_on_square(x,y))
+ return;
+
+ if (amount > random2(20))
+ {
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS,
+ "might bleed now; square: (%d, %d); amount = %d",
+ x, y, amount);
+#endif
+ if (allow_bleeding_on_square(x,y))
+ env.map[x][y].property = FPROP_BLOODY;
+
+ if (spatter)
+ {
+ // smaller chance of spattering surrounding squares
+ for (int i=-1;i<=1;i++)
+ for (int j=-1;j<=1;j++)
+ {
+ if (i == 0 && j == 0) // current square
+ continue;
+
+ // spattering onto walls etc. less likely
+ if (grd[x+i][y+j] < DNGN_MINMOVE && one_chance_in(3))
+ continue;
+
+ maybe_bloodify_square(x+i, y+j, amount/10);
+ }
+ }
+ }
+}
+
+// currently flavour only: colour ground (and possibly adjacent squares) red
+// "damage" depends on damage taken (or hitpoints, if damage higher),
+// or, for sacrifices, on the number of chunks possible to get out of a corpse
+void bleed_onto_floor(int x, int y, int montype, int damage, bool spatter)
+{
+ if (!victim_can_bleed(montype))
+ return;
+
+ maybe_bloodify_square(x, y, damage, spatter);
+}
+
void search_around( bool only_adjacent )
{
int i;
diff --git a/crawl-ref/source/misc.h b/crawl-ref/source/misc.h
index 460c76e403..092ab2eb61 100644
--- a/crawl-ref/source/misc.h
+++ b/crawl-ref/source/misc.h
@@ -71,6 +71,7 @@ void trackers_init_new_level(bool transit);
* *********************************************************************** */
void turn_corpse_into_chunks( item_def &item );
+void bleed_onto_floor(int x, int y, int mon, int damage, bool spatter = false);
// last updated 12may2000 {dlb}
/* ***********************************************************************
diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h
index fc4093a236..100d7edd66 100644
--- a/crawl-ref/source/mon-data.h
+++ b/crawl-ref/source/mon-data.h
@@ -479,7 +479,7 @@
{
MONS_DRAGON, 'D', GREEN, "dragon",
- M_FLIES | M_SPECIAL_ABILITY, //jmf: warm blood?
+ M_FLIES | M_SPECIAL_ABILITY | M_WARM_BLOOD,
MR_RES_POISON | MR_RES_FIRE | MR_VUL_COLD,
2200, 12, MONS_DRAGON, MONS_DRAGON, MH_NATURAL, -4,
{ {AT_BITE, AF_PLAIN, 20}, {AT_CLAW, AF_PLAIN, 13}, {AT_CLAW, AF_PLAIN, 13}, AT_NO_ATK },
@@ -796,7 +796,7 @@
{
MONS_WYVERN, 'D', LIGHTRED, "wyvern",
- M_NO_FLAGS, //jmf: warm blood?
+ M_WARM_BLOOD,
MR_NO_FLAGS,
2000, 10, MONS_WYVERN, MONS_WYVERN, MH_NATURAL, -3,
{ {AT_BITE, AF_PLAIN, 20}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK },
@@ -1544,7 +1544,7 @@
{
MONS_STORM_DRAGON, 'D', LIGHTBLUE, "storm dragon",
- M_SPELLCASTER | M_FLIES,
+ M_SPELLCASTER | M_FLIES | M_WARM_BLOOD,
MR_RES_ELEC | MR_RES_COLD,
2800, 12, MONS_DRAGON, MONS_STORM_DRAGON, MH_NATURAL, -5,
{ {AT_BITE, AF_PLAIN, 25}, {AT_CLAW, AF_PLAIN, 15}, {AT_CLAW, AF_PLAIN, 15}, AT_NO_ATK },
diff --git a/crawl-ref/source/mstuff2.cc b/crawl-ref/source/mstuff2.cc
index 32ac2be14f..b1ff4b3e38 100644
--- a/crawl-ref/source/mstuff2.cc
+++ b/crawl-ref/source/mstuff2.cc
@@ -219,6 +219,9 @@ void mons_trap(struct monsters *monster)
if (damage_taken < 0)
damage_taken = 0;
+
+ bleed_onto_floor(monster->x, monster->y, monster->type,
+ damage_taken, true);
}
revealTrap = true;
diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc
index e6e087d786..f82c9b7c99 100644
--- a/crawl-ref/source/religion.cc
+++ b/crawl-ref/source/religion.cc
@@ -3091,9 +3091,18 @@ static bool bless_weapon( int god, int brand, int colour )
mprf( MSGCH_GOD, "Your weapon shines brightly!" );
simple_god_message( " booms: Use this gift wisely!" );
- if ( god != GOD_LUGONU )
+ if ( god == GOD_SHINING_ONE )
+ {
holy_word( 100, true );
-
+ // un-bloodify surrounding squares
+ for (int i=-3;i<=3;i++)
+ for (int j=-3;j<=3;j++)
+ {
+ if (is_bloodcovered(you.x_pos+i, you.y_pos+j))
+ env.map[you.x_pos+i][you.y_pos+j].property = FPROP_NONE;
+ }
+ }
+
delay(1000);
return (true);
diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc
index 00d5793963..35b7880c8e 100644
--- a/crawl-ref/source/traps.cc
+++ b/crawl-ref/source/traps.cc
@@ -384,8 +384,10 @@ void handle_traps(trap_type trt, int i, bool trap_known)
else
{
mpr("A huge blade swings out and slices into you!");
- ouch( (you.your_level * 2) + random2avg(29, 2)
- - random2(1 + player_AC()), 0, KILLED_BY_TRAP, " blade" );
+ int damage = (you.your_level * 2) + random2avg(29, 2)
+ - random2(1 + player_AC());
+ ouch( damage, 0, KILLED_BY_TRAP, " blade" );
+ bleed_onto_floor(you.x_pos, you.y_pos, -1, damage, true);
}
break;
diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc
index c7c886ca1e..cf22365b0a 100644
--- a/crawl-ref/source/view.cc
+++ b/crawl-ref/source/view.cc
@@ -208,9 +208,15 @@ void set_envmap_prop( int x, int y, int prop )
env.map[x][y].property = prop;
}
-bool is_sanctuary( int x, int y)
+bool is_sanctuary(int x, int y)
{
- return (env.map[x][y].property != FPROP_NONE);
+ return (env.map[x][y].property == FPROP_SANCTUARY_1
+ || env.map[x][y].property == FPROP_SANCTUARY_2);
+}
+
+bool is_bloodcovered(int x, int y)
+{
+ return (env.map[x][y].property == FPROP_BLOODY);
}
bool is_envmap_item(int x, int y)
@@ -368,6 +374,17 @@ static int view_emphasised_colour(int x, int y, dungeon_feature_type feat,
return (oldcolour);
}
+static bool show_bloodcovered(int x, int y)
+{
+ if (!is_bloodcovered(x,y))
+ return (false);
+
+ dungeon_feature_type grid = grd[x][y];
+
+ return (grid_altar_god(grid) == GOD_NO_GOD && !grid_is_trap(grid)
+ && !grid_is_portal(grid) && grid != DNGN_ENTER_SHOP);
+}
+
static void get_symbol( int x, int y,
int object, unsigned *ch,
unsigned short *colour,
@@ -401,8 +418,11 @@ static void get_symbol( int x, int y,
*colour = LIGHTGRAY | colmask; // 1/12
}
}
- else
- if (object < NUM_REAL_FEATURES && env.grid_colours[x][y])
+ else if (object < NUM_REAL_FEATURES && show_bloodcovered(x,y))
+ {
+ *colour = RED | colmask;
+ }
+ else if (object < NUM_REAL_FEATURES && env.grid_colours[x][y])
{
*colour = env.grid_colours[x][y] | colmask;
}
diff --git a/crawl-ref/source/view.h b/crawl-ref/source/view.h
index fec4d5805f..cf3490fc9b 100644
--- a/crawl-ref/source/view.h
+++ b/crawl-ref/source/view.h
@@ -166,6 +166,7 @@ void set_envmap_col( int x, int y, int colour, int flags );
void set_envmap_col( int x, int y, int colour );
void set_envmap_prop( int x, int y, int prop );
bool is_sanctuary( int x, int y );
+bool is_bloodcovered( int x, int y );
bool is_envmap_detected_item(int x, int y);
bool is_envmap_detected_mons(int x, int y);