summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/cloud.cc
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref/source/cloud.cc')
-rw-r--r--crawl-ref/source/cloud.cc240
1 files changed, 222 insertions, 18 deletions
diff --git a/crawl-ref/source/cloud.cc b/crawl-ref/source/cloud.cc
index 0649d03bba..351f1a3773 100644
--- a/crawl-ref/source/cloud.cc
+++ b/crawl-ref/source/cloud.cc
@@ -15,26 +15,33 @@
#include "AppHdr.h"
#include "externs.h"
+#include "branch.h"
#include "cloud.h"
+#include "mapmark.h"
+#include "misc.h"
+#include "place.h"
#include "stuff.h"
#include "terrain.h"
// Returns true if this cloud spreads out as it dissipates.
-static bool cloud_spreads(const cloud_struct &cloud)
+static unsigned char actual_spread_rate(cloud_type type, int spread_rate)
{
- switch (cloud.type)
+ if (spread_rate >= 0)
+ return (unsigned char) spread_rate;
+
+ switch (type)
{
case CLOUD_STEAM:
case CLOUD_GREY_SMOKE:
case CLOUD_BLACK_SMOKE:
- return (true);
+ return 22;
default:
- return (false);
+ return 0;
}
}
static void new_cloud( int cloud, cloud_type type, int x, int y, int decay,
- kill_category whose )
+ kill_category whose, unsigned char spread_rate )
{
ASSERT( env.cloud[ cloud ].type == CLOUD_NONE );
@@ -43,12 +50,13 @@ static void new_cloud( int cloud, cloud_type type, int x, int y, int decay,
env.cloud[ cloud ].x = x;
env.cloud[ cloud ].y = y;
env.cloud[ cloud ].whose = whose;
+ env.cloud[ cloud ].spread_rate = spread_rate;
env.cgrid[ x ][ y ] = cloud;
env.cloud_no++;
}
static void place_new_cloud(cloud_type cltype, int x, int y, int decay,
- kill_category whose)
+ kill_category whose, int spread_rate)
{
if (env.cloud_no >= MAX_CLOUDS)
return;
@@ -58,7 +66,7 @@ static void place_new_cloud(cloud_type cltype, int x, int y, int decay,
{
if (env.cloud[ci].type == CLOUD_NONE) // ie is empty
{
- new_cloud( ci, cltype, x, y, decay, whose );
+ new_cloud( ci, cltype, x, y, decay, whose, spread_rate );
break;
}
}
@@ -90,7 +98,8 @@ static int spread_cloud(const cloud_struct &cloud)
if (newdecay >= cloud.decay)
newdecay = cloud.decay - 1;
- place_new_cloud( cloud.type, x, y, newdecay, cloud.whose );
+ place_new_cloud( cloud.type, x, y, newdecay, cloud.whose,
+ cloud.spread_rate );
extra_decay += 8;
}
@@ -104,8 +113,11 @@ static void dissipate_cloud(int cc, cloud_struct &cloud, int dissipate)
// apply calculated rate to the actual cloud:
cloud.decay -= dissipate;
- if (cloud_spreads(cloud) && cloud.decay > 10 && one_chance_in(5))
+ if (random2(100) < cloud.spread_rate)
+ {
+ cloud.spread_rate -= div_rand_round(cloud.spread_rate, 10);
cloud.decay -= spread_cloud(cloud);
+ }
// check for total dissipation and handle accordingly:
if (cloud.decay < 1)
@@ -137,10 +149,6 @@ void manage_clouds(void)
dissipate *= 4;
}
- // double the amount when slowed - must be applied last(!):
- if (you.duration[DUR_SLOW])
- dissipate *= 2;
-
dissipate_cloud( cc, env.cloud[cc], dissipate );
}
@@ -159,6 +167,7 @@ void delete_cloud( int cloud )
env.cloud[ cloud ].x = 0;
env.cloud[ cloud ].y = 0;
env.cloud[ cloud ].whose = KC_OTHER;
+ env.cloud[ cloud ].spread_rate = 0;
env.cgrid[ cloud_x ][ cloud_y ] = EMPTY_CLOUD;
env.cloud_no--;
}
@@ -183,12 +192,12 @@ void move_cloud( int cloud, int new_x, int new_y )
// Places a cloud with the given stats assuming one doesn't already
// exist at that point.
void check_place_cloud( cloud_type cl_type, int x, int y, int lifetime,
- kill_category whose )
+ kill_category whose, int spread_rate )
{
if (!in_bounds(x, y) || env.cgrid[x][y] != EMPTY_CLOUD)
return;
- place_cloud( cl_type, x, y, lifetime, whose );
+ place_cloud( cl_type, x, y, lifetime, whose, spread_rate );
}
int steam_cloud_damage(const cloud_struct &cloud)
@@ -208,7 +217,7 @@ int steam_cloud_damage(const cloud_struct &cloud)
// cloud under some circumstances.
void place_cloud(cloud_type cl_type, int ctarget_x,
int ctarget_y, int cl_range,
- kill_category whose)
+ kill_category whose, int _spread_rate)
{
int cl_new = -1;
@@ -234,6 +243,8 @@ void place_cloud(cloud_type cl_type, int ctarget_x,
}
}
+ unsigned char spread_rate = actual_spread_rate( cl_type, _spread_rate );
+
// too many clouds
if (env.cloud_no >= MAX_CLOUDS)
{
@@ -261,7 +272,7 @@ void place_cloud(cloud_type cl_type, int ctarget_x,
// create new cloud
if (cl_new != -1)
new_cloud( cl_new, cl_type, ctarget_x, ctarget_y, cl_range * 10,
- whose );
+ whose, spread_rate );
else
{
// find slot for cloud
@@ -270,7 +281,7 @@ void place_cloud(cloud_type cl_type, int ctarget_x,
if (env.cloud[ci].type == CLOUD_NONE) // ie is empty
{
new_cloud( ci, cl_type, ctarget_x, ctarget_y, cl_range * 10,
- whose );
+ whose, spread_rate );
break;
}
}
@@ -298,6 +309,199 @@ cloud_type random_smoke_type()
return CLOUD_DEBUGGING;
}
+void place_fog_machine(fog_machine_type fm_type, cloud_type cl_type,
+ int x, int y, int size, int power)
+{
+ ASSERT(fm_type >= FM_GEYSER && fm_type < NUM_FOG_MACHINE_TYPES);
+ ASSERT(cl_type > CLOUD_NONE && (cl_type < CLOUD_RANDOM
+ || cl_type == CLOUD_DEBUGGING));
+ ASSERT(size >= 1);
+ ASSERT(power >= 1);
+
+ const char* fog_types[] = {
+ "geyser",
+ "spread",
+ "brownian"
+ };
+
+ try
+ {
+ char buf [160];
+ sprintf(buf, "lua_mapless:fog_machine_%s(\"%s\", %d, %d)",
+ fog_types[fm_type], cloud_name(cl_type).c_str(),
+ size, power);
+
+ map_marker *mark = map_lua_marker::parse_marker(buf, "");
+
+ if (mark == NULL)
+ {
+ mprf(MSGCH_DIAGNOSTICS, "Unable to parse fog machine from '%s'",
+ buf);
+ return;
+ }
+
+ mark->pos = coord_def(x, y);
+ env.markers.add(mark);
+ }
+ catch (const std::string &err)
+ {
+ mprf(MSGCH_DIAGNOSTICS, "Error while making fog machine: %s",
+ err.c_str());
+ }
+}
+
+void place_fog_machine(fog_machine_data data, int x, int y)
+{
+ place_fog_machine(data.fm_type, data.cl_type, x, y, data.size,
+ data.power);
+}
+
+bool valid_fog_machine_data(fog_machine_data data)
+{
+ if (data.fm_type < FM_GEYSER || data.fm_type >= NUM_FOG_MACHINE_TYPES)
+ return false;
+
+ if (data.cl_type <= CLOUD_NONE || (data.cl_type >= CLOUD_RANDOM
+ && data.cl_type != CLOUD_DEBUGGING))
+ return false;
+
+ if (data.size < 1 || data.power < 1)
+ return false;
+
+ return true;
+}
+
+int num_fogs_for_place(int level_number, const level_id &place)
+{
+ if (level_number == -1)
+ {
+ switch(place.level_type)
+ {
+ case LEVEL_DUNGEON:
+ level_number = absdungeon_depth(place.branch, place.depth);
+ break;
+ case LEVEL_ABYSS:
+ level_number = 51;
+ break;
+ case LEVEL_PANDEMONIUM:
+ level_number = 52;
+ break;
+ default:
+ level_number = you.your_level;
+ }
+ }
+
+ switch(place.level_type)
+ {
+ case LEVEL_DUNGEON:
+ {
+ Branch &branch = branches[place.branch];
+ ASSERT((branch.num_fogs_function == NULL
+ && branch.rand_fog_function == NULL)
+ || (branch.num_fogs_function != NULL
+ && branch.rand_fog_function != NULL));
+
+ if (branch.num_fogs_function == NULL)
+ return 0;
+
+ return branch.num_fogs_function(level_number);
+ }
+ case LEVEL_ABYSS:
+ return fogs_abyss_number(level_number);
+ case LEVEL_PANDEMONIUM:
+ return fogs_pan_number(level_number);
+ case LEVEL_LABYRINTH:
+ return fogs_lab_number(level_number);
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+fog_machine_data random_fog_for_place(int level_number, const level_id &place)
+{
+ fog_machine_data data = {NUM_FOG_MACHINE_TYPES, CLOUD_NONE, -1, -1};
+
+ if (level_number == -1)
+ {
+ switch(place.level_type)
+ {
+ case LEVEL_DUNGEON:
+ level_number = absdungeon_depth(place.branch, place.depth);
+ break;
+ case LEVEL_ABYSS:
+ level_number = 51;
+ break;
+ case LEVEL_PANDEMONIUM:
+ level_number = 52;
+ break;
+ default:
+ level_number = you.your_level;
+ }
+ }
+
+ switch(place.level_type)
+ {
+ case LEVEL_DUNGEON:
+ {
+ Branch &branch = branches[place.branch];
+ ASSERT(branch.num_fogs_function != NULL
+ && branch.rand_fog_function != NULL);
+ branch.rand_fog_function(level_number, data);
+ return data;
+ }
+ case LEVEL_ABYSS:
+ return fogs_abyss_type(level_number);
+ case LEVEL_PANDEMONIUM:
+ return fogs_pan_type(level_number);
+ case LEVEL_LABYRINTH:
+ return fogs_lab_type(level_number);
+ default:
+ ASSERT(false);
+ return data;
+ }
+
+ ASSERT(false);
+ return data;
+}
+
+int fogs_pan_number(int level_number)
+{
+ return 0;
+}
+
+fog_machine_data fogs_pan_type(int level_number)
+{
+ fog_machine_data data = {NUM_FOG_MACHINE_TYPES, CLOUD_NONE, -1, -1};
+
+ return data;
+}
+
+int fogs_abyss_number(int level_number)
+{
+ return 0;
+}
+
+fog_machine_data fogs_abyss_type(int level_number)
+{
+ fog_machine_data data = {NUM_FOG_MACHINE_TYPES, CLOUD_NONE, -1, -1};
+
+ return data;
+}
+
+int fogs_lab_number(int level_number)
+{
+ return 0;
+}
+
+fog_machine_data fogs_lab_type(int level_number)
+{
+ fog_machine_data data = {NUM_FOG_MACHINE_TYPES, CLOUD_NONE, -1, -1};
+
+ return data;
+}
+
////////////////////////////////////////////////////////////////////////
// cloud_struct