move units and items to ground when it disappears

develop
myk002 2021-06-06 08:31:21 -07:00
parent 61a18b14be
commit c645cd5454
No known key found for this signature in database
GPG Key ID: 8A39CA0FA0C16E78
2 changed files with 46 additions and 13 deletions

@ -2838,17 +2838,18 @@ Options:
dig-now dig-now
======= =======
Instantly completes dig designations, modifying map tiles and creating boulders, Instantly completes dig designations for soil, rock, and mineral tiles,
ores, and gems as if a miner were doing the mining or engraving. By default, all modifying tile shapes and creating boulders, ores, and gems as if a miner were
dig designations on the map are completed and boulder generation follows doing the mining or engraving. By default, the entire map is processed and
standard game rules, but the behavior is configurable. boulder generation follows standard game rules, but the behavior is
configurable.
Note that no units will get mining or engraving experience for the dug/engraved Note that no units will get mining or engraving experience for the dug/engraved
tiles. tiles.
Currently, trees are not chopped down and any designated trees or roots will be Surface tiles, trees, and roots will be ignored. Engravings are also not
ignored. Engravings are also not automatically generated by this plugin as they automatically generated by this plugin as they depend on the skill and creative
depend on the skill and creative choices of individual engravers. choices of individual engravers.
Usage:: Usage::

@ -11,6 +11,7 @@
#include "modules/Maps.h" #include "modules/Maps.h"
#include "modules/MapCache.h" #include "modules/MapCache.h"
#include "modules/Random.h" #include "modules/Random.h"
#include "modules/Units.h"
#include "modules/World.h" #include "modules/World.h"
#include <df/historical_entity.h> #include <df/historical_entity.h>
@ -272,7 +273,6 @@ static bool dig_tile(color_ostream &out, MapExtras::MapCache &map,
std::vector<dug_tile_info> &dug_tiles) { std::vector<dug_tile_info> &dug_tiles) {
df::tiletype tt = map.tiletypeAt(pos); df::tiletype tt = map.tiletypeAt(pos);
// TODO: handle tree trunks, roots, and surface tiles
df::tiletype_material tile_mat = tileMaterial(tt); df::tiletype_material tile_mat = tileMaterial(tt);
if (!isGroundMaterial(tile_mat)) if (!isGroundMaterial(tile_mat))
return false; return false;
@ -593,7 +593,7 @@ static void create_boulders(color_ostream &out,
DFCoord dump_pos; DFCoord dump_pos;
if (Maps::isValidTilePos(options.dump_pos)) { if (Maps::isValidTilePos(options.dump_pos)) {
dump_pos = simulate_fall(options.dump_pos); dump_pos = simulate_fall(options.dump_pos);
if (!Maps::isValidTilePos(dump_pos)) if (!Maps::ensureTileBlock(dump_pos))
out.printerr("Invalid dump tile coordinates! Ensure the --dump" out.printerr("Invalid dump tile coordinates! Ensure the --dump"
" option specifies an open, non-wall tile."); " option specifies an open, non-wall tile.");
} }
@ -627,7 +627,7 @@ static void create_boulders(color_ostream &out,
for (size_t i = 0; i < num_items; ++i) { for (size_t i = 0; i < num_items; ++i) {
DFCoord pos = Maps::isValidTilePos(dump_pos) ? DFCoord pos = Maps::isValidTilePos(dump_pos) ?
dump_pos : simulate_fall(coords[i]); dump_pos : simulate_fall(coords[i]);
if (!Maps::isValidTilePos(pos)) { if (!Maps::ensureTileBlock(pos)) {
out.printerr( out.printerr(
"unable to place boulder generated at (%d, %d, %d)\n", "unable to place boulder generated at (%d, %d, %d)\n",
coords[i].x, coords[i].y, coords[i].z); coords[i].x, coords[i].y, coords[i].z);
@ -652,11 +652,43 @@ static void flood_unhide(color_ostream &out, const DFCoord &pos) {
Lua::SafeCall(out, L, 1, 0); Lua::SafeCall(out, L, 1, 0);
} }
static void unhide_dug_tiles(color_ostream &out, static void post_process_dug_tiles(color_ostream &out,
const std::vector<DFCoord> &dug_coords) { const std::vector<DFCoord> &dug_coords) {
for (DFCoord pos : dug_coords) for (DFCoord pos : dug_coords) {
if (Maps::getTileDesignation(pos)->bits.hidden) if (Maps::getTileDesignation(pos)->bits.hidden)
flood_unhide(out, pos); flood_unhide(out, pos);
df::tile_occupancy &to = *Maps::getTileOccupancy(pos);
if (to.bits.unit or to.bits.item) {
DFCoord resting_pos = simulate_fall(pos);
if (resting_pos == pos)
continue;
if (!Maps::ensureTileBlock(resting_pos)) {
out.printerr("No valid tile beneath (%d, %d, %d); can't move"
" units and items to floor",
pos.x, pos.y, pos.z);
continue;
}
if (to.bits.unit) {
std::vector<df::unit*> units;
Units::getUnitsInBox(units, pos.x, pos.y, pos.z,
pos.x, pos.y, pos.z);
for (auto unit : units)
Units::teleport(unit, resting_pos);
}
if (to.bits.item) {
for (auto item : world->items.other.IN_PLAY) {
if (item->pos == pos and item->flags.bits.on_ground)
item->moveToGround(
resting_pos.x, resting_pos.y, resting_pos.z);
}
}
}
}
} }
static bool get_options(color_ostream &out, static bool get_options(color_ostream &out,
@ -721,7 +753,7 @@ command_result dig_now(color_ostream &out, std::vector<std::string> &params) {
do_dig(out, dug_coords, item_coords, options); do_dig(out, dug_coords, item_coords, options);
create_boulders(out, item_coords, options); create_boulders(out, item_coords, options);
unhide_dug_tiles(out, dug_coords); post_process_dug_tiles (out, dug_coords);
// force the game to recompute its walkability cache // force the game to recompute its walkability cache
world->reindex_pathfinding = true; world->reindex_pathfinding = true;