summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/docs/develop/level_design.txt1
-rw-r--r--crawl-ref/source/beam.cc34
-rw-r--r--crawl-ref/source/cloud.cc44
-rw-r--r--crawl-ref/source/directn.cc2
-rw-r--r--crawl-ref/source/dungeon.cc2
-rw-r--r--crawl-ref/source/enum.h7
-rw-r--r--crawl-ref/source/losparam.cc2
-rw-r--r--crawl-ref/source/mapdef.cc2
-rw-r--r--crawl-ref/source/monstuff.cc3
-rw-r--r--crawl-ref/source/view.cc30
10 files changed, 109 insertions, 18 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 39bd4313ec..3fb98b446c 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -1709,8 +1709,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;
@@ -1719,7 +1720,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()))
{
@@ -1734,12 +1735,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;
}
@@ -3102,7 +3118,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?
diff --git a/crawl-ref/source/cloud.cc b/crawl-ref/source/cloud.cc
index d2c9f5c30b..40f92bb4e4 100644
--- a/crawl-ref/source/cloud.cc
+++ b/crawl-ref/source/cloud.cc
@@ -25,6 +25,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)
{
@@ -130,13 +131,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);
@@ -349,8 +382,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)
@@ -420,6 +452,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;
@@ -456,6 +489,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();
@@ -542,6 +576,7 @@ void in_a_cloud()
switch (env.cloud[cl].type)
{
case CLOUD_FIRE:
+ case CLOUD_FOREST_FIRE:
if (you.duration[DUR_FIRE_SHIELD])
return;
@@ -710,6 +745,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);
@@ -759,6 +795,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/directn.cc b/crawl-ref/source/directn.cc
index 1882388af6..c15a6f09a8 100644
--- a/crawl-ref/source/directn.cc
+++ b/crawl-ref/source/directn.cc
@@ -2654,6 +2654,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 ee1571569b..4f07e96f12 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -4836,6 +4836,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 :
@@ -4923,6 +4924,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 5ef53a802a..58c2c95b13 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.
diff --git a/crawl-ref/source/losparam.cc b/crawl-ref/source/losparam.cc
index c0a3ed0298..f19412616e 100644
--- a/crawl-ref/source/losparam.cc
+++ b/crawl-ref/source/losparam.cc
@@ -97,6 +97,8 @@ opacity_type los_param_base::opacity(const coord_def& p) const
return OPC_OPAQUE;
else if (is_opaque_cloud(cloud_idx(p)))
return OPC_HALF;
+ else if (f == DNGN_TREES)
+ return OPC_HALF;
else
return OPC_CLEAR;
}
diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc
index db17585693..49ea350a1a 100644
--- a/crawl-ref/source/mapdef.cc
+++ b/crawl-ref/source/mapdef.cc
@@ -844,7 +844,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/monstuff.cc b/crawl-ref/source/monstuff.cc
index de0534aeb7..37224b5310 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -5446,6 +5446,7 @@ bool mons_avoids_cloud(const monsters *monster, cloud_type cl_type,
return (!mons_res_rotting(monster));
case CLOUD_FIRE:
+ case CLOUD_FOREST_FIRE:
if (mons_res_fire(monster) > 1)
return (false);
@@ -8822,6 +8823,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);
@@ -9329,6 +9331,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 5fea829d23..931324c5d1 100644
--- a/crawl-ref/source/view.cc
+++ b/crawl-ref/source/view.cc
@@ -423,6 +423,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,
@@ -503,6 +513,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)
{
@@ -1640,6 +1652,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)
@@ -3004,7 +3017,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
},
@@ -3014,7 +3027,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
},
@@ -3024,7 +3037,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
},
@@ -3034,7 +3047,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
},
@@ -3050,7 +3063,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)
@@ -3146,6 +3159,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;