Merge branch 'master' of https://github.com/angavrilov/dfhack into experimental-dontmerge

Conflicts:
	dfhack.init-example
develop
Warmist 2012-09-07 17:24:38 +03:00
commit 0db873493a
21 changed files with 598 additions and 14 deletions

@ -995,6 +995,10 @@ Maps module
Returns a map block object for given df::coord or x,y,z in local tile coordinates.
* ``dfhack.maps.ensureTileBlock(coords)``, or ``ensureTileBlock(x,y,z)``
Like ``getTileBlock``, but if the block is not allocated, try creating it.
* ``dfhack.maps.getRegionBiome(region_coord2d)``, or ``getRegionBiome(x,y)``
Returns the biome info struct for the given global map region.
@ -1304,6 +1308,11 @@ Basic painting functions:
Returns *false* if coordinates out of bounds, or other error.
* ``dfhack.screen.readTile(x,y)``
Retrieves the contents of the specified tile from the screen buffers.
Returns a pen, or *nil* if invalid or TrueType.
* ``dfhack.screen.paintString(pen,x,y,text)``
Paints the string starting at *x,y*. Uses the string characters

@ -1207,6 +1207,9 @@ Returns <em>false</em> in case of error.</p>
<li><p class="first"><tt class="docutils literal">dfhack.maps.getTileBlock(coords)</tt>, or <tt class="docutils literal">getTileBlock(x,y,z)</tt></p>
<p>Returns a map block object for given df::coord or x,y,z in local tile coordinates.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.maps.ensureTileBlock(coords)</tt>, or <tt class="docutils literal">ensureTileBlock(x,y,z)</tt></p>
<p>Like <tt class="docutils literal">getTileBlock</tt>, but if the block is not allocated, try creating it.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.maps.getRegionBiome(region_coord2d)</tt>, or <tt class="docutils literal">getRegionBiome(x,y)</tt></p>
<p>Returns the biome info struct for the given global map region.</p>
</li>
@ -1477,6 +1480,10 @@ Otherwise should be <em>true/false</em>.</p>
</dl>
<p>Returns <em>false</em> if coordinates out of bounds, or other error.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.screen.readTile(x,y)</tt></p>
<p>Retrieves the contents of the specified tile from the screen buffers.
Returns a pen, or <em>nil</em> if invalid or TrueType.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.screen.paintString(pen,x,y,text)</tt></p>
<p>Paints the string starting at <em>x,y</em>. Uses the string characters
in sequence to override the <tt class="docutils literal">ch</tt> field of pen.</p>

@ -56,6 +56,9 @@ keybinding add Alt-R@dwarfmode/QueryBuilding/Some gui/room-list.work
# interface for the liquids plugin
keybinding add Alt-L@dwarfmode/LookAround gui/liquids
# machine power sensitive pressure plate construction
keybinding add Ctrl-Shift-M@dwarfmode/Build/Position/Trap gui/power-meter
# interface for universal game master's editor
keybinding add Alt-Shift-E gui/gm-editor

