Merge branch 'develop' into myk_non_defocusable
						commit
						1debea59a8
					
				
											
												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 { | ||||||
|     CoreSuspender suspend; |     CONFIG_IS_ENABLED = 0, | ||||||
| 
 | }; | ||||||
|     for (df::building *build : world->buildings.other[df::buildings_other_id::NEST_BOX]) | 
 | ||||||
|     { | static int get_config_val(PersistentDataItem &c, int index) { | ||||||
|         auto type = build->getType(); |     if (!c.isValid()) | ||||||
|         if (df::enums::building_type::NestBox == type) |         return -1; | ||||||
|         { |     return c.ival(index); | ||||||
|             bool fertile = false; | } | ||||||
|             df::building_nest_boxst *nb = virtual_cast<df::building_nest_boxst>(build); | static bool get_config_bool(PersistentDataItem &c, int index) { | ||||||
|             if (nb->claimed_by != -1) |     return get_config_val(c, index) == 1; | ||||||
|             { | } | ||||||
|                 df::unit* u = df::unit::find(nb->claimed_by); | static void set_config_val(PersistentDataItem &c, int index, int value) { | ||||||
|                 if (u && u->pregnancy_timer > 0) |     if (c.isValid()) | ||||||
|                     fertile = true; |         c.ival(index) = value; | ||||||
|             } | } | ||||||
|             for (size_t j = 1; j < nb->contained_items.size(); j++) | static void set_config_bool(PersistentDataItem &c, int index, bool value) { | ||||||
|             { |     set_config_val(c, index, value ? 1 : 0); | ||||||
|                 df::item* item = nb->contained_items[j]->item; | } | ||||||
|                 if (item->flags.bits.forbid != fertile) | 
 | ||||||
|                 { | static const int32_t CYCLE_TICKS = 100; // need to react quickly if eggs are unforbidden
 | ||||||
|                     item->flags.bits.forbid = fertile; | static int32_t cycle_timestamp = 0;  // world->frame_counter at last cycle
 | ||||||
|                     out << item->getStackSize() << " eggs " << (fertile ? "forbidden" : "unforbidden.") << endl; | 
 | ||||||
|                 } | 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