diff --git a/library/modules/Materials.cpp b/library/modules/Materials.cpp index ae1c74be3..09f275777 100644 --- a/library/modules/Materials.cpp +++ b/library/modules/Materials.cpp @@ -57,21 +57,6 @@ class Materials::Private uint32_t vector_organic_trees; uint32_t vector_races; uint32_t vector_other; -/* - class t_inorganic_extras - { - public: - uint32_t offset_ore_types; - uint32_t offset_ore_chances; - uint32_t offset_strand_types; - uint32_t offset_strand_chances; - uint32_t offset_value; - uint32_t offset_wall_tile; - uint32_t offset_boulder_tile; - }; - - t_inorganic_extras i_ex; - */ }; Materials::Materials() @@ -87,18 +72,6 @@ Materials::Materials() d->vector_organic_trees = OG_Materials->getAddress ("organics_trees"); d->vector_races = OG_Materials->getAddress("creature_type_vector"); } - /* - OffsetGroup *OG_Offsets = OG_Materials->getGroup("inorganic_extras"); - { - d->i_ex.offset_ore_types = OG_Offsets->getOffset("ore_types"); - d->i_ex.offset_ore_chances = OG_Offsets->getOffset("ore_chances"); - d->i_ex.offset_strand_types = OG_Offsets->getOffset("strand_types"); - d->i_ex.offset_strand_chances = OG_Offsets->getOffset("strand_chances"); - d->i_ex.offset_value = OG_Offsets->getOffset("value"); - d->i_ex.offset_wall_tile = OG_Offsets->getOffset("wall_tile"); - d->i_ex.offset_boulder_tile = OG_Offsets->getOffset("boulder_tile"); - } - */ } Materials::~Materials() @@ -111,41 +84,6 @@ bool Materials::Finish() return true; } -/* -bool API::ReadInorganicMaterials (vector & inorganic) -{ - Process *p = d->owner; - memory_info * minfo = p->getDescriptor(); - int matgloss_address = minfo->getAddress ("mat_inorganics"); - int matgloss_colors = minfo->getOffset ("material_color"); - int matgloss_stone_name_offset = minfo->getOffset("matgloss_stone_name"); - - DfVector p_matgloss (p, matgloss_address); - - uint32_t size = p_matgloss.getSize(); - inorganic.resize (0); - inorganic.reserve (size); - for (uint32_t i = 0; i < size;i++) - { - // read the matgloss pointer from the vector into temp - uint32_t temp = p_matgloss[i]; - // read the string pointed at by - t_matgloss mat; - //cout << temp << endl; - //fill_char_buf(mat.id, d->p->readSTLString(temp)); // reads a C string given an address - p->readSTLString (temp, mat.id, 128); - - p->readSTLString (temp+matgloss_stone_name_offset, mat.name, 128); - mat.fore = (uint8_t) p->readWord (temp + matgloss_colors); - mat.back = (uint8_t) p->readWord (temp + matgloss_colors + 2); - mat.bright = (uint8_t) p->readWord (temp + matgloss_colors + 4); - - inorganic.push_back (mat); - } - return true; -} -*/ - t_matgloss::t_matgloss() { fore = 0; @@ -182,7 +120,6 @@ inline bool ReadNamesOnly(Process* p, uint32_t address, vector & nam { t_matgloss mat; mat.id = *(std::string *)p_matgloss[i]; - //p->readSTLString (p_matgloss[i], mat.id, 128); names.push_back(mat); } return true; @@ -200,7 +137,6 @@ bool Materials::ReadInorganicMaterials (void) t_matglossInorganic mat; mat.id = orig->Inorganic_ID; mat.name = orig->STONE_NAME; - //p->readSTLString (p_matgloss[i] + mat_name, mat.name, 128); mat.ore_types = orig->METAL_ORE_matID; mat.ore_chances = orig->METAL_ORE_prob; @@ -306,10 +242,6 @@ bool Materials::ReadCreatureTypesEx (void) uint32_t caste_bodypart_offset; uint32_t bodypart_id_offset; uint32_t bodypart_category_offset; - //FIXME: this is unused. why do we mess with it when it's not even read? - //uint32_t bodypart_layers_offset; - //uint32_t bodypart_singular_offset; - //uint32_t bodypart_plural_offset; uint32_t color_modifier_part_offset; uint32_t color_modifier_startdate_offset; uint32_t color_modifier_enddate_offset; @@ -322,9 +254,6 @@ bool Materials::ReadCreatureTypesEx (void) OffsetGroup * OG_CasteBodyparts = OG_Creature->getGroup("caste_bodyparts"); bodypart_id_offset = OG_CasteBodyparts->getOffset ("id"); bodypart_category_offset = OG_CasteBodyparts->getOffset ("category"); - //bodypart_layers_offset = OG_CasteBodyparts->getOffset ("layers_vector"); // unused - //bodypart_singular_offset = OG_CasteBodyparts->getOffset ("singular_vector"); // unused - //bodypart_plural_offset = OG_CasteBodyparts->getOffset ("plural_vector"); // unused OffsetGroup * OG_CasteColorMods = OG_Creature->getGroup("caste_color_mods"); color_modifier_part_offset = OG_CasteColorMods->getOffset ("part"); color_modifier_startdate_offset = OG_CasteColorMods->getOffset ("startdate"); @@ -343,12 +272,6 @@ bool Materials::ReadCreatureTypesEx (void) for (uint32_t i = 0; i < size;i++) { t_creaturetype mat; - // FROM race READ - // std::string rawname AT 0, - // char tile_character AT tile_offset, - // word tilecolor.fore : tile_color_offset, - // word tilecolor.back : tile_color_offset + 2, - // word tilecolor.bright : tile_color_offset + 4 mat.id = p->readSTLString (p_races[i]); mat.tile_character = p->readByte( p_races[i] + tile_offset ); mat.tilecolor.fore = p->readWord( p_races[i] + tile_color_offset ); diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index b90905f26..786dc1d6b 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -124,6 +124,7 @@ endif() DFHACK_PLUGIN(reveal reveal.cpp) DFHACK_PLUGIN(probe probe.cpp) +DFHACK_PLUGIN(grow grow.cpp) DFHACK_PLUGIN(prospector prospector.cpp) DFHACK_PLUGIN(rawdump rawdump.cpp) DFHACK_PLUGIN(cleanmap cleanmap.cpp) @@ -133,3 +134,4 @@ DFHACK_PLUGIN(colonies colonies.cpp) DFHACK_PLUGIN(itemhacks itemhacks.cpp) DFHACK_PLUGIN(notes notes.cpp) DFHACK_PLUGIN(mode mode.cpp) +#DFHACK_PLUGIN(tiles tiles.cpp) diff --git a/plugins/grow.cpp b/plugins/grow.cpp index cd5daba6f..44aabfafd 100644 --- a/plugins/grow.cpp +++ b/plugins/grow.cpp @@ -3,68 +3,77 @@ #include #include #include +#include -using namespace std; -#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include -#include -#include -#include -int main(int argc, char *argv[]) +using std::vector; +using std::string; +using namespace DFHack; + +DFhackCExport command_result df_grow (Core * c, vector & parameters); + +DFhackCExport const char * plugin_name ( void ) { - bool temporary_terminal = TemporaryTerminal(); - srand(time(0)); + return "grow"; +} - uint32_t x_max = 0, y_max = 0, z_max = 0; - DFHack::ContextManager manager("Memory.xml"); +DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +{ + commands.clear(); + commands.push_back(PluginCommand("grow", "Grows saplings into trees (with active cursor, only the targetted one).", df_grow)); + return CR_OK; +} - DFHack::Context *context = manager.getSingleContext(); - if (!context->Attach()) - { - std::cerr << "Unable to attach to DF!" << std::endl; - if(temporary_terminal) - std::cin.ignore(); - return 1; - } +DFhackCExport command_result plugin_shutdown ( Core * c ) +{ + return CR_OK; +} - DFHack::Maps *maps = context->getMaps(); +DFhackCExport command_result df_grow (Core * c, vector & parameters) +{ + //uint32_t x_max = 0, y_max = 0, z_max = 0; + c->Suspend(); + DFHack::Maps *maps = c->getMaps(); + Console & con = c->con; if (!maps->Start()) { - std::cerr << "Cannot get map info!" << std::endl; - context->Detach(); - if(temporary_terminal) - std::cin.ignore(); - return 1; + con.printerr("Cannot get map info!\n"); + c->Resume(); + return CR_FAILURE; } - DFHack::Gui * Gui = context->getGui(); - maps->getSize(x_max, y_max, z_max); + //maps->getSize(x_max, y_max, z_max); MapExtras::MapCache map(maps); - uint32_t vegCount = 0; - DFHack::Vegetation *veg = context->getVegetation(); - if (!veg->Start(vegCount)) + DFHack::Vegetation *veg = c->getVegetation(); + if (!veg->all_plants) { - std::cerr << "Unable to read vegetation!" << std::endl; - if(temporary_terminal) - cin.ignore(); - return 1; + 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; - if(maps->ReadVegetation(x/16,y/16,z,&alltrees)) + vector * alltrees; + if(maps->ReadVegetation(x/16,y/16,z,alltrees)) { - for(size_t i = 0 ; i < alltrees.size(); i++) + for(size_t i = 0 ; i < alltrees->size(); i++) { - DFHack::dfh_plant & tree = alltrees[i]; - if(tree.sdata.x == x && tree.sdata.y == y && tree.sdata.z == z) + DFHack::df_plant * tree = alltrees->at(i); + if(tree->x == x && tree->y == y && tree->z == z) { if(DFHack::tileShape(map.tiletypeAt(DFHack::DFCoord(x,y,z))) == DFHack::SAPLING_OK) { - tree.sdata.grow_counter = DFHack::sapling_to_tree_threshold; - veg->Write(tree); + tree->grow_counter = DFHack::sapling_to_tree_threshold; } break; } @@ -74,15 +83,13 @@ int main(int argc, char *argv[]) else { int grown = 0; - for(size_t i = 0 ; i < vegCount; i++) + for(size_t i = 0 ; i < veg->all_plants->size(); i++) { - DFHack::dfh_plant p; - veg->Read(i,p); - uint16_t ttype = map.tiletypeAt(DFHack::DFCoord(p.sdata.x,p.sdata.y,p.sdata.z)); - if(!p.sdata.is_shrub && DFHack::tileShape(ttype) == DFHack::SAPLING_OK) + 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) { - p.sdata.grow_counter = DFHack::sapling_to_tree_threshold; - veg->Write(p); + p->grow_counter = DFHack::sapling_to_tree_threshold; } } } @@ -90,11 +97,7 @@ int main(int argc, char *argv[]) // Cleanup veg->Finish(); maps->Finish(); - context->Detach(); - if(temporary_terminal) - { - std::cout << " Press any key to finish."; - std::cin.ignore(); - } - return 0; + c->Resume(); + return CR_OK; } + diff --git a/plugins/liquids.cpp b/plugins/liquids.cpp deleted file mode 100644 index 6a34d2fab..000000000 --- a/plugins/liquids.cpp +++ /dev/null @@ -1,506 +0,0 @@ -#include -#include -#include -#include -#include -using namespace std; - -#include -#include -using namespace MapExtras; -#include - - - - - -typedef vector coord_vec; - -class Brush -{ -public: - virtual ~Brush(){}; - virtual coord_vec points(MapCache & mc,DFHack::DFCoord start) = 0; -}; -/** - * generic 3D rectangle brush. you can specify the dimensions of - * the rectangle and optionally which tile is its 'center' - */ -class RectangleBrush : public Brush -{ -public: - RectangleBrush(int x, int y, int z = 1, int centerx = -1, int centery = -1, int centerz = -1) - { - if(centerx == -1) - cx_ = x/2; - else - cx_ = centerx; - if(centery == -1) - cy_ = y/2; - else - cy_ = centery; - if(centerz == -1) - cz_ = z/2; - else - cz_ = centerz; - x_ = x; - y_ = y; - z_ = z; - }; - coord_vec points(MapCache & mc, DFHack::DFCoord start) - { - coord_vec v; - DFHack::DFCoord iterstart(start.x - cx_, start.y - cy_, start.z - cz_); - DFHack::DFCoord iter = iterstart; - for(int xi = 0; xi < x_; xi++) - { - for(int yi = 0; yi < y_; yi++) - { - for(int zi = 0; zi < z_; zi++) - { - if(mc.testCoord(iter)) - v.push_back(iter); - iter.z++; - } - iter.z = iterstart.z; - iter.y++; - } - iter.y = iterstart.y; - iter.x ++; - } - return v; - }; - ~RectangleBrush(){}; -private: - int x_, y_, z_; - int cx_, cy_, cz_; -}; - -/** - * stupid block brush, legacy. use when you want to apply something to a whole DF map block. - */ -class BlockBrush : public Brush -{ -public: - BlockBrush(){}; - ~BlockBrush(){}; - coord_vec points(MapCache & mc, DFHack::DFCoord start) - { - coord_vec v; - DFHack::DFCoord blockc = start % 16; - DFHack::DFCoord iterc = blockc * 16; - if( !mc.testCoord(start) ) - return v; - - for(int xi = 0; xi < 16; xi++) - { - for(int yi = 0; yi < 16; yi++) - { - v.push_back(iterc); - iterc.y++; - } - iterc.x ++; - } - return v; - }; -}; - -/** - * Column from a position through open space tiles - * example: create a column of magma - */ -class ColumnBrush : public Brush -{ -public: - ColumnBrush(){}; - ~ColumnBrush(){}; - coord_vec points(MapCache & mc, DFHack::DFCoord start) - { - coord_vec v; - bool juststarted = true; - while (mc.testCoord(start)) - { - uint16_t tt = mc.tiletypeAt(start); - if(DFHack::LowPassable(tt) || juststarted && DFHack::HighPassable(tt)) - { - v.push_back(start); - juststarted = false; - start.z++; - } - else break; - } - return v; - }; -}; - -int main (int argc, char** argv) -{ - bool temporary_terminal = TemporaryTerminal(); - bool quiet = false; - for(int i = 1; i < argc; i++) - { - string test = argv[i]; - if(test == "-q") - { - quiet = true; - } - } - int32_t x,y,z; - - uint32_t x_max,y_max,z_max; - - DFHack::ContextManager DFMgr("Memory.xml"); - DFHack::Context *DF; - DFHack::Maps * Maps; - DFHack::Gui * Position; - Brush * brush = new RectangleBrush(1,1); - string brushname = "point"; - try - { - DF=DFMgr.getSingleContext(); - DF->Attach(); - Maps = DF->getMaps(); - Maps->Start(); - Maps->getSize(x_max,y_max,z_max); - Position = DF->getGui(); - } - catch (exception& e) - { - cerr << e.what() << endl; - if(temporary_terminal) - cin.ignore(); - return 1; - } - bool end = false; - cout << "Welcome to the liquid spawner.\nType 'help' or '?' for a list of available commands, 'q' to quit.\nPress return after a command to confirm." << endl; - string mode="magma"; - - string flowmode="f+"; - string setmode ="s."; - unsigned int amount = 7; - int width = 1, height = 1, z_levels = 1; - while(!end) - { - DF->Resume(); - string command = ""; - cout <<"[" << mode << ":" << brushname << ":" << amount << ":" << flowmode << ":" << setmode << "]# "; - getline(cin, command); - if (std::cin.eof()) - { - command = "q"; - std::cout << std::endl; // No newline from the user here! - } - if(command=="help" || command == "?") - { - cout << "Modes:" << endl - << "m - switch to magma" << endl - << "w - switch to water" << endl - << "o - make obsidian wall instead" << endl - << "of - make obsidian floors" << endl - << "rs - make a river source" << endl - << "f - flow bits only" << endl - << "Set-Modes (only for magma/water):" << endl - << "s+ - only add" << endl - << "s. - set" << endl - << "s- - only remove" << endl - << "Properties (only for magma/water):" << endl - << "f+ - make the spawned liquid flow" << endl - << "f. - don't change flow state (read state in flow mode)" << endl - << "f- - make the spawned liquid static" << endl - << "0-7 - set liquid amount" << endl - << "Brush:" << endl - << "point - single tile [p]" << endl - << "range - block with cursor at bottom north-west [r]" << endl - << " (any place, any size)" << endl - << "block - DF map block with cursor in it" << endl - << " (regular spaced 16x16x1 blocks)" << endl - << "column - Column from cursor, up through free space" << endl - << "Other:" << endl - << "q - quit" << endl - << "help or ? - print this list of commands" << endl - << "empty line - put liquid" << endl - << endl - << "Usage: point the DF cursor at a tile you want to modify" << endl - << "and use the commands available :)" << endl; - } - else if(command == "m") - { - mode = "magma"; - } - else if(command == "o") - { - mode = "obsidian"; - } - else if(command == "of") - { - mode = "obsidian_floor"; - } - else if(command == "w") - { - mode = "water"; - } - else if(command == "f") - { - mode = "flowbits"; - } - else if(command == "rs") - { - mode = "riversource"; - } - else if(command == "point" || command == "p") - { - delete brush; - brushname = "point"; - brush = new RectangleBrush(1,1); - } - else if(command == "range" || command == "r") - { - cout << " :set range width<" << width << "># "; - getline(cin, command); - width = command == "" ? width : atoi (command.c_str()); - if(width < 1) width = 1; - - cout << " :set range height<" << height << "># "; - getline(cin, command); - height = command == "" ? height : atoi (command.c_str()); - if(height < 1) height = 1; - - cout << " :set range z-levels<" << z_levels << "># "; - getline(cin, command); - z_levels = command == "" ? z_levels : atoi (command.c_str()); - if(z_levels < 1) z_levels = 1; - delete brush; - if(width == 1 && height == 1 && z_levels == 1) - { - brushname="point"; - } - else - { - brushname = "range"; - } - brush = new RectangleBrush(width,height,z_levels,0,0,0); - } - else if(command == "block") - { - delete brush; - brushname = "block"; - brush = new BlockBrush(); - } - else if(command == "column") - { - delete brush; - brushname = "column"; - brush = new ColumnBrush(); - } - else if(command == "q") - { - end = true; - } - else if(command == "f+") - { - flowmode = "f+"; - } - else if(command == "f-") - { - flowmode = "f-"; - } - else if(command == "f.") - { - flowmode = "f."; - } - else if(command == "s+") - { - setmode = "s+"; - } - else if(command == "s-") - { - setmode = "s-"; - } - else if(command == "s.") - { - setmode = "s."; - } - // blah blah, bad code, bite me. - else if(command == "0") - amount = 0; - else if(command == "1") - amount = 1; - else if(command == "2") - amount = 2; - else if(command == "3") - amount = 3; - else if(command == "4") - amount = 4; - else if(command == "5") - amount = 5; - else if(command == "6") - amount = 6; - else if(command == "7") - amount = 7; - else if(command.empty()) - { - DF->Suspend(); - do - { - if(!Maps->Start()) - { - cout << "Can't see any DF map loaded." << endl; - break; - } - if(!Position->getCursorCoords(x,y,z)) - { - cout << "Can't get cursor coords! Make sure you have a cursor active in DF." << endl; - break; - } - cout << "cursor coords: " << x << "/" << y << "/" << z << endl; - MapCache mcache(Maps); - DFHack::DFCoord cursor(x,y,z); - coord_vec all_tiles = brush->points(mcache,cursor); - cout << "working..." << endl; - if(mode == "obsidian") - { - coord_vec::iterator iter = all_tiles.begin(); - while (iter != all_tiles.end()) - { - mcache.setTiletypeAt(*iter, 331); - mcache.setTemp1At(*iter,10015); - mcache.setTemp2At(*iter,10015); - DFHack::t_designation des = mcache.designationAt(*iter); - des.bits.flow_size = 0; - mcache.setDesignationAt(*iter, des); - iter ++; - } - } - if(mode == "obsidian_floor") - { - coord_vec::iterator iter = all_tiles.begin(); - while (iter != all_tiles.end()) - { - mcache.setTiletypeAt(*iter, 340); - iter ++; - } - } - else if(mode == "riversource") - { - set seen_blocks; - coord_vec::iterator iter = all_tiles.begin(); - while (iter != all_tiles.end()) - { - mcache.setTiletypeAt(*iter, 90); - - DFHack::t_designation a = mcache.designationAt(*iter); - a.bits.liquid_type = DFHack::liquid_water; - a.bits.liquid_static = false; - a.bits.flow_size = 7; - mcache.setTemp1At(*iter,10015); - mcache.setTemp2At(*iter,10015); - mcache.setDesignationAt(*iter,a); - - Block * b = mcache.BlockAt((*iter)/16); - DFHack::t_blockflags bf = b->BlockFlags(); - bf.bits.liquid_1 = true; - bf.bits.liquid_2 = true; - b->setBlockFlags(bf); - - iter++; - } - } - else if(mode== "magma" || mode== "water" || mode == "flowbits") - { - set seen_blocks; - coord_vec::iterator iter = all_tiles.begin(); - while (iter != all_tiles.end()) - { - DFHack::DFCoord current = *iter; - DFHack::t_designation des = mcache.designationAt(current); - uint16_t tt = mcache.tiletypeAt(current); - DFHack::naked_designation & flow = des.bits; - // don't put liquids into places where they don't belong... - if(!DFHack::FlowPassable(tt)) - { - iter++; - continue; - } - if(mode != "flowbits") - { - if(setmode == "s.") - { - flow.flow_size = amount; - } - else if(setmode == "s+") - { - if(flow.flow_size < amount) - flow.flow_size = amount; - } - else if(setmode == "s-") - { - if (flow.flow_size > amount) - flow.flow_size = amount; - } - if(amount != 0 && mode == "magma") - { - flow.liquid_type = DFHack::liquid_magma; - mcache.setTemp1At(current,12000); - mcache.setTemp2At(current,12000); - } - else if(amount != 0 && mode == "water") - { - flow.liquid_type = DFHack::liquid_water; - mcache.setTemp1At(current,10015); - mcache.setTemp2At(current,10015); - } - else if(amount == 0 && (mode == "water" || mode == "magma")) - { - // reset temperature to sane default - mcache.setTemp1At(current,10015); - mcache.setTemp2At(current,10015); - } - mcache.setDesignationAt(current,des); - } - seen_blocks.insert(mcache.BlockAt((*iter) / 16)); - iter++; - } - set ::iterator biter = seen_blocks.begin(); - while (biter != seen_blocks.end()) - { - DFHack::t_blockflags bflags = (*biter)->BlockFlags(); - if(flowmode == "f+") - { - bflags.bits.liquid_1 = true; - bflags.bits.liquid_2 = true; - (*biter)->setBlockFlags(bflags); - } - else if(flowmode == "f-") - { - bflags.bits.liquid_1 = false; - bflags.bits.liquid_2 = false; - (*biter)->setBlockFlags(bflags); - } - else - { - cout << "flow bit 1 = " << bflags.bits.liquid_1 << endl; - cout << "flow bit 2 = " << bflags.bits.liquid_2 << endl; - } - biter ++; - } - } - if(mcache.WriteAll()) - cout << "OK" << endl; - else - cout << "Something failed horribly! RUN!" << endl; - Maps->Finish(); - } while (0); - } - else - { - cout << command << " : unknown command." << endl; - } - } - DF->Detach(); - if(temporary_terminal && !quiet) - { - cout << "Done. Press any key to continue" << endl; - cin.ignore(); - } - return 0; -} diff --git a/plugins/tiles.cpp b/plugins/tiles.cpp new file mode 100644 index 000000000..479e5f2a4 --- /dev/null +++ b/plugins/tiles.cpp @@ -0,0 +1,492 @@ +#include +#include +#include +#include +#include +using std::vector; +using std::string; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace MapExtras; +using namespace DFHack; + +typedef vector coord_vec; + +class Brush +{ +public: + virtual ~Brush(){}; + virtual coord_vec points(MapCache & mc,DFHack::DFCoord start) = 0; +}; +/** + * generic 3D rectangle brush. you can specify the dimensions of + * the rectangle and optionally which tile is its 'center' + */ +class RectangleBrush : public Brush +{ +public: + RectangleBrush(int x, int y, int z = 1, int centerx = -1, int centery = -1, int centerz = -1) + { + if(centerx == -1) + cx_ = x/2; + else + cx_ = centerx; + if(centery == -1) + cy_ = y/2; + else + cy_ = centery; + if(centerz == -1) + cz_ = z/2; + else + cz_ = centerz; + x_ = x; + y_ = y; + z_ = z; + }; + coord_vec points(MapCache & mc, DFHack::DFCoord start) + { + coord_vec v; + DFHack::DFCoord iterstart(start.x - cx_, start.y - cy_, start.z - cz_); + DFHack::DFCoord iter = iterstart; + for(int xi = 0; xi < x_; xi++) + { + for(int yi = 0; yi < y_; yi++) + { + for(int zi = 0; zi < z_; zi++) + { + if(mc.testCoord(iter)) + v.push_back(iter); + iter.z++; + } + iter.z = iterstart.z; + iter.y++; + } + iter.y = iterstart.y; + iter.x ++; + } + return v; + }; + ~RectangleBrush(){}; +private: + int x_, y_, z_; + int cx_, cy_, cz_; +}; + +/** + * stupid block brush, legacy. use when you want to apply something to a whole DF map block. + */ +class BlockBrush : public Brush +{ +public: + BlockBrush(){}; + ~BlockBrush(){}; + coord_vec points(MapCache & mc, DFHack::DFCoord start) + { + coord_vec v; + DFHack::DFCoord blockc = start % 16; + DFHack::DFCoord iterc = blockc * 16; + if( !mc.testCoord(start) ) + return v; + + for(int xi = 0; xi < 16; xi++) + { + for(int yi = 0; yi < 16; yi++) + { + v.push_back(iterc); + iterc.y++; + } + iterc.x ++; + } + return v; + }; +}; + +/** + * Column from a position through open space tiles + * example: create a column of magma + */ +class ColumnBrush : public Brush +{ +public: + ColumnBrush(){}; + ~ColumnBrush(){}; + coord_vec points(MapCache & mc, DFHack::DFCoord start) + { + coord_vec v; + bool juststarted = true; + while (mc.testCoord(start)) + { + uint16_t tt = mc.tiletypeAt(start); + if(DFHack::LowPassable(tt) || juststarted && DFHack::HighPassable(tt)) + { + v.push_back(start); + juststarted = false; + start.z++; + } + else break; + } + return v; + }; +}; + +DFhackCExport command_result df_tile (Core * c, vector & parameters); +DFhackCExport command_result df_paint (Core * c, vector & parameters); + +DFhackCExport const char * plugin_name ( void ) +{ + return "tiles"; +} + +DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +{ + commands.clear(); + commands.push_back(PluginCommand("tile", "Set tile painter brush.", df_tile)); + commands.push_back(PluginCommand("paint", "Paint with the current brush.", df_paint)); + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown ( Core * c ) +{ + return CR_OK; +} + +DFhackCExport command_result df_tile (Core * c, vector & parameters) +{ + int32_t x,y,z; + uint32_t x_max,y_max,z_max; + DFHack::Maps * Maps; + DFHack::Gui * Position; + Brush * brush = new RectangleBrush(1,1); + string brushname = "point"; + + Maps = c->getMaps(); + Maps->Start(); + Maps->getSize(x_max,y_max,z_max); + Position = c->getGui(); + + string mode="magma"; + + string flowmode="f+"; + string setmode ="s."; + unsigned int amount = 7; + int width = 1, height = 1, z_levels = 1; + + string command = ""; + if(command=="help" || command == "?") + { + c->con.print + ( + "Modes:\n" + "m - switch to magma\n" + "w - switch to water\n" + "o - make obsidian wall instead\n" + "of - make obsidian floors\n" + "rs - make a river source\n" + "f - flow bits only\n" + "Set-Modes (only for magma/water):\n" + "s+ - only add\n" + "s. - set\n" + "s- - only remove\n" + "Properties (only for magma/water):\n" + "f+ - make the spawned liquid flow\n" + "f. - don't change flow state (read state in flow mode)\n" + "f- - make the spawned liquid static\n" + "0-7 - set liquid amount\n" + "Brush:\n" + "point - single tile [p]\n" + "range - block with cursor at bottom north-west [r]\n" + " (any place, any size)\n" + "block - DF map block with cursor in it\n" + " (regular spaced 16x16x1 blocks)\n" + "column - Column from cursor, up through free space\n" + "Other:\n" + "q - quit\n" + "help or ? - print this list of commands\n" + "empty line - put liquid\n" + "\n" + "Usage: point the DF cursor at a tile you want to modify\n" + "and use the commands available :)\n" + ); + } + else if(command == "m") + { + mode = "magma"; + } + else if(command == "o") + { + mode = "obsidian"; + } + else if(command == "of") + { + mode = "obsidian_floor"; + } + else if(command == "w") + { + mode = "water"; + } + else if(command == "f") + { + mode = "flowbits"; + } + else if(command == "rs") + { + mode = "riversource"; + } + else if(command == "point" || command == "p") + { + delete brush; + brushname = "point"; + brush = new RectangleBrush(1,1); + } + else if(command == "range" || command == "r") + { + cout << " :set range width<" << width << "># "; + getline(cin, command); + width = command == "" ? width : atoi (command.c_str()); + if(width < 1) width = 1; + + cout << " :set range height<" << height << "># "; + getline(cin, command); + height = command == "" ? height : atoi (command.c_str()); + if(height < 1) height = 1; + + cout << " :set range z-levels<" << z_levels << "># "; + getline(cin, command); + z_levels = command == "" ? z_levels : atoi (command.c_str()); + if(z_levels < 1) z_levels = 1; + delete brush; + if(width == 1 && height == 1 && z_levels == 1) + { + brushname="point"; + } + else + { + brushname = "range"; + } + brush = new RectangleBrush(width,height,z_levels,0,0,0); + } + else if(command == "block") + { + delete brush; + brushname = "block"; + brush = new BlockBrush(); + } + else if(command == "column") + { + delete brush; + brushname = "column"; + brush = new ColumnBrush(); + } + else if(command == "q") + { + end = true; + } + else if(command == "f+") + { + flowmode = "f+"; + } + else if(command == "f-") + { + flowmode = "f-"; + } + else if(command == "f.") + { + flowmode = "f."; + } + else if(command == "s+") + { + setmode = "s+"; + } + else if(command == "s-") + { + setmode = "s-"; + } + else if(command == "s.") + { + setmode = "s."; + } + // blah blah, bad code, bite me. + else if(command == "0") + amount = 0; + else if(command == "1") + amount = 1; + else if(command == "2") + amount = 2; + else if(command == "3") + amount = 3; + else if(command == "4") + amount = 4; + else if(command == "5") + amount = 5; + else if(command == "6") + amount = 6; + else if(command == "7") + amount = 7; + else if(command.empty()) + { + DF->Suspend(); + do + { + if(!Maps->Start()) + { + cout << "Can't see any DF map loaded." << endl; + break; + } + if(!Position->getCursorCoords(x,y,z)) + { + cout << "Can't get cursor coords! Make sure you have a cursor active in DF." << endl; + break; + } + cout << "cursor coords: " << x << "/" << y << "/" << z << endl; + MapCache mcache(Maps); + DFHack::DFCoord cursor(x,y,z); + coord_vec all_tiles = brush->points(mcache,cursor); + cout << "working..." << endl; + if(mode == "obsidian") + { + coord_vec::iterator iter = all_tiles.begin(); + while (iter != all_tiles.end()) + { + mcache.setTiletypeAt(*iter, 331); + mcache.setTemp1At(*iter,10015); + mcache.setTemp2At(*iter,10015); + DFHack::t_designation des = mcache.designationAt(*iter); + des.bits.flow_size = 0; + mcache.setDesignationAt(*iter, des); + iter ++; + } + } + if(mode == "obsidian_floor") + { + coord_vec::iterator iter = all_tiles.begin(); + while (iter != all_tiles.end()) + { + mcache.setTiletypeAt(*iter, 340); + iter ++; + } + } + else if(mode == "riversource") + { + set seen_blocks; + coord_vec::iterator iter = all_tiles.begin(); + while (iter != all_tiles.end()) + { + mcache.setTiletypeAt(*iter, 90); + + DFHack::t_designation a = mcache.designationAt(*iter); + a.bits.liquid_type = DFHack::liquid_water; + a.bits.liquid_static = false; + a.bits.flow_size = 7; + mcache.setTemp1At(*iter,10015); + mcache.setTemp2At(*iter,10015); + mcache.setDesignationAt(*iter,a); + + Block * b = mcache.BlockAt((*iter)/16); + DFHack::t_blockflags bf = b->BlockFlags(); + bf.bits.liquid_1 = true; + bf.bits.liquid_2 = true; + b->setBlockFlags(bf); + + iter++; + } + } + else if(mode== "magma" || mode== "water" || mode == "flowbits") + { + set seen_blocks; + coord_vec::iterator iter = all_tiles.begin(); + while (iter != all_tiles.end()) + { + DFHack::DFCoord current = *iter; + DFHack::t_designation des = mcache.designationAt(current); + uint16_t tt = mcache.tiletypeAt(current); + DFHack::naked_designation & flow = des.bits; + // don't put liquids into places where they don't belong... + if(!DFHack::FlowPassable(tt)) + { + iter++; + continue; + } + if(mode != "flowbits") + { + if(setmode == "s.") + { + flow.flow_size = amount; + } + else if(setmode == "s+") + { + if(flow.flow_size < amount) + flow.flow_size = amount; + } + else if(setmode == "s-") + { + if (flow.flow_size > amount) + flow.flow_size = amount; + } + if(amount != 0 && mode == "magma") + { + flow.liquid_type = DFHack::liquid_magma; + mcache.setTemp1At(current,12000); + mcache.setTemp2At(current,12000); + } + else if(amount != 0 && mode == "water") + { + flow.liquid_type = DFHack::liquid_water; + mcache.setTemp1At(current,10015); + mcache.setTemp2At(current,10015); + } + else if(amount == 0 && (mode == "water" || mode == "magma")) + { + // reset temperature to sane default + mcache.setTemp1At(current,10015); + mcache.setTemp2At(current,10015); + } + mcache.setDesignationAt(current,des); + } + seen_blocks.insert(mcache.BlockAt((*iter) / 16)); + iter++; + } + set ::iterator biter = seen_blocks.begin(); + while (biter != seen_blocks.end()) + { + DFHack::t_blockflags bflags = (*biter)->BlockFlags(); + if(flowmode == "f+") + { + bflags.bits.liquid_1 = true; + bflags.bits.liquid_2 = true; + (*biter)->setBlockFlags(bflags); + } + else if(flowmode == "f-") + { + bflags.bits.liquid_1 = false; + bflags.bits.liquid_2 = false; + (*biter)->setBlockFlags(bflags); + } + else + { + cout << "flow bit 1 = " << bflags.bits.liquid_1 << endl; + cout << "flow bit 2 = " << bflags.bits.liquid_2 << endl; + } + biter ++; + } + } + if(mcache.WriteAll()) + cout << "OK" << endl; + else + cout << "Something failed horribly! RUN!" << endl; + Maps->Finish(); + } while (0); + } + else + { + cout << command << " : unknown command." << endl; + } + return CR_OK; +}