@ -935,6 +935,13 @@ static int maps_getTileBlock(lua_State *L)
return 1;
}
static int maps_ensureTileBlock(lua_State *L)
{
auto pos = CheckCoordXYZ(L, 1, true);
Lua::PushDFObject(L, Maps::ensureTileBlock(pos));
return 1;
}
static int maps_getRegionBiome(lua_State *L)
{
auto pos = CheckCoordXY(L, 1, true);
@ -951,6 +958,7 @@ static int maps_getTileBiomeRgn(lua_State *L)
static const luaL_Reg dfhack_maps_funcs[] = {
{ "isValidTilePos", maps_isValidTilePos },
{ "getTileBlock", maps_getTileBlock },
{ "ensureTileBlock", maps_ensureTileBlock },
{ "getRegionBiome", maps_getRegionBiome },
{ "getTileBiomeRgn", maps_getTileBiomeRgn },
{ NULL, NULL }
@ -1146,6 +1154,45 @@ static int screen_paintTile(lua_State *L)
return 1;
}
static int screen_readTile(lua_State *L)
{
int x = luaL_checkint(L, 1);
int y = luaL_checkint(L, 2);
Pen pen = Screen::readTile(x, y);
if (!pen.valid())
{
lua_pushnil(L);
}
else
{
lua_newtable(L);
lua_pushinteger(L, pen.ch); lua_setfield(L, -2, "ch");
lua_pushinteger(L, pen.fg); lua_setfield(L, -2, "fg");
lua_pushinteger(L, pen.bg); lua_setfield(L, -2, "bg");
lua_pushboolean(L, pen.bold); lua_setfield(L, -2, "bold");
if (pen.tile)
{
lua_pushinteger(L, pen.tile); lua_setfield(L, -2, "tile");
switch (pen.tile_mode) {
case Pen::CharColor:
lua_pushboolean(L, true); lua_setfield(L, -2, "tile_color");
break;
case Pen::TileColor:
lua_pushinteger(L, pen.tile_fg); lua_setfield(L, -2, "tile_fg");
lua_pushinteger(L, pen.tile_bg); lua_setfield(L, -2, "tile_bg");
break;
default:
break;
}
}
}
return 1;
}
static int screen_paintString(lua_State *L)
{
Pen pen;
@ -1250,6 +1297,7 @@ static const luaL_Reg dfhack_screen_funcs[] = {
{ "getMousePos", screen_getMousePos },
{ "getWindowSize", screen_getWindowSize },
{ "paintTile", screen_paintTile },
{ "readTile", screen_readTile },
{ "paintString", screen_paintString },
{ "fillRect", screen_fillRect },
{ "findGraphicsTile", screen_findGraphicsTile },

@ -253,6 +253,8 @@ public:
bool is_valid() { return valid; }
df::map_block *getRaw() { return block; }
bool Allocate();
MapCache *getParent() { return parent; }
private:
@ -262,6 +264,8 @@ private:
MapCache *parent;
df::map_block *block;
void init();
int biomeIndexAt(df::coord2d p);
bool valid;
@ -347,6 +351,12 @@ class DFHACK_EXPORT MapCache
return BlockAt(df::coord(coord.x>>4,coord.y>>4,coord.z));
}
bool ensureBlockAt(df::coord coord)
{
Block *b = BlockAtTile(coord);
return b ? b->Allocate() : false;
}
df::tiletype baseTiletypeAt (DFCoord tilecoord)
{
Block *b = BlockAtTile(tilecoord);

@ -241,9 +241,11 @@ inline bool isValidTilePos(df::coord pos) { return isValidTilePos(pos.x, pos.y,
*/
extern DFHACK_EXPORT df::map_block * getBlock (int32_t blockx, int32_t blocky, int32_t blockz);
extern DFHACK_EXPORT df::map_block * getTileBlock (int32_t x, int32_t y, int32_t z);
extern DFHACK_EXPORT df::map_block * ensureTileBlock (int32_t x, int32_t y, int32_t z);
inline df::map_block * getBlock (df::coord pos) { return getBlock(pos.x, pos.y, pos.z); }
inline df::map_block * getTileBlock (df::coord pos) { return getTileBlock(pos.x, pos.y, pos.z); }
inline df::map_block * ensureTileBlock (df::coord pos) { return ensureTileBlock(pos.x, pos.y, pos.z); }
extern DFHACK_EXPORT df::tiletype *getTileType(int32_t x, int32_t y, int32_t z);
extern DFHACK_EXPORT df::tile_designation *getTileDesignation(int32_t x, int32_t y, int32_t z);

@ -65,6 +65,9 @@ namespace DFHack
} tile_mode;
int8_t tile_fg, tile_bg;
bool valid() const { return tile >= 0; }
bool empty() const { return ch == 0 && tile == 0; }
Pen(char ch = 0, int8_t fg = 7, int8_t bg = 0, int tile = 0, bool color_tile = false)
: ch(ch), fg(fg&7), bg(bg), bold(!!(fg&8)),
tile(tile), tile_mode(color_tile ? CharColor : AsIs), tile_fg(0), tile_bg(0)
@ -92,6 +95,9 @@ namespace DFHack
/// Paint one screen tile with the given pen
DFHACK_EXPORT bool paintTile(const Pen &pen, int x, int y);
/// Retrieves one screen tile from the buffer
DFHACK_EXPORT Pen readTile(int x, int y);
/// Paint a string onto the screen. Ignores ch and tile of pen.
DFHACK_EXPORT bool paintString(const Pen &pen, int x, int y, const std::string &text);

@ -84,7 +84,7 @@ function mkmodule(module,env)
error("Not a table in package.loaded["..module.."]")
end
end
local plugname = string.match(module,'^plugins%.(%w+)$')
local plugname = string.match(module,'^plugins%.([%w%-]+)$')
if plugname then
dfhack.open_plugin(pkg,plugname)
end

@ -162,10 +162,10 @@ function Painter:fill(x1,y1,x2,y2,pen,bg,bold)
if type(x1) == 'table' then
x1, y1, x2, y2, pen, bg, bold = x1.x1, x1.y1, x1.x2, x1.y2, y1, x2, y2
end
x1 = math.max(x1,self.clip_x1)
y1 = math.max(y1,self.clip_y1)
x2 = math.min(x2,self.clip_x2)
y2 = math.min(y2,self.clip_y2)
x1 = math.max(x1+self.x1,self.clip_x1)
y1 = math.max(y1+self.y1,self.clip_y1)
x2 = math.min(x2+self.x1,self.clip_x2)
y2 = math.min(y2+self.y1,self.clip_y2)
dscreen.fillRect(to_pen(self.cur_pen,pen,bg,bold),x1,y1,x2,y2)
return self
end

@ -127,7 +127,7 @@ function InputBox:onRenderBody(dc)
dc:newline(1)
dc:pen(self.input_pen or COLOR_LIGHTCYAN)
dc:fill(dc.x1+1,dc.y,dc.x2-1,dc.y)
dc:fill(1,dc:localY(),dc.width-2,dc:localY())
local cursor = '_'
if math.floor(dfhack.getTickCount()/300) % 2 == 0 then
@ -135,9 +135,7 @@ function InputBox:onRenderBody(dc)
end
local txt = self.input .. cursor
if #txt > dc.width-2 then
txt = string.sub(txt, #txt-dc.width+3)
-- Add prefix arrow
dc:advance(-1):char(27)
txt = string.char(27)..string.sub(txt, #txt-dc.width+4)
end
dc:string(txt)
end

@ -211,7 +211,14 @@ DEFINE_GET_FOCUS_STRING_HANDLER(dwarfmode)
if (ui_build_selector->building_type < 0)
focus += "/Type";
else if (ui_build_selector->stage != 2)
{
if (ui_build_selector->stage != 1)
focus += "/NoMaterials";
else
focus += "/Position";
focus += "/" + enum_item_key(ui_build_selector->building_type);
}
else
{
focus += "/Material";

@ -157,6 +157,39 @@ df::map_block *Maps::getTileBlock (int32_t x, int32_t y, int32_t z)
return world->map.block_index[x >> 4][y >> 4][z];
}
df::map_block *Maps::ensureTileBlock (int32_t x, int32_t y, int32_t z)
{
if (!isValidTilePos(x,y,z))
return NULL;
auto column = world->map.block_index[x >> 4][y >> 4];
auto &slot = column[z];
if (slot)
return slot;
// Find another block below
int z2 = z;
while (z2 >= 0 && !column[z2]) z2--;
if (z2 < 0)
return NULL;
slot = new df::map_block();
slot->region_pos = column[z2]->region_pos;
slot->map_pos = column[z2]->map_pos;
slot->map_pos.z = z;
// Assume sky
df::tile_designation dsgn(0);
dsgn.bits.light = true;
dsgn.bits.outside = true;
for (int tx = 0; tx < 16; tx++)
for (int ty = 0; ty < 16; ty++)
slot->designation[tx][ty] = dsgn;
return slot;
}
df::tiletype *Maps::getTileType(int32_t x, int32_t y, int32_t z)
{
df::map_block *block = getTileBlock(x,y,z);
@ -513,8 +546,14 @@ MapExtras::Block::Block(MapCache *parent, DFCoord _bcoord) : parent(parent)
valid = false;
bcoord = _bcoord;
block = Maps::getBlock(bcoord);
item_counts = NULL;
tags = NULL;
init();
}
void MapExtras::Block::init()
{
item_counts = NULL;
tiles = NULL;
basemats = NULL;
@ -537,6 +576,23 @@ MapExtras::Block::Block(MapCache *parent, DFCoord _bcoord) : parent(parent)
}
}
bool MapExtras::Block::Allocate()
{
if (block)
return true;
block = Maps::ensureTileBlock(bcoord.x*16, bcoord.y*16, bcoord.z);
if (!block)
return false;
delete item_counts;
delete tiles;
delete basemats;
init();
return true;
}
MapExtras::Block::~Block()
{
delete[] item_counts;

@ -100,7 +100,7 @@ static void doSetTile(const Pen &pen, int index)
bool Screen::paintTile(const Pen &pen, int x, int y)
{
if (!gps) return false;
if (!gps || !pen.valid()) return false;
int dimx = gps->dimx, dimy = gps->dimy;
if (x < 0 || x >= dimx || y < 0 || y >= dimy) return false;
@ -109,6 +109,41 @@ bool Screen::paintTile(const Pen &pen, int x, int y)
return true;
}
Pen Screen::readTile(int x, int y)
{
if (!gps) return Pen(0,0,0,-1);
int dimx = gps->dimx, dimy = gps->dimy;
if (x < 0 || x >= dimx || y < 0 || y >= dimy)
return Pen(0,0,0,-1);
int index = x*dimy + y;
auto screen = gps->screen + index*4;
if (screen[3] & 0x80)
return Pen(0,0,0,-1);
Pen pen(
screen[0], screen[1], screen[2], screen[3]?true:false,
gps->screentexpos[index]
);
if (pen.tile)
{
if (gps->screentexpos_grayscale[index])
{
pen.tile_mode = Screen::Pen::TileColor;
pen.tile_fg = gps->screentexpos_cf[index];
pen.tile_bg = gps->screentexpos_cbr[index];
}
else if (gps->screentexpos_addcolor[index])
{
pen.tile_mode = Screen::Pen::CharColor;
}
}
return pen;
}
bool Screen::paintString(const Pen &pen, int x, int y, const std::string &text)
{
if (!gps || y < 0 || y >= gps->dimy) return false;
@ -132,7 +167,7 @@ bool Screen::paintString(const Pen &pen, int x, int y, const std::string &text)
bool Screen::fillRect(const Pen &pen, int x1, int y1, int x2, int y2)
{
if (!gps) return false;
if (!gps || !pen.valid()) return false;
if (x1 < 0) x1 = 0;
if (y1 < 0) y1 = 0;

@ -0,0 +1,11 @@
local _ENV = mkmodule('plugins.power-meter')
--[[
Native functions:
* makePowerMeter(plate_info,min_power,max_power,invert)
--]]
return _ENV

@ -0,0 +1,237 @@
#include "Core.h"
#include <Console.h>
#include <Export.h>
#include <Error.h>
#include <PluginManager.h>
#include <modules/Gui.h>
#include <modules/Screen.h>
#include <modules/Maps.h>
#include <modules/World.h>
#include <TileTypes.h>
#include <vector>
#include <cstdio>
#include <stack>
#include <string>
#include <cmath>
#include <string.h>
#include <VTableInterpose.h>
#include "df/graphic.h"
#include "df/building_trapst.h"
#include "df/builtin_mats.h"
#include "df/world.h"
#include "df/buildings_other_id.h"
#include "df/machine.h"
#include "df/machine_info.h"
#include "df/building_drawbuffer.h"
#include "df/ui.h"
#include "df/viewscreen_dwarfmodest.h"
#include "df/ui_build_selector.h"
#include "df/flow_info.h"
#include "df/report.h"
#include "MiscUtils.h"
using std::vector;
using std::string;
using std::stack;
using namespace DFHack;
using namespace df::enums;
using df::global::gps;
using df::global::world;
using df::global::ui;
using df::global::ui_build_selector;
DFHACK_PLUGIN("power-meter");
static const uint32_t METER_BIT = 0x80000000U;
static void init_plate_info(df::pressure_plate_info &plate_info)
{
plate_info.water_min = 1;
plate_info.water_max = 7;
plate_info.flags.whole = METER_BIT;
plate_info.flags.bits.water = true;
plate_info.flags.bits.resets = true;
}
/*
* Hook for the pressure plate itself. Implements core logic.
*/
struct trap_hook : df::building_trapst {
typedef df::building_trapst interpose_base;
// Engine detection
bool is_power_meter()
{
return trap_type == trap_type::PressurePlate &&
(plate_info.flags.whole & METER_BIT) != 0;
}
inline bool is_fully_built()
{
return getBuildStage() >= getMaxBuildStage();
}
DEFINE_VMETHOD_INTERPOSE(void, getName, (std::string *buf))
{
if (is_power_meter())
{
buf->clear();
*buf += "Power Meter";
return;
}
INTERPOSE_NEXT(getName)(buf);
}
DEFINE_VMETHOD_INTERPOSE(void, updateAction, ())
{
if (is_power_meter())
{
auto pdsgn = Maps::getTileDesignation(centerx,centery,z);
if (pdsgn)
{
bool active = false;
auto &gears = world->buildings.other[buildings_other_id::GEAR_ASSEMBLY];
for (size_t i = 0; i < gears.size(); i++)
{
// Adjacent
auto gear = gears[i];
int deltaxy = abs(centerx - gear->centerx) + abs(centery - gear->centery);
if (gear->z != z || deltaxy != 1)
continue;
// Linked to machine
auto info = gears[i]->getMachineInfo();
if (!info || info->machine_id < 0)
continue;
// an active machine
auto machine = df::machine::find(info->machine_id);
if (!machine || !machine->flags.bits.active)
continue;
// with adequate power?
int power = machine->cur_power - machine->min_power;
if (power < 0 || machine->cur_power <= 0)
continue;
if (power < plate_info.track_min)
continue;
if (power > plate_info.track_max && plate_info.track_max >= 0)
continue;
active = true;
break;
}
if (plate_info.flags.bits.citizens)
active = !active;
// Temporarily set the tile water amount based on power state
auto old_dsgn = *pdsgn;
pdsgn->bits.liquid_type = tile_liquid::Water;
pdsgn->bits.flow_size = (active ? 7 : 0);
INTERPOSE_NEXT(updateAction)();
*pdsgn = old_dsgn;
return;
}
}
INTERPOSE_NEXT(updateAction)();
}
DEFINE_VMETHOD_INTERPOSE(void, drawBuilding, (df::building_drawbuffer *db, void *unk))
{
INTERPOSE_NEXT(drawBuilding)(db, unk);
if (is_power_meter() && is_fully_built())
{
db->fore[0][0] = 3;
}
}
};
IMPLEMENT_VMETHOD_INTERPOSE(trap_hook, getName);
IMPLEMENT_VMETHOD_INTERPOSE(trap_hook, updateAction);
IMPLEMENT_VMETHOD_INTERPOSE(trap_hook, drawBuilding);
static bool enabled = false;
static void enable_hooks(bool enable)
{
enabled = enable;
INTERPOSE_HOOK(trap_hook, getName).apply(enable);
INTERPOSE_HOOK(trap_hook, updateAction).apply(enable);
INTERPOSE_HOOK(trap_hook, drawBuilding).apply(enable);
}
static bool makePowerMeter(df::pressure_plate_info *info, int min_power, int max_power, bool invert)
{
CHECK_NULL_POINTER(info);
if (!enabled)
{
auto pworld = Core::getInstance().getWorld();
auto entry = pworld->GetPersistentData("power-meter/enabled", NULL);
if (!entry.isValid())
return false;
enable_hooks(true);
}
init_plate_info(*info);
info->track_min = min_power;
info->track_max = max_power;
info->flags.bits.citizens = invert;
return true;
}
DFHACK_PLUGIN_LUA_FUNCTIONS {
DFHACK_LUA_FUNCTION(makePowerMeter),
DFHACK_LUA_END
};
DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event)
{
switch (event) {
case SC_MAP_LOADED:
{
auto pworld = Core::getInstance().getWorld();
bool enable = pworld->GetPersistentData("power-meter/enabled").isValid();
if (enable)
{
out.print("Enabling the power meter plugin.\n");
enable_hooks(true);
}
}
break;
case SC_MAP_UNLOADED:
enable_hooks(false);
break;
default:
break;
}
return CR_OK;
}
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{
if (Core::getInstance().isMapLoaded())
plugin_onstatechange(out, SC_MAP_LOADED);
return CR_OK;
}
DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{
enable_hooks(false);
return CR_OK;
}

@ -3,6 +3,7 @@
local utils = require 'utils'
local gui = require 'gui'
local guidm = require 'gui.dwarfmode'
local dlg = require 'gui.dialogs'
local liquids = require('plugins.liquids')
@ -199,6 +200,42 @@ function LiquidsUI:onRenderBody(dc)
dc:string("Enter", COLOR_LIGHTGREEN):string(": Paint")
end
function ensure_blocks(cursor, size, cb)
local cx,cy,cz = pos2xyz(cursor)
local all = true
for x=1,size.x or 1,16 do
for y=1,size.y or 1,16 do
for z=1,size.z do
if not dfhack.maps.getTileBlock(cx+x-1, cy+y-1, cz+z-1) then
all = false
end
end
end
end
if all then
cb()
return
end
dlg.showYesNoPrompt(
'Instantiate Blocks',
'Not all map blocks are allocated - instantiate?\n\nWarning: new untested feature.',
COLOR_YELLOW,
function()
for x=1,size.x or 1,16 do
for y=1,size.y or 1,16 do
for z=1,size.z do
dfhack.maps.ensureTileBlock(cx+x-1, cy+y-1, cz+z-1)
end
end
end
cb()
end,
function()
cb()
end
)
end
function LiquidsUI:onInput(keys)
local paint = self.paint:get()
local liquid = paint.liquid
@ -239,13 +276,15 @@ function LiquidsUI:onInput(keys)
else
guidm.clearSelection()
end
liquids.paint(
local cb = curry(
liquids.paint,
cursor,
self.brush:get().tag, self.paint:get().tag,
self.amount, size,
self.set:get().tag, self.flow:get().tag,
self.permaflow:get().tag
)
ensure_blocks(cursor, size, cb)
elseif self:propagateMoveKeys(keys) then
return
elseif keys.D_LOOK_ARENA_WATER then

@ -0,0 +1,116 @@
-- Interface front-end for power-meter plugin.
local utils = require 'utils'
local gui = require 'gui'
local guidm = require 'gui.dwarfmode'
local dlg = require 'gui.dialogs'
local plugin = require('plugins.power-meter')
local bselector = df.global.ui_build_selector
PowerMeter = defclass(PowerMeter, guidm.MenuOverlay)
PowerMeter.focus_path = 'power-meter'
function PowerMeter:init()
self:init_fields{
min_power = 0, max_power = -1, invert = false,
}
guidm.MenuOverlay.init(self)
return self
end
function PowerMeter:onShow()
guidm.MenuOverlay.onShow(self)
-- Send an event to update the errors
bselector.plate_info.flags.whole = 0
self:sendInputToParent('BUILDING_TRIGGER_ENABLE_WATER')
end
function PowerMeter:onRenderBody(dc)
dc:fill(0,0,dc.width-1,13,gui.CLEAR_PEN)
dc:seek(1,1):pen(COLOR_WHITE)
dc:string("Power Meter"):newline():newline(1)
dc:string("Placement"):newline():newline(1)
dc:string("Excess power range:")
dc:newline(3):string("as", COLOR_LIGHTGREEN)
dc:string(": Min ")
if self.min_power <= 0 then
dc:string("(any)")
else
dc:string(''..self.min_power)
end
dc:newline(3):string("zx", COLOR_LIGHTGREEN)
dc:string(": Max ")
if self.max_power < 0 then
dc:string("(any)")
else
dc:string(''..self.max_power)
end
dc:newline():newline(1)
dc:string("i",COLOR_LIGHTGREEN):string(": ")
if self.invert then
dc:string("Inverted")
else
dc:string("Not inverted")
end
end
function PowerMeter:onInput(keys)
if keys.CUSTOM_I then
self.invert = not self.invert
elseif keys.BUILDING_TRIGGER_MIN_WATER_UP then
self.min_power = self.min_power + 10
elseif keys.BUILDING_TRIGGER_MIN_WATER_DOWN then
self.min_power = math.max(0, self.min_power - 10)
elseif keys.BUILDING_TRIGGER_MAX_WATER_UP then
if self.max_power < 0 then
self.max_power = 0
else
self.max_power = self.max_power + 10
end
elseif keys.BUILDING_TRIGGER_MAX_WATER_DOWN then
self.max_power = math.max(-1, self.max_power - 10)
elseif keys.LEAVESCREEN then
self:dismiss()
self:sendInputToParent('LEAVESCREEN')
elseif keys.SELECT then
if #bselector.errors == 0 then
if not plugin.makePowerMeter(
bselector.plate_info,
self.min_power, self.max_power, self.invert
)
then
dlg.showMessage(
'Power Meter',
'Could not initialize.', COLOR_LIGHTRED
)
self:dismiss()
self:sendInputToParent('LEAVESCREEN')
return
end
self:sendInputToParent('SELECT')
if bselector.stage ~= 1 then
self:dismiss()
end
end
elseif self:propagateMoveKeys(keys) then
return
end
end
if dfhack.gui.getCurFocus() ~= 'dwarfmode/Build/Position/Trap'
or bselector.building_subtype ~= df.trap_type.PressurePlate
then
qerror("This script requires the main dwarfmode view in build pressure plate mode")
end
local list = mkinstance(PowerMeter):init()
list:show()