summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/abl-show.cc14
-rw-r--r--crawl-ref/source/beam.cc1
-rw-r--r--crawl-ref/source/cloud.cc31
-rw-r--r--crawl-ref/source/dat/altar.des2
-rw-r--r--crawl-ref/source/dat/crypt.des19
-rw-r--r--crawl-ref/source/describe.cc8
-rw-r--r--crawl-ref/source/dungeon.cc146
-rw-r--r--crawl-ref/source/enum.h4
-rw-r--r--crawl-ref/source/fight.cc10
-rw-r--r--crawl-ref/source/fight.h2
-rw-r--r--crawl-ref/source/godabil.cc379
-rw-r--r--crawl-ref/source/godwrath.cc5
-rw-r--r--crawl-ref/source/mon-act.cc74
-rw-r--r--crawl-ref/source/mon-data.h4
-rw-r--r--crawl-ref/source/monster.cc15
-rw-r--r--crawl-ref/source/newgame.cc2
-rw-r--r--crawl-ref/source/religion.cc38
-rw-r--r--crawl-ref/source/rltiles/dc-misc.txt2
-rw-r--r--crawl-ref/source/rltiles/dc-mon.txt5
-rw-r--r--crawl-ref/source/rltiles/effect/cloud_gloom.pngbin0 -> 177 bytes
-rw-r--r--crawl-ref/source/show.cc6
-rw-r--r--crawl-ref/source/skills2.cc19
-rw-r--r--crawl-ref/source/tilepick.cc14
23 files changed, 568 insertions, 232 deletions
diff --git a/crawl-ref/source/abl-show.cc b/crawl-ref/source/abl-show.cc
index e6a0ee2d4c..66c878dcb3 100644
--- a/crawl-ref/source/abl-show.cc
+++ b/crawl-ref/source/abl-show.cc
@@ -145,8 +145,8 @@ ability_type god_abilities[MAX_NUM_GODS][MAX_GOD_ABILITIES] =
{ ABIL_JIYVA_CALL_JELLY, ABIL_NON_ABILITY, ABIL_NON_ABILITY,
ABIL_JIYVA_SLIMIFY, ABIL_JIYVA_CURE_BAD_MUTATION },
// Fedhas
- { ABIL_FEDHAS_SUNLIGHT, ABIL_FEDHAS_PLANT_RING, ABIL_FEDHAS_RAIN,
- ABIL_FEDHAS_SPAWN_SPORES, ABIL_FEDHAS_EVOLUTION },
+ { ABIL_FEDHAS_EVOLUTION, ABIL_FEDHAS_SUNLIGHT, ABIL_FEDHAS_PLANT_RING,
+ ABIL_FEDHAS_SPAWN_SPORES, ABIL_FEDHAS_RAIN},
// Cheibriados
{ ABIL_NON_ABILITY, ABIL_CHEIBRIADOS_TIME_BEND, ABIL_NON_ABILITY,
ABIL_CHEIBRIADOS_SLOUCH, ABIL_CHEIBRIADOS_TIME_STEP },
@@ -327,11 +327,12 @@ static const ability_def Ability_List[] =
// Fedhas
{ ABIL_FEDHAS_FUNGAL_BLOOM, "Decomposition", 0, 0, 0, 0, ABFLAG_NONE },
+ { ABIL_FEDHAS_EVOLUTION, "Evolution", 2, 0, 0, 0, ABFLAG_FRUIT},
{ ABIL_FEDHAS_SUNLIGHT, "Sunlight", 2, 0, 0, 0, ABFLAG_NONE},
- { ABIL_FEDHAS_PLANT_RING, "Growth", 2, 0, 0, 1, ABFLAG_FRUIT},
- { ABIL_FEDHAS_RAIN, "Rain", 4, 0, 100, 2, ABFLAG_NONE},
+ { ABIL_FEDHAS_PLANT_RING, "Growth", 2, 0, 0, 0, ABFLAG_FRUIT},
{ ABIL_FEDHAS_SPAWN_SPORES, "Reproduction", 4, 0, 50, 2, ABFLAG_NONE},
- { ABIL_FEDHAS_EVOLUTION, "Evolution", 4, 0, 0, 2, ABFLAG_FRUIT},
+ { ABIL_FEDHAS_RAIN, "Rain", 4, 0, 100, 4, ABFLAG_NONE},
+
// Cheibriados
{ ABIL_CHEIBRIADOS_PONDEROUSIFY, "Make Ponderous", 2, 0, 0, 0, ABFLAG_NONE },
@@ -682,6 +683,7 @@ static talent _get_talent(ability_type ability, bool check_confused)
case ABIL_LUGONU_ABYSS_EXIT:
case ABIL_JIYVA_CALL_JELLY:
case ABIL_FEDHAS_SUNLIGHT:
+ case ABIL_FEDHAS_EVOLUTION:
invoc = true;
failure = 30 - (you.piety / 20) - (6 * you.skills[SK_INVOCATIONS]);
break;
@@ -767,7 +769,6 @@ static talent _get_talent(ability_type ability, bool check_confused)
case ABIL_OKAWARU_HASTE:
case ABIL_MAKHLEB_GREATER_SERVANT_OF_MAKHLEB:
case ABIL_LUGONU_CORRUPT:
- case ABIL_FEDHAS_EVOLUTION:
invoc = true;
failure = 70 - (you.piety / 25) - (you.skills[SK_INVOCATIONS] * 4);
break;
@@ -1990,7 +1991,6 @@ static bool _do_ability(const ability_def& abil)
case ABIL_FEDHAS_EVOLUTION:
if (!evolve_flora())
{
- canned_msg(MSG_NOTHING_HAPPENS);
return (false);
}
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index 36c47d85b8..49b464b608 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -6396,6 +6396,7 @@ std::string beam_type_name(beam_type type)
case BEAM_VISUAL: return ("visual effects");
case BEAM_TORMENT_DAMAGE: return ("torment damage");
case BEAM_STEAL_FOOD: return ("steal food");
+ case BEAM_GLOOM: return ("gloom");
case NUM_BEAMS: DEBUGSTR("invalid beam type");
return ("INVALID");
diff --git a/crawl-ref/source/cloud.cc b/crawl-ref/source/cloud.cc
index 823164846d..50e27a3fd2 100644
--- a/crawl-ref/source/cloud.cc
+++ b/crawl-ref/source/cloud.cc
@@ -12,6 +12,7 @@
#include "externs.h"
+#include "areas.h"
#include "branch.h"
#include "cloud.h"
#include "colour.h"
@@ -41,6 +42,8 @@ static int _actual_spread_rate(cloud_type type, int spread_rate)
switch (type)
{
+ case CLOUD_GLOOM:
+ return 50;
case CLOUD_STEAM:
case CLOUD_GREY_SMOKE:
case CLOUD_BLACK_SMOKE:
@@ -227,6 +230,22 @@ void manage_clouds()
dissipate *= 4;
else if ((cloud.type == CLOUD_COLD || cloud.type == CLOUD_RAIN) && grd(cloud.pos) == DNGN_LAVA)
dissipate *= 4;
+ else if (cloud.type == CLOUD_GLOOM)
+ {
+ int count = 0;
+ for (adjacent_iterator ai(cloud.pos); ai; ++ai)
+ if (env.cgrid(*ai) != EMPTY_CLOUD)
+ if (env.cloud[env.cgrid(*ai)].type == CLOUD_GLOOM)
+ count++;
+
+ if (!haloers(cloud.pos).empty() && !silenced(cloud.pos))
+ count = 0;
+
+ if (count < 4)
+ dissipate *= 50;
+ else
+ dissipate /= 20;
+ }
expose_items_to_element(cloud2beam(cloud.type), cloud.pos, 2);
@@ -514,6 +533,8 @@ cloud_type beam2cloud(beam_type flavour)
return CLOUD_RAIN;
case BEAM_POTION_MUTAGENIC:
return CLOUD_MUTAGENIC;
+ case BEAM_GLOOM:
+ return CLOUD_GLOOM;
case BEAM_RANDOM:
return CLOUD_RANDOM;
}
@@ -539,6 +560,7 @@ beam_type cloud2beam(cloud_type flavour)
case CLOUD_CHAOS: return BEAM_CHAOS;
case CLOUD_RAIN: return BEAM_POTION_RAIN;
case CLOUD_MUTAGENIC: return BEAM_POTION_MUTAGENIC;
+ case CLOUD_GLOOM: return BEAM_GLOOM;
case CLOUD_RANDOM: return BEAM_RANDOM;
}
}
@@ -833,6 +855,11 @@ void in_a_cloud()
}
break;
+ case CLOUD_GLOOM:
+ mprf("You are engulfed in %s!", !name.empty() ? name.c_str() : "a thick gloom");
+
+ break;
+
default:
break;
}
@@ -887,6 +914,7 @@ bool is_harmless_cloud(cloud_type type)
case CLOUD_MIST:
case CLOUD_RAIN:
case CLOUD_MAGIC_TRAIL:
+ case CLOUD_GLOOM:
case CLOUD_DEBUGGING:
return (true);
default:
@@ -963,6 +991,8 @@ std::string cloud_name(cloud_type type)
return "mutagenic fog";
case CLOUD_MAGIC_TRAIL:
return "magical condensation";
+ case CLOUD_GLOOM:
+ return "gloom";
default:
return "buggy goodness";
}
@@ -1078,6 +1108,7 @@ int get_cloud_colour(int cloudno)
case CLOUD_PURPLE_SMOKE:
case CLOUD_TLOC_ENERGY:
+ case CLOUD_GLOOM:
which_colour = MAGENTA;
break;
diff --git a/crawl-ref/source/dat/altar.des b/crawl-ref/source/dat/altar.des
index 9d67838a2d..513838d30d 100644
--- a/crawl-ref/source/dat/altar.des
+++ b/crawl-ref/source/dat/altar.des
@@ -444,7 +444,7 @@ SUBST: y = c.
COLOUR: 1. = random
MARKER: P = lua:fog_machine { cloud_type="blue smoke", walk_dist=1, \
size=9, pow_max=20, delay=10, buildup_amnt=14, buildup_time=7, \
- spread_rate=3, start_clouds=1 }
+ spread_rate=3, start_clouds=1, colour="blue" }
: if crawl.coinflip() then
KFEAT: _ = altar_lugonu
KFEAT: P = enter_abyss
diff --git a/crawl-ref/source/dat/crypt.des b/crawl-ref/source/dat/crypt.des
index c1b6ade7cf..174bc6fbde 100644
--- a/crawl-ref/source/dat/crypt.des
+++ b/crawl-ref/source/dat/crypt.des
@@ -601,6 +601,25 @@ MONS: flying skull / skeletal warrior / w:40 nothing
KFEAT: ^ = alarm trap
SUBST: F = G:100 F:1
KMONS: F = orange crystal statue / silver statue / ice statue
+{{
+lua_marker("m", portal_desc { wall_phase =1 })
+
+function drop_walls (data, triggerable, triggerer, marker, ev)
+ if data.trig == true then
+ return
+ else
+ data.trig = true
+ end
+
+ crawl.mpr("The liches are set free!", "warning")
+ for slave in iter.slave_iterator("wall_phase", 1) do
+ dgn.terrain_changed(slave.x, slave.y, "floor", false, false, false)
+ end
+end
+
+lua_marker("|", Triggerable.synchronized_markers(function_at_spot(drop_walls,
+ { trig = false}, true, { only_at_slave = true, listen_to_slaves = true })))
+}}
MAP
.....................
.....................
diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc
index 396e6a674b..83524b08da 100644
--- a/crawl-ref/source/describe.cc
+++ b/crawl-ref/source/describe.cc
@@ -3372,11 +3372,9 @@ const char *divine_title[NUM_GODS][8] =
{"Scum", "Jelly", "Squelcher", "Dissolver",
"Putrid Slime", "Consuming %s", "Archjelly", "Royal Jelly"},
- // Fedhas Madash -- nature theme. Titles could use some work, but the
- // progression is generally from nature lover to walking disaster.
- // -cao
- {"Walking Fertiliser", "Green %s", "Photosynthesist", "Planter",
- "Nimbus", "Sporadic Warrior", "Green Death", "Force of Nature"},
+ // Fedhas Madash -- nature theme. Titles could use some work
+ {"Walking Fertiliser", "Green %s", "Inducer", "Photosynthesist",
+ "Planter", "Sporadic Warrior", "Nimbus", "Force of Nature"},
// Cheibriados -- slow theme
{"Unwound %s", "Timekeeper", "Righteous Timekeeper", "Chronographer",
diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc
index cc3e884478..fdf91dd06b 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -155,7 +155,9 @@ static bool _join_the_dots_rigorous(const coord_def &from,
static void _build_river(dungeon_feature_type river_type); //mv
static void _build_lake(dungeon_feature_type lake_type); //mv
-static void _ruin_level();
+static void _ruin_level(int ruination = 10, int plant_density = 5);
+static void _add_plant_clumps(int frequency = 10, int clump_density = 12,
+ int clump_radius = 4);
static void _bigger_room();
static void _plan_main(int level_number, int force_plan);
@@ -1135,11 +1137,6 @@ static void _build_layout_skeleton(int level_number, int level_type,
_builder_extras(level_number, level_type);
}
}
-
- if (player_in_branch(BRANCH_LAIR))
- {
- _ruin_level();
- }
}
static int _num_items_wanted(int level_number)
@@ -1790,7 +1787,7 @@ static void _build_overflow_temples(int level_number)
if (!dgn_ensure_vault_placed(_build_vaults(level_number, vault), false))
{
#ifdef DEBUG_TEMPLES
- mprf(MSGCH_DIAGNOSTICS, "Couldn't place overlfow temple '%s', "
+ mprf(MSGCH_DIAGNOSTICS, "Couldn't place overflow temple '%s', "
"vetoing level.", vault->name.c_str());
#endif
return;
@@ -1837,6 +1834,16 @@ static void _build_dungeon_level(int level_number, int level_type)
if (!player_in_branch(BRANCH_DIS) && !player_in_branch(BRANCH_VAULTS))
_hide_doors();
+ if (player_in_branch(BRANCH_LAIR))
+ {
+ int depth = player_branch_depth() + 1;
+ do {
+ _ruin_level(20 - depth, depth / 2 + 5);
+ _add_plant_clumps(12 - depth, 18 - depth / 4, depth / 4 + 2);
+ depth -= 3;
+ } while (depth > 0);
+ }
+
// Change pre-rock to rock, and pre-floor to floor.
dgn_replace_area(0, 0, GXM-1, GYM-1, DNGN_BUILDER_SPECIAL_WALL,
DNGN_ROCK_WALL);
@@ -7736,22 +7743,27 @@ static void _build_lake(dungeon_feature_type lake_type) //mv
}
}
-static void _ruin_level()
+static void _ruin_level(int ruination /* = 10 */, int plant_density /* = 5 */)
{
std::vector<coord_def> to_replace;
for (rectangle_iterator ri(1); ri; ++ri)
{
- /* only try to replace wall tiles */
- if (!feat_is_wall(grd(*ri)))
+ /* only try to replace wall and door tiles */
+ if (!feat_is_wall(grd(*ri)) && !feat_is_door(grd(*ri)))
{
continue;
}
+ /* don't mess with permarock */
+ if (grd(*ri) == DNGN_PERMAROCK_WALL) {
+ continue;
+ }
+
int floor_count = 0;
for (adjacent_iterator ai(*ri); ai; ++ai)
{
- if (!feat_is_wall(grd(*ai)))
+ if (!feat_is_wall(grd(*ai)) && !feat_is_door(grd(*ai)))
{
floor_count++;
}
@@ -7759,7 +7771,7 @@ static void _ruin_level()
/* chance of removing the tile is dependent on the number of adjacent
* floor tiles */
- if (x_chance_in_y(floor_count, 10))
+ if (x_chance_in_y(floor_count, ruination))
{
to_replace.push_back(*ri);
}
@@ -7769,13 +7781,115 @@ static void _ruin_level()
it != to_replace.end();
++it)
{
+ /* only remove some doors, to preserve tactical options */
/* XXX: should this pick a random adjacent floor type, rather than
* just hardcoding DNGN_FLOOR? */
- grd(*it) = DNGN_FLOOR;
+ if (feat_is_wall(grd(*it)) ||
+ (coinflip() && feat_is_door(grd(*it))))
+ {
+ grd(*it) = DNGN_FLOOR;
+ }
- /* replace some ruined walls with plants/fungi */
- if (one_chance_in(5)) {
- mons_place(mgen_data(coinflip() ? MONS_PLANT : MONS_FUNGUS));
+ /* but remove doors if we've removed all adjacent walls */
+ for (adjacent_iterator wai(*it); wai; ++wai)
+ {
+ if (feat_is_door(grd(*wai)))
+ {
+ bool remove = true;
+ for (adjacent_iterator dai(*wai); dai; ++dai)
+ {
+ if (feat_is_wall(grd(*dai)))
+ {
+ remove = false;
+ }
+ }
+ if (remove)
+ {
+ grd(*wai) = DNGN_FLOOR;
+ }
+ }
+ }
+
+ /* replace some ruined walls with plants/fungi/bushes */
+ if (one_chance_in(plant_density))
+ {
+ mgen_data mg;
+ mg.cls = one_chance_in(20) ? MONS_BUSH :
+ coinflip() ? MONS_PLANT :
+ MONS_FUNGUS;
+ mg.pos = *it;
+ mons_place(mgen_data(mg));
+ }
+ }
+}
+
+static void _add_plant_clumps(int frequency /* = 10 */,
+ int clump_density /* = 12 */,
+ int clump_radius /* = 4 */)
+{
+ for (rectangle_iterator ri(1); ri; ++ri)
+ {
+ mgen_data mg;
+ if (mgrd(*ri) != NON_MONSTER)
+ {
+ /* clump plants around things that already exist */
+ monster_type type = menv[mgrd(*ri)].type;
+ if ((type == MONS_PLANT ||
+ type == MONS_FUNGUS ||
+ type == MONS_BUSH) && one_chance_in(frequency)) {
+ mg.cls = type;
+ }
+ else {
+ continue;
+ }
+ }
+ else {
+ continue;
+ }
+
+ std::vector<coord_def> to_place;
+ to_place.push_back(*ri);
+ for (int i = 1; i < clump_radius; ++i)
+ {
+ for (radius_iterator rad(*ri, i, C_SQUARE); rad; ++rad)
+ {
+ if (grd(*rad) != DNGN_FLOOR)
+ {
+ continue;
+ }
+
+ /* make sure the iterator stays valid */
+ std::vector<coord_def> more_to_place;
+ for (std::vector<coord_def>::const_iterator it = to_place.begin();
+ it != to_place.end();
+ ++it)
+ {
+ if (*rad == *it)
+ {
+ continue;
+ }
+ /* only place plants next to previously placed plants */
+ if (abs(rad->x - it->x) <= 1 && abs(rad->y - it->y) <= 1)
+ {
+ if (one_chance_in(clump_density)) {
+ more_to_place.push_back(*rad);
+ }
+ }
+ }
+ to_place.insert(to_place.end(), more_to_place.begin(), more_to_place.end());
+ }
+ }
+
+ for (std::vector<coord_def>::const_iterator it = to_place.begin();
+ it != to_place.end();
+ ++it)
+ {
+ if (*it == *ri)
+ {
+ continue;
+ }
+ mg.pos = *it;
+ mons_place(mgen_data(mg));
}
}
}
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index 90b38b78ae..622cee97ad 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -254,6 +254,7 @@ enum beam_type // beam[].flavour
BEAM_POTION_BLUE_SMOKE,
BEAM_POTION_PURPLE_SMOKE,
BEAM_POTION_RAIN,
+ BEAM_GLOOM,
BEAM_POTION_RANDOM,
BEAM_LAST_REAL = BEAM_POTION_RANDOM,
@@ -420,9 +421,10 @@ enum cloud_type
CLOUD_TLOC_ENERGY,
CLOUD_FOREST_FIRE,
CLOUD_STEAM,
+ CLOUD_GLOOM,
CLOUD_OPAQUE_FIRST = CLOUD_BLACK_SMOKE,
- CLOUD_OPAQUE_LAST = CLOUD_STEAM,
+ CLOUD_OPAQUE_LAST = CLOUD_GLOOM,
CLOUD_MIASMA,
CLOUD_MIST,
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index 1b7e53e9fd..ef9f525e0f 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -5821,6 +5821,16 @@ static void mons_lose_attack_energy(monsters *attacker, int wpn_speed,
}
}
+bool monster_attack_actor(monsters *attacker, actor *defender,
+ bool allow_unarmed)
+{
+ ASSERT(defender == &you || defender->atype() == ACT_MONSTER);
+ return (defender->atype() == ACT_PLAYER ?
+ monster_attack(attacker, allow_unarmed)
+ : monsters_fight(attacker, dynamic_cast<monsters*>(defender),
+ allow_unarmed));
+}
+
// A monster attacking the player.
bool monster_attack(monsters* attacker, bool allow_unarmed)
{
diff --git a/crawl-ref/source/fight.h b/crawl-ref/source/fight.h
index 538858a4d8..70427a8ec1 100644
--- a/crawl-ref/source/fight.h
+++ b/crawl-ref/source/fight.h
@@ -56,6 +56,8 @@ int resist_adjust_damage(actor *defender, beam_type flavour,
int weapon_str_weight( object_class_type wpn_class, int wpn_type );
bool you_attack(int monster_attacked, bool unarmed_attacks);
+bool monster_attack_actor(monsters *attacker, actor *defender,
+ bool allow_unarmed);
bool monster_attack(monsters* attacker, bool allow_unarmed = true);
bool monsters_fight(monsters* attacker, monsters* attacked,
bool allow_unarmed = true);
diff --git a/crawl-ref/source/godabil.cc b/crawl-ref/source/godabil.cc
index f6a1d82c1d..e0a0aa06f1 100644
--- a/crawl-ref/source/godabil.cc
+++ b/crawl-ref/source/godabil.cc
@@ -345,7 +345,7 @@ bool fedhas_shoot_through(const bolt & beam, const monsters * victim)
{
monsters * temp = dynamic_cast<monsters *> (originator);
if (!temp)
- return false;
+ return (false);
origin_worships_fedhas = temp->god == GOD_FEDHAS;
origin_attitude = temp->attitude;
}
@@ -485,7 +485,7 @@ int fungal_bloom()
return (processed_count);
}
-static int _create_plant(coord_def & target)
+static int _create_plant(coord_def & target, int hp_adjust = 0)
{
if (actor_at(target) || !mons_class_can_pass(MONS_PLANT, grd(target)))
return (0);
@@ -504,8 +504,16 @@ static int _create_plant(coord_def & target)
if (plant != -1)
{
env.mons[plant].flags |= MF_ATT_CHANGE_ATTEMPT;
+ env.mons[plant].max_hit_points += hp_adjust;
+ env.mons[plant].hit_points += hp_adjust;
+
if (you.see_cell(target))
- mpr("A plant grows up from the ground.");
+ {
+ if (hp_adjust)
+ mpr("A plant grows up from the ground, it is strengthened by Fedhas.");
+ else
+ mpr("A plant grows up from the ground.");
+ }
}
@@ -536,6 +544,9 @@ bool sunlight()
int plant_count = 0;
int processed_count = 0;
+ // This is dealt with outside of the main loop.
+ int cloud_count = 0;
+
// FIXME: Uncomfortable level of code duplication here but the explosion
// code in bolt subjects the input radius to r*(r+1) for the threshold and
// since r is an integer we can never get just the 4-connected neighbours.
@@ -634,6 +645,20 @@ bool sunlight()
}
}
+ // We damage clousd for a large radius, though.
+ for (radius_iterator ai(base, 7); ai; ++ai)
+ {
+ if (env.cgrid(*ai) != EMPTY_CLOUD)
+ {
+ const int cloudidx = env.cgrid(*ai);
+ if (env.cloud[cloudidx].type == CLOUD_GLOOM)
+ {
+ cloud_count++;
+ delete_cloud(cloudidx);
+ }
+ }
+ }
+
#ifndef USE_TILE
// Move the cursor out of the way (it looks weird).
cgotoxy(base.x, base.y, GOTO_DNGN);
@@ -650,13 +675,16 @@ bool sunlight()
if (evap_count)
mprf("Some water evaporates in the bright sunlight.");
+ if (cloud_count)
+ mprf("Sunlight penetrates the thick gloom.");
+
return (processed_count);
}
template<typename T>
bool less_second(const T & left, const T & right)
{
- return left.second < right.second;
+ return (left.second < right.second);
}
typedef std::pair<coord_def, int> point_distance;
@@ -858,23 +886,94 @@ int _prompt_for_fruit(int & count, const char * prompt_string)
return (rc);
}
+bool _prompt_amount(int max, int & selected, const std::string & prompt)
+{
+ selected = max;
+ while (true)
+ {
+ msg::streams(MSGCH_PROMPT) << prompt <<" (" << max << " max)"<< std::endl;
+
+ unsigned char keyin = get_ch();
+
+ // Cancel
+ if (keyin == ESCAPE || keyin == ' ')
+ {
+ canned_msg( MSG_OK );
+ return (false);
+ }
+
+ // Default is max
+ if (keyin == '\n' || keyin == '\r')
+ return (true);
+
+ // Otherwise they should enter a digit
+ if (isdigit(keyin))
+ {
+ selected = keyin - '0';
+ if (selected > 0 && selected <= max)
+ return (true);
+ }
+ // else they entered some garbage?
+ }
+
+ return (max);
+}
+
+
+int _collect_fruit(std::vector<std::pair<int,int> > & available_fruit)
+{
+ int total=0;
+
+ for (int i = 0; i < ENDOFPACK; i++)
+ {
+ if (you.inv[i].is_valid()
+ && is_fruit(you.inv[i]) )
+ {
+ total += you.inv[i].quantity;
+ available_fruit.push_back(std::pair<int,int> (you.inv[i].quantity, i));
+ }
+ }
+
+ return (total);
+}
+
+bool _less_first(const std::pair<int, int> & left, const std::pair<int, int> & right)
+{
+ return (left.first < right.first);
+}
+void _decrease_amount(std::vector<std::pair<int, int> > & available, int amount)
+{
+ int total_decrease = amount;
+ for (unsigned i=0; i < available.size() && amount > 0; i++)
+ {
+
+ int decrease_amount = available[i].first;
+ if (decrease_amount > amount)
+ {
+ decrease_amount = amount;
+ }
+ amount -= decrease_amount;
+ dec_inv_item_quantity(available[i].second, decrease_amount);
+ }
+ if (total_decrease > 1)
+ mprf("%d pieces of fruit are consumed!", total_decrease);
+ else
+ mpr("A piece of fruit is consumed!");
+
+}
+
// Create a ring or partial ring around the caster. The user is
// prompted to select a stack of fruit, and then plants are placed on open
// squares adjacent to the user. Of course, one piece of fruit is
// consumed per plant, so a complete ring may not be formed.
bool plant_ring_from_fruit()
{
- int possible_count;
- int created_count = 0;
- int rc = _prompt_for_fruit(possible_count,
- "Use which fruit? [0-9] specify amount");
-
- // Prompt failed?
- if (rc < 0)
- return (false);
+ // How much fruit is available?
+ std::vector<std::pair<int, int> > collected_fruit;
+ int total_fruit = _collect_fruit(collected_fruit);
+ // How many adjacent open spaces are there?
std::vector<coord_def> adjacent;
-
for (adjacent_iterator adj_it(you.pos()); adj_it; ++adj_it)
{
if (mons_class_can_pass(MONS_PLANT, env.grid(*adj_it))
@@ -884,22 +983,34 @@ bool plant_ring_from_fruit()
}
}
- if ((int)adjacent.size() > possible_count)
+ int max_use = std::min(total_fruit, int(adjacent.size()) );
+
+ // Don't prompt if we can't do anything (due to having no fruit or
+ // no squares to place plants on).
+ if (max_use == 0)
+ return (false);
+
+ // And how many plants does the user want to create?
+ int target_count;
+ if (!_prompt_amount(max_use, target_count, "How many plants will you create?"))
{
- prioritise_adjacent(you.pos(), adjacent);
+ return (false);
}
- unsigned target_count =
- (possible_count < (int)adjacent.size()) ? possible_count
- : adjacent.size();
+ if ((int)adjacent.size() > target_count)
+ prioritise_adjacent(you.pos(), adjacent);
+
+ int hp_adjust = you.skills[SK_INVOCATIONS] * 10;
- for (unsigned i = 0; i < target_count; ++i)
+ int created_count = 0;
+ for (int i = 0; i < target_count; ++i)
{
- if (_create_plant(adjacent[i]))
+ if (_create_plant(adjacent[i], hp_adjust))
created_count++;
}
- dec_inv_item_quantity(rc, created_count);
+ std::sort(collected_fruit.begin(), collected_fruit.end(), _less_first);
+ _decrease_amount(collected_fruit, created_count);
return (created_count);
}
@@ -1059,19 +1170,19 @@ int corpse_spores(beh_type behavior)
struct monster_conversion
{
+ monster_conversion()
+ {
+ base_monster = NULL;
+ piety_cost = 0;
+ fruit_cost = 0;
+
+ }
monsters * base_monster;
- int cost;
+ int piety_cost;
+ int fruit_cost;
monster_type new_type;
};
-bool operator<(const monster_conversion & left,
- const monster_conversion & right)
-{
- if (left.cost == right.cost)
- return (coinflip());
-
- return (left.cost < right.cost);
-}
// Given a monster (which should be a plant/fungus), see if
// evolve_flora() can upgrade it, and set up a monster_conversion
@@ -1080,27 +1191,24 @@ bool operator<(const monster_conversion & left,
bool _possible_evolution(monsters * input,
monster_conversion & possible_monster)
{
- int plant_cost = 10;
- int toadstool_cost = 1;
- int fungus_cost = 5;
-
possible_monster.base_monster = input;
switch (input->mons_species())
{
case MONS_PLANT:
- possible_monster.cost = plant_cost;
+ case MONS_BUSH:
possible_monster.new_type = MONS_OKLOB_PLANT;
+ possible_monster.fruit_cost = 1;
break;
case MONS_FUNGUS:
case MONS_BALLISTOMYCETE:
- possible_monster.cost = fungus_cost;
possible_monster.new_type = MONS_WANDERING_MUSHROOM;
+ possible_monster.piety_cost = 1;
break;
case MONS_TOADSTOOL:
- possible_monster.cost = toadstool_cost;
- possible_monster.new_type = MONS_BALLISTOMYCETE;
+ possible_monster.new_type = MONS_WANDERING_MUSHROOM;
+ possible_monster.piety_cost = 2;
break;
default:
@@ -1110,70 +1218,138 @@ bool _possible_evolution(monsters * input,
return (true);
}
+void _collect_adjacent_monsters(std::vector<monster_conversion> & available,
+ const coord_def & center)
+{
+ for (adjacent_iterator adjacent(center, false); adjacent; ++adjacent)
+ {
+ monsters * candidate = monster_at(*adjacent);
+ monster_conversion monster_upgrade;
+ if (candidate && _possible_evolution(candidate, monster_upgrade))
+ available.push_back(monster_upgrade);
+ }
+}
+
+void _cost_summary(int oklob_count, int wandering_count, int total_in_range)
+{
+ mesclr(true);
+ if (oklob_count)
+ {
+ std::string str = (oklob_count > 1 ? "ts" : "t");
+ mprf("Upgrading %d plan%s to oklob plan%s (%d fruit)",
+ oklob_count, str.c_str(), str.c_str(), oklob_count);
+ }
+
+ if (wandering_count)
+ mprf("Upgrading %d fungi to wandering mushroo%s (piety cost)",
+ wandering_count, (wandering_count > 1 ? "ms" : "m "));
+}
+
bool evolve_flora()
{
- int rc;
- int available_count;
+ // Collect adjacent monsters
+ std::vector<monster_conversion> available_monsters;
+ _collect_adjacent_monsters(available_monsters, you.pos());
- int points_per_fruit = 8;
- int oklob_cost = 10;
+ // No monsters in range can be upgraded.
+ if (available_monsters.empty() )
+ {
+ mpr("No flora in range can be evolved.");
+ return (false);
+ }
- float approx_oklob_rate = float(points_per_fruit)/float(oklob_cost);
+ // What are the total costs of all adjacent upgrades?
+ int piety_cost = 0;
+ int fruit_cost = 0;
- char prompt_string[100];
- memset(prompt_string,0,100);
- sprintf(prompt_string,
- "Use which fruit? %1.1f oklob plants per fruit, [0-9] specify amount",
- approx_oklob_rate);
+ int oklob_generation = 0;
+ int wandering_generation = 0;
- rc = _prompt_for_fruit(available_count, prompt_string);
+ for (unsigned i=0; i < available_monsters.size(); i++)
+ {
+ piety_cost += available_monsters[i].piety_cost;
+ fruit_cost += available_monsters[i].fruit_cost;
+ switch(available_monsters[i].new_type)
+ {
+ case MONS_OKLOB_PLANT:
+ oklob_generation++;
+ break;
+ case MONS_WANDERING_MUSHROOM:
+ wandering_generation++;
+ break;
+
+ default:
+ break;
+ }
+ }
- // Prompt failed?
- if (rc < 0)
- return (false);
- int points = points_per_fruit * available_count;
- int starting_points = points;
+ std::vector<std::pair<int, int> > collected_fruit;
+ int total_fruit = _collect_fruit(collected_fruit);
+ int useable_fruit = std::min(total_fruit, fruit_cost);
- std::priority_queue<monster_conversion> available_targets;
+ _cost_summary(useable_fruit, wandering_generation, available_monsters.size());
- monster_conversion temp_conversion;
+ crawl_state.darken_range = 1;
+ viewwindow(false, false);
- for (radius_iterator rad(you.pos(), LOS_RADIUS, true, true, true);
- rad; ++rad)
+ int target_fruit = useable_fruit;
+ // Ask the user how many fruit to use
+ if (useable_fruit > 1)
+ {
+ if(!_prompt_amount(useable_fruit, target_fruit,
+ "How many oklobs will you create?"))
+ {
+ crawl_state.darken_range = -1;
+ viewwindow(false,false);
+ return (false);
+ }
+ }
+ else
{
- monsters * target = monster_at(*rad);
+ delay(500);
+ }
- if (!target)
- continue;
+ crawl_state.darken_range = -1;
+ viewwindow(false, false);
- if (_possible_evolution(target, temp_conversion))
- available_targets.push(temp_conversion);
- }
+ int fruit_used = target_fruit;
+ int reduction = fruit_cost - target_fruit;
- // Nothing available to upgrade.
- if (available_targets.empty())
+ if (int(available_monsters.size()) <= reduction)
{
- mpr("No flora in sight can be evolved.");
- return (false);
+ mprf("Not enough fruit available.");
+ return false;
}
int plants_evolved = 0;
int toadstools_evolved = 0;
int fungi_evolved = 0;
- while (!available_targets.empty() && points > 0)
- {
- monster_conversion current_target = available_targets.top();
- monsters * current_plant = current_target.base_monster;
- available_targets.pop();
+ std::random_shuffle(available_monsters.begin(), available_monsters.end() );
- // Can we afford this thing?
- if (current_target.cost > points)
- continue;
+ for (unsigned i=0; i < available_monsters.size(); i++)
+ {
+ monsters * current_plant = available_monsters[i].base_monster;
+ monster_conversion current_target = available_monsters[i];
- points -= current_target.cost;
+ if (current_target.new_type == MONS_OKLOB_PLANT)
+ {
+ if (target_fruit)
+ target_fruit--;
+ else
+ continue;
+ }
+ else if (you.piety > current_target.piety_cost)
+ {
+ lose_piety(current_target.piety_cost);
+ }
+ // This would wipe out our remaining piety, so don't do it.
+ else
+ {
+ continue;
+ }
switch (current_plant->mons_species())
{
@@ -1199,58 +1375,15 @@ bool evolve_flora()
// Try to remove slowly dying in case we are upgrading a
// toadstool, and spore production in case we are upgrading a
- // fungus.
+ // ballistomycete.
current_plant->del_ench(ENCH_SLOWLY_DYING);
current_plant->del_ench(ENCH_SPORE_PRODUCTION);
-
- // Maybe we can upgrade it again?
- if (_possible_evolution(current_plant, temp_conversion)
- && temp_conversion.cost <= points)
- {
- available_targets.push(temp_conversion);
- }
- }
-
- // How many pieces of fruit did we use up?
- int points_used = starting_points - points;
- int fruit_used = points_used / points_per_fruit;
- if (points_used % points_per_fruit)
- fruit_used++;
-
- // The player didn't have enough points to upgrade anything (probably
- // supplied only one fruit).
- if (!fruit_used)
- {
- mpr("Not enough fruit to cause evolution.");
- return (false);
}
- dec_inv_item_quantity(rc, fruit_used);
-
- // Mention how many plants were used.
- if (fruit_used > 1)
- mprf("%d pieces of fruit are consumed!", fruit_used);
- else
- mpr("A piece of fruit is consumed!");
-
- // Messaging for generated plants.
- if (plants_evolved > 1)
- mprf("%d plants can now spit acid.", plants_evolved);
- else if (plants_evolved == 1)
- mpr("A plant can now spit acid.");
-
- if (toadstools_evolved > 1)
- mprf("%d toadstools gained stability.", toadstools_evolved);
- else if (toadstools_evolved == 1)
- mpr("A toadstool gained stability.");
-
- if (fungi_evolved > 1)
+ if (fruit_used)
{
- mprf("%d fungal colonies can now pick up their mycelia and move.",
- fungi_evolved);
+ _decrease_amount(collected_fruit, fruit_used);
}
- else if (fungi_evolved == 1)
- mpr("A fungal colony can now pick up its mycelia and move.");
return (true);
}
diff --git a/crawl-ref/source/godwrath.cc b/crawl-ref/source/godwrath.cc
index 5be08ab8f1..a2ad1c79ed 100644
--- a/crawl-ref/source/godwrath.cc
+++ b/crawl-ref/source/godwrath.cc
@@ -91,8 +91,9 @@ static bool _okawaru_random_servant()
: MONS_TITAN); // 5%
return (create_monster(
- mgen_data::hostile_at(mon_type, "the fury of Okawaru",
- true, 0, 0, you.pos(), 0, GOD_OKAWARU)) != -1);
+ mgen_data::hostile_at(mon_type, "the fury of Okawaru",
+ true, 6, MON_SUMM_WRATH, you.pos(), 0,
+ GOD_OKAWARU)) != -1);
}
static bool _tso_retribution()
diff --git a/crawl-ref/source/mon-act.cc b/crawl-ref/source/mon-act.cc
index 2065414df9..bc15130cc4 100644
--- a/crawl-ref/source/mon-act.cc
+++ b/crawl-ref/source/mon-act.cc
@@ -44,6 +44,7 @@
#include "random.h"
#include "religion.h"
#include "shopping.h" // for item values
+#include "spells1.h"
#include "state.h"
#include "stuff.h"
#include "terrain.h"
@@ -739,6 +740,10 @@ static bool _handle_reaching(monsters *monster)
bool ret = false;
item_def *wpn = monster->weapon(0);
const mon_attack_def attk(mons_attack_spec(monster, 0));
+ actor *foe = monster->get_foe();
+
+ if (!foe)
+ return (false);
if (monster->submerged())
return (false);
@@ -746,47 +751,35 @@ static bool _handle_reaching(monsters *monster)
if (mons_aligned(monster->mindex(), monster->foe))
return (false);
- if ((wpn && get_weapon_brand(*wpn) == SPWPN_REACHING)
- || (attk.flavour == AF_REACH && attk.damage))
+ const coord_def foepos(foe->pos());
+ const coord_def delta(foepos - monster->pos());
+ const int grid_distance(delta.rdist());
+ const coord_def middle(monster->pos() + delta / 2);
+
+ if (grid_distance == 2
+ // The monster has to be attacking the correct position.
+ && monster->target == foepos
+ // With a reaching weapon OR ...
+ && ((wpn && get_weapon_brand(*wpn) == SPWPN_REACHING)
+ // ... with a native reaching attack, provided the attack
+ // is not on a full diagonal.
+ || (attk.flavour == AF_REACH && attk.damage
+ && delta.abs() <= 5))
+ // And with no dungeon furniture in the way of the reaching
+ // attack; if the middle square is empty, skip the LOS check.
+ && (grd(middle) > DNGN_MAX_NONREACH
+ || (monster->foe == MHITYOU?
+ you.see_cell_no_trans(monster->pos())
+ : monster->mon_see_cell(foepos, true))))
{
- if (monster->foe == MHITYOU)
- {
- const coord_def delta = monster->pos() - you.pos();
- const int x_middle = std::max(monster->pos().x, you.pos().x)
- - (abs(delta.x) / 2);
- const int y_middle = std::max(monster->pos().y, you.pos().y)
- - (abs(delta.y) / 2);
- const coord_def middle(x_middle, y_middle);
+ ret = true;
+ monster_attack_actor(monster, foe, false);
- // This check isn't redundant -- player may be invisible.
- if (monster->target == you.pos()
- && grid_distance(monster->pos(), you.pos()) == 2
- && (you.see_cell_no_trans(monster->pos())
- || grd(middle) > DNGN_MAX_NONREACH))
- {
- ret = true;
- monster_attack(monster, false);
- }
- }
- else if (monster->foe != MHITNOT)
- {
- monsters& mfoe = menv[monster->foe];
- coord_def foepos = mfoe.pos();
- // Same comments as to invisibility as above.
- if (monster->target == foepos
- && monster->mon_see_cell(foepos, true)
- && grid_distance(monster->pos(), foepos) == 2)
- {
- ret = true;
- monsters_fight(monster, &mfoe, false);
- }
- }
+ // Player saw the item reach.
+ if (wpn && !is_artefact(*wpn) && you.can_see(monster))
+ set_ident_flags(*wpn, ISFLAG_KNOW_TYPE);
}
- // Player saw the item reach.
- if (ret && wpn && !is_artefact(*wpn) && you.can_see(monster))
- set_ident_flags(*wpn, ISFLAG_KNOW_TYPE);
-
return (ret);
}
@@ -3454,6 +3447,13 @@ static bool _monster_move(monsters *monster)
2 + random2(3), monster->kill_alignment(),
KILL_MON_MISSILE );
}
+
+ // Commented out, but left in as an example of gloom. {due}
+ //if (monster->type == MONS_SHADOW)
+ //{
+ // big_cloud (CLOUD_GLOOM, monster->kill_alignment(), monster->pos(), 10 + random2(5), 2 + random2(8));
+ //}
+
}
else
{
diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h
index b46e13b2c0..26ab9513fb 100644
--- a/crawl-ref/source/mon-data.h
+++ b/crawl-ref/source/mon-data.h
@@ -1532,7 +1532,7 @@ static monsterentry mondata[] = {
MONS_SNAPPING_TURTLE, 't', GREEN, "snapping turtle",
M_COLD_BLOOD,
MR_NO_FLAGS,
- 500, 5, MONS_SNAPPING_TURTLE, MONS_SNAPPING_TURTLE, MH_NATURAL, -3,
+ 500, 10, MONS_SNAPPING_TURTLE, MONS_SNAPPING_TURTLE, MH_NATURAL, -3,
{ {AT_BITE, AF_REACH, 30}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK },
{ 10, 3, 6, 0 },
16, 5, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_HISS,
@@ -1544,7 +1544,7 @@ static monsterentry mondata[] = {
MONS_ALLIGATOR_SNAPPING_TURTLE, 't', LIGHTGREEN, "alligator snapping turtle",
M_COLD_BLOOD,
MR_NO_FLAGS,
- 1000, 5, MONS_SNAPPING_TURTLE, MONS_ALLIGATOR_SNAPPING_TURTLE,
+ 1000, 10, MONS_SNAPPING_TURTLE, MONS_ALLIGATOR_SNAPPING_TURTLE,
MH_NATURAL, -3,
{ {AT_BITE, AF_REACH, 50}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK },
{ 16, 7, 4, 0 },
diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc
index 9bb2e8a298..d1d6f659a9 100644
--- a/crawl-ref/source/monster.cc
+++ b/crawl-ref/source/monster.cc
@@ -6103,13 +6103,14 @@ void monsters::react_to_damage(int damage, beam_type flavour, kill_category whos
static const char *enchant_names[] =
{
- "none", "slow", "haste", "might", "fear", "conf", "inv", "pois", "bers",
- "rot", "summon", "abj", "backlit", "charm", "fire",
- "gloshifter", "shifter", "tp", "wary", "submerged",
- "short-lived", "paralysis", "sick", "sleep", "fatigue", "held",
- "blood-lust", "neutral", "petrifying", "petrified", "magic-vulnerable",
- "soul-ripe", "decay", "hungry", "flopping", "spore-producing",
- "downtrodden", "swift", "tide", "frenzied", "bug"
+ "none", "berserk", "haste", "might", "fatigue", "slow", "fear",
+ "confusion", "invis", "poison", "rot", "summon", "abj", "corona",
+ "charm", "sticky_flame", "glowing_shapeshifter", "shapeshifter", "tp",
+ "sleep_wary", "submerged", "short_lived", "paralysis", "sick",
+ "sleepy", "held", "battle_frenzy", "temp_pacif", "petrifying",
+ "petrified", "lowered_mr", "soul_ripe", "slowly_dying", "eat_items",
+ "aquatic_land", "spore_production", "slouch", "swift", "tide",
+ "insane", "buggy"
};
static const char *_mons_enchantment_name(enchant_type ench)
diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc
index cf51b30a1a..f3358e52f4 100644
--- a/crawl-ref/source/newgame.cc
+++ b/crawl-ref/source/newgame.cc
@@ -4515,7 +4515,7 @@ bool _give_items_skills()
you.skills[SK_STEALTH] = 2;
you.skills[SK_STABBING] = 2;
you.skills[SK_TRAPS_DOORS] = 2;
- you.skills[SK_CROSSBOWS] = 1;
+ you.skills[SK_THROWING] = 2;
break;
case JOB_ASSASSIN:
diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc
index 3d5fe9d31e..0c79623409 100644
--- a/crawl-ref/source/religion.cc
+++ b/crawl-ref/source/religion.cc
@@ -299,11 +299,11 @@ const char* god_gain_power_messages[NUM_GODS][MAX_GOD_ABILITIES] =
"call upon Jiyva to remove your harmful mutations"
},
// Fedhas
- { "call sunshine",
+ { "induce evolution",
+ "call sunshine",
"cause a ring of plants to grow",
- "control the weather",
"spawn explosive spores",
- "induce evolution"
+ "control the weather"
},
// Cheibriados
{ "Cheibriados is slowing your {biology}.",
@@ -406,11 +406,11 @@ const char* god_lose_power_messages[NUM_GODS][MAX_GOD_ABILITIES] =
"call upon Jiyva to remove your harmful mutations"
},
// Fedhas
- { "call sunshine",
+ { "induce evolution",
+ "call sunshine",
"cause a ring of plants to grow",
- "control the weather",
"spawn explosive spores",
- "induce evolution"
+ "control the weather"
},
// Cheibriados
{ "Cheibriados will no longer slow your {biology}.",
@@ -2812,6 +2812,21 @@ bool did_god_conduct(conduct_type thing_done, int level, bool known,
case DID_FRIEND_DIED:
switch (you.religion)
{
+
+ case GOD_FEDHAS:
+ // Toadstools are exempt from this conduct
+ if (victim && fedhas_protects(victim)
+ && victim->mons_species() != MONS_TOADSTOOL)
+ {
+ // level is (1 + monsterHD/2) for this conduct,
+ // trying a fixed cost since plant HD aren't that
+ // meaningful. -cao
+ piety_change = -1;
+ retval = true;
+ break;
+ }
+ break;
+
case GOD_ELYVILON: // healer god cares more about this
// Converted allies (marked as TSOites) can be martyrs.
if (victim && victim->god == GOD_SHINING_ONE)
@@ -2829,17 +2844,6 @@ bool did_god_conduct(conduct_type thing_done, int level, bool known,
break;
// fall through
- case GOD_FEDHAS:
- // double-check god because of fall-throughs from other gods
- // Toadstools are an exception for this conduct
- if (you.religion == GOD_FEDHAS && (!victim
- || !fedhas_protects(victim)
- || victim->mons_species() == MONS_TOADSTOOL))
- {
- break;
- }
- // fall through
-
case GOD_OKAWARU:
piety_change = -level;
retval = true;
diff --git a/crawl-ref/source/rltiles/dc-misc.txt b/crawl-ref/source/rltiles/dc-misc.txt
index 92329d2dd8..8050483dcd 100644
--- a/crawl-ref/source/rltiles/dc-misc.txt
+++ b/crawl-ref/source/rltiles/dc-misc.txt
@@ -42,6 +42,8 @@ cloud_rain1 CLOUD_RAIN
cloud_rain2
cloud_grey_smoke CLOUD_MIST
+cloud_gloom CLOUD_GLOOM
+
#########MAP
%sdir dc-misc
%corpse 0
diff --git a/crawl-ref/source/rltiles/dc-mon.txt b/crawl-ref/source/rltiles/dc-mon.txt
index 3570121966..16983a8b83 100644
--- a/crawl-ref/source/rltiles/dc-mon.txt
+++ b/crawl-ref/source/rltiles/dc-mon.txt
@@ -193,6 +193,7 @@ pit_fiend MONS_PIT_FIEND
shadow_fiend MONS_SHADOW_FIEND
# type '2' demons
+beast MONS_BEAST
ice_devil MONS_ICE_DEVIL
lorocyproca MONS_LOROCYPROCA
reaper MONS_REAPER
@@ -204,7 +205,6 @@ blue_devil MONS_BLUE_DEVIL
chaos_spawn MONS_CHAOS_SPAWN
demonic_crawler MONS_DEMONIC_CRAWLER
hellion MONS_HELLION
-hellwing MONS_HELLWING
iron_devil MONS_IRON_DEVIL
neqoxec MONS_NEQOXEC
orange_demon MONS_ORANGE_DEMON
@@ -213,11 +213,12 @@ tormentor MONS_TORMENTOR
ynoxinul MONS_YNOXINUL
# type '4' demons
-beast MONS_BEAST
hairy_devil MONS_HAIRY_DEVIL
red_devil MONS_RED_DEVIL
rotting_devil MONS_ROTTING_DEVIL
smoke_demon MONS_SMOKE_DEMON
+#sixfirhy MONS_SIXFIRHY
+hellwing MONS_HELLWING
# type '5' demons
imp MONS_IMP
diff --git a/crawl-ref/source/rltiles/effect/cloud_gloom.png b/crawl-ref/source/rltiles/effect/cloud_gloom.png
new file mode 100644
index 0000000000..914e500a3c
--- /dev/null
+++ b/crawl-ref/source/rltiles/effect/cloud_gloom.png
Binary files differ
diff --git a/crawl-ref/source/show.cc b/crawl-ref/source/show.cc
index 0148d92438..342c424dcd 100644
--- a/crawl-ref/source/show.cc
+++ b/crawl-ref/source/show.cc
@@ -272,7 +272,11 @@ void show_def::_update_cloud(int cloudno)
const coord_def e = grid2show(env.cloud[cloudno].pos);
int which_colour = get_cloud_colour(cloudno);
_set_backup(e);
- grid(e).cls = SH_CLOUD;
+ if (env.cloud[cloudno].type != CLOUD_GLOOM)
+ {
+ grid(e).cls = SH_CLOUD;
+ }
+
grid(e).colour = which_colour;
#ifdef USE_TILE
diff --git a/crawl-ref/source/skills2.cc b/crawl-ref/source/skills2.cc
index 3dd241f9fd..2d182e0b4b 100644
--- a/crawl-ref/source/skills2.cc
+++ b/crawl-ref/source/skills2.cc
@@ -1283,11 +1283,14 @@ static const skill_type skill_display_order[] =
SK_BLANK_LINE,
- SK_ARMOUR, SK_DODGING, SK_STEALTH, SK_STABBING, SK_SHIELDS, SK_TRAPS_DOORS,
+ SK_ARMOUR, SK_DODGING, SK_STABBING, SK_SHIELDS,
- SK_BLANK_LINE,
SK_COLUMN_BREAK,
+ SK_STEALTH, SK_TRAPS_DOORS,
+
+ SK_BLANK_LINE,
+
SK_SPELLCASTING, SK_CONJURATIONS, SK_ENCHANTMENTS, SK_SUMMONINGS,
SK_NECROMANCY, SK_TRANSLOCATIONS, SK_TRANSMUTATIONS,
SK_FIRE_MAGIC, SK_ICE_MAGIC, SK_AIR_MAGIC, SK_EARTH_MAGIC, SK_POISON_MAGIC,
@@ -1370,7 +1373,7 @@ static void _display_skill_table(bool show_aptitudes, bool show_description)
if (you.skills[x] == 27)
textcolor(YELLOW);
- if (you.skills[x] == 0 || you.skills[x] == 27)
+ if (you.skills[x] == 0 || !show_description && you.skills[x] == 27)
putch(' ');
else
putch(lcount++);
@@ -1437,7 +1440,7 @@ static void _display_skill_table(bool show_aptitudes, bool show_description)
else
{
// NOTE: If any more skills added, must adapt letters to go into caps.
- cgotoxy(1, bottom_line-2);
+ cgotoxy(1, bottom_line-3);
textcolor(LIGHTGREY);
if (show_description)
@@ -1449,7 +1452,8 @@ static void _display_skill_table(bool show_aptitudes, bool show_description)
else
{
cprintf("Press the letter of a skill to choose whether you want to "
- "practise it.");
+ "practise it." EOL "Skills marked with '+' will train more "
+ "quickly than those with '-'.");
}
cgotoxy(1, bottom_line-1);
@@ -1517,7 +1521,10 @@ void show_skills()
if (x == SK_BLANK_LINE || x == SK_COLUMN_BREAK)
continue;
- if (you.skills[x] == 0 || you.skills[x] == 27)
+ if (you.skills[x] == 0)
+ continue;
+
+ if (!show_description && you.skills[x] == 27)
continue;
if (keyin == lcount)
diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc
index 9e5b4fd390..d56139759a 100644
--- a/crawl-ref/source/tilepick.cc
+++ b/crawl-ref/source/tilepick.cc
@@ -817,10 +817,12 @@ int tileidx_monster_base(const monsters *mon, bool detected)
return TILEP_MONS_HAIRY_DEVIL;
case MONS_ROTTING_DEVIL:
return TILEP_MONS_ROTTING_DEVIL;
- case MONS_BEAST:
- return TILEP_MONS_BEAST;
case MONS_SMOKE_DEMON:
return TILEP_MONS_SMOKE_DEMON;
+// case MONS_SIXFIRHY: // TODO
+// return TILEP_MONS_SIXFIRHY;
+ case MONS_HELLWING:
+ return TILEP_MONS_HELLWING;
// '3' demons
case MONS_HELLION:
@@ -835,8 +837,6 @@ int tileidx_monster_base(const monsters *mon, bool detected)
return TILEP_MONS_NEQOXEC;
case MONS_ORANGE_DEMON:
return TILEP_MONS_ORANGE_DEMON;
- case MONS_HELLWING:
- return TILEP_MONS_HELLWING;
case MONS_YNOXINUL:
return TILEP_MONS_YNOXINUL;
case MONS_DEMONIC_CRAWLER:
@@ -847,6 +847,8 @@ int tileidx_monster_base(const monsters *mon, bool detected)
return TILEP_MONS_CHAOS_SPAWN;
// '2' demon
+ case MONS_BEAST:
+ return TILEP_MONS_BEAST;
case MONS_SUN_DEMON:
return TILEP_MONS_SUN_DEMON;
case MONS_REAPER:
@@ -2796,6 +2798,10 @@ static int _tileidx_cloud(cloud_struct cl)
ch = TILE_CLOUD_RAIN + random2(tile_main_count(TILE_CLOUD_RAIN));
break;
+ case CLOUD_GLOOM:
+ ch = TILE_CLOUD_GLOOM;
+ break;
+
default:
ch = TILE_CLOUD_GREY_SMOKE;
break;