diff --git a/library/include/modules/Maps.h b/library/include/modules/Maps.h index 72dd45ea2..16f4e15c9 100644 --- a/library/include/modules/Maps.h +++ b/library/include/modules/Maps.h @@ -321,7 +321,7 @@ extern DFHACK_EXPORT bool SortBlockEvents(uint32_t x, uint32_t y, uint32_t z, extern DFHACK_EXPORT bool RemoveBlockEvent(uint32_t x, uint32_t y, uint32_t z, df::block_square_event * which ); /// read all plants in this block -extern DFHACK_EXPORT bool ReadVegetation(uint32_t x, uint32_t y, uint32_t z, std::vector*& plants); +extern DFHACK_EXPORT bool ReadVegetation(uint32_t x, uint32_t y, uint32_t z, std::vector*& plants); } } diff --git a/library/include/modules/Vegetation.h b/library/include/modules/Vegetation.h index 1e49bd5b2..7169588c0 100644 --- a/library/include/modules/Vegetation.h +++ b/library/include/modules/Vegetation.h @@ -34,48 +34,13 @@ distribution. #include "Module.h" #include "Types.h" #include "DataDefs.h" -#include "df/language_name.h" +#include "df/plant.h" namespace DFHack { /** * \ingroup grp_vegetation */ const uint32_t sapling_to_tree_threshold = 0x1D880; - /** - * \ingroup grp_vegetation - */ - #pragma pack(push, 2) - struct df_plant - { - df::language_name name; - union - { - uint16_t type; - struct - { - bool watery : 1; - bool is_shrub : 1; - }; - }; - uint16_t material; // +0x3E - uint16_t x; // +0x40 - uint16_t y; // +0x42 - uint16_t z; // +0x44 - uint16_t padding; // +0x46 - uint32_t grow_counter; // +0x48 - uint16_t temperature_1; // +0x4C - uint16_t temperature_2; // +0x4E - maybe fraction? - uint32_t is_burning; // 0x50: yes, just one flag - uint32_t hitpoints; // 0x54 - /** - * 0x58 - the updates are staggered into 9? groups. this seems to be what differentiates the plants. - */ - uint16_t update_order; - uint16_t padding2; - // a vector is here - // some more temperature stuff after that - }; - #pragma pack(pop) /** * The Vegetation module * \ingroup grp_vegetation @@ -87,7 +52,6 @@ namespace DFHack Vegetation(); ~Vegetation(); bool Finish(){return true;}; - std::vector *all_plants; }; } #endif diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp index 1b4661004..424954bc3 100644 --- a/library/modules/Maps.cpp +++ b/library/modules/Maps.cpp @@ -592,12 +592,12 @@ bool Maps::ReadGeology (vector < vector >& assign) return true; } -bool Maps::ReadVegetation(uint32_t x, uint32_t y, uint32_t z, std::vector*& plants) +bool Maps::ReadVegetation(uint32_t x, uint32_t y, uint32_t z, std::vector*& plants) { df::map_block *block = getBlock(x,y,z); if (!block) return false; - plants = (vector *)&block->plants; + plants = &block->plants; return true; } diff --git a/library/modules/Vegetation.cpp b/library/modules/Vegetation.cpp index fe07d97b8..f6ce6aeb2 100644 --- a/library/modules/Vegetation.cpp +++ b/library/modules/Vegetation.cpp @@ -46,16 +46,6 @@ Module* DFHack::createVegetation() Vegetation::Vegetation() { - Core & c = Core::getInstance(); - try - { - OffsetGroup * OG_Veg = c.vinfo->getGroup("Vegetation"); - all_plants = (vector *) OG_Veg->getAddress ("vector"); - } - catch(exception &) - { - all_plants = 0; - } } Vegetation::~Vegetation() diff --git a/plugins/getplants.cpp b/plugins/getplants.cpp index c2ddc4992..a4b954c4b 100644 --- a/plugins/getplants.cpp +++ b/plugins/getplants.cpp @@ -1,4 +1,4 @@ -// Designate all matching plants for gathering/cutting +// (un)designate matching plants for gathering/cutting #include "Core.h" #include "Console.h" @@ -19,137 +19,144 @@ using std::string; using std::vector; using std::set; using namespace DFHack; +using namespace df::enums; using df::global::world; DFhackCExport command_result df_getplants (Core * c, vector & parameters) { - string plantMatStr = ""; - set plantIDs; - set plantNames; - bool deselect = false, exclude = false, treesonly = false, shrubsonly = false; + string plantMatStr = ""; + set plantIDs; + set plantNames; + bool deselect = false, exclude = false, treesonly = false, shrubsonly = false; - int count = 0; - for (size_t i = 0; i < parameters.size(); i++) - { - if(parameters[i] == "help" || parameters[i] == "?") - { - c->con.print("Specify the types of trees to cut down and/or shrubs to gather by their plant names, separated by spaces.\n" - "Options:\n" - "\t-t - Select trees only (exclude shrubs)\n" - "\t-s - Select shrubs only (exclude trees)\n" - "\t-c - Clear designations instead of setting them\n" - "\t-x - Apply selected action to all plants except those specified\n" - "Specifying both -t and -s will have no effect.\n" - "If no plant IDs are specified, all valid plant IDs will be listed.\n" - ); - return CR_OK; - } - else if(parameters[i] == "-t") - treesonly = true; - else if(parameters[i] == "-s") - shrubsonly = true; - else if(parameters[i] == "-c") - deselect = true; - else if(parameters[i] == "-x") - exclude = true; - else plantNames.insert(parameters[i]); - } + int count = 0; + for (size_t i = 0; i < parameters.size(); i++) + { + if(parameters[i] == "help" || parameters[i] == "?") + { + c->con.print("Specify the types of trees to cut down and/or shrubs to gather by their plant IDs, separated by spaces.\n" + "Options:\n" + "\t-t - Select trees only (exclude shrubs)\n" + "\t-s - Select shrubs only (exclude trees)\n" + "\t-c - Clear designations instead of setting them\n" + "\t-x - Apply selected action to all plants except those specified\n" + "Specifying both -t and -s will have no effect.\n" + "If no plant IDs are specified, all valid plant IDs will be listed.\n" + ); + return CR_WRONG_USAGE; + } + else if(parameters[i] == "-t") + treesonly = true; + else if(parameters[i] == "-s") + shrubsonly = true; + else if(parameters[i] == "-c") + deselect = true; + else if(parameters[i] == "-x") + exclude = true; + else + plantNames.insert(parameters[i]); + } + if (treesonly && shrubsonly) + { + c->con.printerr("Cannot specify both -t and -s at the same time!\n"); + return CR_WRONG_USAGE; + } - CoreSuspender suspend(c); + CoreSuspender suspend(c); - for (int i = 0; i < world->raws.plants.all.size(); i++) - { - df::plant_raw *plant = world->raws.plants.all[i]; - if (plantNames.find(plant->id) != plantNames.end()) - { - plantNames.erase(plant->id); - plantIDs.insert(i); - } - } - if (plantNames.size() > 0) - { - c->con.printerr("Invalid plant ID(s):"); - for (set::const_iterator it = plantNames.begin(); it != plantNames.end(); it++) - c->con.printerr(" %s", it->c_str()); - c->con.printerr("\n"); - return CR_FAILURE; - } + for (int i = 0; i < world->raws.plants.all.size(); i++) + { + df::plant_raw *plant = world->raws.plants.all[i]; + if (plantNames.find(plant->id) != plantNames.end()) + { + plantNames.erase(plant->id); + plantIDs.insert(i); + } + } + if (plantNames.size() > 0) + { + c->con.printerr("Invalid plant ID(s):"); + for (set::const_iterator it = plantNames.begin(); it != plantNames.end(); it++) + c->con.printerr(" %s", it->c_str()); + c->con.printerr("\n"); + return CR_FAILURE; + } - if (plantIDs.size() == 0) - { - c->con.print("Valid plant IDs:\n"); - for (int i = 0; i < world->raws.plants.all.size(); i++) - { - df::plant_raw *plant = world->raws.plants.all[i]; - if (plant->flags.is_set(df::plant_raw_flags::GRASS)) - continue; - c->con.print("* (%s) %s - %s\n", plant->flags.is_set(df::plant_raw_flags::TREE) ? "tree" : "shrub", plant->id.c_str(), plant->name.c_str()); - } - return CR_OK; - } + if (plantIDs.size() == 0) + { + c->con.print("Valid plant IDs:\n"); + for (int i = 0; i < world->raws.plants.all.size(); i++) + { + df::plant_raw *plant = world->raws.plants.all[i]; + if (plant->flags.is_set(plant_raw_flags::GRASS)) + continue; + c->con.print("* (%s) %s - %s\n", plant->flags.is_set(plant_raw_flags::TREE) ? "tree" : "shrub", plant->id.c_str(), plant->name.c_str()); + } + return CR_OK; + } - count = 0; - for (int i = 0; i < world->map.map_blocks.size(); i++) - { - df::map_block *cur = world->map.map_blocks[i]; - bool dirty = false; - for (int j = 0; j < cur->plants.size(); j++) - { - const df_plant *plant = (df_plant *)cur->plants[i]; - int x = plant->x % 16; - int y = plant->y % 16; - if (plantIDs.find(plant->material) != plantIDs.end()) - { - if (exclude) - continue; - } - else - { - if (!exclude) - continue; - } - TileShape shape = tileShape(cur->tiletype[x][y]); - if (plant->is_shrub && (treesonly || shape != SHRUB_OK)) - continue; - if (!plant->is_shrub && (shrubsonly || (shape != TREE_OK && shape != TREE_DEAD))) - continue; - if (cur->designation[x][y].bits.hidden) - continue; - if (deselect && cur->designation[x][y].bits.dig != df::tile_dig_designation::No) - { - cur->designation[x][y].bits.dig = df::tile_dig_designation::No; - dirty = true; - ++count; - } - if (!deselect && cur->designation[x][y].bits.dig != df::tile_dig_designation::Default) - { - cur->designation[x][y].bits.dig = df::tile_dig_designation::Default; - dirty = true; - ++count; - } - } - if (dirty) - cur->flags.set(df::block_flags::Designated); - } - if (count) - c->con.print("Updated %d plant designations.\n", count); - return CR_OK; + count = 0; + for (int i = 0; i < world->map.map_blocks.size(); i++) + { + df::map_block *cur = world->map.map_blocks[i]; + bool dirty = false; + for (int j = 0; j < cur->plants.size(); j++) + { + const df::plant *plant = cur->plants[i]; + int x = plant->pos.x % 16; + int y = plant->pos.y % 16; + if (plantIDs.find(plant->material) != plantIDs.end()) + { + if (exclude) + continue; + } + else + { + if (!exclude) + continue; + } + TileShape shape = tileShape(cur->tiletype[x][y]); + if (plant->flags.bits.is_shrub && (treesonly || shape != SHRUB_OK)) + continue; + if (!plant->flags.bits.is_shrub && (shrubsonly || (shape != TREE_OK && shape != TREE_DEAD))) + continue; + if (cur->designation[x][y].bits.hidden) + continue; + if (deselect && cur->designation[x][y].bits.dig == tile_dig_designation::Default) + { + cur->designation[x][y].bits.dig = tile_dig_designation::No; + dirty = true; + ++count; + } + if (!deselect && cur->designation[x][y].bits.dig == tile_dig_designation::No) + { + cur->designation[x][y].bits.dig = tile_dig_designation::Default; + dirty = true; + ++count; + } + } + if (dirty) + cur->flags.set(block_flags::Designated); + } + if (count) + c->con.print("Updated %d plant designations.\n", count); + return CR_OK; } DFhackCExport const char * plugin_name ( void ) { - return "getplants"; + return "getplants"; } DFhackCExport command_result plugin_init ( Core * c, vector &commands) { - commands.clear(); - commands.push_back(PluginCommand("getplants", "Cut down all of the specified trees or gather all of the specified shrubs", df_getplants)); - return CR_OK; + commands.clear(); + commands.push_back(PluginCommand("getplants", "Cut down all of the specified trees or gather all of the specified shrubs", df_getplants)); + return CR_OK; } DFhackCExport command_result plugin_shutdown ( Core * c ) { - return CR_OK; -} + return CR_OK; +} \ No newline at end of file diff --git a/plugins/plants.cpp b/plugins/plants.cpp index 99a8d1b62..9bfe5081f 100644 --- a/plugins/plants.cpp +++ b/plugins/plants.cpp @@ -19,6 +19,8 @@ using std::vector; using std::string; using namespace DFHack; +using df::global::world; + DFhackCExport command_result df_grow (Core * c, vector & parameters); DFhackCExport command_result df_immolate (Core * c, vector & parameters); DFhackCExport command_result df_extirpate (Core * c, vector & parameters); @@ -109,19 +111,13 @@ static command_result immolations (Core * c, do_what what, bool shrubs, bool tre uint32_t x_max, y_max, z_max; Maps::getSize(x_max, y_max, z_max); MapExtras::MapCache map; - DFHack::Vegetation *veg = c->getVegetation(); - if (!veg->all_plants) - { - std::cerr << "Unable to read vegetation!" << std::endl; - return CR_FAILURE; - } if(shrubs || trees) { int destroyed = 0; - for(size_t i = 0 ; i < veg->all_plants->size(); i++) + for(size_t i = 0 ; i < world->plants.all.size(); i++) { - DFHack::df_plant *p = veg->all_plants->at(i); - if(shrubs && p->is_shrub || trees && !p->is_shrub) + df::plant *p = world->plants.all[i]; + if(shrubs && p->flags.bits.is_shrub || trees && !p->flags.bits.is_shrub) { if (what == do_immolate) p->is_burning = true; @@ -136,14 +132,14 @@ static command_result immolations (Core * c, do_what what, bool shrubs, bool tre int32_t x,y,z; if(Gui->getCursorCoords(x,y,z)) { - vector * alltrees; + vector * alltrees; if(Maps::ReadVegetation(x/16,y/16,z,alltrees)) { bool didit = false; for(size_t i = 0 ; i < alltrees->size(); i++) { - DFHack::df_plant * tree = alltrees->at(i); - if(tree->x == x && tree->y == y && tree->z == z) + df::plant * tree = alltrees->at(i); + if(tree->pos.x == x && tree->pos.y == y && tree->pos.z == z) { if(what == do_immolate) tree->is_burning = true; @@ -166,7 +162,6 @@ static command_result immolations (Core * c, do_what what, bool shrubs, bool tre } } // Cleanup - veg->Finish(); c->Resume(); return CR_OK; } @@ -218,24 +213,17 @@ DFhackCExport command_result df_grow (Core * c, vector & parameters) return CR_FAILURE; } MapExtras::MapCache map; - DFHack::Vegetation *veg = c->getVegetation(); - if (!veg->all_plants) - { - con.printerr("Unable to read vegetation!\n"); - c->Resume(); - return CR_FAILURE; - } DFHack::Gui *Gui = c->getGui(); int32_t x,y,z; if(Gui->getCursorCoords(x,y,z)) { - vector * alltrees; + vector * alltrees; if(Maps::ReadVegetation(x/16,y/16,z,alltrees)) { for(size_t i = 0 ; i < alltrees->size(); i++) { - DFHack::df_plant * tree = alltrees->at(i); - if(tree->x == x && tree->y == y && tree->z == z) + df::plant * tree = alltrees->at(i); + if(tree->pos.x == x && tree->pos.y == y && tree->pos.z == z) { if(DFHack::tileShape(map.tiletypeAt(DFHack::DFCoord(x,y,z))) == DFHack::SAPLING_OK) { @@ -249,11 +237,11 @@ DFhackCExport command_result df_grow (Core * c, vector & parameters) else { int grown = 0; - for(size_t i = 0 ; i < veg->all_plants->size(); i++) + for(size_t i = 0 ; i < world->plants.all.size(); i++) { - DFHack::df_plant *p = veg->all_plants->at(i); - uint16_t ttype = map.tiletypeAt(DFHack::DFCoord(p->x,p->y,p->z)); - if(!p->is_shrub && DFHack::tileShape(ttype) == DFHack::SAPLING_OK) + df::plant *p = world->plants.all[i]; + uint16_t ttype = map.tiletypeAt(df::coord(p->pos.x,p->pos.y,p->pos.z)); + if(!p->flags.bits.is_shrub && DFHack::tileShape(ttype) == DFHack::SAPLING_OK) { p->grow_counter = DFHack::sapling_to_tree_threshold; } @@ -261,7 +249,6 @@ DFhackCExport command_result df_grow (Core * c, vector & parameters) } // Cleanup - veg->Finish(); c->Resume(); return CR_OK; } diff --git a/plugins/prospector.cpp b/plugins/prospector.cpp index 00e0913b2..a3d5344bf 100644 --- a/plugins/prospector.cpp +++ b/plugins/prospector.cpp @@ -69,7 +69,7 @@ bool operator>(const matdata & q1, const matdata & q2) typedef std::map MatMap; typedef std::vector< pair > MatSorter; -typedef std::vector PlantList; +typedef std::vector PlantList; #define TO_PTR_VEC(obj_vec, ptr_vec) \ ptr_vec.clear(); \ @@ -403,12 +403,12 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector & par { for (PlantList::const_iterator it = plants->begin(); it != plants->end(); it++) { - const DFHack::df_plant & plant = *(*it); - df::coord2d loc(plant.x, plant.y); + const df::plant & plant = *(*it); + df::coord2d loc(plant.pos.x, plant.pos.y); loc = loc % 16; if (showHidden || !b->DesignationAt(loc).bits.hidden) { - if(plant.is_shrub) + if(plant.flags.bits.is_shrub) plantMats[plant.material].add(global_z); else treeMats[plant.material].add(global_z);