diff options
Diffstat (limited to 'crawl-ref')
-rw-r--r-- | crawl-ref/source/cloud.cc | 36 | ||||
-rw-r--r-- | crawl-ref/source/cloud.h | 4 | ||||
-rw-r--r-- | crawl-ref/source/dat/clua/lm_fog.lua | 163 | ||||
-rw-r--r-- | crawl-ref/source/dat/clua/luamark.lua | 1 | ||||
-rw-r--r-- | crawl-ref/source/dgnevent.h | 11 | ||||
-rw-r--r-- | crawl-ref/source/externs.h | 1 | ||||
-rw-r--r-- | crawl-ref/source/files.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/luadgn.cc | 210 | ||||
-rw-r--r-- | crawl-ref/source/spells1.cc | 4 | ||||
-rw-r--r-- | crawl-ref/source/spells1.h | 2 | ||||
-rw-r--r-- | crawl-ref/source/spells4.cc | 6 | ||||
-rw-r--r-- | crawl-ref/source/spells4.h | 4 | ||||
-rw-r--r-- | crawl-ref/source/spl-util.cc | 84 | ||||
-rw-r--r-- | crawl-ref/source/spl-util.h | 5 | ||||
-rw-r--r-- | crawl-ref/source/tags.cc | 2 |
15 files changed, 471 insertions, 64 deletions
diff --git a/crawl-ref/source/cloud.cc b/crawl-ref/source/cloud.cc index 05c5dcaa70..65128cf79d 100644 --- a/crawl-ref/source/cloud.cc +++ b/crawl-ref/source/cloud.cc @@ -20,21 +20,24 @@ #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 20; 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 +46,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 +62,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 +94,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,7 +109,7 @@ 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.decay -= spread_cloud(cloud); // check for total dissipation and handle accordingly: @@ -159,6 +164,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 +189,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 +214,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 +240,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 +269,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 +278,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; } } diff --git a/crawl-ref/source/cloud.h b/crawl-ref/source/cloud.h index be7502d6a0..e0d02d27ed 100644 --- a/crawl-ref/source/cloud.h +++ b/crawl-ref/source/cloud.h @@ -20,9 +20,9 @@ void delete_cloud( int cloud ); void move_cloud( int cloud, int new_x, int new_y ); void check_place_cloud( cloud_type cl_type, int x, int y, int lifetime, - kill_category whose ); + kill_category whose, int spread_rate = -1 ); void place_cloud(cloud_type cl_type, int ctarget_x, int ctarget_y, - int cl_range, kill_category whose); + int cl_range, kill_category whose, int spread_rate = -1 ); void manage_clouds(void); diff --git a/crawl-ref/source/dat/clua/lm_fog.lua b/crawl-ref/source/dat/clua/lm_fog.lua new file mode 100644 index 0000000000..62853cb9b7 --- /dev/null +++ b/crawl-ref/source/dat/clua/lm_fog.lua @@ -0,0 +1,163 @@ +------------------------------------------------------------------------------ +-- lm_tmsg.lua: +-- Fog machines. +-- +-- There are three different "pure" ways to use a fog machine marker: +-- +-- 1) Repeatedly lay down medium to large clouds on top of the marker +-- and let them pile up on one another. (One of the cloud grids in +-- the gfirst laid cloud has to decay away before this is this really +-- starts working. +-- +-- 2) Perform random walks from the marker and place a single-grid cloud +-- at the destination of each walk. +-- +-- 3) Place a single-grid cloud on the marker and let it spread out. +-- +-- Comibining these different methods, along with varying the differrent +-- parameters, can be used to achieve different effects. +-- +-- Marker parameters: +-- +-- cloud_type: The name of the cloud type to use. Defaults to "thin mist". +-- walk_dist: The distance to move over the course of one random walk. +-- defaults to 0. +-- pow_min: The minimum "power" (lifetime) of each cloud; defaults to 1. +-- pow_max: The maximum power of each cloud; must be provided. +-- pow_rolls: The number of rolls of [pow_min, pow_max], with the average +-- value uses; increasing the values makes the average value more likely +-- and exterme values less likely. Defaults to 1. +-- delay, delay_min and delay_max: The delay between laying down one cloud +-- and the next. 10 is equal to normal-speed player turn. Either +-- delay or delay_max and delay_min must be provided. Providing just +-- "delay" is equivalent to delay_min and delay_max being equal. +-- size, size_min and size_max: The number of grids each cloud will cover. +-- Either size or size_max and size_min must be provided. Providing +-- just "size" is equivalent to size_min and size_max being equal. +-- spread_rate: The rate at which a cloud spreads. Must either be +-- -1 (default spread rate that varies by cloud type) or between +-- 0 and 100 inclusive. +-- start_clouds: The number of clouds to lay when the level containing +-- the cloud machine is entered. This is necessary since clouds +-- are cleared when the player leaves a level. +------------------------------------------------------------------------------ + +FogMachine = { } +FogMachine.__index = FogMachine + +function FogMachine:_new() + local m = { } + setmetatable(m, self) + self.__index = self + return m +end + +function FogMachine:new(pars) + if not pars then + error("No parameters provided") + end + + if not pars.pow_max then + error("No pow_max provided.") + end + + if not (pars.delay or (pars.delay_min and pars.delay_max)) then + error("Delay parameters not provided.") + end + + if not (pars.size or (pars.size_min and pars.size_max)) then + error("Size parameters not provided.") + end + + local m = FogMachine:_new() + m.cloud_type = pars.cloud_type or "thin mist" + m.walk_dist = pars.walk_dist or 0 + m.pow_min = pars.pow_min or 1 + m.pow_max = pars.pow_max + m.pow_rolls = pars.pow_rolls or 3 + m.delay_min = pars.delay_min or pars.delay or 1 + m.delay_max = pars.delay_max or pars.delay + m.kill_cat = pars.kill_cat or "other" + m.size_min = pars.size_min or pars.size or 1 + m.size_max = pars.size_max or pars.size + m.spread_rate = pars.spread_rate or -1 + m.start_clouds = pars.start_clouds or 1 + m.countdown = 0 + + return m +end + +function FogMachine:do_fog(marker) + local x, y = marker:pos() + if self.walk_dist > 0 then + x, y = dgn.random_walk(x, y, self.walk_dist) + end + + dgn.apply_area_cloud(x, y, self.pow_min, self.pow_max, self.pow_rolls, + crawl.random_range(self.size_min, self.size_max, 1), + self.cloud_type, self.kill_cat, self.spread_rate) +end + +function FogMachine:activate(marker, verbose) + local _x, _y = marker:pos() + dgn.register_listener(dgn.dgn_event_type('turn'), marker) + dgn.register_listener(dgn.dgn_event_type('entered_level'), marker) +end + +function FogMachine:event(marker, ev) + local _x, _y = marker:pos() + if ev:type() == dgn.dgn_event_type('turn') then + self.countdown = self.countdown - ev:ticks() + + while self.countdown <= 0 do + self:do_fog(marker) + self.countdown = self.countdown + + crawl.random_range(self.delay_min, self.delay_max, 1) + end + elseif ev:type() == dgn.dgn_event_type('entered_level') then + for i = 1, self.start_clouds do + self:do_fog(marker) + self.countdown = crawl.random_range(self.delay_min, self.delay_max, 1) + end + end +end + +function FogMachine:write(marker, th) + file.marshall(th, self.cloud_type) + file.marshall(th, self.walk_dist) + file.marshall(th, self.pow_min) + file.marshall(th, self.pow_max) + file.marshall(th, self.pow_rolls) + file.marshall(th, self.delay_min) + file.marshall(th, self.delay_max) + file.marshall(th, self.kill_cat) + file.marshall(th, self.size_min) + file.marshall(th, self.size_max) + file.marshall(th, self.spread_rate) + file.marshall(th, self.start_clouds) + file.marshall(th, self.countdown) +end + +function FogMachine:read(marker, th) + self.cloud_type = file.unmarshall_string(th) + self.walk_dist = file.unmarshall_number(th) + self.pow_min = file.unmarshall_number(th) + self.pow_max = file.unmarshall_number(th) + self.pow_rolls = file.unmarshall_number(th) + self.delay_min = file.unmarshall_number(th) + self.delay_max = file.unmarshall_number(th) + self.kill_cat = file.unmarshall_string(th) + self.size_min = file.unmarshall_number(th) + self.size_max = file.unmarshall_number(th) + self.spread_rate = file.unmarshall_number(th) + self.start_clouds = file.unmarshall_number(th) + self.countdown = file.unmarshall_number(th) + + setmetatable(self, FogMachine) + + return self +end + +function fog_machine(pars) + return FogMachine:new(pars) +end diff --git a/crawl-ref/source/dat/clua/luamark.lua b/crawl-ref/source/dat/clua/luamark.lua index 0c29327ab5..cc677f18c1 100644 --- a/crawl-ref/source/dat/clua/luamark.lua +++ b/crawl-ref/source/dat/clua/luamark.lua @@ -7,6 +7,7 @@ dofile('clua/lm_pdesc.lua') dofile('clua/lm_1way.lua') dofile('clua/lm_timed.lua') dofile('clua/lm_flags.lua') +dofile('clua/lm_fog.lua') function dlua_marker_function(table, name) return table[name] diff --git a/crawl-ref/source/dgnevent.h b/crawl-ref/source/dgnevent.h index bc394cab77..3ccd1d0246 100644 --- a/crawl-ref/source/dgnevent.h +++ b/crawl-ref/source/dgnevent.h @@ -22,11 +22,12 @@ enum dgn_event_type DET_PLAYER_MOVED = 0x0004, DET_LEAVING_LEVEL = 0x0008, DET_ENTERING_LEVEL = 0x0010, - DET_PLAYER_IN_LOS = 0x0020, // Player just entered LOS. - DET_PLAYER_CLIMBS = 0x0040, // Player climbing stairs. - DET_MONSTER_DIED = 0x0080, - DET_ITEM_PICKUP = 0x0100, - DET_FEAT_CHANGE = 0x0200 + DET_ENTERED_LEVEL = 0x0020, + DET_PLAYER_IN_LOS = 0x0040, // Player just entered LOS. + DET_PLAYER_CLIMBS = 0x0080, // Player climbing stairs. + DET_MONSTER_DIED = 0x0100, + DET_ITEM_PICKUP = 0x0200, + DET_FEAT_CHANGE = 0x0400 }; class dgn_event diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h index ec7ea1cd49..7fc2a7870a 100644 --- a/crawl-ref/source/externs.h +++ b/crawl-ref/source/externs.h @@ -1167,6 +1167,7 @@ struct cloud_struct int y; cloud_type type; int decay; + unsigned char spread_rate; kill_category whose; }; diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 15b693fbf9..303b16707d 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1068,6 +1068,8 @@ bool load( dungeon_feature_type stair_taken, int load_mode, if (just_created_level) you.attribute[ATTR_ABYSS_ENTOURAGE] = 0; + dungeon_events.fire_event(DET_ENTERED_LEVEL); + return just_created_level; } // end load() diff --git a/crawl-ref/source/luadgn.cc b/crawl-ref/source/luadgn.cc index e1c60b05b5..bb76ad0a4a 100644 --- a/crawl-ref/source/luadgn.cc +++ b/crawl-ref/source/luadgn.cc @@ -11,6 +11,7 @@ #include "branch.h" #include "clua.h" +#include "cloud.h" #include "direct.h" #include "dungeon.h" #include "files.h" @@ -20,6 +21,8 @@ #include "mapdef.h" #include "mapmark.h" #include "maps.h" +#include "misc.h" +#include "spl-util.h" #include "stuff.h" #include "tags.h" #include "terrain.h" @@ -1159,9 +1162,9 @@ static int dgn_feature_name(lua_State *ls) static const char *dgn_event_type_names[] = { - "none", "turn", "mons_move", "player_move", "leave_level", "enter_level", - "player_los", "player_climb", "monster_dies", "item_pickup", - "feat_change" + "none", "turn", "mons_move", "player_move", "leave_level", + "entering_level", "entered_level", "player_los", "player_climb", + "monster_dies", "item_pickup", "feat_change" }; static dgn_event_type dgn_event_type_by_name(const std::string &name) @@ -1453,6 +1456,205 @@ static int dgn_floor_halo(lua_State *ls) return (0); } +#define SQRT_2 1.41421356237309504880 + +static int dgn_random_walk(lua_State *ls) +{ + const int x = luaL_checkint(ls, 1); + const int y = luaL_checkint(ls, 2); + const int dist = luaL_checkint(ls, 3); + + // Fourth param being true means that we can move past + // statues. + const dungeon_feature_type minmove = + lua_isnil(ls, 4) ? DNGN_MINMOVE : DNGN_ORCISH_IDOL; + + if (!in_bounds(x, y)) + { + char buf[80]; + sprintf(buf, "Point (%d,%d) isn't in bounds.", x, y); + luaL_argerror(ls, 1, buf); + return (0); + } + if (dist < 1) + { + luaL_argerror(ls, 3, "Distance must be positive."); + return (0); + } + + float dist_left = dist; + // Allow movement to all 8 adjacent squares if distance is 1 + // (needed since diagonal moves are distance sqrt(2)) + if (dist == 1) + dist_left = SQRT_2; + + int moves_left = dist; + coord_def pos(x, y); + while (dist_left >= 1.0 && moves_left-- > 0) + { + int okay_dirs = 0; + int dir = -1; + for (int j = 0; j < 8; j++) + { + const coord_def new_pos = pos + Compass[j]; + const float move_dist = (j % 2 == 0) ? 1.0 : SQRT_2; + + if (in_bounds(new_pos) && grd(new_pos) >= minmove + && move_dist <= dist_left) + { + if (one_chance_in(++okay_dirs)) + dir = j; + } + } + + if (okay_dirs == 0) + break; + + if (one_chance_in(++okay_dirs)) + continue; + + pos += Compass[dir]; + dist_left -= (dir % 2 == 0) ? 1.0 : SQRT_2; + } + + dlua_push_coord(ls, pos); + + return (2); +} + +static cloud_type dgn_cloud_name_to_type(std::string name) +{ + lowercase(name); + + if (name == "random") + return (CLOUD_RANDOM); + else if (name == "debugging") + return (CLOUD_DEBUGGING); + + for (int i = CLOUD_NONE; i < CLOUD_RANDOM; i++) + if (cloud_name(static_cast<cloud_type>(i)) == name) + return static_cast<cloud_type>(i); + + return (CLOUD_NONE); +} + +static kill_category dgn_kill_name_to_category(std::string name) +{ + if (name == "") + return KC_OTHER; + + lowercase(name); + + if (name == "you") + return KC_YOU; + else if (name == "friendly") + return KC_FRIENDLY; + else if (name == "other") + return KC_OTHER; + else + return KC_NCATEGORIES; +} + +static int lua_cloud_pow_min; +static int lua_cloud_pow_max; +static int lua_cloud_pow_rolls; + +static int make_a_lua_cloud(int x, int y, int garbage, int spread_rate, + cloud_type ctype, kill_category whose) +{ + UNUSED( garbage ); + const int pow = random_range(lua_cloud_pow_min, + lua_cloud_pow_max, + lua_cloud_pow_rolls); + place_cloud( ctype, x, y, pow, whose, spread_rate ); + + return 1; +} + +static int dgn_apply_area_cloud(lua_State *ls) +{ + const int x = luaL_checkint(ls, 1); + const int y = luaL_checkint(ls, 2); + lua_cloud_pow_min = luaL_checkint(ls, 3); + lua_cloud_pow_max = luaL_checkint(ls, 4); + lua_cloud_pow_rolls = luaL_checkint(ls, 5); + const int size = luaL_checkint(ls, 6); + + const cloud_type ctype = dgn_cloud_name_to_type(luaL_checkstring(ls, 7)); + const char* kname = lua_isstring(ls, 8) ? luaL_checkstring(ls, 8) + : ""; + const kill_category kc = dgn_kill_name_to_category(kname); + + const int spread_rate = lua_isnumber(ls, 9) ? luaL_checkint(ls, 9) : -1; + + if (!in_bounds(x, y)) + { + char buf[80]; + sprintf(buf, "Point (%d,%d) isn't in bounds.", x, y); + luaL_argerror(ls, 1, buf); + return (0); + } + + if (lua_cloud_pow_min < 0) + { + luaL_argerror(ls, 4, "pow_min must be non-negative"); + return (0); + } + + if (lua_cloud_pow_max < lua_cloud_pow_min) + { + luaL_argerror(ls, 5, "pow_max must not be less than pow_min"); + return (0); + } + + if (lua_cloud_pow_max == 0) + { + luaL_argerror(ls, 5, "pow_max must be positive"); + return (0); + } + + if (lua_cloud_pow_rolls <= 0) + { + luaL_argerror(ls, 6, "pow_rolls must be positive"); + return (0); + } + + if (size < 1) + { + luaL_argerror(ls, 4, "size must be positive."); + return (0); + } + + if (ctype == CLOUD_NONE) + { + std::string error = "Invalid cloud type '"; + error += luaL_checkstring(ls, 7); + error += "'"; + luaL_argerror(ls, 7, error.c_str()); + return (0); + } + + if (kc == KC_NCATEGORIES) + { + std::string error = "Invalid kill category '"; + error += kname; + error += "'"; + luaL_argerror(ls, 8, error.c_str()); + return (0); + } + + if (spread_rate < -1 || spread_rate > 100) + { + luaL_argerror(ls, 9, "spread_rate must be between -1 and 100," + "inclusive"); + return (0); + } + + apply_area_cloud(make_a_lua_cloud, x, y, 0, size, + ctype, kc, spread_rate); + + return (0); +} static const struct luaL_reg dgn_lib[] = { @@ -1513,6 +1715,8 @@ static const struct luaL_reg dgn_lib[] = { "set_lt_callback", lua_dgn_set_lt_callback}, { "fixup_stairs", dgn_fixup_stairs}, { "floor_halo", dgn_floor_halo}, + { "random_walk", dgn_random_walk}, + { "apply_area_cloud", dgn_apply_area_cloud}, { NULL, NULL } }; diff --git a/crawl-ref/source/spells1.cc b/crawl-ref/source/spells1.cc index b419fe0bf7..35a8e8179b 100644 --- a/crawl-ref/source/spells1.cc +++ b/crawl-ref/source/spells1.cc @@ -580,10 +580,10 @@ int cast_big_c(int pow, cloud_type cty, kill_category whose, bolt &beam) } // end cast_big_c() void big_cloud(cloud_type cl_type, kill_category whose, - int cl_x, int cl_y, int pow, int size) + int cl_x, int cl_y, int pow, int size, int spread_rate) { apply_area_cloud(make_a_normal_cloud, cl_x, cl_y, pow, size, - cl_type, whose); + cl_type, whose, spread_rate); } // end big_cloud() static int healing_spell( int healed ) diff --git a/crawl-ref/source/spells1.h b/crawl-ref/source/spells1.h index 2504f7670d..5764bdef73 100644 --- a/crawl-ref/source/spells1.h +++ b/crawl-ref/source/spells1.h @@ -58,7 +58,7 @@ int cast_healing(int power); * called from: beam - it_use3 - spells - spells1 * *********************************************************************** */ void big_cloud(cloud_type cl_type, kill_category whose, int cl_x, int cl_y, - int pow, int size); + int pow, int size, int spread_rate = -1); // last updated 24may2000 {dlb} diff --git a/crawl-ref/source/spells4.cc b/crawl-ref/source/spells4.cc index 8b75b917c7..1742ba2589 100644 --- a/crawl-ref/source/spells4.cc +++ b/crawl-ref/source/spells4.cc @@ -1568,12 +1568,12 @@ static int make_a_rot_cloud(int x, int y, int pow, cloud_type ctype) return 0; } // end make_a_rot_cloud() -int make_a_normal_cloud(int x, int y, int pow, cloud_type ctype, - kill_category whose) +int make_a_normal_cloud(int x, int y, int pow, int spread_rate, + cloud_type ctype, kill_category whose) { place_cloud( ctype, x, y, (3 + random2(pow / 4) + random2(pow / 4) + random2(pow / 4)), - whose ); + whose, spread_rate ); return 1; } // end make_a_normal_cloud() diff --git a/crawl-ref/source/spells4.h b/crawl-ref/source/spells4.h index 515c8cc5a6..4a0b745d05 100644 --- a/crawl-ref/source/spells4.h +++ b/crawl-ref/source/spells4.h @@ -20,8 +20,8 @@ struct bolt; std::string your_hand(bool plural); bool backlight_monsters(int x, int y, int pow, int garbage); -int make_a_normal_cloud(int x, int y, int pow, cloud_type ctype, - kill_category); +int make_a_normal_cloud(int x, int y, int pow, int spread_rate, + cloud_type ctype, kill_category); int disperse_monsters(int x, int y, int pow, int message); void cast_bend(int pow); diff --git a/crawl-ref/source/spl-util.cc b/crawl-ref/source/spl-util.cc index 918592a9ef..2f06175670 100644 --- a/crawl-ref/source/spl-util.cc +++ b/crawl-ref/source/spl-util.cc @@ -54,9 +54,10 @@ static int spell_list[NUM_SPELLS]; #define SPELLDATASIZE (sizeof(spelldata)/sizeof(struct spell_desc)) static struct spell_desc *seekspell(spell_type spellid); -static bool cloud_helper(int (*func)(int, int, int, cloud_type, kill_category), - int x, int y, - int pow, cloud_type ctype, kill_category ); +static bool cloud_helper(int (*func)(int, int, int, int, cloud_type, + kill_category), + int x, int y, int pow, int spread_rate, + cloud_type ctype, kill_category ); /* * BEGIN PUBLIC FUNCTIONS @@ -539,17 +540,19 @@ int apply_area_within_radius( int (*func) (int, int, int, int), // We really need some sort of a queue structure, since ideally I'd like // to do a (shallow) breadth-first-search of the dungeon floor. // This ought to work okay for small clouds. -void apply_area_cloud( int (*func) (int, int, int, cloud_type, kill_category), +void apply_area_cloud( int (*func) (int, int, int, int, cloud_type, + kill_category), int x, int y, int pow, int number, cloud_type ctype, - kill_category whose ) + kill_category whose, int spread_rate ) { int spread, clouds_left = number; int good_squares = 0, neighbours[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; int dx = 1, dy = 1; bool x_first; - if (clouds_left && cloud_helper(func, x, y, pow, ctype, whose)) + if (clouds_left && cloud_helper(func, x, y, pow, spread_rate, + ctype, whose)) clouds_left--; if (!clouds_left) @@ -564,28 +567,32 @@ void apply_area_cloud( int (*func) (int, int, int, cloud_type, kill_category), if (x_first) { - if (clouds_left && cloud_helper(func, x + dx, y, pow, ctype, whose)) + if (clouds_left && cloud_helper(func, x + dx, y, pow, spread_rate, + ctype, whose)) { clouds_left--; good_squares++; neighbours[0]++; } - if (clouds_left && cloud_helper(func, x - dx, y, pow, ctype, whose)) + if (clouds_left && cloud_helper(func, x - dx, y, pow, spread_rate, + ctype, whose)) { clouds_left--; good_squares++; neighbours[1]++; } - if (clouds_left && cloud_helper(func, x, y + dy, pow, ctype, whose)) + if (clouds_left && cloud_helper(func, x, y + dy, pow, spread_rate, + ctype, whose)) { clouds_left--; good_squares++; neighbours[2]++; } - if (clouds_left && cloud_helper(func, x, y - dy, pow, ctype, whose)) + if (clouds_left && cloud_helper(func, x, y - dy, pow, spread_rate, + ctype, whose)) { clouds_left--; good_squares++; @@ -594,28 +601,32 @@ void apply_area_cloud( int (*func) (int, int, int, cloud_type, kill_category), } else { - if (clouds_left && cloud_helper(func, x, y + dy, pow, ctype, whose)) + if (clouds_left && cloud_helper(func, x, y + dy, pow, spread_rate, + ctype, whose)) { clouds_left--; good_squares++; neighbours[2]++; } - if (clouds_left && cloud_helper(func, x, y - dy, pow, ctype, whose)) + if (clouds_left && cloud_helper(func, x, y - dy, pow, spread_rate, + ctype, whose)) { clouds_left--; good_squares++; neighbours[3]++; } - if (clouds_left && cloud_helper(func, x + dx, y, pow, ctype, whose)) + if (clouds_left && cloud_helper(func, x + dx, y, pow, spread_rate, + ctype, whose)) { clouds_left--; good_squares++; neighbours[0]++; } - if (clouds_left && cloud_helper(func, x - dx, y, pow, ctype, whose)) + if (clouds_left && cloud_helper(func, x - dx, y, pow, spread_rate, + ctype, whose)) { clouds_left--; good_squares++; @@ -624,28 +635,32 @@ void apply_area_cloud( int (*func) (int, int, int, cloud_type, kill_category), } // now diagonals; we could randomize dx & dy again here - if (clouds_left && cloud_helper(func, x + dx, y + dy, pow, ctype, whose)) + if (clouds_left && cloud_helper(func, x + dx, y + dy, pow, spread_rate, + ctype, whose)) { clouds_left--; good_squares++; neighbours[4]++; } - if (clouds_left && cloud_helper(func, x - dx, y + dy, pow, ctype, whose)) + if (clouds_left && cloud_helper(func, x - dx, y + dy, pow, spread_rate, + ctype, whose)) { clouds_left--; good_squares++; neighbours[5]++; } - if (clouds_left && cloud_helper(func, x + dx, y - dy, pow, ctype, whose)) + if (clouds_left && cloud_helper(func, x + dx, y - dy, pow, spread_rate, + ctype, whose)) { clouds_left--; good_squares++; neighbours[6]++; } - if (clouds_left && cloud_helper(func, x - dx, y - dy, pow, ctype, whose)) + if (clouds_left && cloud_helper(func, x - dx, y - dy, pow, spread_rate, + ctype, whose)) { clouds_left--; good_squares++; @@ -667,28 +682,36 @@ void apply_area_cloud( int (*func) (int, int, int, cloud_type, kill_category), switch (i) { case 0: - apply_area_cloud(func, x + dx, y, pow, spread, ctype, whose); + apply_area_cloud(func, x + dx, y, pow, spread, ctype, whose, + spread_rate); break; case 1: - apply_area_cloud(func, x - dx, y, pow, spread, ctype, whose); + apply_area_cloud(func, x - dx, y, pow, spread, ctype, whose, + spread_rate); break; case 2: - apply_area_cloud(func, x, y + dy, pow, spread, ctype, whose); + apply_area_cloud(func, x, y + dy, pow, spread, ctype, whose, + spread_rate); break; case 3: - apply_area_cloud(func, x, y - dy, pow, spread, ctype, whose); + apply_area_cloud(func, x, y - dy, pow, spread, ctype, whose, + spread_rate); break; case 4: - apply_area_cloud(func, x + dx, y + dy, pow, spread, ctype, whose); + apply_area_cloud(func, x + dx, y + dy, pow, spread, ctype, whose, + spread_rate); break; case 5: - apply_area_cloud(func, x - dx, y + dy, pow, spread, ctype, whose); + apply_area_cloud(func, x - dx, y + dy, pow, spread, ctype, whose, + spread_rate); break; case 6: - apply_area_cloud(func, x + dx, y - dy, pow, spread, ctype, whose); + apply_area_cloud(func, x + dx, y - dy, pow, spread, ctype, whose, + spread_rate); break; case 7: - apply_area_cloud(func, x - dx, y - dy, pow, spread, ctype, whose); + apply_area_cloud(func, x - dx, y - dy, pow, spread, ctype, whose, + spread_rate); break; } } @@ -831,13 +854,14 @@ static spell_desc *seekspell(spell_type spell) return (index != -1? &spelldata[index] : NULL); } -static bool cloud_helper(int (*func)(int, int, int, cloud_type, kill_category), - int x, int y, - int pow, cloud_type ctype, kill_category whose ) +static bool cloud_helper(int (*func)(int, int, int, int, cloud_type, + kill_category), + int x, int y, int pow, int spread_rate, + cloud_type ctype, kill_category whose ) { if (!grid_is_solid(grd[x][y]) && env.cgrid[x][y] == EMPTY_CLOUD) { - func(x, y, pow, ctype, whose); + func(x, y, pow, spread_rate, ctype, whose); return true; } diff --git a/crawl-ref/source/spl-util.h b/crawl-ref/source/spl-util.h index 67f76133ef..56986ab064 100644 --- a/crawl-ref/source/spl-util.h +++ b/crawl-ref/source/spl-util.h @@ -128,9 +128,10 @@ bool spell_direction( dist &spelld, bolt &pbolt, bool needs_path = true, const char *prompt = NULL ); -void apply_area_cloud(int (*func) (int, int, int, cloud_type, kill_category), +void apply_area_cloud(int (*func) (int, int, int, int, cloud_type, + kill_category), int x, int y, int pow, int number, cloud_type ctype, - kill_category); + kill_category kc, int spread_rate = -1); const char *spelltype_name(unsigned int which_spelltype); diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index 8640b2e758..8aeabbf1c1 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -1510,6 +1510,7 @@ static void tag_construct_level(struct tagHeader &th) marshallByte(th, env.cloud[i].y); marshallByte(th, env.cloud[i].type); marshallShort(th, env.cloud[i].decay); + marshallByte(th, (char) env.cloud[i].spread_rate); marshallShort(th, env.cloud[i].whose); } @@ -1748,6 +1749,7 @@ static void tag_read_level( struct tagHeader &th, char minorVersion ) env.cloud[i].y = unmarshallByte(th); env.cloud[i].type = static_cast<cloud_type>(unmarshallByte(th)); env.cloud[i].decay = unmarshallShort(th); + env.cloud[i].spread_rate = (unsigned char) unmarshallByte(th); env.cloud[i].whose = static_cast<kill_category>(unmarshallShort(th)); } |