#include "Core.h" #include "DataDefs.h" #include "Export.h" #include "PluginManager.h" #include "modules/EventManager.h" #include "modules/MapCache.h" #include "modules/Maps.h" #include "df/coord.h" #include "df/global_objects.h" #include "df/job.h" #include "df/map_block.h" #include "df/tile_dig_designation.h" #include "df/world.h" #include #include #include using namespace DFHack; using namespace std; DFHACK_PLUGIN("digFlood"); REQUIRE_GLOBAL(world); command_result digFlood (color_ostream &out, std::vector & parameters); void onDig(color_ostream& out, void* ptr); void maybeExplore(color_ostream& out, MapExtras::MapCache& cache, df::coord pt, set& jobLocations); EventManager::EventHandler digHandler(onDig, 0); //bool enabled = false; DFHACK_PLUGIN_IS_ENABLED(enabled); bool digAll = false; set autodigMaterials; DFhackCExport command_result plugin_enable(color_ostream& out, bool enable) { if (enabled == enable) return CR_OK; enabled = enable; if ( enabled ) { EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, digHandler, plugin_self); } else { EventManager::unregisterAll(plugin_self); } return CR_OK; } DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.push_back(PluginCommand( "digFlood", "Automatically dig out veins as you discover them.", digFlood)); return CR_OK; } void onDig(color_ostream& out, void* ptr) { CoreSuspender bob; df::job* job = (df::job*)ptr; if ( job->completion_timer > 0 ) return; if ( job->job_type != df::enums::job_type::Dig && job->job_type != df::enums::job_type::CarveUpwardStaircase && job->job_type != df::enums::job_type::CarveDownwardStaircase && job->job_type != df::enums::job_type::CarveUpDownStaircase && job->job_type != df::enums::job_type::CarveRamp && job->job_type != df::enums::job_type::DigChannel ) return; set jobLocations; for ( df::job_list_link* link = &world->jobs.list; link != NULL; link = link->next ) { if ( link->item == NULL ) continue; if ( link->item->job_type != df::enums::job_type::Dig && link->item->job_type != df::enums::job_type::CarveUpwardStaircase && link->item->job_type != df::enums::job_type::CarveDownwardStaircase && link->item->job_type != df::enums::job_type::CarveUpDownStaircase && link->item->job_type != df::enums::job_type::CarveRamp && link->item->job_type != df::enums::job_type::DigChannel ) continue; jobLocations.insert(link->item->pos); } MapExtras::MapCache cache; df::coord pos = job->pos; for ( int16_t a = -1; a <= 1; a++ ) { for ( int16_t b = -1; b <= 1; b++ ) { maybeExplore(out, cache, df::coord(pos.x+a,pos.y+b,pos.z), jobLocations); } } cache.trash(); } void maybeExplore(color_ostream& out, MapExtras::MapCache& cache, df::coord pt, set& jobLocations) { if ( !Maps::isValidTilePos(pt) ) { return; } df::map_block* block = Maps::getTileBlock(pt); if (!block) return; if ( block->designation[pt.x&0xF][pt.y&0xF].bits.hidden ) return; df::tiletype type = block->tiletype[pt.x&0xF][pt.y&0xF]; if ( ENUM_ATTR(tiletype, material, type) != df::enums::tiletype_material::MINERAL ) return; if ( ENUM_ATTR(tiletype, shape, type) != df::enums::tiletype_shape::WALL ) return; if ( block->designation[pt.x&0xF][pt.y&0xF].bits.dig != df::enums::tile_dig_designation::No ) return; uint32_t xMax,yMax,zMax; Maps::getSize(xMax,yMax,zMax); if ( pt.x == 0 || pt.y == 0 || pt.x+1 == int32_t(xMax)*16 || pt.y+1 == int32_t(yMax)*16 ) return; if ( jobLocations.find(pt) != jobLocations.end() ) { return; } int16_t mat = cache.veinMaterialAt(pt); if ( mat == -1 ) return; if ( !digAll ) { df::inorganic_raw* inorganic = world->raws.inorganics[mat]; if ( autodigMaterials.find(inorganic->id) == autodigMaterials.end() ) { return; } } block->designation[pt.x&0xF][pt.y&0xF].bits.dig = df::enums::tile_dig_designation::Default; block->flags.bits.designated = true; // *process_dig = true; // *process_jobs = true; } command_result digFlood (color_ostream &out, std::vector & parameters) { bool adding = true; set toAdd, toRemove; for ( size_t a = 0; a < parameters.size(); a++ ) { int32_t i = (int32_t)strtol(parameters[a].c_str(), NULL, 0); if ( i == 0 && parameters[a] == "0" ) { plugin_enable(out, false); adding = false; continue; } else if ( i == 1 ) { plugin_enable(out, true); adding = true; continue; } if ( parameters[a] == "CLEAR" ) { autodigMaterials.clear(); continue; } if ( parameters[a] == "digAll0" ) { digAll = false; continue; } if ( parameters[a] == "digAll1" ) { digAll = true; continue; } for ( size_t b = 0; b < world->raws.inorganics.size(); b++ ) { df::inorganic_raw* inorganic = world->raws.inorganics[b]; if ( parameters[a] == inorganic->id ) { if ( adding ) toAdd.insert(parameters[a]); else toRemove.insert(parameters[a]); goto loop; } } out.print("Could not find material \"%s\".\n", parameters[a].c_str()); return CR_WRONG_USAGE; loop: continue; } autodigMaterials.insert(toAdd.begin(), toAdd.end()); for ( auto a = toRemove.begin(); a != toRemove.end(); a++ ) autodigMaterials.erase(*a); return CR_OK; }