summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Borowski <kilobyte@angband.pl>2009-10-13 09:56:41 +0200
committerAdam Borowski <kilobyte@angband.pl>2009-10-13 09:57:09 +0200
commit7cb4b819399d86effcf5890498f3e89dcb8a7178 (patch)
treed591f28e24caaf7196a93dbf7f02deb727413f9f
parent072864bdfdb2befa0cb865dbe4234f7f0c8dec39 (diff)
parentffa4e38d65ac1f41a20f3820d38c4d54291c9a8f (diff)
downloadcrawl-ref-7cb4b819399d86effcf5890498f3e89dcb8a7178.tar.gz
crawl-ref-7cb4b819399d86effcf5890498f3e89dcb8a7178.zip
Merge branch 'trees'.
There's still the issue of glyph choice, and cutting them down with an axe is not coded yet.
-rw-r--r--crawl-ref/docs/develop/level_design.txt1
-rw-r--r--crawl-ref/source/beam.cc64
-rw-r--r--crawl-ref/source/cloud.cc44
-rw-r--r--crawl-ref/source/dat/clua/loadmaps.lua2
-rw-r--r--crawl-ref/source/dat/database/quotes.txt24
-rw-r--r--crawl-ref/source/dat/descript/features.txt16
-rw-r--r--crawl-ref/source/dat/descript/monsters.txt4
-rw-r--r--crawl-ref/source/dat/mini.des30
-rw-r--r--crawl-ref/source/dat/shoals.des13
-rw-r--r--crawl-ref/source/describe.cc5
-rw-r--r--crawl-ref/source/directn.cc2
-rw-r--r--crawl-ref/source/dungeon.cc2
-rw-r--r--crawl-ref/source/enum.h8
-rw-r--r--crawl-ref/source/externs.h2
-rw-r--r--crawl-ref/source/losparam.cc5
-rw-r--r--crawl-ref/source/mapdef.cc2
-rw-r--r--crawl-ref/source/mon-data.h11
-rw-r--r--crawl-ref/source/mon-util.cc15
-rw-r--r--crawl-ref/source/monstuff.cc3
-rw-r--r--crawl-ref/source/view.cc30
20 files changed, 232 insertions, 51 deletions
diff --git a/crawl-ref/docs/develop/level_design.txt b/crawl-ref/docs/develop/level_design.txt
index 6c973d6220..0ddde1d32b 100644
--- a/crawl-ref/docs/develop/level_design.txt
+++ b/crawl-ref/docs/develop/level_design.txt
@@ -156,6 +156,7 @@ Terrain
v - metal wall - grounds electricity (DNGN_METAL_WALL)
b - crystal wall - reflects cold and fire (DNGN_GREEN_CRYSTAL_WALL)
a - wax wall - can melt (DNGN_WAX_WALL)
+ t - trees - a single square doesn't block LOS (DNGN_TREES)
. - floor (DNGN_FLOOR)
+ - closed door (DNGN_CLOSED_DOOR)
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index ae882b0c9e..39d700aa8c 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -1693,8 +1693,9 @@ void bolt::digging_wall_effect()
void bolt::fire_wall_effect()
{
- // Fire only affects wax walls.
- if (grd(pos()) != DNGN_WAX_WALL)
+ dungeon_feature_type feat;
+ // Fire only affects wax walls and trees.
+ if ((feat=grd(pos())) != DNGN_WAX_WALL && (feat != DNGN_TREES))
{
finish_beam();
return;
@@ -1703,7 +1704,7 @@ void bolt::fire_wall_effect()
if (!is_superhot())
{
// No actual effect.
- if (flavour != BEAM_HELLFIRE)
+ if (flavour != BEAM_HELLFIRE && feat == DNGN_WAX_WALL)
{
if (see_grid(pos()))
{
@@ -1718,12 +1719,27 @@ void bolt::fire_wall_effect()
{
// Destroy the wall.
grd(pos()) = DNGN_FLOOR;
- if (see_grid(pos()))
- emit_message(MSGCH_PLAIN, "The wax bubbles and burns!");
- else if (player_can_smell())
- emit_message(MSGCH_PLAIN, "You smell burning wax.");
+ if (feat == DNGN_WAX_WALL)
+ {
+ if (see_grid(pos()))
+ emit_message(MSGCH_PLAIN, "The wax bubbles and burns!");
+ else if (player_can_smell())
+ emit_message(MSGCH_PLAIN, "You smell burning wax.");
+ place_cloud(CLOUD_FIRE, pos(), random2(10)+15, whose_kill(), killer());
+ }
+ else
+ {
+ if (see_grid(pos()))
+ emit_message(MSGCH_PLAIN, "The tree burns like a torch!");
+ else if (player_can_smell())
+ emit_message(MSGCH_PLAIN, "You smell burning wood.");
+ if (whose_kill() == KC_YOU)
+ did_god_conduct(DID_KILL_PLANT, 1, effect_known, 0);
+ else if (whose_kill() == KC_FRIENDLY)
+ did_god_conduct(DID_ALLY_KILLED_PLANT, 1, effect_known, 0);
+ place_cloud(CLOUD_FOREST_FIRE, pos(), random2(30)+25, whose_kill(), killer(), 5);
+ }
- place_cloud(CLOUD_FIRE, pos(), random2(10)+15, whose_kill(), killer());
obvious_effect = true;
}
@@ -2198,25 +2214,16 @@ int mons_adjust_flavoured(monsters *monster, bolt &pbolt, int hurted,
if (doFlavouredEffects)
simple_monster_message(monster, " resists.");
}
- else if (original < hurted)
+ else if (original < hurted && doFlavouredEffects)
{
if (mons_is_icy(monster->type))
- {
- if (doFlavouredEffects)
- simple_monster_message(monster, " melts!");
- }
+ simple_monster_message(monster, " melts!");
+ else if (monster->type == MONS_BUSH)
+ simple_monster_message(monster, " is on fire!");
+ else if (pbolt.flavour == BEAM_FIRE)
+ simple_monster_message(monster, " is burned terribly!");
else
- {
- if (doFlavouredEffects)
- {
- if (pbolt.flavour == BEAM_FIRE)
- simple_monster_message(monster,
- " is burned terribly!");
- else
- simple_monster_message(monster,
- " is scalded terribly!");
- }
- }
+ simple_monster_message(monster, " is scalded terribly!");
}
break;
@@ -3092,7 +3099,7 @@ bool bolt::affects_wall(dungeon_feature_type wall) const
if (flavour == BEAM_DISINTEGRATION && damage.num >= 3)
return (true);
- if (is_fiery() && wall == DNGN_WAX_WALL)
+ if (is_fiery() && (wall == DNGN_WAX_WALL || wall == DNGN_TREES))
return (true);
// eye of devastation?
@@ -4569,6 +4576,13 @@ void bolt::affect_monster(monsters* mon)
return;
}
+ // Missiles go past bushes.
+ if (!is_beam && mon->type == MONS_BUSH)
+ {
+ apply_hit_funcs(mon, 0);
+ return;
+ }
+
// Fire storm creates these, so we'll avoid affecting them
if (name == "great blast of fire" && mon->type == MONS_FIRE_VORTEX)
{
diff --git a/crawl-ref/source/cloud.cc b/crawl-ref/source/cloud.cc
index 7591920662..4e66215059 100644
--- a/crawl-ref/source/cloud.cc
+++ b/crawl-ref/source/cloud.cc
@@ -23,6 +23,7 @@ REVISION("$Rev$");
#include "terrain.h"
#include "view.h"
#include "mutation.h"
+#include "los.h"
static int _actual_spread_rate(cloud_type type, int spread_rate)
{
@@ -132,13 +133,45 @@ static int _spread_cloud(const cloud_struct &cloud)
return (extra_decay);
}
+static void _spread_fire(const cloud_struct &cloud)
+{
+ int make_flames = one_chance_in(5);
+
+ for ( adjacent_iterator ai(cloud.pos); ai; ++ai )
+ {
+ if (!in_bounds(*ai)
+ || env.cgrid(*ai) != EMPTY_CLOUD
+ || is_sanctuary(*ai))
+ continue;
+
+ // burning trees produce flames all around
+ if (!grid_is_solid(*ai) && make_flames)
+ _place_new_cloud( CLOUD_FIRE, *ai, cloud.decay/2+1, cloud.whose,
+ cloud.killer, cloud.spread_rate );
+
+ // forest fire doesn't spread in all directions at once,
+ // every neighbouring square gets a separate roll
+ if (grd(*ai) == DNGN_TREES && one_chance_in(20))
+ {
+ if (see_grid(*ai))
+ mpr("The forest fire spreads!");
+ grd(*ai) = DNGN_FLOOR;
+ _place_new_cloud( cloud.type, *ai, random2(30)+25, cloud.whose,
+ cloud.killer, cloud.spread_rate );
+ }
+
+ }
+}
+
static void _dissipate_cloud(int cloudidx, int dissipate)
{
cloud_struct &cloud = env.cloud[cloudidx];
// Apply calculated rate to the actual cloud.
cloud.decay -= dissipate;
- if (x_chance_in_y(cloud.spread_rate, 100))
+ if (cloud.type == CLOUD_FOREST_FIRE)
+ _spread_fire(cloud);
+ else if (x_chance_in_y(cloud.spread_rate, 100))
{
cloud.spread_rate -= div_rand_round(cloud.spread_rate, 10);
cloud.decay -= _spread_cloud(cloud);
@@ -379,8 +412,7 @@ bool is_opaque_cloud(unsigned char cloud_idx)
return (false);
const int ctype = env.cloud[cloud_idx].type;
- return (ctype == CLOUD_BLACK_SMOKE
- || ctype >= CLOUD_GREY_SMOKE && ctype <= CLOUD_STEAM);
+ return (ctype >= CLOUD_OPAQUE_FIRST && ctype <= CLOUD_OPAQUE_LAST);
}
cloud_type cloud_type_at(const coord_def &c)
@@ -452,6 +484,7 @@ beam_type cloud2beam(cloud_type flavour)
default:
case CLOUD_NONE: return BEAM_NONE;
case CLOUD_FIRE: return BEAM_FIRE;
+ case CLOUD_FOREST_FIRE: return BEAM_FIRE;
case CLOUD_STINK: return BEAM_POTION_STINKING_CLOUD;
case CLOUD_COLD: return BEAM_COLD;
case CLOUD_POISON: return BEAM_POISON;
@@ -489,6 +522,7 @@ int max_cloud_damage(cloud_type cl_type, int power)
switch (cl_type)
{
case CLOUD_FIRE:
+ case CLOUD_FOREST_FIRE:
if (you.duration[DUR_FIRE_SHIELD])
return (0);
resist = player_res_fire();
@@ -575,6 +609,7 @@ void in_a_cloud()
switch (env.cloud[cl].type)
{
case CLOUD_FIRE:
+ case CLOUD_FOREST_FIRE:
if (you.duration[DUR_FIRE_SHIELD])
return;
@@ -750,6 +785,7 @@ bool is_damaging_cloud(cloud_type type, bool temp)
{
// always harmful...
case CLOUD_FIRE:
+ case CLOUD_FOREST_FIRE:
// ... unless a Ring of Flames is up and it's a fire cloud.
if (temp && you.duration[DUR_FIRE_SHIELD])
return (false);
@@ -823,6 +859,8 @@ std::string cloud_name(cloud_type type)
{
case CLOUD_FIRE:
return "flame";
+ case CLOUD_FOREST_FIRE:
+ return "fire";
case CLOUD_STINK:
return "noxious fumes";
case CLOUD_COLD:
diff --git a/crawl-ref/source/dat/clua/loadmaps.lua b/crawl-ref/source/dat/clua/loadmaps.lua
index c6d197e335..1dde1ad737 100644
--- a/crawl-ref/source/dat/clua/loadmaps.lua
+++ b/crawl-ref/source/dat/clua/loadmaps.lua
@@ -18,7 +18,7 @@ local des_files = {
"altar.des", "bazaar.des", "bailey.des", "entry.des", "elf.des",
"float.des", "hells.des", "hive.des", "icecave.des", "lab.des",
"lair.des", "large.des", "layout.des", "mini.des", "ossuary.des",
- "orc.des", "pan.des", "sewer.des", "temple.des", "trove.des",
+ "orc.des", "pan.des", "sewer.des", "shoals.des", "temple.des", "trove.des",
"vaults.des", "crypt.des", "ziggurat.des", "zot.des", "rooms.des"
}
diff --git a/crawl-ref/source/dat/database/quotes.txt b/crawl-ref/source/dat/database/quotes.txt
index 0bd7e9391a..1de77e5784 100644
--- a/crawl-ref/source/dat/database/quotes.txt
+++ b/crawl-ref/source/dat/database/quotes.txt
@@ -52,6 +52,18 @@ A one-way gate to the infinite horrors of the Abyss
the abyss gazes also into you."
-Friedrich Nietzsche, "Beyond Good and Evil"
%%%%
+A portal to a secret trove of treasure
+
+"'Stop thief! Stop thief!' There is a magic in the sound. The tradesman
+ leaves his counter, and the car-man his waggon; the butcher throws down
+ his tray; the baker his basket; the milkman his pail; the errand-boy
+ his parcels; the school-boy his marbles; the paviour his pickaxe; the
+ child his battledore. Away they run, pell-mell, helter-skelter, slap-dash:
+ tearing, yelling, screaming, knocking down the passengers as they turn
+ the corners, rousing up the dogs, and astonishing the fowls: and streets,
+ squares, and courts, re-echo with the sound."
+ -Charles Dickens, "Oliver Twist"
+%%%%
A rock wall
"I know not whether Laws be right,
@@ -75,6 +87,11 @@ controlling them; then pray that your grieves may slumber, and the
brotherhood of remorse not break their chain."
-Nathaniel Hawthorne
%%%%
+Trees
+
+"Only YOU can prevent forest fires!"
+ -Smokey the Bear
+%%%%
####################################################
# Items
####################################################
@@ -529,6 +546,13 @@ bumblebee
From every opening Flower!"
-Isaac Watts. 1715.
%%%%
+bush
+
+"And the angel of the LORD appeared unto him in a flame of fire out of the
+ midst of a bush: and he looked, and, behold, the bush burned with fire, and
+ the bush was not consumed."
+ -KJV Bible, Ex3:2.
+%%%%
butterfly
"Happiness is a butterfly, which when pursued, is always just beyond your
diff --git a/crawl-ref/source/dat/descript/features.txt b/crawl-ref/source/dat/descript/features.txt
index b8c58e3797..a3e40a5869 100644
--- a/crawl-ref/source/dat/descript/features.txt
+++ b/crawl-ref/source/dat/descript/features.txt
@@ -139,18 +139,6 @@ A one-way gate to the infinite horrors of the Abyss
A one-way gate to a demon-haunted realm, riven by chaos, its very substance impermanent and whimsical, filled with creatures out of nightmare.
%%%%
-A portal to a secret trove of treasure
-
-"'Stop thief! Stop thief!' There is a magic in the sound. The tradesman
- leaves his counter, and the car-man his waggon; the butcher throws down
- his tray; the baker his basket; the milkman his pail; the errand-boy
- his parcels; the school-boy his marbles; the paviour his pickaxe; the
- child his battledore. Away they run, pell-mell, helter-skelter, slap-dash:
- tearing, yelling, screaming, knocking down the passengers as they turn
- the corners, rousing up the dogs, and astonishing the fowls: and streets,
- squares, and courts, re-echo with the sound."
- -Charles Dickens, "Oliver Twist"
-%%%%
A rock wall
This wall consists of simple rock.
@@ -347,3 +335,7 @@ Some shallow water
This waist-deep, misty water makes movement and combat cumbersome for landlubbers - sometimes dangerous, but never directly fatal.
%%%%
+Trees
+
+While the dungeon is filled with dim magic light, in most places it is not bright enough to sustain any larger plants. It is uneven, though, and there are spots where, with the grace of Feawn, trees as big as those on the surface can grow underground.
+%%%%
diff --git a/crawl-ref/source/dat/descript/monsters.txt b/crawl-ref/source/dat/descript/monsters.txt
index 0908bacdc5..618a85040a 100644
--- a/crawl-ref/source/dat/descript/monsters.txt
+++ b/crawl-ref/source/dat/descript/monsters.txt
@@ -412,6 +412,10 @@ brown ooze
A viscous liquid, flowing along the floor in search of organic matter to corrode.
%%%%
+bush
+
+A woody plant that, unlike trees, can be removed even with bare hands. It looks dry enough to be easily set on fire, and it isn't very dense so arrows are likely to go past it.
+%%%%
water moccasin
A largish venomous brown snake. It usually lives near water, and is an able swimmer.
diff --git a/crawl-ref/source/dat/mini.des b/crawl-ref/source/dat/mini.des
index 2c5e8c78d4..1de16335d9 100644
--- a/crawl-ref/source/dat/mini.des
+++ b/crawl-ref/source/dat/mini.des
@@ -2425,3 +2425,33 @@ xxxxx"x........x+xxxxx........x"xxxxx
........xx'x...xm+++mx...x'xx........
..................@..................
ENDMAP
+
+#################################################################
+# And for now, something woody (1KB)
+#
+NAME: forest_paths
+DEPTH: D, Lair
+MAP
+tttttttttttttttttttttttttt@tttttttttttttttttttttt
+tttttttttttttttttttttttttt...tttttttttttttttttttt
+tttttttttttttttttttttttttttt..tttttttttttttt0}ttt
+ttttttttt.tt......ttttttttttt..tttttttttttt..tttt
+tttttttt.t...ttt.0.tttttttttt.tttttttttt...tttttt
+tt......tttttttt...ttttttttttt.tttttt...ttttttttt
+t.ttttttttttttttt....tttttttttt.tttt.tttttttttttt
+@ttttttttttttttt..tttttttttttt..tt...tttttttttttt
+ttttttttttttttt..tttttttttttttt....tttttttttttttt
+tttttttttttttttt..ttttttttttttttt.ttttttttttttttt
+tttttttttttttttt....tttttttttttt.tttttttttt...ttt
+tttttttttttttttttt.....tttttttttt..ttttttt..*..tt
+ttttttttttttttttttttt....ttttttttt.ttttttt.000.tt
+ttttttttttttttttttttttt...tttttttt.ttttt......ttt
+ttttttttttttttttttttttttt....tttt.ttttttt.tt.t0tt
+tttttttttttttttttttttttttttt.....tttttttt.ttttttt
+....ttttttttttttttttttttttt...tttttttttt.tttttttt
+@....tttttttt...ttttttttttt...tttttttt..ttttttttt
+ttttt..ttt....tt...tt........0.ttttt..ttttttttttt
+ttttttt....ttttttt....ttttttt..ttt..ttttttttttttt
+tttttttttttttttttttttttttttttt....ttttttttttttttt
+ttttttttttttttttttttttttttttttttttttttttttttttttt
+ENDMAP
diff --git a/crawl-ref/source/dat/shoals.des b/crawl-ref/source/dat/shoals.des
index 12e6803c84..8928e8009d 100644
--- a/crawl-ref/source/dat/shoals.des
+++ b/crawl-ref/source/dat/shoals.des
@@ -94,6 +94,19 @@ MAP
...
ENDMAP
+NAME: yaktaur_hedge
+DEPTH: Shoal
+MONS: bush
+MONS: yaktaur
+MAP
+.......
+.11111.
+.1...1.
+.1.1.1.
+.1.121.
+.1.111.
+.......
+ENDMAP
##############################################################################
# Branch ends.
diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc
index 9f78b628d8..aff6afc172 100644
--- a/crawl-ref/source/describe.cc
+++ b/crawl-ref/source/describe.cc
@@ -2688,6 +2688,9 @@ static std::string _monster_stat_description(const monsters& mon)
if (mons_immune_magic(&mon))
result << pronoun << " is immune to magical enchantments.$";
+ if (mons_class_flag(mon.type, M_STATIONARY))
+ result << pronoun << " cannot move.$";
+
// These differ between ghost demon monsters, so would be spoily.
if (!mons_is_ghost_demon(mon.type))
{
@@ -2699,7 +2702,7 @@ static std::string _monster_stat_description(const monsters& mon)
// Unusual monster speed.
const int speed = mons_base_speed(&mon);
- if (speed != 10)
+ if (speed != 10 && speed != 0)
{
result << pronoun << " is ";
if (speed < 7)
diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc
index d119668aae..e3d758a195 100644
--- a/crawl-ref/source/directn.cc
+++ b/crawl-ref/source/directn.cc
@@ -2653,6 +2653,8 @@ static std::string _base_feature_desc(dungeon_feature_type grid,
return ("translucent stone wall");
case DNGN_CLEAR_PERMAROCK_WALL:
return ("translucent unnaturally hard rock wall");
+ case DNGN_TREES:
+ return ("Trees");
case DNGN_ORCISH_IDOL:
if (you.species == SP_HILL_ORC)
return ("idol of Beogh");
diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc
index c8103e2f1a..1a22de6180 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -4831,6 +4831,7 @@ dungeon_feature_type map_feature(map_def *map, const coord_def &c, int rawfeat)
(rawfeat == 'm') ? DNGN_CLEAR_ROCK_WALL :
(rawfeat == 'n') ? DNGN_CLEAR_STONE_WALL :
(rawfeat == 'o') ? DNGN_CLEAR_PERMAROCK_WALL :
+ (rawfeat == 't') ? DNGN_TREES :
(rawfeat == '+') ? DNGN_CLOSED_DOOR :
(rawfeat == '=') ? DNGN_SECRET_DOOR :
(rawfeat == 'w') ? DNGN_DEEP_WATER :
@@ -4918,6 +4919,7 @@ static void _vault_grid( vault_placement &place,
(vgrid == 'm') ? DNGN_CLEAR_ROCK_WALL :
(vgrid == 'n') ? DNGN_CLEAR_STONE_WALL :
(vgrid == 'o') ? DNGN_CLEAR_PERMAROCK_WALL :
+ (vgrid == 't') ? DNGN_TREES :
(vgrid == '+') ? DNGN_CLOSED_DOOR :
(vgrid == '=') ? DNGN_SECRET_DOOR :
(vgrid == 'w') ? DNGN_DEEP_WATER :
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index 4d186f9e91..58376fb08c 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -431,6 +431,11 @@ enum cloud_type
CLOUD_GREY_SMOKE,
CLOUD_BLUE_SMOKE,
CLOUD_PURP_SMOKE,
+ CLOUD_FOREST_FIRE,
+
+ CLOUD_OPAQUE_FIRST = CLOUD_BLACK_SMOKE,
+ CLOUD_OPAQUE_LAST = CLOUD_FOREST_FIRE,
+
CLOUD_STEAM,
CLOUD_MIASMA,
CLOUD_MIST,
@@ -945,6 +950,7 @@ enum dungeon_char_type
DCHAR_ITEM_GOLD,
DCHAR_ITEM_AMULET, // 30
DCHAR_CLOUD, // 31
+ DCHAR_TREES,
DCHAR_SPACE,
DCHAR_FIRED_FLASK,
@@ -1016,6 +1022,7 @@ enum dungeon_feature_type
// Highest grid value which can't be reached through.
DNGN_MAX_NONREACH = DNGN_CLEAR_PERMAROCK_WALL,
+ DNGN_TREES,
DNGN_OPEN_SEA, // Shoals equivalent for permarock
// Can be seen through and reached past.
@@ -1863,6 +1870,7 @@ enum monster_type // (int) menv[].type
MONS_FLAMING_CORPSE,
MONS_HARPY,
MONS_TOADSTOOL, // 198
+ MONS_BUSH,
//jmf: end new monsters
MONS_WHITE_IMP = 220, // 220
MONS_LEMURE,
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index 1c4d291f8c..732f4fe497 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -1336,7 +1336,7 @@ public:
void scale_hp(int num, int den);
bool gain_exp(int exp);
- void react_to_damage(int damage, beam_type flavour);
+ void react_to_damage(int damage, beam_type flavour, kill_category whose);
void forget_random_spell();
diff --git a/crawl-ref/source/losparam.cc b/crawl-ref/source/losparam.cc
index 9b83e28b11..833ee04003 100644
--- a/crawl-ref/source/losparam.cc
+++ b/crawl-ref/source/losparam.cc
@@ -92,11 +92,16 @@ unsigned short los_param_base::cloud_idx(const coord_def& p) const
opacity_type los_param_base::opacity(const coord_def& p) const
{
+ int m;
dungeon_feature_type f = feature(p);
if (grid_is_opaque(f))
return OPC_OPAQUE;
else if (is_opaque_cloud(cloud_idx(p)))
return OPC_HALF;
+ else if (f == DNGN_TREES)
+ return OPC_HALF;
+ else if ((m = mgrd(trans(p))) != NON_MONSTER && menv[m].type == MONS_BUSH)
+ return OPC_HALF;
else
return OPC_CLEAR;
}
diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc
index a9e1fc855d..face8ab8d7 100644
--- a/crawl-ref/source/mapdef.cc
+++ b/crawl-ref/source/mapdef.cc
@@ -843,7 +843,7 @@ int map_lines::glyph(const coord_def &c) const
bool map_lines::is_solid(int gly) const
{
- return (gly == 'x' || gly == 'c' || gly == 'b' || gly == 'v');
+ return (gly == 'x' || gly == 'c' || gly == 'b' || gly == 'v' || gly == 't');
}
void map_lines::check_borders()
diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h
index 106987988f..830ee12274 100644
--- a/crawl-ref/source/mon-data.h
+++ b/crawl-ref/source/mon-data.h
@@ -2520,6 +2520,17 @@ static monsterentry mondata[] = {
HT_LAND, 10, DEFAULT_ENERGY, MONUSE_NOTHING, MONEAT_NOTHING, SIZE_SMALL
},
+{
+ MONS_BUSH, 'P', BROWN, "bush",
+ M_NO_EXP_GAIN | M_STATIONARY,
+ MR_RES_POISON | MR_VUL_FIRE | MR_RES_ASPHYX,
+ 0, 10, MONS_PLANT, MONS_BUSH, MH_PLANT, MAG_IMMUNE,
+ { AT_NO_ATK, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK },
+ { 20, 3, 5, 0 },
+ 30, 0, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
+ HT_LAND, 0, DEFAULT_ENERGY, MONUSE_NOTHING, MONEAT_NOTHING, SIZE_BIG
+},
+
// queen insects ('Q')
{
MONS_QUEEN_BEE, 'Q', YELLOW, "queen bee",
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index e5c4cca512..f1562b5df7 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -25,6 +25,7 @@ REVISION("$Rev$");
#include "artefact.h"
#include "beam.h"
+#include "cloud.h"
#include "database.h"
#include "debug.h"
#include "delay.h"
@@ -644,6 +645,7 @@ bool mons_is_slime(const monsters *mon)
bool mons_class_is_plant(int mc)
{
return (mons_genus(mc) == MONS_PLANT
+ || mons_genus(mc) == MONS_BUSH
|| mons_genus(mc) == MONS_FUNGUS);
}
@@ -6292,7 +6294,11 @@ int monsters::hurt(const actor *agent, int amount, beam_type flavour,
// Allow the victim to exhibit passive damage behaviour (royal
// jelly).
- react_to_damage(amount, flavour);
+ kill_category whose = (agent == NULL) ? KC_OTHER :
+ (agent->atype() == ACT_PLAYER) ? KC_YOU :
+ mons_friendly_real((monsters*)agent) ? KC_FRIENDLY :
+ KC_OTHER;
+ react_to_damage(amount, flavour, whose);
}
if (cleanup_dead && (hit_points <= 0 || hit_dice <= 0) && type != -1)
@@ -8441,7 +8447,7 @@ item_type_id_state_type monsters::drink_potion_effect(potion_type ptype)
return (ident);
}
-void monsters::react_to_damage(int damage, beam_type flavour)
+void monsters::react_to_damage(int damage, beam_type flavour, kill_category whose)
{
if (!alive())
return;
@@ -8507,6 +8513,11 @@ void monsters::react_to_damage(int damage, beam_type flavour)
menv[number].hurt(&you, damage, flavour);
}
}
+ else if (type == MONS_BUSH && flavour == BEAM_FIRE
+ && damage>8 && x_chance_in_y(damage, 20))
+ {
+ place_cloud(CLOUD_FIRE, pos(), 20+random2(15), whose, 5);
+ }
}
/////////////////////////////////////////////////////////////////////////
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index daf446fb0a..e2c53a68a7 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -5499,6 +5499,7 @@ bool mons_avoids_cloud(const monsters *monster, cloud_struct cloud,
return (!mons_res_rotting(monster));
case CLOUD_FIRE:
+ case CLOUD_FOREST_FIRE:
if (mons_res_fire(monster) > 1)
return (false);
@@ -8892,6 +8893,7 @@ static bool _mon_can_move_to_pos(const monsters *monster,
if (monster->type == MONS_WATER_ELEMENTAL
&& (target_grid == DNGN_LAVA
|| targ_cloud_type == CLOUD_FIRE
+ || targ_cloud_type == CLOUD_FOREST_FIRE
|| targ_cloud_type == CLOUD_STEAM))
{
return (false);
@@ -9399,6 +9401,7 @@ static void _mons_in_cloud(monsters *monster)
return;
case CLOUD_FIRE:
+ case CLOUD_FOREST_FIRE:
if (monster->type == MONS_FIRE_VORTEX
|| monster->type == MONS_EFREET
|| monster->type == MONS_FIRE_ELEMENTAL)
diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc
index 5a2d319397..e9499f2181 100644
--- a/crawl-ref/source/view.cc
+++ b/crawl-ref/source/view.cc
@@ -419,6 +419,16 @@ static bool _show_bloodcovered(const coord_def& where)
return (!is_critical_feature(grid) && !grid_is_trap(grid));
}
+static unsigned short _tree_colour(const coord_def& where)
+{
+ uint32_t h = where.x;
+ h+=h<<10; h^=h>>6;
+ h += where.y;
+ h+=h<<10; h^=h>>6;
+ h+=h<<3; h^=h>>11; h+=h<<15;
+ return (h>>30) ? GREEN : LIGHTGREEN;
+}
+
static void _get_symbol( const coord_def& where,
int object, unsigned *ch,
unsigned short *colour,
@@ -499,6 +509,8 @@ static void _get_symbol( const coord_def& where,
// already set.
if (fdef.colour != BLACK)
*colour = fdef.colour | colmask;
+ else if (object == DNGN_TREES)
+ *colour = _tree_colour(where) | colmask;
if (fdef.em_colour != fdef.colour && fdef.em_colour)
{
@@ -1636,6 +1648,7 @@ inline static void _update_cloud_grid(int cloudno)
switch (env.cloud[cloudno].type)
{
case CLOUD_FIRE:
+ case CLOUD_FOREST_FIRE:
if (env.cloud[cloudno].decay <= 20)
which_colour = RED;
else if (env.cloud[cloudno].decay <= 40)
@@ -3001,7 +3014,7 @@ static const unsigned dchar_table[ NUM_CSET ][ NUM_DCHAR_TYPES ] =
'#', '*', '.', ',', '\'', '+', '^', '>', '<', // wall .. stairs up
'_', '\\', '}', '{', '8', '~', '~', // altar .. item detect
'0', ')', '[', '/', '%', '?', '=', '!', '(', // orb .. missile
- ':', '|', '}', '%', '$', '"', '#', // book .. cloud
+ ':', '|', '}', '%', '$', '"', '#', '@', // book .. trees
' ', '!', '#', '%', ':', ')', '*', '+', // space .. fired_burst
'/', '=', '?', 'X', '[', '`', '#' // fi_stick .. explosion
},
@@ -3011,7 +3024,7 @@ static const unsigned dchar_table[ NUM_CSET ][ NUM_DCHAR_TYPES ] =
177, 176, 249, 250, '\'', 254, '^', '>', '<', // wall .. stairs up
220, 239, 244, 247, '8', '~', '~', // altar .. item detect
'0', ')', '[', '/', '%', '?', '=', '!', '(', // orb .. missile
- '+', '\\', '}', '%', '$', '"', '#', // book .. cloud
+ '+', '\\', '}', '%', '$', '"', '#', 234, // book .. trees
' ', '!', '#', '%', '+', ')', '*', '+', // space .. fired_burst
'/', '=', '?', 'X', '[', '`', '#' // fi_stick .. explosion
},
@@ -3021,7 +3034,7 @@ static const unsigned dchar_table[ NUM_CSET ][ NUM_DCHAR_TYPES ] =
225, 224, 254, ':', '\'', 238, '^', '>', '<', // wall .. stairs up
251, 182, 167, 187, '8', 171, 168, // altar .. item detect
'0', ')', '[', '/', '%', '?', '=', '!', '(', // orb .. missile
- '+', '\\', '}', '%', '$', '"', '#', // book .. cloud
+ '+', '\\', '}', '%', '$', '"', '#', '@', // book .. trees
' ', '!', '#', '%', '+', ')', '*', '+', // space .. fired_burst
'/', '=', '?', 'X', '[', '`', '#' // fi_stick .. explosion
},
@@ -3031,7 +3044,7 @@ static const unsigned dchar_table[ NUM_CSET ][ NUM_DCHAR_TYPES ] =
0x2592, 0x2591, 0xB7, 0x25E6, '\'', 0x25FC, '^', '>', '<',
'_', 0x2229, 0x2320, 0x2248, '8', '~', '~',
'0', ')', '[', '/', '%', '?', '=', '!', '(',
- '+', '|', '}', '%', '$', '"', '#',
+ '+', '|', '}', '%', '$', '"', '#', 0x2663,
' ', '!', '#', '%', '+', ')', '*', '+', // space .. fired_burst
'/', '=', '?', 'X', '[', '`', '#' // fi_stick .. explosion
},
@@ -3047,7 +3060,7 @@ dungeon_char_type dchar_by_name(const std::string &name)
"item_orb", "item_weapon", "item_armour", "item_wand", "item_food",
"item_scroll", "item_ring", "item_potion", "item_missile", "item_book",
"item_stave", "item_miscellany", "item_corpse", "item_gold",
- "item_amulet", "cloud"
+ "item_amulet", "cloud", "trees",
};
for (unsigned i = 0; i < sizeof(dchar_names) / sizeof(*dchar_names); ++i)
@@ -3143,6 +3156,13 @@ void init_feature_table( void )
Feature[i].minimap = MF_WALL;
break;
+ case DNGN_TREES:
+ Feature[i].dchar = DCHAR_TREES;
+ Feature[i].magic_symbol = Options.char_table[ DCHAR_WALL_MAGIC ];
+ Feature[i].colour = BLACK; // overridden later
+ Feature[i].minimap = MF_WALL;
+ break;
+
case DNGN_OPEN_SEA:
#ifdef USE_TILE
Feature[i].dchar = DCHAR_WAVY;