expose tiletype setting to Lua

develop
Myk Taylor 2023-01-27 13:38:49 -08:00
parent 22dd49ce38
commit f700ef90b8
No known key found for this signature in database
GPG Key ID: 8A39CA0FA0C16E78
1 changed files with 164 additions and 123 deletions

@ -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
};