summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/abyss.cc1
-rw-r--r--crawl-ref/source/areas.cc265
-rw-r--r--crawl-ref/source/areas.h9
-rw-r--r--crawl-ref/source/beam.cc1
-rw-r--r--crawl-ref/source/effects.cc1
-rw-r--r--crawl-ref/source/fight.cc1
-rw-r--r--crawl-ref/source/main.cc1
-rw-r--r--crawl-ref/source/makefile.obj1
-rw-r--r--crawl-ref/source/religion.cc1
-rw-r--r--crawl-ref/source/spells3.cc233
-rw-r--r--crawl-ref/source/spells3.h2
11 files changed, 282 insertions, 234 deletions
diff --git a/crawl-ref/source/abyss.cc b/crawl-ref/source/abyss.cc
index d125f0b61a..bd76a3c3cb 100644
--- a/crawl-ref/source/abyss.cc
+++ b/crawl-ref/source/abyss.cc
@@ -11,6 +11,7 @@
#include <stdlib.h>
#include <algorithm>
+#include "areas.h"
#include "artefact.h"
#include "cloud.h"
#include "colour.h"
diff --git a/crawl-ref/source/areas.cc b/crawl-ref/source/areas.cc
new file mode 100644
index 0000000000..538735703e
--- /dev/null
+++ b/crawl-ref/source/areas.cc
@@ -0,0 +1,265 @@
+/*
+ * File: areas.cc
+ * Summary: Tracking effects that affect areas for durations.
+ * Silence, sanctuary, halos, ...
+ */
+
+#include "AppHdr.h"
+
+#include "areas.h"
+
+#include "beam.h"
+#include "cloud.h"
+#include "coord.h"
+#include "coordit.h"
+#include "directn.h"
+#include "env.h"
+#include "fprop.h"
+#include "mon-behv.h"
+#include "mon-iter.h"
+#include "mon-stuff.h"
+#include "mon-util.h"
+#include "monster.h"
+#include "player.h"
+#include "religion.h"
+#include "stuff.h"
+#include "traps.h"
+#include "travel.h"
+#include "viewgeom.h"
+
+// Is where inside a circle within LOS, with the given radius,
+// centered on the player's position? If so, return the distance to it.
+// Otherwise, return -1.
+static int _inside_circle(const coord_def& where, int radius)
+{
+ if (!in_bounds(where))
+ return -1;
+
+ const coord_def ep = grid2view(where);
+ if (!in_los_bounds(ep))
+ return -1;
+
+ const int dist = distance(where, you.pos());
+ if (dist > radius*radius)
+ return -1;
+
+ return (dist);
+}
+
+static void _remove_sanctuary_property(const coord_def& where)
+{
+ env.pgrid(where) &= ~(FPROP_SANCTUARY_1 | FPROP_SANCTUARY_2);
+}
+
+bool remove_sanctuary(bool did_attack)
+{
+ if (env.sanctuary_time)
+ env.sanctuary_time = 0;
+
+ if (!in_bounds(env.sanctuary_pos))
+ return (false);
+
+ const int radius = 5;
+ bool seen_change = false;
+ for (radius_iterator ri(env.sanctuary_pos, radius, C_SQUARE); ri; ++ri)
+ if (is_sanctuary(*ri))
+ {
+ _remove_sanctuary_property(*ri);
+ if (you.see_cell(*ri))
+ seen_change = true;
+ }
+
+ env.sanctuary_pos.set(-1, -1);
+
+ if (did_attack)
+ {
+ if (seen_change)
+ simple_god_message(" revokes the gift of sanctuary.", GOD_ZIN);
+ did_god_conduct(DID_FRIEND_DIED, 3);
+ }
+
+ // Now that the sanctuary is gone, monsters aren't afraid of it
+ // anymore.
+ for (monster_iterator mi; mi; ++mi)
+ mons_stop_fleeing_from_sanctuary(*mi);
+
+ if (is_resting())
+ stop_running();
+
+ return (true);
+}
+
+// For the last (radius) counter turns the sanctuary will slowly shrink.
+void decrease_sanctuary_radius()
+{
+ const int radius = 5;
+
+ // For the last (radius-1) turns 33% chance of not decreasing.
+ if (env.sanctuary_time < radius && one_chance_in(3))
+ return;
+
+ int size = --env.sanctuary_time;
+ if (size >= radius)
+ return;
+
+ if (you.running && is_sanctuary(you.pos()))
+ {
+ mpr("The sanctuary starts shrinking.", MSGCH_DURATION);
+ stop_running();
+ }
+
+ for (radius_iterator ri(env.sanctuary_pos, size+1, C_SQUARE); ri; ++ri)
+ {
+ int dist = distance(*ri, env.sanctuary_pos);
+
+ // If necessary overwrite sanctuary property.
+ if (dist > size*size)
+ _remove_sanctuary_property(*ri);
+ }
+
+ // Special case for time-out of sanctuary.
+ if (!size)
+ {
+ _remove_sanctuary_property(env.sanctuary_pos);
+ if (you.see_cell(env.sanctuary_pos))
+ mpr("The sanctuary disappears.", MSGCH_DURATION);
+ }
+}
+
+void create_sanctuary(const coord_def& center, int time)
+{
+ env.sanctuary_pos = center;
+ env.sanctuary_time = time;
+
+ // radius could also be influenced by Inv
+ // and would then have to be stored globally.
+ const int radius = 5;
+ int blood_count = 0;
+ int trap_count = 0;
+ int scare_count = 0;
+ int cloud_count = 0;
+ monsters *seen_mon = NULL;
+
+ for (radius_iterator ri(center, radius, C_POINTY); ri; ++ri)
+ {
+ const int dist = _inside_circle(*ri, radius);
+
+ if (dist == -1)
+ continue;
+
+ const coord_def pos = *ri;
+ if (testbits(env.pgrid(pos), FPROP_BLOODY) && you.see_cell(pos))
+ blood_count++;
+
+ if (trap_def* ptrap = find_trap(pos))
+ {
+ if (!ptrap->is_known())
+ {
+ ptrap->reveal();
+ ++trap_count;
+ }
+ }
+
+ // forming patterns
+ const int x = pos.x - center.x, y = pos.y - center.y;
+ bool in_yellow = false;
+ switch (random2(4))
+ {
+ case 0: // outward rays
+ in_yellow = (x == 0 || y == 0 || x == y || x == -y);
+ break;
+ case 1: // circles
+ in_yellow = (dist >= (radius-1)*(radius-1)
+ && dist <= radius*radius
+ || dist >= (radius/2-1)*(radius/2-1)
+ && dist <= radius*radius/4);
+ break;
+ case 2: // latticed
+ in_yellow = (x%2 == 0 || y%2 == 0);
+ break;
+ case 3: // cross-like
+ in_yellow = (abs(x)+abs(y) < 5 && x != y && x != -y);
+ break;
+ default:
+ break;
+ }
+
+ env.pgrid(pos) |= (in_yellow ? FPROP_SANCTUARY_1
+ : FPROP_SANCTUARY_2);
+
+ env.pgrid(pos) &= ~(FPROP_BLOODY);
+
+ // Scare all attacking monsters inside sanctuary, and make
+ // all friendly monsters inside sanctuary stop attacking and
+ // move towards the player.
+ if (monsters* mon = monster_at(pos))
+ {
+ if (mon->friendly())
+ {
+ mon->foe = MHITYOU;
+ mon->target = center;
+ mon->behaviour = BEH_SEEK;
+ behaviour_event(mon, ME_EVAL, MHITYOU);
+ }
+ else if (!mon->wont_attack())
+ {
+ if (mons_is_mimic(mon->type))
+ {
+ mimic_alert(mon);
+ if (you.can_see(mon))
+ {
+ scare_count++;
+ seen_mon = mon;
+ }
+ }
+ else if (mons_is_influenced_by_sanctuary(mon))
+ {
+ mons_start_fleeing_from_sanctuary(mon);
+
+ // Check to see that monster is actually fleeing.
+ if (mons_is_fleeing(mon) && you.can_see(mon))
+ {
+ scare_count++;
+ seen_mon = mon;
+ }
+ }
+ }
+ }
+
+ if (!is_harmless_cloud(cloud_type_at(pos)))
+ {
+ delete_cloud(env.cgrid(pos));
+ if (you.see_cell(pos))
+ cloud_count++;
+ }
+ } // radius loop
+
+ // Messaging.
+ if (trap_count > 0)
+ {
+ mpr("By Zin's power hidden traps are revealed to you.",
+ MSGCH_GOD);
+ }
+
+ if (cloud_count == 1)
+ {
+ mpr("By Zin's power the foul cloud within the sanctuary is "
+ "swept away.", MSGCH_GOD);
+ }
+ else if (cloud_count > 1)
+ {
+ mpr("By Zin's power all foul fumes within the sanctuary are "
+ "swept away.", MSGCH_GOD);
+ }
+
+ if (blood_count > 0)
+ {
+ mpr("By Zin's power all blood is cleared from the sanctuary.",
+ MSGCH_GOD);
+ }
+
+ if (scare_count == 1 && seen_mon != NULL)
+ simple_monster_message(seen_mon, " turns to flee the light!");
+ else if (scare_count > 0)
+ mpr("The monsters scatter in all directions!");
+}
diff --git a/crawl-ref/source/areas.h b/crawl-ref/source/areas.h
new file mode 100644
index 0000000000..04ca393a6d
--- /dev/null
+++ b/crawl-ref/source/areas.h
@@ -0,0 +1,9 @@
+#ifndef AREAS_H
+#define AREAS_H
+
+void create_sanctuary(const coord_def& center, int time);
+bool remove_sanctuary(bool did_attack = false);
+void decrease_sanctuary_radius();
+
+#endif
+
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index 7ae4688b32..f76b053ffc 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -20,6 +20,7 @@
#include "externs.h"
#include "options.h"
+#include "areas.h"
#include "attitude-change.h"
#include "cio.h"
#include "cloud.h"
diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc
index d8421bc99e..7ca4d02028 100644
--- a/crawl-ref/source/effects.cc
+++ b/crawl-ref/source/effects.cc
@@ -19,6 +19,7 @@
#include "externs.h"
#include "options.h"
+#include "areas.h"
#include "artefact.h"
#include "beam.h"
#include "cloud.h"
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index 5df207a29b..e048be701a 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -16,6 +16,7 @@
#include "externs.h"
#include "options.h"
+#include "areas.h"
#include "artefact.h"
#include "attitude-change.h"
#include "beam.h"
diff --git a/crawl-ref/source/main.cc b/crawl-ref/source/main.cc
index c09ccf8e65..874ce8dc65 100644
--- a/crawl-ref/source/main.cc
+++ b/crawl-ref/source/main.cc
@@ -38,6 +38,7 @@
#include "abl-show.h"
#include "abyss.h"
+#include "areas.h"
#include "artefact.h"
#include "arena.h"
#include "branch.h"
diff --git a/crawl-ref/source/makefile.obj b/crawl-ref/source/makefile.obj
index ab77aadb21..28028d1be2 100644
--- a/crawl-ref/source/makefile.obj
+++ b/crawl-ref/source/makefile.obj
@@ -3,6 +3,7 @@ abl-show.o \
abyss.o \
actor.o \
actor-los.o \
+areas.o \
arena.o \
artefact.o \
attitude-change.o \
diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc
index ef41b8e9fb..58ad61ecc6 100644
--- a/crawl-ref/source/religion.cc
+++ b/crawl-ref/source/religion.cc
@@ -23,6 +23,7 @@
#include "options.h"
#include "abl-show.h"
+#include "areas.h"
#include "artefact.h"
#include "attitude-change.h"
#include "beam.h"
diff --git a/crawl-ref/source/spells3.cc b/crawl-ref/source/spells3.cc
index 973add3d88..a4270b035b 100644
--- a/crawl-ref/source/spells3.cc
+++ b/crawl-ref/source/spells3.cc
@@ -1715,105 +1715,6 @@ bool entomb(int powc)
return (number_built > 0);
}
-// Is where inside a circle within LOS, with the given radius,
-// centered on the player's position? If so, return the distance to it.
-// Otherwise, return -1.
-static int _inside_circle(const coord_def& where, int radius)
-{
- if (!in_bounds(where))
- return -1;
-
- const coord_def ep = grid2view(where);
- if (!in_los_bounds(ep))
- return -1;
-
- const int dist = distance(where, you.pos());
- if (dist > radius*radius)
- return -1;
-
- return (dist);
-}
-
-static void _remove_sanctuary_property(const coord_def& where)
-{
- env.pgrid(where) &= ~(FPROP_SANCTUARY_1 | FPROP_SANCTUARY_2);
-}
-
-bool remove_sanctuary(bool did_attack)
-{
- if (env.sanctuary_time)
- env.sanctuary_time = 0;
-
- if (!in_bounds(env.sanctuary_pos))
- return (false);
-
- const int radius = 5;
- bool seen_change = false;
- for (radius_iterator ri(env.sanctuary_pos, radius, C_SQUARE); ri; ++ri)
- if (is_sanctuary(*ri))
- {
- _remove_sanctuary_property(*ri);
- if (you.see_cell(*ri))
- seen_change = true;
- }
-
- env.sanctuary_pos.set(-1, -1);
-
- if (did_attack)
- {
- if (seen_change)
- simple_god_message(" revokes the gift of sanctuary.", GOD_ZIN);
- did_god_conduct(DID_FRIEND_DIED, 3);
- }
-
- // Now that the sanctuary is gone, monsters aren't afraid of it
- // anymore.
- for (monster_iterator mi; mi; ++mi)
- mons_stop_fleeing_from_sanctuary(*mi);
-
- if (is_resting())
- stop_running();
-
- return (true);
-}
-
-// For the last (radius) counter turns the sanctuary will slowly shrink.
-void decrease_sanctuary_radius()
-{
- const int radius = 5;
-
- // For the last (radius-1) turns 33% chance of not decreasing.
- if (env.sanctuary_time < radius && one_chance_in(3))
- return;
-
- int size = --env.sanctuary_time;
- if (size >= radius)
- return;
-
- if (you.running && is_sanctuary(you.pos()))
- {
- mpr("The sanctuary starts shrinking.", MSGCH_DURATION);
- stop_running();
- }
-
- for (radius_iterator ri(env.sanctuary_pos, size+1, C_SQUARE); ri; ++ri)
- {
- int dist = distance(*ri, env.sanctuary_pos);
-
- // If necessary overwrite sanctuary property.
- if (dist > size*size)
- _remove_sanctuary_property(*ri);
- }
-
- // Special case for time-out of sanctuary.
- if (!size)
- {
- _remove_sanctuary_property(env.sanctuary_pos);
- if (you.see_cell(env.sanctuary_pos))
- mpr("The sanctuary disappears.", MSGCH_DURATION);
- }
-}
-
bool cast_sanctuary(const int power)
{
// Casting is disallowed while previous sanctuary in effect.
@@ -1836,142 +1737,10 @@ bool cast_sanctuary(const int power)
delay(1000);
#endif
- env.sanctuary_pos = you.pos();
- env.sanctuary_time = 7 + you.skills[SK_INVOCATIONS] / 2;
-
// Pets stop attacking and converge on you.
you.pet_target = MHITYOU;
- // radius could also be influenced by Inv
- // and would then have to be stored globally.
- const int radius = 5;
- int blood_count = 0;
- int trap_count = 0;
- int scare_count = 0;
- int cloud_count = 0;
- monsters *seen_mon = NULL;
-
- for (radius_iterator ri(you.pos(), radius, C_POINTY); ri; ++ri)
- {
- const int dist = _inside_circle(*ri, radius);
-
- if (dist == -1)
- continue;
-
- const coord_def pos = *ri;
- if (testbits(env.pgrid(pos), FPROP_BLOODY) && you.see_cell(pos))
- blood_count++;
-
- if (trap_def* ptrap = find_trap(pos))
- {
- if (!ptrap->is_known())
- {
- ptrap->reveal();
- ++trap_count;
- }
- }
-
- // forming patterns
- const int x = pos.x - you.pos().x, y = pos.y - you.pos().y;
- bool in_yellow = false;
- switch (random2(4))
- {
- case 0: // outward rays
- in_yellow = (x == 0 || y == 0 || x == y || x == -y);
- break;
- case 1: // circles
- in_yellow = (dist >= (radius-1)*(radius-1)
- && dist <= radius*radius
- || dist >= (radius/2-1)*(radius/2-1)
- && dist <= radius*radius/4);
- break;
- case 2: // latticed
- in_yellow = (x%2 == 0 || y%2 == 0);
- break;
- case 3: // cross-like
- in_yellow = (abs(x)+abs(y) < 5 && x != y && x != -y);
- break;
- default:
- break;
- }
-
- env.pgrid(pos) |= (in_yellow ? FPROP_SANCTUARY_1
- : FPROP_SANCTUARY_2);
-
- env.pgrid(pos) &= ~(FPROP_BLOODY);
-
- // Scare all attacking monsters inside sanctuary, and make
- // all friendly monsters inside sanctuary stop attacking and
- // move towards the player.
- if (monsters* mon = monster_at(pos))
- {
- if (mon->friendly())
- {
- mon->foe = MHITYOU;
- mon->target = you.pos();
- mon->behaviour = BEH_SEEK;
- behaviour_event(mon, ME_EVAL, MHITYOU);
- }
- else if (!mon->wont_attack())
- {
- if (mons_is_mimic(mon->type))
- {
- mimic_alert(mon);
- if (you.can_see(mon))
- {
- scare_count++;
- seen_mon = mon;
- }
- }
- else if (mons_is_influenced_by_sanctuary(mon))
- {
- mons_start_fleeing_from_sanctuary(mon);
-
- // Check to see that monster is actually fleeing.
- if (mons_is_fleeing(mon) && you.can_see(mon))
- {
- scare_count++;
- seen_mon = mon;
- }
- }
- }
- }
-
- if (!is_harmless_cloud(cloud_type_at(pos)))
- {
- delete_cloud(env.cgrid(pos));
- if (you.see_cell(pos))
- cloud_count++;
- }
- } // radius loop
-
- if (trap_count > 0)
- {
- mpr("By Zin's power hidden traps are revealed to you.",
- MSGCH_GOD);
- }
-
- if (cloud_count == 1)
- {
- mpr("By Zin's power the foul cloud within the sanctuary is "
- "swept away.", MSGCH_GOD);
- }
- else if (cloud_count > 1)
- {
- mpr("By Zin's power all foul fumes within the sanctuary are "
- "swept away.", MSGCH_GOD);
- }
-
- if (blood_count > 0)
- {
- mpr("By Zin's power all blood is cleared from the sanctuary.",
- MSGCH_GOD);
- }
-
- if (scare_count == 1 && seen_mon != NULL)
- simple_monster_message(seen_mon, " turns to flee the light!");
- else if (scare_count > 0)
- mpr("The monsters scatter in all directions!");
+ create_sanctuary(you.pos(), 7 + you.skills[SK_INVOCATIONS] / 2);
return (true);
}
diff --git a/crawl-ref/source/spells3.h b/crawl-ref/source/spells3.h
index 6b2cb7dad4..394df3e9fe 100644
--- a/crawl-ref/source/spells3.h
+++ b/crawl-ref/source/spells3.h
@@ -19,8 +19,6 @@ bool cast_bone_shards(int power, bolt &);
bool cast_selective_amnesia(bool force);
bool cast_smiting(int power, const coord_def& where);
-bool remove_sanctuary(bool did_attack = false);
-void decrease_sanctuary_radius();
bool cast_sanctuary(const int power);
bool project_noise();
bool detect_curse(bool suppress_msg);