|
|
|
@ -259,7 +259,7 @@ struct TileType
|
|
|
|
|
|
|
|
|
|
inline bool matches(const df::tiletype source,
|
|
|
|
|
const df::tile_designation des,
|
|
|
|
|
const t_matpair mat)
|
|
|
|
|
const t_matpair mat) const
|
|
|
|
|
{
|
|
|
|
|
bool rv = true;
|
|
|
|
|
rv &= (shape == -1 || shape == tileShape(source));
|
|
|
|
@ -735,93 +735,37 @@ bool processTileType(color_ostream & out, TileType &paint, std::vector<std::stri
|
|
|
|
|
return found;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
command_result executePaintJob(color_ostream &out,
|
|
|
|
|
const tiletypes_options &opts)
|
|
|
|
|
{
|
|
|
|
|
if (paint.empty())
|
|
|
|
|
{
|
|
|
|
|
out.printerr("Set the paint first.\n");
|
|
|
|
|
return CR_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CoreSuspender suspend;
|
|
|
|
|
|
|
|
|
|
if (!Maps::IsValid())
|
|
|
|
|
{
|
|
|
|
|
out.printerr("Map is not available!\n");
|
|
|
|
|
return CR_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t x_max = 0, y_max = 0, z_max = 0;
|
|
|
|
|
Maps::getSize(x_max, y_max, z_max);
|
|
|
|
|
|
|
|
|
|
df::coord cursor;
|
|
|
|
|
if (Maps::isValidTilePos(opts.cursor))
|
|
|
|
|
{
|
|
|
|
|
cursor = opts.cursor;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
cursor = Gui::getCursorPos();
|
|
|
|
|
if (!cursor.isValid())
|
|
|
|
|
{
|
|
|
|
|
out.printerr("Can't get cursor coords! Make sure you have a cursor active in DF or specify the --cursor option.\n");
|
|
|
|
|
return CR_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!opts.quiet)
|
|
|
|
|
out.print("Cursor coords: (%d, %d, %d)\n",
|
|
|
|
|
cursor.x, cursor.y, cursor.z);
|
|
|
|
|
|
|
|
|
|
MapExtras::MapCache map;
|
|
|
|
|
coord_vec all_tiles = brush->points(map, cursor);
|
|
|
|
|
if (!opts.quiet)
|
|
|
|
|
out.print("working...\n");
|
|
|
|
|
|
|
|
|
|
// Force the game to recompute its walkability cache
|
|
|
|
|
world->reindex_pathfinding = true;
|
|
|
|
|
|
|
|
|
|
int failures = 0;
|
|
|
|
|
|
|
|
|
|
for (coord_vec::iterator iter = all_tiles.begin(); iter != all_tiles.end(); ++iter)
|
|
|
|
|
{
|
|
|
|
|
MapExtras::Block *blk = map.BlockAtTile(*iter);
|
|
|
|
|
static bool paintTile(MapExtras::MapCache &map, const df::coord &pos,
|
|
|
|
|
const TileType &target, const TileType &match = TileType()) {
|
|
|
|
|
MapExtras::Block *blk = map.BlockAtTile(pos);
|
|
|
|
|
if (!blk)
|
|
|
|
|
continue;
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
df::tiletype source = map.tiletypeAt(*iter);
|
|
|
|
|
df::tile_designation des = map.designationAt(*iter);
|
|
|
|
|
df::tiletype source = map.tiletypeAt(pos);
|
|
|
|
|
df::tile_designation des = map.designationAt(pos);
|
|
|
|
|
|
|
|
|
|
// Stone painting operates on the base layer
|
|
|
|
|
if (paint.stone_material >= 0)
|
|
|
|
|
source = blk->baseTiletypeAt(*iter);
|
|
|
|
|
if (target.stone_material >= 0)
|
|
|
|
|
source = blk->baseTiletypeAt(pos);
|
|
|
|
|
|
|
|
|
|
t_matpair basemat = blk->baseMaterialAt(*iter);
|
|
|
|
|
t_matpair basemat = blk->baseMaterialAt(pos);
|
|
|
|
|
|
|
|
|
|
if (!filter.matches(source, des, basemat))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (!match.matches(source, des, basemat))
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
df::tiletype_shape shape = paint.shape;
|
|
|
|
|
df::tiletype_shape shape = target.shape;
|
|
|
|
|
if (shape == tiletype_shape::NONE)
|
|
|
|
|
{
|
|
|
|
|
shape = tileShape(source);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
df::tiletype_material material = paint.material;
|
|
|
|
|
df::tiletype_material material = target.material;
|
|
|
|
|
if (material == tiletype_material::NONE)
|
|
|
|
|
{
|
|
|
|
|
material = tileMaterial(source);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
df::tiletype_special special = paint.special;
|
|
|
|
|
df::tiletype_special special = target.special;
|
|
|
|
|
if (special == tiletype_special::NONE)
|
|
|
|
|
{
|
|
|
|
|
special = tileSpecial(source);
|
|
|
|
|
}
|
|
|
|
|
df::tiletype_variant variant = paint.variant;
|
|
|
|
|
|
|
|
|
|
df::tiletype_variant variant = target.variant;
|
|
|
|
|
/*
|
|
|
|
|
* FIXME: variant should be:
|
|
|
|
|
* 1. If user variant:
|
|
|
|
@ -848,52 +792,37 @@ command_result executePaintJob(color_ostream &out,
|
|
|
|
|
// Remove direction from directionless tiles
|
|
|
|
|
DFHack::TileDirection direction = tileDirection(source);
|
|
|
|
|
if (!(material == tiletype_material::RIVER || shape == tiletype_shape::BROOK_BED || special == tiletype_special::TRACK || (shape == tiletype_shape::WALL && (material == tiletype_material::CONSTRUCTION || special == tiletype_special::SMOOTH))))
|
|
|
|
|
{
|
|
|
|
|
direction.whole = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
df::tiletype type = DFHack::findTileType(shape, material, variant, special, direction);
|
|
|
|
|
// hack for empty space
|
|
|
|
|
if (shape == tiletype_shape::EMPTY && material == tiletype_material::AIR && variant == tiletype_variant::VAR_1 && special == tiletype_special::NORMAL && direction.whole == 0)
|
|
|
|
|
{
|
|
|
|
|
type = tiletype::OpenSpace;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// make sure it's not invalid
|
|
|
|
|
if(type != tiletype::Void)
|
|
|
|
|
{
|
|
|
|
|
if (paint.stone_material >= 0)
|
|
|
|
|
{
|
|
|
|
|
if (!blk->setStoneAt(*iter, type, paint.stone_material, paint.vein_type, true, true))
|
|
|
|
|
failures++;
|
|
|
|
|
if (type != tiletype::Void) {
|
|
|
|
|
if (target.stone_material >= 0) {
|
|
|
|
|
if (!blk->setStoneAt(pos, type, target.stone_material, target.vein_type, true, true))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
map.setTiletypeAt(*iter, type);
|
|
|
|
|
map.setTiletypeAt(pos, type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paint.hidden > -1)
|
|
|
|
|
{
|
|
|
|
|
des.bits.hidden = paint.hidden;
|
|
|
|
|
}
|
|
|
|
|
if (target.hidden > -1)
|
|
|
|
|
des.bits.hidden = target.hidden;
|
|
|
|
|
|
|
|
|
|
if (paint.light > -1)
|
|
|
|
|
{
|
|
|
|
|
des.bits.light = paint.light;
|
|
|
|
|
}
|
|
|
|
|
if (target.light > -1)
|
|
|
|
|
des.bits.light = target.light;
|
|
|
|
|
|
|
|
|
|
if (paint.subterranean > -1)
|
|
|
|
|
{
|
|
|
|
|
des.bits.subterranean = paint.subterranean;
|
|
|
|
|
}
|
|
|
|
|
if (target.subterranean > -1)
|
|
|
|
|
des.bits.subterranean = target.subterranean;
|
|
|
|
|
|
|
|
|
|
if (paint.skyview > -1)
|
|
|
|
|
{
|
|
|
|
|
des.bits.outside = paint.skyview;
|
|
|
|
|
}
|
|
|
|
|
if (target.skyview > -1)
|
|
|
|
|
des.bits.outside = target.skyview;
|
|
|
|
|
|
|
|
|
|
if (paint.aquifer > -1)
|
|
|
|
|
{
|
|
|
|
|
des.bits.water_table = paint.aquifer;
|
|
|
|
|
}
|
|
|
|
|
if (target.aquifer > -1)
|
|
|
|
|
des.bits.water_table = target.aquifer;
|
|
|
|
|
|
|
|
|
|
// Remove liquid from walls, etc
|
|
|
|
|
if (type != (df::tiletype)-1 && !DFHack::FlowPassable(type))
|
|
|
|
@ -907,7 +836,63 @@ command_result executePaintJob(color_ostream &out,
|
|
|
|
|
//des.bits.water_salt = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
map.setDesignationAt(*iter, des);
|
|
|
|
|
map.setDesignationAt(pos, des);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
command_result executePaintJob(color_ostream &out,
|
|
|
|
|
const tiletypes_options &opts)
|
|
|
|
|
{
|
|
|
|
|
if (paint.empty())
|
|
|
|
|
{
|
|
|
|
|
out.printerr("Set the paint first.\n");
|
|
|
|
|
return CR_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CoreSuspender suspend;
|
|
|
|
|
|
|
|
|
|
if (!Maps::IsValid())
|
|
|
|
|
{
|
|
|
|
|
out.printerr("Map is not available!\n");
|
|
|
|
|
return CR_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t x_max = 0, y_max = 0, z_max = 0;
|
|
|
|
|
Maps::getSize(x_max, y_max, z_max);
|
|
|
|
|
|
|
|
|
|
df::coord cursor;
|
|
|
|
|
if (Maps::isValidTilePos(opts.cursor))
|
|
|
|
|
{
|
|
|
|
|
cursor = opts.cursor;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
cursor = Gui::getCursorPos();
|
|
|
|
|
if (!cursor.isValid())
|
|
|
|
|
{
|
|
|
|
|
out.printerr("Can't get cursor coords! Make sure you have a cursor active in DF or specify the --cursor option.\n");
|
|
|
|
|
return CR_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!opts.quiet)
|
|
|
|
|
out.print("Cursor coords: (%d, %d, %d)\n",
|
|
|
|
|
cursor.x, cursor.y, cursor.z);
|
|
|
|
|
|
|
|
|
|
MapExtras::MapCache map;
|
|
|
|
|
coord_vec all_tiles = brush->points(map, cursor);
|
|
|
|
|
if (!opts.quiet)
|
|
|
|
|
out.print("working...\n");
|
|
|
|
|
|
|
|
|
|
// Force the game to recompute its walkability cache
|
|
|
|
|
world->reindex_pathfinding = true;
|
|
|
|
|
|
|
|
|
|
int failures = 0;
|
|
|
|
|
|
|
|
|
|
for (coord_vec::iterator iter = all_tiles.begin(); iter != all_tiles.end(); ++iter)
|
|
|
|
|
{
|
|
|
|
|
if (!paintTile(map, *iter, paint, filter))
|
|
|
|
|
++failures;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (failures > 0)
|
|
|
|
@ -1135,3 +1120,59 @@ command_result df_tiletypes_here_point (color_ostream &out, vector <string> & pa
|
|
|
|
|
brush = old;
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool setTile(color_ostream &out, df::coord pos, df::tiletype_shape shape,
|
|
|
|
|
df::tiletype_material material, df::tiletype_special special,
|
|
|
|
|
df::tiletype_variant variant) {
|
|
|
|
|
if (!Maps::isValidTilePos(pos)) {
|
|
|
|
|
out.printerr("Invalid map position: %d, %d, %d\n", pos.x, pos.y, pos.z);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!is_valid_enum_item(shape)) {
|
|
|
|
|
out.printerr("Invalid shape type: %d\n", shape);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (!is_valid_enum_item(material)) {
|
|
|
|
|
out.printerr("Invalid material type: %d\n", material);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (!is_valid_enum_item(special)) {
|
|
|
|
|
out.printerr("Invalid special type: %d\n", special);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (!is_valid_enum_item(variant)) {
|
|
|
|
|
out.printerr("Invalid variant type: %d\n", variant);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TileType target;
|
|
|
|
|
target.shape = shape;
|
|
|
|
|
target.material = material;
|
|
|
|
|
target.special = special;
|
|
|
|
|
target.variant = variant;
|
|
|
|
|
|
|
|
|
|
MapExtras::MapCache map;
|
|
|
|
|
return paintTile(map, pos, target) && map.WriteAll();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int tiletypes_setTile(lua_State *L) {
|
|
|
|
|
color_ostream *out = Lua::GetOutput(L);
|
|
|
|
|
if (!out)
|
|
|
|
|
out = &Core::getInstance().getConsole();
|
|
|
|
|
|
|
|
|
|
df::coord pos;
|
|
|
|
|
Lua::CheckDFAssign(L, &pos, 1);
|
|
|
|
|
df::tiletype_shape shape = (df::tiletype_shape)lua_tointeger(L, 2);
|
|
|
|
|
df::tiletype_material material = (df::tiletype_material)lua_tointeger(L, 3);
|
|
|
|
|
df::tiletype_special special = (df::tiletype_special)lua_tointeger(L, 4);
|
|
|
|
|
df::tiletype_variant variant = (df::tiletype_variant)lua_tointeger(L, 5);
|
|
|
|
|
|
|
|
|
|
Lua::Push(L, setTile(*out, pos, shape, material, special, variant));
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DFHACK_PLUGIN_LUA_COMMANDS {
|
|
|
|
|
DFHACK_LUA_COMMAND(tiletypes_setTile),
|
|
|
|
|
DFHACK_LUA_END
|
|
|
|
|
};
|
|
|
|
|