Support permaflow in liquids, including the gui.

develop
Alexander Gavrilov 2012-08-26 20:08:28 +04:00
parent bee33fd486
commit 8171652323
2 changed files with 144 additions and 32 deletions

@ -101,17 +101,36 @@ static const char *modify_mode_name[] = {
"+", ".", "-", NULL
};
enum PermaflowMode {
PF_KEEP, PF_NONE,
PF_NORTH, PF_SOUTH, PF_EAST, PF_WEST,
PF_NORTHEAST, PF_NORTHWEST, PF_SOUTHEAST, PF_SOUTHWEST
};
static const char *permaflow_name[] = {
".", "-", "N", "S", "E", "W",
"NE", "NW", "SE", "SW", NULL
};
#define X(name) tile_liquid_flow_dir::name
static const df::tile_liquid_flow_dir permaflow_id[] = {
X(none), X(none), X(north), X(south), X(east), X(west),
X(northeast), X(northwest), X(southeast), X(southwest)
};
#undef X
struct OperationMode {
BrushType brush;
PaintMode paint;
ModifyMode flowmode;
ModifyMode setmode;
PermaflowMode permaflow;
unsigned int amount;
df::coord size;
OperationMode() :
brush(B_POINT), paint(P_MAGMA),
flowmode(M_INC), setmode(M_KEEP), amount(7),
flowmode(M_INC), setmode(M_KEEP), permaflow(PF_KEEP), amount(7),
size(1,1,1)
{}
} cur_mode;
@ -119,6 +138,17 @@ struct OperationMode {
command_result df_liquids_execute(color_ostream &out);
command_result df_liquids_execute(color_ostream &out, OperationMode &mode, df::coord pos);
static void print_prompt(std::ostream &str, OperationMode &cur_mode)
{
str <<"[" << paint_mode_name[cur_mode.paint] << ":" << brush_name[cur_mode.brush];
if (cur_mode.brush == B_RANGE)
str << "(w" << cur_mode.size.x << ":h" << cur_mode.size.y << ":z" << cur_mode.size.z << ")";
str << ":" << cur_mode.amount << ":f" << modify_mode_name[cur_mode.flowmode]
<< ":s" << modify_mode_name[cur_mode.setmode]
<< ":pf" << permaflow_name[cur_mode.permaflow]
<< "]";
}
command_result df_liquids (color_ostream &out_, vector <string> & parameters)
{
if(!out_.is_console())
@ -154,11 +184,8 @@ command_result df_liquids (color_ostream &out_, vector <string> & parameters)
string input = "";
std::stringstream str;
str <<"[" << paint_mode_name[cur_mode.paint] << ":" << brush_name[cur_mode.brush];
if (cur_mode.brush == B_RANGE)
str << "(w" << cur_mode.size.x << ":h" << cur_mode.size.y << ":z" << cur_mode.size.z << ")";
str << ":" << cur_mode.amount << ":f" << modify_mode_name[cur_mode.flowmode]
<< ":s" << modify_mode_name[cur_mode.setmode] << "]#";
print_prompt(str, cur_mode);
str << "# ";
if(out.lineedit(str.str(),input,liquids_hist) == -1)
return CR_FAILURE;
liquids_hist.add(input);
@ -185,6 +212,10 @@ command_result df_liquids (color_ostream &out_, vector <string> & parameters)
<< "f+ - make the spawned liquid flow" << endl
<< "f. - don't change flow state (read state in flow mode)" << endl
<< "f- - make the spawned liquid static" << endl
<< "Permaflow (only for water):" << endl
<< "pf. - don't change permaflow state" << endl
<< "pf- - make the spawned liquid static" << endl
<< "pf[NS][EW] - make the spawned liquid permanently flow" << endl
<< "0-7 - set liquid amount" << endl
<< "Brush:" << endl
<< "point - single tile [p]" << endl
@ -297,6 +328,20 @@ command_result df_liquids (color_ostream &out_, vector <string> & parameters)
{
cur_mode.setmode = M_KEEP;
}
else if (command.size() > 2 && memcmp(command.c_str(), "pf", 2) == 0)
{
auto *tail = command.c_str()+2;
for (int pm = PF_KEEP; pm <= PF_SOUTHWEST; pm++)
{
if (strcmp(tail, permaflow_name[pm]) != 0)
continue;
cur_mode.permaflow = PermaflowMode(pm);
tail = NULL;
break;
}
if (tail)
out << command << " : invalid permaflow mode" << endl;
}
// blah blah, bad code, bite me.
else if(command == "0")
cur_mode.amount = 0;
@ -339,11 +384,8 @@ command_result df_liquids_here (color_ostream &out, vector <string> & parameters
}
out.print("Run liquids-here with these parameters: ");
out << "[" << paint_mode_name[cur_mode.paint] << ":" << brush_name[cur_mode.brush];
if (cur_mode.brush == B_RANGE)
out << "(w" << cur_mode.size.x << ":h" << cur_mode.size.y << ":z" << cur_mode.size.z << ")";
out << ":" << cur_mode.amount << ":f" << modify_mode_name[cur_mode.flowmode]
<< ":" << modify_mode_name[cur_mode.setmode] << "]\n";
print_prompt(out, cur_mode);
out << endl;
return df_liquids_execute(out);
}
@ -489,6 +531,7 @@ command_result df_liquids_execute(color_ostream &out, OperationMode &cur_mode, d
iter ++;
continue;
}
auto raw_block = block->getRaw();
df::tile_designation des = mcache.designationAt(current);
df::tiletype tt = mcache.tiletypeAt(current);
// don't put liquids into places where they don't belong...
@ -548,6 +591,12 @@ command_result df_liquids_execute(color_ostream &out, OperationMode &cur_mode, d
// request flow engine updates
block->enableBlockUpdates(new_amount != old_amount, new_liquid != old_liquid);
}
if (cur_mode.permaflow != PF_KEEP && raw_block)
{
auto &flow = raw_block->liquid_flow[current.x&15][current.y&15];
flow.bits.perm_flow_dir = permaflow_id[cur_mode.permaflow];
flow.bits.temp_flow_timer = 0;
}
seen_blocks.insert(block);
iter++;
}
@ -593,7 +642,7 @@ static int paint(lua_State *L)
df::coord pos;
OperationMode mode;
lua_settop(L, 7);
lua_settop(L, 8);
Lua::CheckDFAssign(L, &pos, 1);
if (!pos.isValid())
luaL_argerror(L, 1, "invalid cursor position");
@ -606,6 +655,7 @@ static int paint(lua_State *L)
Lua::CheckDFAssign(L, &mode.size, 5);
mode.setmode = (ModifyMode)luaL_checkoption(L, 6, ".", modify_mode_name);
mode.flowmode = (ModifyMode)luaL_checkoption(L, 7, "+", modify_mode_name);
mode.permaflow = (PermaflowMode)luaL_checkoption(L, 8, ".", permaflow_name);
lua_pushboolean(L, df_liquids_execute(*Lua::GetOutput(L), mode, pos));
return 1;

