Merge branch 'develop' into myk_pause_forced
commit
7fbd95896d
Binary file not shown.
After Width: | Height: | Size: 639 B |
@ -0,0 +1,67 @@
|
|||||||
|
local _ENV = mkmodule('plugins.seedwatch')
|
||||||
|
|
||||||
|
local argparse = require('argparse')
|
||||||
|
|
||||||
|
local function process_args(opts, args)
|
||||||
|
if args[1] == 'help' then
|
||||||
|
opts.help = true
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
return argparse.processArgsGetopt(args, {
|
||||||
|
{'h', 'help', handler=function() opts.help = true end},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
local function print_status()
|
||||||
|
print(('seedwatch is %s'):format(isEnabled() and "enabled" or "disabled"))
|
||||||
|
print()
|
||||||
|
print('usable seed counts and current targets:')
|
||||||
|
local watch_map, seed_counts = seedwatch_getData()
|
||||||
|
local sum = 0
|
||||||
|
local plants = df.global.world.raws.plants.all
|
||||||
|
for k,v in pairs(seed_counts) do
|
||||||
|
print((' %4d/%d %s'):format(v, watch_map[k] or 0, plants[k].id))
|
||||||
|
sum = sum + v
|
||||||
|
end
|
||||||
|
print()
|
||||||
|
print(('total usable seeds: %d'):format(sum))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function set_target(name, num)
|
||||||
|
if not name or #name == 0 then
|
||||||
|
qerror('must specify "all" or plant name')
|
||||||
|
end
|
||||||
|
|
||||||
|
num = tonumber(num)
|
||||||
|
num = num and math.floor(num) or nil
|
||||||
|
if not num or num < 0 then
|
||||||
|
qerror('target must be a non-negative integer')
|
||||||
|
end
|
||||||
|
|
||||||
|
seedwatch_setTarget(name, num)
|
||||||
|
end
|
||||||
|
|
||||||
|
function parse_commandline(...)
|
||||||
|
local args, opts = {...}, {}
|
||||||
|
local positionals = process_args(opts, args)
|
||||||
|
|
||||||
|
if opts.help then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local command = positionals[1]
|
||||||
|
if not command or command == 'status' then
|
||||||
|
print_status()
|
||||||
|
elseif command == 'clear' then
|
||||||
|
set_target('all', 0)
|
||||||
|
elseif positionals[2] and positionals[3] then
|
||||||
|
set_target(positionals[2], positionals[3])
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return _ENV
|
@ -1,120 +1,153 @@
|
|||||||
#include "Core.h"
|
#include "Debug.h"
|
||||||
#include "Console.h"
|
|
||||||
#include "Export.h"
|
|
||||||
#include "PluginManager.h"
|
#include "PluginManager.h"
|
||||||
|
|
||||||
#include "DataDefs.h"
|
#include "modules/Persistence.h"
|
||||||
|
#include "modules/World.h"
|
||||||
|
|
||||||
#include "df/world.h"
|
#include "df/world.h"
|
||||||
#include "df/plotinfost.h"
|
|
||||||
#include "df/building_nest_boxst.h"
|
#include "df/building_nest_boxst.h"
|
||||||
#include "df/building_type.h"
|
|
||||||
#include "df/buildings_other_id.h"
|
|
||||||
#include "df/global_objects.h"
|
|
||||||
#include "df/item.h"
|
#include "df/item.h"
|
||||||
#include "df/unit.h"
|
#include "df/unit.h"
|
||||||
#include "df/building.h"
|
|
||||||
#include "df/items_other_id.h"
|
|
||||||
#include "df/creature_raw.h"
|
|
||||||
#include "modules/MapCache.h"
|
|
||||||
#include "modules/Items.h"
|
|
||||||
|
|
||||||
|
|
||||||
using std::vector;
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::endl;
|
|
||||||
using namespace DFHack;
|
using namespace DFHack;
|
||||||
using namespace df::enums;
|
using namespace df::enums;
|
||||||
|
|
||||||
using df::global::world;
|
DFHACK_PLUGIN("nestboxes");
|
||||||
using df::global::plotinfo;
|
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
|
||||||
|
|
||||||
static command_result nestboxes(color_ostream &out, vector <string> & parameters);
|
REQUIRE_GLOBAL(world);
|
||||||
|
|
||||||
DFHACK_PLUGIN("nestboxes");
|
namespace DFHack {
|
||||||
|
// for configuration-related logging
|
||||||
|
DBG_DECLARE(nestboxes, config, DebugCategory::LINFO);
|
||||||
|
// for logging during the periodic scan
|
||||||
|
DBG_DECLARE(nestboxes, cycle, DebugCategory::LINFO);
|
||||||
|
}
|
||||||
|
|
||||||
DFHACK_PLUGIN_IS_ENABLED(enabled);
|
static const string CONFIG_KEY = string(plugin_name) + "/config";
|
||||||
|
static PersistentDataItem config;
|
||||||
|
|
||||||
static void eggscan(color_ostream &out)
|
enum ConfigValues {
|
||||||
{
|
CONFIG_IS_ENABLED = 0,
|
||||||
CoreSuspender suspend;
|
};
|
||||||
|
|
||||||
for (df::building *build : world->buildings.other[df::buildings_other_id::NEST_BOX])
|
static int get_config_val(PersistentDataItem &c, int index) {
|
||||||
{
|
if (!c.isValid())
|
||||||
auto type = build->getType();
|
return -1;
|
||||||
if (df::enums::building_type::NestBox == type)
|
return c.ival(index);
|
||||||
{
|
|
||||||
bool fertile = false;
|
|
||||||
df::building_nest_boxst *nb = virtual_cast<df::building_nest_boxst>(build);
|
|
||||||
if (nb->claimed_by != -1)
|
|
||||||
{
|
|
||||||
df::unit* u = df::unit::find(nb->claimed_by);
|
|
||||||
if (u && u->pregnancy_timer > 0)
|
|
||||||
fertile = true;
|
|
||||||
}
|
|
||||||
for (size_t j = 1; j < nb->contained_items.size(); j++)
|
|
||||||
{
|
|
||||||
df::item* item = nb->contained_items[j]->item;
|
|
||||||
if (item->flags.bits.forbid != fertile)
|
|
||||||
{
|
|
||||||
item->flags.bits.forbid = fertile;
|
|
||||||
out << item->getStackSize() << " eggs " << (fertile ? "forbidden" : "unforbidden.") << endl;
|
|
||||||
}
|
}
|
||||||
|
static bool get_config_bool(PersistentDataItem &c, int index) {
|
||||||
|
return get_config_val(c, index) == 1;
|
||||||
}
|
}
|
||||||
|
static void set_config_val(PersistentDataItem &c, int index, int value) {
|
||||||
|
if (c.isValid())
|
||||||
|
c.ival(index) = value;
|
||||||
}
|
}
|
||||||
|
static void set_config_bool(PersistentDataItem &c, int index, bool value) {
|
||||||
|
set_config_val(c, index, value ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const int32_t CYCLE_TICKS = 100; // need to react quickly if eggs are unforbidden
|
||||||
|
static int32_t cycle_timestamp = 0; // world->frame_counter at last cycle
|
||||||
|
|
||||||
|
static void do_cycle(color_ostream &out, int32_t *num_enabled_seeds, int32_t *num_disabled_seeds);
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_init(color_ostream &out, std::vector <PluginCommand> &commands) {
|
||||||
|
DEBUG(config,out).print("initializing %s\n", plugin_name);
|
||||||
|
|
||||||
|
return CR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) {
|
||||||
|
if (!Core::getInstance().isWorldLoaded()) {
|
||||||
|
out.printerr("Cannot enable %s without a loaded world.\n", plugin_name);
|
||||||
|
return CR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands)
|
if (enable != is_enabled) {
|
||||||
{
|
is_enabled = enable;
|
||||||
if (world && plotinfo) {
|
DEBUG(config,out).print("%s from the API; persisting\n",
|
||||||
commands.push_back(
|
is_enabled ? "enabled" : "disabled");
|
||||||
PluginCommand(
|
set_config_bool(config, CONFIG_IS_ENABLED, is_enabled);
|
||||||
"nestboxes",
|
} else {
|
||||||
"Protect fertile eggs incubating in a nestbox.",
|
DEBUG(config,out).print("%s from the API, but already %s; no action\n",
|
||||||
nestboxes));
|
is_enabled ? "enabled" : "disabled",
|
||||||
|
is_enabled ? "enabled" : "disabled");
|
||||||
}
|
}
|
||||||
return CR_OK;
|
return CR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
DFhackCExport command_result plugin_shutdown ( color_ostream &out )
|
DFhackCExport command_result plugin_shutdown (color_ostream &out) {
|
||||||
{
|
DEBUG(config,out).print("shutting down %s\n", plugin_name);
|
||||||
|
|
||||||
return CR_OK;
|
return CR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
DFhackCExport command_result plugin_onupdate(color_ostream &out)
|
DFhackCExport command_result plugin_load_data (color_ostream &out) {
|
||||||
{
|
config = World::GetPersistentData(CONFIG_KEY);
|
||||||
if (!enabled)
|
|
||||||
return CR_OK;
|
|
||||||
|
|
||||||
static unsigned cnt = 0;
|
if (!config.isValid()) {
|
||||||
if ((++cnt % 5) != 0)
|
DEBUG(config,out).print("no config found in this save; initializing\n");
|
||||||
return CR_OK;
|
config = World::AddPersistentData(CONFIG_KEY);
|
||||||
|
set_config_bool(config, CONFIG_IS_ENABLED, is_enabled);
|
||||||
|
}
|
||||||
|
|
||||||
eggscan(out);
|
is_enabled = get_config_bool(config, CONFIG_IS_ENABLED);
|
||||||
|
DEBUG(config,out).print("loading persisted enabled state: %s\n",
|
||||||
|
is_enabled ? "true" : "false");
|
||||||
|
|
||||||
return CR_OK;
|
return CR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
DFhackCExport command_result plugin_enable(color_ostream &out, bool enable)
|
DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event) {
|
||||||
{
|
if (event == DFHack::SC_WORLD_UNLOADED) {
|
||||||
enabled = enable;
|
if (is_enabled) {
|
||||||
|
DEBUG(config,out).print("world unloaded; disabling %s\n",
|
||||||
|
plugin_name);
|
||||||
|
is_enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
return CR_OK;
|
return CR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static command_result nestboxes(color_ostream &out, vector <string> & parameters)
|
DFhackCExport command_result plugin_onupdate(color_ostream &out) {
|
||||||
{
|
if (is_enabled && world->frame_counter - cycle_timestamp >= CYCLE_TICKS) {
|
||||||
CoreSuspender suspend;
|
int32_t num_enabled_seeds, num_disabled_seeds;
|
||||||
|
do_cycle(out, &num_enabled_seeds, &num_disabled_seeds);
|
||||||
if (parameters.size() == 1) {
|
if (0 < num_enabled_seeds)
|
||||||
if (parameters[0] == "enable")
|
out.print("%s: enabled %d seed types for cooking\n",
|
||||||
enabled = true;
|
plugin_name, num_enabled_seeds);
|
||||||
else if (parameters[0] == "disable")
|
if (0 < num_disabled_seeds)
|
||||||
enabled = false;
|
out.print("%s: protected %d seed types from cooking\n",
|
||||||
else
|
plugin_name, num_disabled_seeds);
|
||||||
return CR_WRONG_USAGE;
|
|
||||||
} else {
|
|
||||||
out << "Plugin " << (enabled ? "enabled" : "disabled") << "." << endl;
|
|
||||||
}
|
}
|
||||||
return CR_OK;
|
return CR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////
|
||||||
|
// cycle logic
|
||||||
|
//
|
||||||
|
|
||||||
|
static void do_cycle(color_ostream &out, int32_t *num_enabled_seed_types, int32_t *num_disabled_seed_types) {
|
||||||
|
DEBUG(cycle,out).print("running %s cycle\n", plugin_name);
|
||||||
|
|
||||||
|
// mark that we have recently run
|
||||||
|
cycle_timestamp = world->frame_counter;
|
||||||
|
|
||||||
|
for (df::building_nest_boxst *nb : world->buildings.other.NEST_BOX) {
|
||||||
|
bool fertile = false;
|
||||||
|
if (nb->claimed_by != -1) {
|
||||||
|
df::unit *u = df::unit::find(nb->claimed_by);
|
||||||
|
if (u && u->pregnancy_timer > 0)
|
||||||
|
fertile = true;
|
||||||
|
}
|
||||||
|
for (auto &contained_item : nb->contained_items) {
|
||||||
|
df::item *item = contained_item->item;
|
||||||
|
if (item->flags.bits.forbid != fertile) {
|
||||||
|
item->flags.bits.forbid = fertile;
|
||||||
|
out.print("%d eggs %s.\n", item->getStackSize(), fertile ? "forbidden" : "unforbidden");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue