summaryrefslogtreecommitdiff
path: root/plugins/devel
diff options
context:
space:
mode:
authorAlexander Gavrilov2012-09-01 17:52:51 +0400
committerAlexander Gavrilov2012-09-01 17:52:51 +0400
commitbae85ac77d977ce543fc2e36f42aed3a10f79a5c (patch)
tree4e15e95c2fc28659476156e9eb5d9b7592c55aea /plugins/devel
parent74501d3197d23c657524204b8f99253f7102f6f3 (diff)
downloaddfhack-bae85ac77d977ce543fc2e36f42aed3a10f79a5c.tar.gz
dfhack-bae85ac77d977ce543fc2e36f42aed3a10f79a5c.tar.bz2
dfhack-bae85ac77d977ce543fc2e36f42aed3a10f79a5c.tar.xz
Make the steam engine consume liquids from Z level below.
Diffstat (limited to 'plugins/devel')
-rw-r--r--plugins/devel/steam-engine.cpp195
1 files changed, 193 insertions, 2 deletions
diff --git a/plugins/devel/steam-engine.cpp b/plugins/devel/steam-engine.cpp
index 6f83c41d..1f45e511 100644
--- a/plugins/devel/steam-engine.cpp
+++ b/plugins/devel/steam-engine.cpp
@@ -4,6 +4,8 @@
#include <PluginManager.h>
#include <modules/Gui.h>
#include <modules/Screen.h>
+#include <modules/Maps.h>
+#include <TileTypes.h>
#include <vector>
#include <cstdio>
#include <stack>
@@ -24,6 +26,9 @@
#include "df/machine.h"
#include "df/job.h"
#include "df/building_drawbuffer.h"
+#include "df/ui.h"
+#include "df/viewscreen_dwarfmodest.h"
+#include "df/ui_build_selector.h"
#include "MiscUtils.h"
@@ -35,6 +40,7 @@ using namespace df::enums;
using df::global::gps;
using df::global::world;
+using df::global::ui;
using df::global::ui_build_selector;
DFHACK_PLUGIN("steam-engine");
@@ -70,6 +76,29 @@ static const int hearth_colors[6][2] = {
{ COLOR_GREY, 1 }
};
+void enable_updates_at(df::coord pos, bool flow, bool temp)
+{
+ static const int delta[4][2] = { { -1, -1 }, { 1, -1 }, { -1, 1 }, { 1, 1 } };
+
+ for (int i = 0; i < 4; i++)
+ {
+ auto blk = Maps::getTileBlock(pos.x+delta[i][0], pos.y+delta[i][1], pos.z);
+ Maps::enableBlockUpdates(blk, flow, temp);
+ }
+}
+
+void decrement_flow(df::coord pos, int amount)
+{
+ auto pldes = Maps::getTileDesignation(pos);
+ if (!pldes) return;
+
+ int nsize = std::max(0, pldes->bits.flow_size - amount);
+ pldes->bits.flow_size = nsize;
+ pldes->bits.flow_forbid = (nsize > 3 || pldes->bits.liquid_type == tile_liquid::Magma);
+
+ enable_updates_at(pos, true, false);
+}
+
struct liquid_hook : df::item_liquid_miscst {
typedef df::item_liquid_miscst interpose_base;
@@ -128,8 +157,65 @@ struct workshop_hook : df::building_workshopst {
flags.whole = (flags.whole & 0x0FFFFFFFU) | uint32_t((count & 15) << 28);
}
- void absorb_unit(steam_engine_workshop *engine, df::item_liquid_miscst *liquid)
+ bool find_liquids(df::coord *pwater, df::coord *pmagma, bool is_magma, bool any_level)
+ {
+ if (!is_magma)
+ pmagma = NULL;
+
+ for (int x = x1; x <= x2; x++)
+ {
+ for (int y = y1; y <= y2; y++)
+ {
+ auto ptile = Maps::getTileType(x,y,z);
+ if (!ptile || !LowPassable(*ptile))
+ continue;
+
+ auto pltile = Maps::getTileType(x,y,z-1);
+ if (!pltile || !FlowPassable(*pltile))
+ continue;
+
+ auto pldes = Maps::getTileDesignation(x,y,z-1);
+ if (!pldes || pldes->bits.flow_size == 0)
+ continue;
+
+ if (pldes->bits.liquid_type == tile_liquid::Magma)
+ {
+ if (!pmagma || (!any_level && pldes->bits.flow_size < 4))
+ continue;
+
+ *pmagma = df::coord(x,y,z-1);
+ if (pwater->isValid())
+ return true;
+ }
+ else
+ {
+ if (!any_level && pldes->bits.flow_size < 3)
+ continue;
+
+ *pwater = df::coord(x,y,z-1);
+ if (!pmagma || pmagma->isValid())
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ bool absorb_unit(steam_engine_workshop *engine, df::item_liquid_miscst *liquid)
{
+ df::coord water, magma;
+
+ if (!find_liquids(&water, &magma, engine->is_magma, true))
+ {
+ liquid->addWear(WEAR_TICKS*4+1, true, false);
+ return false;
+ }
+
+ decrement_flow(water, 1);
+ if (engine->is_magma)
+ decrement_flow(magma, 1);
+
liquid->flags.bits.in_building = true;
liquid->mat_state.whole |= liquid_hook::BOILING_FLAG;
liquid->temperature = liquid->getBoilingPoint()-1;
@@ -138,6 +224,9 @@ struct workshop_hook : df::building_workshopst {
// This affects where the steam appears to come from
if (engine->hearth_tile.isValid())
liquid->pos = df::coord(x1+engine->hearth_tile.x, y1+engine->hearth_tile.y, z);
+
+ enable_updates_at(liquid->pos, false, true);
+ return true;
}
bool boil_unit(df::item_liquid_miscst *liquid)
@@ -178,7 +267,8 @@ struct workshop_hook : df::building_workshopst {
liquid->wear != 0)
continue;
- absorb_unit(engine, liquid);
+ if (!absorb_unit(engine, liquid))
+ continue;
}
if (*count < engine->max_capacity)
@@ -330,6 +420,18 @@ struct workshop_hook : df::building_workshopst {
return INTERPOSE_NEXT(canConnectToMachine)(info);
}
+ // Operation logic
+ DEFINE_VMETHOD_INTERPOSE(bool, isUnpowered, ())
+ {
+ if (auto engine = get_steam_engine())
+ {
+ df::coord water, magma;
+ return !find_liquids(&water, &magma, engine->is_magma, false);
+ }
+
+ return INTERPOSE_NEXT(isUnpowered)();
+ }
+
DEFINE_VMETHOD_INTERPOSE(void, updateAction, ())
{
if (auto engine = get_steam_engine())
@@ -402,6 +504,18 @@ struct workshop_hook : df::building_workshopst {
db->fore[pos.x][pos.y] = hearth_colors[power][0];
db->bright[pos.x][pos.y] = hearth_colors[power][1];
}
+
+ // Set liquid indicator state
+ if (engine->water_tile.isValid() || engine->magma_tile.isValid())
+ {
+ df::coord water, magma;
+ find_liquids(&water, &magma, engine->is_magma, false);
+
+ if (engine->water_tile.isValid() && !water.isValid())
+ db->fore[engine->water_tile.x][engine->water_tile.y] = 0;
+ if (engine->magma_tile.isValid() && engine->is_magma && !magma.isValid())
+ db->fore[engine->magma_tile.x][engine->magma_tile.y] = 0;
+ }
}
}
@@ -421,10 +535,84 @@ IMPLEMENT_VMETHOD_INTERPOSE(workshop_hook, isPowerSource);
IMPLEMENT_VMETHOD_INTERPOSE(workshop_hook, categorize);
IMPLEMENT_VMETHOD_INTERPOSE(workshop_hook, uncategorize);
IMPLEMENT_VMETHOD_INTERPOSE(workshop_hook, canConnectToMachine);
+IMPLEMENT_VMETHOD_INTERPOSE(workshop_hook, isUnpowered);
IMPLEMENT_VMETHOD_INTERPOSE(workshop_hook, updateAction);
IMPLEMENT_VMETHOD_INTERPOSE(workshop_hook, drawBuilding);
IMPLEMENT_VMETHOD_INTERPOSE(workshop_hook, deconstructItems);
+struct dwarfmode_hook : df::viewscreen_dwarfmodest
+{
+ typedef df::viewscreen_dwarfmodest interpose_base;
+
+ steam_engine_workshop *get_steam_engine()
+ {
+ if (ui->main.mode == ui_sidebar_mode::Build &&
+ ui_build_selector->stage == 1 &&
+ ui_build_selector->building_type == building_type::Workshop &&
+ ui_build_selector->building_subtype == workshop_type::Custom)
+ {
+ return find_steam_engine(ui_build_selector->custom_type);
+ }
+
+ return NULL;
+ }
+
+ void check_hanging_tiles(steam_engine_workshop *engine)
+ {
+ using df::global::cursor;
+
+ if (!engine) return;
+
+ bool error = false;
+
+ int x1 = cursor->x - engine->def->workloc_x;
+ int y1 = cursor->y - engine->def->workloc_y;
+
+ for (int x = 0; x < engine->def->dim_x; x++)
+ {
+ for (int y = 0; y < engine->def->dim_y; y++)
+ {
+ if (ui_build_selector->tiles[x][y] >= 5)
+ continue;
+
+ auto ptile = Maps::getTileType(x1+x,y1+y,cursor->z);
+ if (ptile && !isOpenTerrain(*ptile))
+ continue;
+
+ ui_build_selector->tiles[x][y] = 6;
+ error = true;
+ }
+ }
+
+ if (error)
+ {
+ const char *msg = "Hanging - use down stair.";
+ ui_build_selector->errors.push_back(new std::string(msg));
+ }
+ }
+
+ DEFINE_VMETHOD_INTERPOSE(void, feed, (set<df::interface_key> *input))
+ {
+ steam_engine_workshop *engine = get_steam_engine();
+
+ // Selector insists that workshops cannot be placed hanging
+ // unless they require magma, so pretend we always do.
+ if (engine)
+ engine->def->needs_magma = true;
+
+ INTERPOSE_NEXT(feed)(input);
+
+ // Restore the flag
+ if (engine)
+ engine->def->needs_magma = engine->is_magma;
+
+ // And now, check for open space
+ check_hanging_tiles(get_steam_engine());
+ }
+};
+
+IMPLEMENT_VMETHOD_INTERPOSE(dwarfmode_hook, feed);
+
static bool find_engines()
{
engines.clear();
@@ -492,9 +680,12 @@ static void enable_hooks(bool enable)
INTERPOSE_HOOK(workshop_hook, categorize).apply(enable);
INTERPOSE_HOOK(workshop_hook, uncategorize).apply(enable);
INTERPOSE_HOOK(workshop_hook, canConnectToMachine).apply(enable);
+ INTERPOSE_HOOK(workshop_hook, isUnpowered).apply(enable);
INTERPOSE_HOOK(workshop_hook, updateAction).apply(enable);
INTERPOSE_HOOK(workshop_hook, drawBuilding).apply(enable);
INTERPOSE_HOOK(workshop_hook, deconstructItems).apply(enable);
+
+ INTERPOSE_HOOK(dwarfmode_hook, feed).apply(enable);
}
DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event)