@ -16,12 +16,12 @@ local brushes = {
}
local paints = {
{ tag = 'water', caption = 'Water', liquid = true, key = 'w' },
{ tag = 'magma', caption = 'Magma', liquid = true, key = 'l' },
{ tag = 'water', caption = 'Water', liquid = true, flow = true, key = 'w' },
{ tag = 'magma', caption = 'Magma', liquid = true, flow = true, key = 'l' },
{ tag = 'obsidian', caption = 'Obsidian Wall' },
{ tag = 'obsidian_floor', caption = 'Obsidian Floor' },
{ tag = 'riversource', caption = 'River Source' },
{ tag = 'flowbits', caption = 'Flow Updates' },
{ tag = 'flowbits', caption = 'Flow Updates', flow = true },
{ tag = 'wclean', caption = 'Clean Salt/Stagnant' },
}
@ -37,6 +37,19 @@ local setmode = {
{ tag = '-', caption = 'Only Decrease' },
}
local permaflows = {
{ tag = '.', caption = "Keep Permaflow" },
{ tag = '-', caption = 'Remove Permaflow' },
{ tag = 'N', caption = 'Set Permaflow N' },
{ tag = 'S', caption = 'Set Permaflow S' },
{ tag = 'E', caption = 'Set Permaflow E' },
{ tag = 'W', caption = 'Set Permaflow W' },
{ tag = 'NE', caption = 'Set Permaflow NE' },
{ tag = 'NW', caption = 'Set Permaflow NW' },
{ tag = 'SE', caption = 'Set Permaflow SE' },
{ tag = 'SW', caption = 'Set Permaflow SW' },
}
Toggle = defclass(Toggle)
function Toggle:init(items)
@ -80,6 +93,7 @@ function LiquidsUI:init()
paint = mkinstance(Toggle):init(paints),
flow = mkinstance(Toggle):init(flowbits),
set = mkinstance(Toggle):init(setmode),
permaflow = mkinstance(Toggle):init(permaflows),
amount = 7,
}
guidm.MenuOverlay.init(self)
@ -90,15 +104,8 @@ function LiquidsUI:onDestroy()
guidm.clearSelection()
end
function LiquidsUI:onRenderBody(dc)
dc:clear():seek(1,1):string("Paint Liquids Cheat", COLOR_WHITE)
local cursor = guidm.getCursorPos()
local block = dfhack.maps.getTileBlock(cursor)
local tile = block.tiletype[cursor.x%16][cursor.y%16]
local dsgn = block.designation[cursor.x%16][cursor.y%16]
dc:seek(2,3):string(df.tiletype.attrs[tile].caption, COLOR_CYAN):newline(2)
function render_liquid(dc, block, x, y)
local dsgn = block.designation[x%16][y%16]
if dsgn.flow_size > 0 then
if dsgn.liquid_type == df.tile_liquid.Magma then
@ -111,7 +118,51 @@ function LiquidsUI:onRenderBody(dc)
end
dc:string(" ["..dsgn.flow_size.."/7]")
else
dc:string('No Liquid', COLOR_DARKGREY)
dc:string('No Liquid')
end
end
local permaflow_abbr = {
north = 'N', south = 'S', east = 'E', west = 'W',
northeast = 'NE', northwest = 'NW', southeast = 'SE', southwest = 'SW'
}
function render_flow_state(dc, block, x, y)
local flow = block.liquid_flow[x%16][y%16]
if block.flags.update_liquid then
dc:string("Updating", COLOR_GREEN)
else
dc:string("Static")
end
dc:string(", ")
if flow.perm_flow_dir ~= 0 then
local tag = df.tile_liquid_flow_dir[flow.perm_flow_dir]
dc:string("Permaflow "..(permaflow_abbr[tag] or tag), COLOR_CYAN)
elseif flow.temp_flow_timer > 0 then
dc:string("Flowing "..flow.temp_flow_timer, COLOR_GREEN)
else
dc:string("No Flow")
end
end
function LiquidsUI:onRenderBody(dc)
dc:clear():seek(1,1):string("Paint Liquids Cheat", COLOR_WHITE)
local cursor = guidm.getCursorPos()
local block = dfhack.maps.getTileBlock(cursor)
if block then
local x, y = pos2xyz(cursor)
local tile = block.tiletype[x%16][y%16]
dc:seek(2,3):string(df.tiletype.attrs[tile].caption, COLOR_CYAN)
dc:newline(2):pen(COLOR_DARKGREY)
render_liquid(dc, block, x, y)
dc:newline(2):pen(COLOR_DARKGREY)
render_flow_state(dc, block, x, y)
else
dc:seek(2,3):string("No map data", COLOR_RED):advance(0,2)
end
dc:newline():pen(COLOR_GREY)
@ -121,10 +172,10 @@ function LiquidsUI:onRenderBody(dc)
dc:newline(1):string("p", COLOR_LIGHTGREEN):string(": ")
self.paint:render(dc)
local liquid = self.paint:get().liquid
local paint = self.paint:get()
dc:newline()
if liquid then
if paint.liquid then
dc:newline(1):string("Amount: "..self.amount)
dc:advance(1):string("("):string("-+", COLOR_LIGHTGREEN):string(")")
dc:newline(3):string("s", COLOR_LIGHTGREEN):string(": ")
@ -133,8 +184,15 @@ function LiquidsUI:onRenderBody(dc)
dc:advance(0,2)
end
dc:newline():newline(1):string("f", COLOR_LIGHTGREEN):string(": ")
self.flow:render(dc)
dc:newline()
if paint.flow then
dc:newline(1):string("f", COLOR_LIGHTGREEN):string(": ")
self.flow:render(dc)
dc:newline(1):string("r", COLOR_LIGHTGREEN):string(": ")
self.permaflow:render(dc)
else
dc:advance(0,2)
end
dc:newline():newline(1):pen(COLOR_WHITE)
dc:string("Esc", COLOR_LIGHTGREEN):string(": Back, ")
@ -142,7 +200,8 @@ function LiquidsUI:onRenderBody(dc)
end
function LiquidsUI:onInput(keys)
local liquid = self.paint:get().liquid
local paint = self.paint:get()
local liquid = paint.liquid
if keys.CUSTOM_B then
self.brush:step()
elseif keys.CUSTOM_P then
@ -153,8 +212,10 @@ function LiquidsUI:onInput(keys)
self.amount = math.min(7, self.amount+1)
elseif liquid and keys.CUSTOM_S then
self.set:step()
elseif keys.CUSTOM_F then
elseif paint.flow and keys.CUSTOM_F then
self.flow:step()
elseif paint.flow and keys.CUSTOM_R then
self.permaflow:step()
elseif keys.LEAVESCREEN then
if guidm.getSelection() then
guidm.clearSelection()
@ -182,7 +243,8 @@ function LiquidsUI:onInput(keys)
cursor,
self.brush:get().tag, self.paint:get().tag,
self.amount, size,
self.set:get().tag, self.flow:get().tag
self.set:get().tag, self.flow:get().tag,
self.permaflow:get().tag
)
elseif self:propagateMoveKeys(keys) then
return