diff options
-rw-r--r-- | crawl-ref/docs/develop/level_design.txt | 1 | ||||
-rw-r--r-- | crawl-ref/source/beam.cc | 34 | ||||
-rw-r--r-- | crawl-ref/source/cloud.cc | 44 | ||||
-rw-r--r-- | crawl-ref/source/directn.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/dungeon.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/enum.h | 7 | ||||
-rw-r--r-- | crawl-ref/source/losparam.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/mapdef.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/monstuff.cc | 3 | ||||
-rw-r--r-- | crawl-ref/source/view.cc | 30 |
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; |