From 757491f1120655e0d7473f77a0b49c67fff9049e Mon Sep 17 00:00:00 2001
From: Anuradha Dissanayake
Date: Wed, 4 Jun 2014 22:12:30 +1200
Subject: [PATCH 1/4] Add automelt plugin
---
NEWS | 3 +
Readme.rst | 9 ++
plugins/CMakeLists.txt | 1 +
plugins/automelt.cpp | 282 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 295 insertions(+)
create mode 100644 plugins/automelt.cpp
diff --git a/NEWS b/NEWS
index 3c53c5b5f..1501157a4 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,8 @@
DFHack future
+ New plugins:
+ - automelt: allows marking stockpiles for automelt (i.e. any items placed in stocpile will be designated for melting)
+
DFHack 0.40.11-r1
Internals:
diff --git a/Readme.rst b/Readme.rst
index 570910576..cafe22069 100644
--- a/Readme.rst
+++ b/Readme.rst
@@ -2646,6 +2646,15 @@ toggle this option on, instead of returning you to the main construction menu af
materials, it returns you back to this screen. If you use this along with several autoselect
enabled materials, you should be able to place complex constructions more conveniently.
+Stockpile Automation
+====================
+Enable the automelt plugin in your dfhack.init with
+ ``enable automelt``
+
+When querying a stockpile an option will appear to toggle automelt for this stockpile.
+Any items placed in this stockpile will be designated to be melted.
+
+
gui/advfort
===========
diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt
index 823b9aa75..ad4dc5674 100644
--- a/plugins/CMakeLists.txt
+++ b/plugins/CMakeLists.txt
@@ -89,6 +89,7 @@ if (BUILD_SUPPORTED)
DFHACK_PLUGIN(autodump autodump.cpp)
DFHACK_PLUGIN(autolabor autolabor.cpp)
DFHACK_PLUGIN(automaterial automaterial.cpp)
+ DFHACK_PLUGIN(automelt automelt.cpp)
DFHACK_PLUGIN(autotrade autotrade.cpp)
DFHACK_PLUGIN(burrows burrows.cpp LINK_LIBRARIES lua)
DFHACK_PLUGIN(building-hacks building-hacks.cpp LINK_LIBRARIES lua)
diff --git a/plugins/automelt.cpp b/plugins/automelt.cpp
new file mode 100644
index 000000000..0c6a7b33f
--- /dev/null
+++ b/plugins/automelt.cpp
@@ -0,0 +1,282 @@
+#include "uicommon.h"
+
+#include "modules/Gui.h"
+
+#include "df/world.h"
+#include "df/world_raws.h"
+#include "df/building_def.h"
+#include "df/viewscreen_dwarfmodest.h"
+#include "df/building_stockpilest.h"
+#include "modules/Items.h"
+#include "df/ui.h"
+#include "modules/Maps.h"
+#include "modules/World.h"
+#include "df/item_quality.h"
+
+using df::global::world;
+using df::global::cursor;
+using df::global::ui;
+using df::building_stockpilest;
+
+DFHACK_PLUGIN("automelt");
+#define PLUGIN_VERSION 0.3
+
+static const string PERSISTENCE_KEY = "automelt/stockpiles";
+
+static void mark_all_in_stockpiles(vector &stockpiles)
+{
+ std::vector &items = world->items.other[items_other_id::IN_PLAY];
+
+ // Precompute a bitmask with the bad flags
+ df::item_flags bad_flags;
+ bad_flags.whole = 0;
+
+#define F(x) bad_flags.bits.x = true;
+ F(dump); F(forbid); F(garbage_collect);
+ F(hostile); F(on_fire); F(rotten); F(trader);
+ F(in_building); F(construction); F(artifact);
+ F(spider_web); F(owned); F(in_job);
+#undef F
+
+ size_t marked_count = 0;
+ for (size_t i = 0; i < items.size(); i++)
+ {
+ df::item *item = items[i];
+ if (item->flags.whole & bad_flags.whole)
+ continue;
+
+ if (!can_melt(item))
+ continue;
+
+ if (is_set_to_melt(item))
+ continue;
+
+ auto &melting_items = world->items.other[items_other_id::ANY_MELT_DESIGNATED];
+ for (auto it = stockpiles.begin(); it != stockpiles.end(); it++)
+ {
+ if (!it->inStockpile(item))
+ continue;
+
+ ++marked_count;
+ insert_into_vector(melting_items, &df::item::id, item);
+ item->flags.bits.melt = true;
+ }
+ }
+
+ if (marked_count)
+ Gui::showAnnouncement("Marked " + int_to_string(marked_count) + " items to melt", COLOR_GREEN, false);
+}
+
+/*
+ * Stockpile Monitoring
+ */
+
+class StockpileMonitor
+{
+public:
+ bool isMonitored(df::building_stockpilest *sp)
+ {
+ for (auto it = monitored_stockpiles.begin(); it != monitored_stockpiles.end(); it++)
+ {
+ if (it->matches(sp))
+ return true;
+ }
+
+ return false;
+ }
+
+ void add(df::building_stockpilest *sp)
+ {
+ auto pile = PersistentStockpileInfo(sp, PERSISTENCE_KEY);
+ if (pile.isValid())
+ {
+ monitored_stockpiles.push_back(PersistentStockpileInfo(pile));
+ monitored_stockpiles.back().save();
+ }
+ }
+
+ void remove(df::building_stockpilest *sp)
+ {
+ for (auto it = monitored_stockpiles.begin(); it != monitored_stockpiles.end(); it++)
+ {
+ if (it->matches(sp))
+ {
+ it->remove();
+ monitored_stockpiles.erase(it);
+ break;
+ }
+ }
+ }
+
+ void doCycle()
+ {
+ for (auto it = monitored_stockpiles.begin(); it != monitored_stockpiles.end();)
+ {
+ if (!it->isValid())
+ it = monitored_stockpiles.erase(it);
+ else
+ ++it;
+ }
+
+ mark_all_in_stockpiles(monitored_stockpiles);
+ }
+
+ void reset()
+ {
+ monitored_stockpiles.clear();
+ std::vector items;
+ DFHack::World::GetPersistentData(&items, PERSISTENCE_KEY);
+
+ for (auto i = items.begin(); i != items.end(); i++)
+ {
+ auto pile = PersistentStockpileInfo(*i, PERSISTENCE_KEY);
+ if (pile.load())
+ monitored_stockpiles.push_back(PersistentStockpileInfo(pile));
+ else
+ pile.remove();
+ }
+ }
+
+
+private:
+ vector monitored_stockpiles;
+};
+
+static StockpileMonitor monitor;
+
+#define DELTA_TICKS 610
+
+DFhackCExport command_result plugin_onupdate ( color_ostream &out )
+{
+ if(!Maps::IsValid())
+ return CR_OK;
+
+ static decltype(world->frame_counter) last_frame_count = 0;
+
+ if (DFHack::World::ReadPauseState())
+ return CR_OK;
+
+ if (world->frame_counter - last_frame_count < DELTA_TICKS)
+ return CR_OK;
+
+ last_frame_count = world->frame_counter;
+
+ monitor.doCycle();
+
+ return CR_OK;
+}
+
+
+/*
+ * Interface
+ */
+
+struct melt_hook : public df::viewscreen_dwarfmodest
+{
+ typedef df::viewscreen_dwarfmodest interpose_base;
+
+ bool handleInput(set *input)
+ {
+ building_stockpilest *sp = get_selected_stockpile();
+ if (!sp)
+ return false;
+
+ if (input->count(interface_key::CUSTOM_SHIFT_M))
+ {
+ if (monitor.isMonitored(sp))
+ monitor.remove(sp);
+ else
+ monitor.add(sp);
+ }
+
+ return false;
+ }
+
+ DEFINE_VMETHOD_INTERPOSE(void, feed, (set *input))
+ {
+ if (!handleInput(input))
+ INTERPOSE_NEXT(feed)(input);
+ }
+
+ DEFINE_VMETHOD_INTERPOSE(void, render, ())
+ {
+ INTERPOSE_NEXT(render)();
+
+ building_stockpilest *sp = get_selected_stockpile();
+ if (!sp)
+ return;
+
+ auto dims = Gui::getDwarfmodeViewDims();
+ int left_margin = dims.menu_x1 + 1;
+ int x = left_margin;
+ int y = 25;
+
+ OutputToggleString(x, y, "Auto melt", "Shift-M", monitor.isMonitored(sp), true, left_margin);
+ }
+};
+
+IMPLEMENT_VMETHOD_INTERPOSE(melt_hook, feed);
+IMPLEMENT_VMETHOD_INTERPOSE(melt_hook, render);
+
+
+static command_result automelt_cmd(color_ostream &out, vector & parameters)
+{
+ if (!parameters.empty())
+ {
+ if (parameters.size() == 1 && toLower(parameters[0])[0] == 'v')
+ {
+ out << "Automelt" << endl << "Version: " << PLUGIN_VERSION << endl;
+ }
+ }
+
+ return CR_OK;
+}
+
+DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event)
+{
+ switch (event)
+ {
+ case DFHack::SC_MAP_LOADED:
+ monitor.reset();
+ break;
+ case DFHack::SC_MAP_UNLOADED:
+ break;
+ default:
+ break;
+ }
+ return CR_OK;
+}
+
+DFHACK_PLUGIN_IS_ENABLED(is_enabled);
+
+DFhackCExport command_result plugin_enable(color_ostream &out, bool enable)
+{
+ if (!gps)
+ return CR_FAILURE;
+
+ if (enable != is_enabled)
+ {
+ if (!INTERPOSE_HOOK(melt_hook, feed).apply(enable) ||
+ !INTERPOSE_HOOK(melt_hook, render).apply(enable))
+ return CR_FAILURE;
+
+ is_enabled = enable;
+ }
+
+ return CR_OK;
+}
+
+DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands)
+{
+ commands.push_back(
+ PluginCommand(
+ "automelt", "Automatically flag metal items in marked stockpiles for melting.",
+ automelt_cmd, false, ""));
+
+ return CR_OK;
+}
+
+DFhackCExport command_result plugin_shutdown ( color_ostream &out )
+{
+ return CR_OK;
+}
From 60d126379a94b6dcfa626063816fc3e0155f3dcc Mon Sep 17 00:00:00 2001
From: Eric Wald
Date: Tue, 9 Sep 2014 20:36:48 -0600
Subject: [PATCH 2/4] Automelt documentation updates.
---
Readme.html | 10 ++++++++++
Readme.rst | 5 +++--
dfhack.init-example | 2 +-
3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/Readme.html b/Readme.html
index ca3194d6c..7d30a4b82 100644
--- a/Readme.html
+++ b/Readme.html
@@ -528,6 +528,7 @@ access DF memory and allow for easier development of new tools.
Dwarf Manipulator
Search
AutoMaterial
+Stockpile Automation
gui/advfort
gui/assign-rack
gui/choose-weapons
@@ -3264,6 +3265,15 @@ toggle this option on, instead of returning you to the main construction menu af
materials, it returns you back to this screen. If you use this along with several autoselect
enabled materials, you should be able to place complex constructions more conveniently.
+
+
+
Enable the automelt plugin in your dfhack.init with:
+
+enable automelt
+
+
When querying a stockpile an option will appear to toggle automelt for this stockpile.
+Any items placed in this stockpile will be designated to be melted.
+
This script allows to perform jobs in adventure mode. For more complete help
diff --git a/Readme.rst b/Readme.rst
index cafe22069..250bad89d 100644
--- a/Readme.rst
+++ b/Readme.rst
@@ -2648,8 +2648,9 @@ enabled materials, you should be able to place complex constructions more conven
Stockpile Automation
====================
-Enable the automelt plugin in your dfhack.init with
- ``enable automelt``
+Enable the automelt plugin in your dfhack.init with::
+
+ enable automelt
When querying a stockpile an option will appear to toggle automelt for this stockpile.
Any items placed in this stockpile will be designated to be melted.
diff --git a/dfhack.init-example b/dfhack.init-example
index 891fbfa81..f5ac6a016 100644
--- a/dfhack.init-example
+++ b/dfhack.init-example
@@ -170,7 +170,7 @@ enable search
enable automaterial
# Other interface improvement tools
-#enable dwarfmonitor mousequery autotrade buildingplan resume zone
+#enable dwarfmonitor mousequery automelt autotrade buildingplan resume zone
# allow the fortress bookkeeper to queue jobs through the manager
stockflow enable
From 8bc2f02aee2becd601b84b819b0f08d10ae118c7 Mon Sep 17 00:00:00 2001
From: Eric Wald
Date: Tue, 9 Sep 2014 20:51:58 -0600
Subject: [PATCH 3/4] Moving the automelt hotkey next to autotrade.
---
plugins/automelt.cpp | 4 ++--
plugins/autotrade.cpp | 4 ++--
plugins/stocks.cpp | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/plugins/automelt.cpp b/plugins/automelt.cpp
index 0c6a7b33f..0fac4ed86 100644
--- a/plugins/automelt.cpp
+++ b/plugins/automelt.cpp
@@ -209,9 +209,9 @@ struct melt_hook : public df::viewscreen_dwarfmodest
auto dims = Gui::getDwarfmodeViewDims();
int left_margin = dims.menu_x1 + 1;
int x = left_margin;
- int y = 25;
+ int y = dims.y2 - 6;
- OutputToggleString(x, y, "Auto melt", "Shift-M", monitor.isMonitored(sp), true, left_margin);
+ OutputToggleString(x, y, "Auto melt", "M", monitor.isMonitored(sp), true, left_margin, COLOR_WHITE, COLOR_LIGHTRED);
}
};
diff --git a/plugins/autotrade.cpp b/plugins/autotrade.cpp
index 6e60d35d1..3194dd0d6 100644
--- a/plugins/autotrade.cpp
+++ b/plugins/autotrade.cpp
@@ -421,7 +421,7 @@ struct trade_hook : public df::viewscreen_dwarfmodest
auto dims = Gui::getDwarfmodeViewDims();
int left_margin = dims.menu_x1 + 1;
int x = left_margin;
- int y = dims.y2 - 4;
+ int y = dims.y2 - 5;
int links = 0;
links += sp->links.give_to_pile.size();
@@ -429,7 +429,7 @@ struct trade_hook : public df::viewscreen_dwarfmodest
links += sp->links.give_to_workshop.size();
links += sp->links.take_from_workshop.size();
if (links + 12 >= y)
- y += 4;
+ y += 5;
OutputToggleString(x, y, "Auto trade", "T", monitor.isMonitored(sp), true, left_margin, COLOR_WHITE, COLOR_LIGHTRED);
}
diff --git a/plugins/stocks.cpp b/plugins/stocks.cpp
index 64e4d4dba..44332a118 100644
--- a/plugins/stocks.cpp
+++ b/plugins/stocks.cpp
@@ -1376,7 +1376,7 @@ struct stocks_stockpile_hook : public df::viewscreen_dwarfmodest
auto dims = Gui::getDwarfmodeViewDims();
int left_margin = dims.menu_x1 + 1;
int x = left_margin;
- int y = dims.y2 - 5;
+ int y = dims.y2 - 4;
int links = 0;
links += sp->links.give_to_pile.size();
From e76b8c4b6b4027670002cebce966b497e236ffeb Mon Sep 17 00:00:00 2001
From: Eric Wald
Date: Tue, 9 Sep 2014 21:08:38 -0600
Subject: [PATCH 4/4] Merging automelt hotkey into autotrade line when links
intrude.
The new interface looks significantly different, but only when there are too many stockpile links to show the lines in their usual places.
The difference between bright green and grey should be obvious most of the time, right?
---
plugins/automelt.cpp | 18 ++++++++++++++++--
plugins/autotrade.cpp | 13 ++++++++++---
2 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/plugins/automelt.cpp b/plugins/automelt.cpp
index 0fac4ed86..58cbdd20c 100644
--- a/plugins/automelt.cpp
+++ b/plugins/automelt.cpp
@@ -210,8 +210,22 @@ struct melt_hook : public df::viewscreen_dwarfmodest
int left_margin = dims.menu_x1 + 1;
int x = left_margin;
int y = dims.y2 - 6;
-
- OutputToggleString(x, y, "Auto melt", "M", monitor.isMonitored(sp), true, left_margin, COLOR_WHITE, COLOR_LIGHTRED);
+
+ int links = 0;
+ links += sp->links.give_to_pile.size();
+ links += sp->links.take_from_pile.size();
+ links += sp->links.give_to_workshop.size();
+ links += sp->links.take_from_workshop.size();
+ bool state = monitor.isMonitored(sp);
+
+ if (links + 12 >= y) {
+ y = dims.y2;
+ OutputString(COLOR_WHITE, x, y, "Auto: ");
+ OutputString(COLOR_LIGHTRED, x, y, "M");
+ OutputString(state? COLOR_LIGHTGREEN: COLOR_GREY, x, y, "elt ");
+ } else {
+ OutputToggleString(x, y, "Auto melt", "M", state, true, left_margin, COLOR_WHITE, COLOR_LIGHTRED);
+ }
}
};
diff --git a/plugins/autotrade.cpp b/plugins/autotrade.cpp
index 3194dd0d6..da7da3204 100644
--- a/plugins/autotrade.cpp
+++ b/plugins/autotrade.cpp
@@ -428,10 +428,17 @@ struct trade_hook : public df::viewscreen_dwarfmodest
links += sp->links.take_from_pile.size();
links += sp->links.give_to_workshop.size();
links += sp->links.take_from_workshop.size();
- if (links + 12 >= y)
- y += 5;
+ bool state = monitor.isMonitored(sp);
- OutputToggleString(x, y, "Auto trade", "T", monitor.isMonitored(sp), true, left_margin, COLOR_WHITE, COLOR_LIGHTRED);
+ if (links + 12 >= y) {
+ y = dims.y2;
+ OutputString(COLOR_WHITE, x, y, "Auto: ");
+ x += 5;
+ OutputString(COLOR_LIGHTRED, x, y, "T");
+ OutputString(state? COLOR_LIGHTGREEN: COLOR_GREY, x, y, "rade ");
+ } else {
+ OutputToggleString(x, y, "Auto trade", "T", state, true, left_margin, COLOR_WHITE, COLOR_LIGHTRED);
+ }
}
};