int main(int argc, char *argv[]) { bool temporary_terminal = TemporaryTerminal(); uint32_t x_max = 0, y_max = 0, z_max = 0; DFHack::ContextManager manager("Memory.xml"); 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; } DFHack::Maps *maps = context->getMaps(); if (!maps->Start()) { std::cerr << "Cannot get map info!" << std::endl; context->Detach(); if(temporary_terminal) std::cin.ignore(); return 1; } maps->getSize(x_max, y_max, z_max); MapExtras::MapCache map(maps); for(uint32_t z = 0; z < z_max; z++) { for(uint32_t b_y = 0; b_y < y_max; b_y++) { for(uint32_t b_x = 0; b_x < x_max; b_x++) { // Get the map block DFHack::DFCoord blockCoord(b_x, b_y); MapExtras::Block *b = map.BlockAt(DFHack::DFCoord(b_x, b_y, z)); if (!b || !b->valid) { continue; } DFHack::t_blockflags flags = b->BlockFlags(); flags.whole = flags.whole ^ 0xFFFFFFFF; b->setBlockFlags(flags); b->Write(); } // block x } // block y } // z maps->Finish(); context->Detach(); return 0; }
int main(int argc, char** argv) { if(argc < 2) { ::std::cout << "gimme a file!" << ::std::endl; return 1; } ::std::ifstream map_in(argv[1]); ::std::vector< ::std::string > dig_map; while (map_in.good() && !map_in.eof() && !map_in.bad()) { ::std::string line; map_in >> line; dig_map.push_back(line); } dig_map.resize(dig_map.size() - 1); DFHack::ContextManager DFMgr("Memory.xml"); DFHack::Context * DF = DFMgr.getSingleContext(); try { DF->Attach(); } catch (::std::exception& e) { ::std::cerr << e.what() << ::std::endl; #ifndef LINUX_BUILD ::std::cin.ignore(); #endif return 1; } DFHack::Maps *layers = DF->getMaps(); if (layers && layers->Start()) { dig(layers, DF->getGui(), dig_map, true); ::std::cout << "Finished digging" << ::std::endl; layers->Finish(); if (!DF->Detach()) { ::std::cerr << "Unable to detach DF process" << ::std::endl; } } else { ::std::cerr << "Unable to init map" << ::std::endl; } #ifndef LINUX_BUILD ::std::cout << "Done. Press any key to continue" << ::std::endl; ::std::cin.ignore(); #endif return 0; }
DFhackCExport command_result df_flows (Core * c, vector <string> & parameters) { uint32_t x_max,y_max,z_max; DFHack::designations40d designations; DFHack::Maps *Maps; c->Suspend(); Maps = c->getMaps(); // init the map if(!Maps->Start()) { c->con.printerr("Can't init map.\n"); c->Resume(); return CR_FAILURE; } DFHack::t_blockflags bflags; Maps->getSize(x_max,y_max,z_max); // walk the map, count flowing tiles, magma, water uint32_t flow1=0, flow2=0, flowboth=0, water=0, magma=0; c->con.print("Counting flows and liquids ...\n"); for(uint32_t x = 0; x< x_max;x++) { for(uint32_t y = 0; y< y_max;y++) { for(uint32_t z = 0; z< z_max;z++) { if(Maps->getBlock(x,y,z)) { Maps->ReadBlockFlags(x, y, z, bflags); Maps->ReadDesignations(x, y, z, &designations); if (bflags.bits.liquid_1) flow1++; if (bflags.bits.liquid_2) flow2++; if (bflags.bits.liquid_1 && bflags.bits.liquid_2) flowboth++; for (uint32_t i = 0; i < 16;i++) for (uint32_t j = 0; j < 16;j++) { if (designations[i][j].bits.liquid_type == DFHack::liquid_magma) magma++; if (designations[i][j].bits.liquid_type == DFHack::liquid_water) water++; } } } } } c->con.print("Blocks with liquid_1=true: %d\n" "Blocks with liquid_2=true: %d\n" "Blocks with both: %d\n" "Water tiles: %d\n" "Magma tiles: %d\n" ,flow1, flow2, flowboth, water, magma ); c->Resume(); return CR_OK; }
DFhackCExport command_result cleanmap (Core * c, vector <string> & parameters) { const uint32_t water_idx = 6; const uint32_t mud_idx = 12; bool snow = false; bool mud = false; bool help = false; for(int i = 0; i < parameters.size();i++) { if(parameters[i] == "snow") snow = true; else if(parameters[i] == "mud") mud = true; else if(parameters[i] == "help" ||parameters[i] == "?") { help = true; } } if(help) { c->con.print("This command cleans the coverings from the map. Snow and mud are ignored by default.\n" "Options:\n" "snow - also remove snow\n" "mud - also remove mud\n" ); return CR_OK; } c->Suspend(); vector<DFHack::t_spattervein *> splatter; DFHack::Maps *Mapz = c->getMaps(); // init the map if(!Mapz->Start()) { c->con << "Can't init map." << std::endl; c->Resume(); return CR_FAILURE; } uint32_t x_max,y_max,z_max; Mapz->getSize(x_max,y_max,z_max); // walk the map for(uint32_t x = 0; x< x_max;x++) { for(uint32_t y = 0; y< y_max;y++) { for(uint32_t z = 0; z< z_max;z++) { df_block * block = Mapz->getBlock(x,y,z); if(block) { Mapz->SortBlockEvents(x,y,z,0,0,&splatter); for(int i = 0; i < 16; i++) for(int j = 0; j < 16; j++) { block->occupancy[i][j].bits.arrow_color = 0; block->occupancy[i][j].bits.broken_arrows_variant = 0; } for(uint32_t i = 0; i < splatter.size(); i++) { DFHack::t_spattervein * vein = splatter[i]; // filter snow if(!snow && vein->mat1 == water_idx && vein->matter_state == DFHack::state_powder) continue; // filter mud if(!mud && vein->mat1 == mud_idx && vein->matter_state == DFHack::state_solid) continue; Mapz->RemoveBlockEvent(x,y,z,(t_virtual *) vein); } } } } } c->Resume(); return CR_OK; }
DFhackCExport command_result filltraffic(DFHack::Core * c, std::vector<std::string> & params) { //Maximum map size. uint32_t x_max,y_max,z_max; //Source and target traffic types. e_traffic source = traffic_normal; e_traffic target = traffic_normal; //Option flags bool updown = false; bool checkpit = true; bool checkbuilding = true; //Loop through parameters for(int i = 0; i < params.size();i++) { if(params[i] == "help" || params[i] == "?") { c->con.print("Flood-fill selected traffic type from the cursor.\n" "Traffic Type Codes:\n" "\tH: High Traffic\n" "\tN: Normal Traffic\n" "\tL: Low Traffic\n" "\tR: Restricted Traffic\n" "Other Options:\n" "\tX: Fill accross z-levels.\n" "\tB: Include buildings and stockpiles.\n" "\tP: Include empty space.\n" "Example:\n" "'filltraffic H' - When used in a room with doors,\n" " it will set traffic to HIGH in just that room." ); return CR_OK; } switch (toupper(params[i][0])) { case 'H': target = traffic_high; break; case 'N': target = traffic_normal; break; case 'L': target = traffic_low; break; case 'R': target = traffic_restricted; break; case 'X': updown = true; break; case 'B': checkbuilding = false; break; case 'P': checkpit = false; break; } } //Initialization. c->Suspend(); DFHack::Maps * Maps = c->getMaps(); DFHack::Gui * Gui = c->getGui(); // init the map if(!Maps->Start()) { c->con.printerr("Can't init map. Make sure you have a map loaded in DF.\n"); c->Resume(); return CR_FAILURE; } int32_t cx, cy, cz; Maps->getSize(x_max,y_max,z_max); uint32_t tx_max = x_max * 16; uint32_t ty_max = y_max * 16; Gui->getCursorCoords(cx,cy,cz); while(cx == -30000) { c->con.printerr("Cursor is not active.\n"); c->Resume(); return CR_FAILURE; } DFHack::DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz); MapExtras::MapCache * MCache = new MapExtras::MapCache(Maps); DFHack::t_designation des = MCache->designationAt(xy); int16_t tt = MCache->tiletypeAt(xy); DFHack::t_occupancy oc; if (checkbuilding) oc = MCache->occupancyAt(xy); source = des.bits.traffic; if(source == target) { c->con.printerr("This tile is already set to the target traffic type.\n"); delete MCache; c->Resume(); return CR_FAILURE; } if(DFHack::isWallTerrain(tt)) { c->con.printerr("This tile is a wall. Please select a passable tile.\n"); delete MCache; c->Resume(); return CR_FAILURE; } if(checkpit && DFHack::isOpenTerrain(tt)) { c->con.printerr("This tile is a hole. Please select a passable tile.\n"); delete MCache; c->Resume(); return CR_FAILURE; } if(checkbuilding && oc.bits.building) { c->con.printerr("This tile contains a building. Please select an empty tile.\n"); delete MCache; c->Resume(); return CR_FAILURE; } c->con.print("%d/%d/%d ... FILLING!\n", cx,cy,cz); //Naive four-way or six-way flood fill with possible tiles on a stack. stack <DFHack::DFCoord> flood; flood.push(xy); while(!flood.empty()) { xy = flood.top(); flood.pop(); des = MCache->designationAt(xy); if (des.bits.traffic != source) continue; tt = MCache->tiletypeAt(xy); if(DFHack::isWallTerrain(tt)) continue; if(checkpit && DFHack::isOpenTerrain(tt)) continue; if (checkbuilding) { oc = MCache->occupancyAt(xy); if(oc.bits.building) continue; } //This tile is ready. Set its traffic level and add surrounding tiles. if (MCache->testCoord(xy)) { des.bits.traffic = target; MCache->setDesignationAt(xy,des); if (xy.x > 0) { flood.push(DFHack::DFCoord(xy.x - 1, xy.y, xy.z)); } if (xy.x < tx_max - 1) { flood.push(DFHack::DFCoord(xy.x + 1, xy.y, xy.z)); } if (xy.y > 0) { flood.push(DFHack::DFCoord(xy.x, xy.y - 1, xy.z)); } if (xy.y < ty_max - 1) { flood.push(DFHack::DFCoord(xy.x, xy.y + 1, xy.z)); } if (updown) { if (xy.z > 0 && DFHack::LowPassable(tt)) { flood.push(DFHack::DFCoord(xy.x, xy.y, xy.z - 1)); } if (xy.z < z_max && DFHack::HighPassable(tt)) { flood.push(DFHack::DFCoord(xy.x, xy.y, xy.z + 1)); } } } } MCache->WriteAll(); c->Resume(); return CR_OK; }
DFhackCExport command_result tiletraffic(DFHack::Core * c, std::vector<std::string> & params) { //Target traffic types. e_traffic target = traffic_normal; //!!! Options Later !!! //Loop through parameters for(int i = 0; i < params.size();i++) { if(params[i] == "help" || params[i] == "?") { c->con.print("Set traffic types for all tiles on the map.\n" "Traffic Type Codes:\n" " H: High Traffic\n" " N: Normal Traffic\n" " L: Low Traffic\n" " R: Restricted Traffic\n" ); return CR_OK; } switch (toupper(params[i][0])) { case 'H': target = traffic_high; break; case 'N': target = traffic_normal; break; case 'L': target = traffic_low; break; case 'R': target = traffic_restricted; break; } } //Initialization. c->Suspend(); DFHack::Maps * Maps = c->getMaps(); DFHack::Gui * Gui = c->getGui(); // init the map if(!Maps->Start()) { c->con.printerr("Can't init map. Make sure you have a map loaded in DF.\n"); c->Resume(); return CR_FAILURE; } //Maximum map size. uint32_t x_max,y_max,z_max; Maps->getSize(x_max,y_max,z_max); uint32_t tx_max = x_max * 16; uint32_t ty_max = y_max * 16; MapExtras::MapCache * MCache = new MapExtras::MapCache(Maps); c->con.print("Entire map ... FILLING!\n"); //Loop through every single tile for(uint32_t x = 0; x <= tx_max; x++) { for(uint32_t y = 0; y <= ty_max; y++) { for(uint32_t z = 0; z <= z_max; z++) { DFHack::DFCoord tile = DFHack::DFCoord(x, y, z); DFHack::t_designation des = MCache->designationAt(tile); des.bits.traffic = target; MCache->setDesignationAt(tile, des); } } } MCache->WriteAll(); c->Resume(); return CR_OK; }
int main (int numargs, const char ** args) { map<string, string> buildCommands; buildCommands["building_stockpilest"]=""; buildCommands["building_zonest"]=""; buildCommands["building_construction_blueprintst"]=""; buildCommands["building_wagonst"]=""; buildCommands["building_armor_standst"]="a"; buildCommands["building_bedst"]="b"; buildCommands["building_seatst"]="c"; buildCommands["building_burial_receptaclest"]="n"; buildCommands["building_doorst"]="d"; buildCommands["building_floodgatest"]="x"; buildCommands["building_floor_hatchst"]="H"; buildCommands["building_wall_gratest"]="W"; buildCommands["building_floor_gratest"]="G"; buildCommands["building_vertical_barsst"]="B"; buildCommands["building_floor_barsst"]="alt-b"; buildCommands["building_cabinetst"]="f"; buildCommands["building_containerst"]="h"; buildCommands["building_shopst"]=""; buildCommands["building_workshopst"]=""; buildCommands["building_alchemists_laboratoryst"]="wa"; buildCommands["building_carpenters_workshopst"]="wc"; buildCommands["building_farmers_workshopst"]="ww"; buildCommands["building_masons_workshopst"]="wm"; buildCommands["building_craftdwarfs_workshopst"]="wr"; buildCommands["building_jewelers_workshopst"]="wj"; buildCommands["building_metalsmiths_workshopst"]="wf"; buildCommands["building_magma_forgest"]=""; buildCommands["building_bowyers_workshopst"]="wb"; buildCommands["building_mechanics_workshopst"]="wt"; buildCommands["building_siege_workshopst"]="ws"; buildCommands["building_butchers_shopst"]="wU"; buildCommands["building_leather_worksst"]="we"; buildCommands["building_tanners_shopst"]="wn"; buildCommands["building_clothiers_shopst"]="wk"; buildCommands["building_fisheryst"]="wh"; buildCommands["building_stillst"]="wl"; buildCommands["building_loomst"]="wo"; buildCommands["building_quernst"]="wq"; buildCommands["building_kennelsst"]="k"; buildCommands["building_kitchenst"]="wz"; buildCommands["building_asheryst"]="wy"; buildCommands["building_dyers_shopst"]="wd"; buildCommands["building_millstonest"]="wM"; buildCommands["building_farm_plotst"]="p"; buildCommands["building_weapon_rackst"]="r"; buildCommands["building_statuest"]="s"; buildCommands["building_tablest"]="t"; buildCommands["building_paved_roadst"]="o"; buildCommands["building_bridgest"]="g"; buildCommands["building_wellst"]="l"; buildCommands["building_siege enginest"]="i"; buildCommands["building_catapultst"]="ic"; buildCommands["building_ballistast"]="ib"; buildCommands["building_furnacest"]=""; buildCommands["building_wood_furnacest"]="ew"; buildCommands["building_smelterst"]="es"; buildCommands["building_glass_furnacest"]="ek"; buildCommands["building_kilnst"]="ek"; buildCommands["building_magma_smelterst"]="es"; buildCommands["building_magma_glass_furnacest"]="ek"; buildCommands["building_magma_kilnst"]="ek"; buildCommands["building_glass_windowst"]="y"; buildCommands["building_gem_windowst"]="Y"; buildCommands["building_tradedepotst"]="D"; buildCommands["building_mechanismst"]=""; buildCommands["building_leverst"]="Tl"; buildCommands["building_pressure_platest"]="Tp"; buildCommands["building_cage_trapst"]="Tc"; buildCommands["building_stonefall_trapst"]="Ts"; buildCommands["building_weapon_trapst"]="Tw"; buildCommands["building_spikest"]=""; buildCommands["building_animal_trapst"]="m"; buildCommands["building_screw_pumpst"]="Ms"; buildCommands["building_water_wheelst"]="Mw"; buildCommands["building_windmillst"]="Mm"; buildCommands["building_gear_assemblyst"]="Mg"; buildCommands["building_horizontal_axlest"]="Mh"; buildCommands["building_vertical_axlest"]="Mv"; buildCommands["building_supportst"]="S"; buildCommands["building_cagest"]="j"; buildCommands["building_archery_targetst"]="A"; buildCommands["building_restraintst"]="v"; DFHack::ContextManager DFMgr("Memory.xml"); DFHack::Context *DF = DFMgr.getSingleContext(); try { DF->Attach(); } catch (std::exception& e) { std::cerr << e.what() << std::endl; #ifndef LINUX_BUILD cin.ignore(); #endif return 1; } DFHack::Gui *Gui = DF->getGui(); DFHack::VersionInfo* mem = DF->getMemoryInfo(); DFHack::Process * p = DF->getProcess(); OffsetGroup * OG_Maps = mem->getGroup("Maps"); OffsetGroup * OG_MapBlock = OG_Maps->getGroup("block"); OffsetGroup * OG_LocalFt = OG_Maps->getGroup("features")->getGroup("local"); uint32_t designations = OG_MapBlock->getOffset("designation"); uint32_t block_feature1 = OG_MapBlock->getOffset("feature_local"); uint32_t block_feature2 = OG_MapBlock->getOffset("feature_global"); uint32_t region_x_offset = OG_Maps->getAddress("region_x"); uint32_t region_y_offset = OG_Maps->getAddress("region_y"); uint32_t region_z_offset = OG_Maps->getAddress("region_z"); uint32_t feature1_start_ptr = OG_LocalFt->getAddress("start_ptr"); int32_t regionX, regionY, regionZ; // read position of the region inside DF world p->readDWord (region_x_offset, (uint32_t &)regionX); p->readDWord (region_y_offset, (uint32_t &)regionY); p->readDWord (region_z_offset, (uint32_t &)regionZ); while(1){ int32_t cx1,cy1,cz1; cx1 = -30000; while(cx1 == -30000) { DF->ForceResume(); cout << "Set cursor at first position, then press any key"; cin.ignore(); DF->Suspend(); Gui->getCursorCoords(cx1,cy1,cz1); } uint32_t tx1,ty1,tz1; tx1 = cx1/16; ty1 = cy1/16; tz1 = cz1; int32_t cx2,cy2,cz2; cx2 = -30000; while(cx2 == -30000) { DF->Resume(); cout << "Set cursor at second position, then press any key"; cin.ignore(); DF->Suspend(); Gui->getCursorCoords(cx2,cy2,cz2); } uint32_t tx2,ty2,tz2; tx2 = cx2/16; ty2 = cy2/16; tz2 = cz2; sort(tx1,tx2); sort(ty1,ty2); sort(tz1,tz2); sort(cx1,cx2); sort(cy1,cy2); sort(cz1,cz2); vector <vector<vector<string> > >dig(cz2-cz1+1,vector<vector<string> >(cy2-cy1+1,vector<string>(cx2-cx1+1))); vector <vector<vector<string> > >build(cz2-cz1+1,vector<vector<string> >(cy2-cy1+1,vector<string>(cx2-cx1+1))); mapblock40d block; DFHack::Maps *Maps = DF->getMaps(); Maps->Start(); for(uint32_t y = ty1;y<=ty2;y++) { for(uint32_t x = tx1;x<=tx2;x++) { for(uint32_t z = tz1;z<=tz2;z++) { if(Maps->isValidBlock(x,y,z)) { if(Maps->ReadBlock40d(x,y,z,&block)) { int ystart,yend,xstart,xend; ystart=xstart=0; yend=xend=15; if(y == ty2) { yend = cy2 % 16; } if(y == ty1) { ystart = cy1 % 16; } if(x == tx2) { xend = cx2 % 16; } if(x == tx1) { xstart = cx1 % 16; } int zidx = z-tz1; for(int yy = ystart; yy <= yend;yy++) { int yidx = yy+(16*(y-ty1)-(cy1%16)); for(int xx = xstart; xx <= xend;xx++) { int xidx = xx+(16*(x-tx1)-(cx1%16)); int16_t tt = block.tiletypes[xx][yy]; DFHack::TileShape ts = DFHack::tileShape(tt); if(DFHack::isOpenTerrain(tt) || DFHack::isFloorTerrain(tt)) { dig[zidx][yidx][xidx] = "d"; } else if(DFHack::STAIR_DOWN == ts) { dig [zidx][yidx][xidx] = "j"; build [zidx][yidx][xidx] = "Cd"; } else if(DFHack::STAIR_UP == ts) { dig [zidx][yidx][xidx] = "u"; build [zidx][yidx][xidx] = "Cu"; } else if(DFHack::STAIR_UPDOWN == ts) { dig [zidx][yidx][xidx] = "i"; build [zidx][yidx][xidx] = "Cx"; } else if(DFHack::isRampTerrain(tt)) { dig [zidx][yidx][xidx] = "r"; build [zidx][yidx][xidx] = "Cr"; } else if(DFHack::isWallTerrain(tt)) { build [zidx][yidx][xidx] = "Cw"; } } yidx++; } } } } } } DFHack::Buildings * Bld = DF->getBuildings(); std::map <uint32_t, std::string> custom_workshop_types; uint32_t numBuildings; if(Bld->Start(numBuildings)) { Bld->ReadCustomWorkshopTypes(custom_workshop_types); for(uint32_t i = 0; i < numBuildings; i++) { DFHack::t_building temp; Bld->Read(i, temp); if(temp.type != 0xFFFFFFFF) // check if type isn't invalid { std::string typestr; mem->resolveClassIDToClassname(temp.type, typestr); if(temp.z == cz1 && cx1 <= temp.x1 && cx2 >= temp.x2 && cy1 <= temp.y1 && cy2 >= temp.y2) { string currStr = build[temp.z-cz1][temp.y1-cy1][temp.x1-cx1]; stringstream stream; string newStr = buildCommands[typestr]; if(temp.x1 != temp.x2) { stream << "(" << temp.x2-temp.x1+1 << "x" << temp.y2-temp.y1+1 << ")"; newStr += stream.str(); } build[temp.z-cz1][temp.y1-cy1][temp.x1-cx1] = newStr + currStr; } } } } // for testing purposes //ofstream outfile("test.txt"); // printVecOfVec(outfile, dig,'\t'); // outfile << endl; // printVecOfVec(outfile, build,'\t'); // outfile << endl; // outfile.close(); int32_t cx3,cy3,cz3,cx4,cy4,cz4; uint32_t tx3,ty3,tz3,tx4,ty4,tz4; char result; while(1){ cx3 = -30000; while(cx3 == -30000){ DF->Resume(); cout << "Set cursor at new position, then press any key:"; result = cin.get(); DF->Suspend(); Gui->getCursorCoords(cx3,cy3,cz3); } if(result == 'q'){ break; } cx4 = cx3+cx2-cx1; cy4 = cy3+cy2-cy1; cz4 = cz3+cz2-cz1; tx3=cx3/16; ty3=cy3/16; tz3=cz3; tx4=cx4/16; ty4=cy4/16; tz4=cz4; DFHack::WindowIO * Win = DF->getWindowIO(); designations40d designationBlock; for(uint32_t y = ty3;y<=ty4;y++) { for(uint32_t x = tx3;x<=tx4;x++) { for(uint32_t z = tz3;z<=tz4;z++) { Maps->Start(); Maps->ReadBlock40d(x,y,z,&block); Maps->ReadDesignations(x,y,z,&designationBlock); int ystart,yend,xstart,xend; ystart=xstart=0; yend=xend=15; if(y == ty4){ yend = cy4 % 16; } if(y == ty3){ ystart = cy3 % 16; } if(x == tx4){ xend = cx4 % 16; } if(x == tx3){ xstart = cx3 % 16; } int zidx = z-tz3; for(int yy = ystart; yy <= yend;yy++){ int yidx = yy+(16*(y-ty3)-(cy3%16)); for(int xx = xstart; xx <= xend;xx++){ int xidx = xx+(16*(x-tx3)-(cx3%16)); if(dig[zidx][yidx][xidx] != ""){ char test = dig[zidx][yidx][xidx].c_str()[0]; switch (test){ case 'd': designationBlock[xx][yy].bits.dig = DFHack::designation_default; break; case 'i': designationBlock[xx][yy].bits.dig = DFHack::designation_ud_stair; break; case 'u': designationBlock[xx][yy].bits.dig = DFHack::designation_u_stair; break; case 'j': designationBlock[xx][yy].bits.dig = DFHack::designation_d_stair; break; case 'r': designationBlock[xx][yy].bits.dig = DFHack::designation_ramp; break; } } } yidx++; } Maps->Start(); Maps->WriteDesignations(x,y,z,&designationBlock); } } } } } DF->Detach(); #ifndef LINUX_BUILD std::cout << "Done. Press any key to continue" << std::endl; cin.ignore(); #endif return 0; }
DFhackCExport command_result vdig (Core * c, vector <string> & parameters) { uint32_t x_max,y_max,z_max; bool updown = false; for(int i = 0; i < parameters.size();i++) { if(parameters.size() && parameters[0]=="x") updown = true; else if(parameters[i] == "help" || parameters[i] == "?") { c->con.print("Designates a whole vein under the cursor for digging.\n" "Options:\n" "x - follow veins through z-levels with stairs.\n" ); return CR_OK; } } Console & con = c->con; c->Suspend(); DFHack::Maps * Maps = c->getMaps(); DFHack::Gui * Gui = c->getGui(); // init the map if(!Maps->Start()) { con.printerr("Can't init map. Make sure you have a map loaded in DF.\n"); c->Resume(); return CR_FAILURE; } int32_t cx, cy, cz; Maps->getSize(x_max,y_max,z_max); uint32_t tx_max = x_max * 16; uint32_t ty_max = y_max * 16; Gui->getCursorCoords(cx,cy,cz); while(cx == -30000) { con.printerr("Cursor is not active. Point the cursor at a vein.\n"); c->Resume(); return CR_FAILURE; } DFHack::DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz); if(xy.x == 0 || xy.x == tx_max - 1 || xy.y == 0 || xy.y == ty_max - 1) { con.printerr("I won't dig the borders. That would be cheating!\n"); c->Resume(); return CR_FAILURE; } MapExtras::MapCache * MCache = new MapExtras::MapCache(Maps); DFHack::t_designation des = MCache->designationAt(xy); int16_t tt = MCache->tiletypeAt(xy); int16_t veinmat = MCache->veinMaterialAt(xy); if( veinmat == -1 ) { con.printerr("This tile is not a vein.\n"); delete MCache; c->Resume(); return CR_FAILURE; } con.print("%d/%d/%d tiletype: %d, veinmat: %d, designation: 0x%x ... DIGGING!\n", cx,cy,cz, tt, veinmat, des.whole); stack <DFHack::DFCoord> flood; flood.push(xy); while( !flood.empty() ) { DFHack::DFCoord current = flood.top(); flood.pop(); int16_t vmat2 = MCache->veinMaterialAt(current); tt = MCache->tiletypeAt(current); if(!DFHack::isWallTerrain(tt)) continue; if(vmat2!=veinmat) continue; // found a good tile, dig+unset material DFHack::t_designation des = MCache->designationAt(current); DFHack::t_designation des_minus; DFHack::t_designation des_plus; des_plus.whole = des_minus.whole = 0; int16_t vmat_minus = -1; int16_t vmat_plus = -1; bool below = 0; bool above = 0; if(updown) { if(MCache->testCoord(current-1)) { below = 1; des_minus = MCache->designationAt(current-1); vmat_minus = MCache->veinMaterialAt(current-1); } if(MCache->testCoord(current+1)) { above = 1; des_plus = MCache->designationAt(current+1); vmat_plus = MCache->veinMaterialAt(current+1); } } if(MCache->testCoord(current)) { MCache->clearMaterialAt(current); if(current.x < tx_max - 2) { flood.push(DFHack::DFCoord(current.x + 1, current.y, current.z)); if(current.y < ty_max - 2) { flood.push(DFHack::DFCoord(current.x + 1, current.y + 1,current.z)); flood.push(DFHack::DFCoord(current.x, current.y + 1,current.z)); } if(current.y > 1) { flood.push(DFHack::DFCoord(current.x + 1, current.y - 1,current.z)); flood.push(DFHack::DFCoord(current.x, current.y - 1,current.z)); } } if(current.x > 1) { flood.push(DFHack::DFCoord(current.x - 1, current.y,current.z)); if(current.y < ty_max - 2) { flood.push(DFHack::DFCoord(current.x - 1, current.y + 1,current.z)); flood.push(DFHack::DFCoord(current.x, current.y + 1,current.z)); } if(current.y > 1) { flood.push(DFHack::DFCoord(current.x - 1, current.y - 1,current.z)); flood.push(DFHack::DFCoord(current.x, current.y - 1,current.z)); } } if(updown) { if(current.z > 0 && below && vmat_minus == vmat2) { flood.push(current-1); if(des_minus.bits.dig == DFHack::designation_d_stair) des_minus.bits.dig = DFHack::designation_ud_stair; else des_minus.bits.dig = DFHack::designation_u_stair; MCache->setDesignationAt(current-1,des_minus); des.bits.dig = DFHack::designation_d_stair; } if(current.z < z_max - 1 && above && vmat_plus == vmat2) { flood.push(current+ 1); if(des_plus.bits.dig == DFHack::designation_u_stair) des_plus.bits.dig = DFHack::designation_ud_stair; else des_plus.bits.dig = DFHack::designation_d_stair; MCache->setDesignationAt(current+1,des_plus); if(des.bits.dig == DFHack::designation_d_stair) des.bits.dig = DFHack::designation_ud_stair; else des.bits.dig = DFHack::designation_u_stair; } } if(des.bits.dig == DFHack::designation_no) des.bits.dig = DFHack::designation_default; MCache->setDesignationAt(current,des); } } MCache->WriteAll(); c->Resume(); return CR_OK; }
int main (void) { uint32_t x_max,y_max,z_max; DFHack::designations40d designations; DFHack::ContextManager DFMgr("Memory.xml"); DFHack::Context *DF; try { DF = DFMgr.getSingleContext(); DF->Attach(); } catch (exception& e) { cerr << e.what() << endl; #ifndef LINUX_BUILD cin.ignore(); #endif return 1; } DFHack::Maps *Maps =DF->getMaps(); DFHack::Gui *Gui =DF->getGui(); // walk the map, save the hide bits, reveal. cout << "Pausing..." << endl; // horrible hack to make sure the pause is really set // preblem here is that we could be 'arriving' at the wrong time and DF could be in the middle of a frame. // that could mean that revealing, even with suspending DF's thread, would mean unleashing hell *in the same frame* // this here hack sets the pause state, resumes DF, waits a second for it to enter the pause (I know, BS value.) and suspends. Gui->SetPauseState(true); DF->Resume(); waitmsec(1000); DF->Suspend(); // init the map if(!Maps->Start()) { cerr << "Can't init map." << endl; #ifndef LINUX_BUILD cin.ignore(); #endif return 1; } cout << "Revealing, please wait..." << endl; Maps->getSize(x_max,y_max,z_max); vector <hideblock> hidesaved; for(uint32_t x = 0; x< x_max;x++) { for(uint32_t y = 0; y< y_max;y++) { for(uint32_t z = 0; z< z_max;z++) { if(Maps->isValidBlock(x,y,z)) { hideblock hb; hb.x = x; hb.y = y; hb.z = z; // read block designations Maps->ReadDesignations(x,y,z, &designations); // change the hidden flag to 0 for (uint32_t i = 0; i < 16;i++) for (uint32_t j = 0; j < 16;j++) { hb.hiddens[i][j] = designations[i][j].bits.hidden; designations[i][j].bits.hidden = 0; } hidesaved.push_back(hb); // write the designations back Maps->WriteDesignations(x,y,z, &designations); } } } } // FIXME: force game pause here! DF->Detach(); cout << "Map revealed. The game has been paused for you." << endl; cout << "Unpausing can unleash the forces of hell!" << endl << endl; cout << "Press any key to unreveal." << endl; cout << "Close to keep the map revealed." << endl; cin.ignore(); cout << "Unrevealing... please wait." << endl; // FIXME: do some consistency checks here! DF->Attach(); Maps = DF->getMaps(); Maps->Start(); for(int i = 0; i < hidesaved.size();i++) { hideblock & hb = hidesaved[i]; Maps->ReadDesignations(hb.x,hb.y,hb.z, &designations); for (uint32_t i = 0; i < 16;i++) for (uint32_t j = 0; j < 16;j++) { designations[i][j].bits.hidden = hb.hiddens[i][j]; } Maps->WriteDesignations(hb.x,hb.y,hb.z, &designations); } #ifndef LINUX_BUILD cout << "Done. Press any key to continue" << endl; cin.ignore(); #endif return 0; }
int main (void) { int32_t x,y,z,tx,ty; //DFHack::designations40d designations; DFHack::tiletypes40d tiles; //DFHack::t_temperatures temp1,temp2; uint32_t x_max,y_max,z_max; int32_t oldT, newT; int count, dirty; //Brush defaults DFHack::TileShape BrushClass = DFHack::WALL; DFHack::TileMaterial BrushMat = DFHack::tilematerial_invalid; int BrushType = -1; DFHack::ContextManager DFMgr("Memory.xml"); DFHack::Context *DF; DFHack::Maps * Maps; DFHack::Gui * Gui; try { DF=DFMgr.getSingleContext(); DF->Attach(); Maps = DF->getMaps(); Maps->Start(); Maps->getSize(x_max,y_max,z_max); Gui = DF->getGui(); } catch (exception& e) { cerr << e.what() << endl; #ifndef LINUX_BUILD cin.ignore(); #endif return 1; } bool end = false; cout << "Welcome to the Tile Drawing tool.\nType 'help' or ? for a list of available commands, 'q' to quit" << endl; string mode = "wall"; string command = ""; while(!end) { DF->Resume(); cout << endl << ":"; getline(cin, command); int ch = command[0]; if(command.length()<=0) ch=0; if( ((int)command.find("help")) >=0 ) ch='?'; //under windows, find was casting unsigned! switch(ch) { case '?': cout << "Modes:" << endl << "O - draw Open Space" << endl << "M - draw material only (shape unchanged)" << endl << "m number - use Material value entered" << endl << "r - use Rock/stone material" << endl << "l - use Soil material" << endl << "v - use Vein material" << endl << "H - draw tile shape only (material unchanged)" << endl << "h number - draw Tile Shape value entered" << endl << "w - draw Wall tiles" << endl << "f - draw Floor tiles" << endl << "t number - draw exact tile type entered" << endl << "Commands:" << endl << "p - print tile shapes and materials, and current brush" << endl << "P - print all tile types" << endl << "q - quit" << endl << "help OR ? - print this list of commands" << endl << "d - being drawing" << endl << endl << "Usage:\nChoose a mode (default is walls), then enter 'd' to being drawing.\nMove the cursor in DF wherever you want to draw.\nPress any key to pause drawing." << endl; break; case 'p': //Classes printf("\nTile Type Classes:\n"); for(int i=0;i<DFHack::tileshape_count;++i) { printf("%4i ; %s\n", i, DFHack::TileShapeString[i] ,0 ); } //Materials printf("\nTile Type Materials:\n"); for(int i=0;i<DFHack::tilematerial_count;++i) { printf("%4i ; %s\n", i, DFHack::TileMaterialString[i] ,0 ); } //fall through... case 10: case 13: case 0: //Print current cursor & brush settings. cout << "\nCurrent Brush:\n"; cout << "tile = "; if(BrushClass<0) cout<<"(not drawing)"; else cout<<DFHack::TileShapeString[BrushClass]; cout << endl; cout << "mat = "; if(BrushMat<0) cout<<"(not drawing)"; else cout<<DFHack::TileMaterialString[BrushMat]; cout << endl; cout << "type = "; if(BrushType<0){ cout<<"(not drawing)"; }else{ printtiletype(BrushType); } break; case 'P': cout << "\nAll Valid Tile Types:\n"; for(int i=0;i<TILE_TYPE_ARRAY_LENGTH;++i) { if( DFHack::tileTypeTable[i].name ) printtiletype(i); } case 'w': BrushType=-1; BrushClass = DFHack::WALL; cout << "Tile brush shape set to Wall." << endl; break; case 'f': BrushType=-1; BrushClass = DFHack::FLOOR; cout << "Tile brush shape set to Floor." << endl; break; case 'h': BrushType=-1; BrushClass = (DFHack::TileShape)atol( command.c_str()+1 ); cout << "Tile brush shape set to " << BrushClass << endl; break; case 'M': BrushClass = DFHack::tileshape_invalid; cout << "Tile brush will not draw tile shape." << endl; break; case 'r': BrushType=-1; BrushMat = DFHack::STONE; cout << "Tile brush material set to Rock." << endl; break; case 'l': BrushType=-1; BrushMat = DFHack::SOIL; cout << "Tile brush material set to Soil." << endl; break; case 'v': BrushType=-1; BrushMat = DFHack::VEIN; cout << "Tile brush material set to Vein." << endl; break; case 'm': BrushType=-1; BrushMat = (DFHack::TileMaterial)atol( command.c_str()+1 ); cout << "Tile brush material set to " << BrushMat << endl; break; case 'H': BrushMat = DFHack::tilematerial_invalid; cout << "Tile brush will not draw material." << endl; break; case 'O': BrushType=-1; BrushClass = DFHack::EMPTY; BrushMat = DFHack::AIR; cout << "Tile brush will draw Open Space." << endl; break; case 't': BrushClass = DFHack::tileshape_invalid ; BrushMat = DFHack::tilematerial_invalid; BrushType = atol( command.c_str()+1 ); cout << "Tile brush type set to:" << endl; printtiletype(BrushType); break; case 'q': end = true; cout << "Bye!" << endl; break; case 'd': { count=0; cout << "Beginning to draw at cursor." << endl << "Press any key to stop drawing." << endl; //DF->Suspend(); kbhit(); //throw away, just to be sure. for(;;) { if(!Maps->Start()) { cout << "Can't see any DF map loaded." << endl; break; } if(!Gui->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; tx=x%16; ty=y%16; if(!Maps->isValidBlock(x/16,y/16,z)) { cout << "Invalid block." << endl; break; } //Read the tiles. dirty=0; Maps->ReadTileTypes((x/16),(y/16),z, &tiles); oldT = tiles[tx][ty]; newT = -1; if( 0<BrushType ){ //Explicit tile type set. Trust the user. newT = BrushType; }else if( 0==BrushMat && 0==BrushClass ){ //Special case, Empty Air. newT = 32; }else if( BrushMat>=0 && BrushClass>=0 && ( BrushClass != DFHack::tileTypeTable[oldT].shape || BrushMat != DFHack::tileTypeTable[oldT].material) ){ //Set tile material and class newT = DFHack::findTileType(BrushClass,BrushMat, DFHack::tileTypeTable[oldT].variant , DFHack::tileTypeTable[oldT].special , DFHack::tileTypeTable[oldT].direction ); if(newT<0) newT = DFHack::findTileType(BrushClass,BrushMat, DFHack::tilevariant_invalid, DFHack::tileTypeTable[oldT].special , DFHack::tileTypeTable[oldT].direction ); if(newT<0) newT = DFHack::findTileType(BrushClass,BrushMat, DFHack::tilevariant_invalid , DFHack::tileTypeTable[oldT].special , (uint32_t)0 ); }else if( BrushMat<0 && BrushClass>=0 && BrushClass != DFHack::tileTypeTable[oldT].shape ){ //Set current tile class only, as accurately as can be expected newT = DFHack::findSimilarTileType(oldT,BrushClass); }else if( BrushClass<0 && BrushMat>=0 && BrushMat != DFHack::tileTypeTable[oldT].material ){ //Set current tile material only newT = DFHack::findTileType(DFHack::tileTypeTable[oldT].shape,BrushMat, DFHack::tileTypeTable[oldT].variant , DFHack::tileTypeTable[oldT].special , DFHack::tileTypeTable[oldT].direction ); if(newT<0) newT = DFHack::findTileType(DFHack::tileTypeTable[oldT].shape,BrushMat, DFHack::tilevariant_invalid , DFHack::tileTypeTable[oldT].special , DFHack::tileTypeTable[oldT].direction ); if(newT<0) newT = DFHack::findTileType(DFHack::tileTypeTable[oldT].shape,BrushMat, DFHack::tilevariant_invalid , DFHack::tileTypeTable[oldT].special , (uint32_t)0 ); } //If no change, skip it (couldn't find a good tile type, or already what we want) if ( newT > 0 && oldT != newT ){ //Set new tile type tiles[tx][ty] = newT; dirty=-1; } //If anything was changed, write it all. if (dirty) { //Maps->WriteDesignations(x/16,y/16,z/16, &designations); Maps->WriteTileTypes(x/16,y/16,z, &tiles); printf("(%4d,%4d,%4d)",x,y,z); ++count; } Maps->Finish(); Sleep(10); if( kbhit() ) break; } cin.clear(); cout << endl << count << " tiles were drawn." << endl << "Drawing halted. Entering command mode." << endl; } continue; break; default: cout << "Unknown command: " << command << endl; } } DF->Detach(); #ifndef LINUX_BUILD cout << "Done. Press any key to continue" << endl; cin.ignore(); #endif return 0; }
/** * Book of Immolations, chapter 1, verse 35: * Armok emerged from the hellish depths and beheld the sunny realms for the first time. * And he cursed the plants and trees for their bloodless wood, turning them into ash and smoldering ruin. * Armok was pleased and great temples were built by the dwarves, for they shared his hatred for trees and plants. */ static command_result immolations (Core * c, do_what what, bool shrubs, bool trees, bool help) { static const char * what1 = "destroys"; static const char * what2 = "burns"; if(help) { c->con.print("Without any options, this command %s a plant under the cursor.\n" "Options:\n" "shrubs - affect all shrubs\n" "trees - affect all trees\n" "all - affect all plants\n", what == do_immolate? what2 : what1 ); return CR_OK; } c->Suspend(); DFHack::Maps *maps = c->getMaps(); if (!maps->Start()) { c->con.printerr( "Cannot get map info!\n"); c->Resume(); return CR_FAILURE; } DFHack::Gui * Gui = c->getGui(); uint32_t x_max, y_max, z_max; maps->getSize(x_max, y_max, z_max); MapExtras::MapCache map(maps); 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++) { DFHack::df_plant *p = veg->all_plants->at(i); if(shrubs && p->is_shrub || trees && !p->is_shrub) { if (what == do_immolate) p->is_burning = true; p->hitpoints = 0; destroyed ++; } } c->con.print("Praise Armok!\n"); } else { int32_t x,y,z; if(Gui->getCursorCoords(x,y,z)) { vector<DFHack::df_plant *> * 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) { if(what == do_immolate) tree->is_burning = true; tree->hitpoints = 0; didit = true; break; } } /* if(!didit) { cout << "----==== There's NOTHING there! ====----" << endl; } */ } } else { c->con.printerr("No mass destruction and no cursor...\n" ); } } // Cleanup veg->Finish(); maps->Finish(); c->Resume(); return CR_OK; }
DFhackCExport command_result df_grow (Core * c, vector <string> & parameters) { for(int i = 0; i < parameters.size();i++) { if(parameters[i] == "help" || parameters[i] == "?") { c->con.print("This command turns all living saplings into full-grown trees.\n"); return CR_OK; } } c->Suspend(); DFHack::Maps *maps = c->getMaps(); Console & con = c->con; if (!maps->Start()) { con.printerr("Cannot get map info!\n"); c->Resume(); return CR_FAILURE; } //maps->getSize(x_max, y_max, z_max); MapExtras::MapCache map(maps); 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<DFHack::df_plant *> * 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) { if(DFHack::tileShape(map.tiletypeAt(DFHack::DFCoord(x,y,z))) == DFHack::SAPLING_OK) { tree->grow_counter = DFHack::sapling_to_tree_threshold; } break; } } } } else { int grown = 0; for(size_t i = 0 ; i < veg->all_plants->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) { p->grow_counter = DFHack::sapling_to_tree_threshold; } } } // Cleanup veg->Finish(); maps->Finish(); c->Resume(); return CR_OK; }
int main (void) { bool temporary_terminal = TemporaryTerminal(); uint32_t x_max,y_max,z_max; DFHack::designations40d designations; DFHack::tiletypes40d tiles; int32_t oldT, newT; uint64_t count = 0; int dirty=0; DFHack::ContextManager DFMgr("Memory.xml"); DFHack::Context *DF = DFMgr.getSingleContext(); //Init try { DF->Attach(); } catch (exception& e) { cerr << e.what() << endl; if(temporary_terminal) cin.ignore(); return 1; } DFHack::Maps *Mapz = DF->getMaps(); // init the map if (!Mapz->Start()) { cerr << "Can't init map." << endl; if(temporary_terminal) cin.ignore(); return 1; } Mapz->getSize(x_max,y_max,z_max); if(!Mapz->StartFeatures()) { cerr << "Can't get features." << endl; if(temporary_terminal) cin.ignore(); return 1; } // walk the map for (uint32_t x = 0; x< x_max;x++) { for (uint32_t y = 0; y< y_max;y++) { for (uint32_t z = 0; z< z_max;z++) { DFHack::t_feature * locf = 0; DFHack::t_feature * glof = 0; if (Mapz->ReadFeatures(x,y,z,&locf,&glof)) { // we're looking for addy tubes if(!locf) continue; if(locf->type != DFHack::feature_Adamantine_Tube) continue; dirty=0; Mapz->ReadDesignations(x,y,z, &designations); Mapz->ReadTileTypes(x,y,z, &tiles); for (uint32_t ty=0;ty<16;++ty) { for (uint32_t tx=0;tx<16;++tx) { if(!designations[tx][ty].bits.feature_local) continue; oldT = tiles[tx][ty]; if ( DFHack::tileShape(oldT) != DFHack::WALL ) { //Current tile is not a wall. //Set current tile, as accurately as can be expected //newT = DFHack::findSimilarTileType(oldT,DFHack::WALL); newT = DFHack::findTileType( DFHack::WALL, DFHack::FEATSTONE, DFHack::tilevariant_invalid, DFHack::TILE_NORMAL, DFHack::TileDirection() ); //If no change, skip it (couldn't find a good tile type) if ( oldT == newT) continue; //Set new tile type, clear designation tiles[tx][ty] = newT; dirty=1; ++count; } } } //If anything was changed, write it all. if (dirty) { Mapz->WriteTileTypes(x,y,z, &tiles); } } } } } DF->Detach(); cout << "Found and changed " << count << " tiles." << endl; if(temporary_terminal) { cout << "Done. Press any key to continue" << endl; cin.ignore(); } return 0; }
int main (int argc, const char* argv[]) { // Command line options bool updown = false; bool quiet = true; // let's be more useful when double-clicked on windows #ifndef LINUX_BUILD quiet = false; #endif int dig_up_n = 5; int dig_down_n = 5; for(int i = 1; i < argc; i++) { string arg_cur = argv[i]; string arg_next = ""; int arg_next_int = -99999; /* Check if argv[i+1] is a number >= 0 */ if (i < argc-1) { arg_next = argv[i+1]; arg_next_int = strtoint(arg_next); if (arg_next != "0" && arg_next_int == 0) { arg_next_int = -99999; } } if (arg_cur == "-x") { updown = true; } else if (arg_cur == "-q") { quiet = true; } else if(arg_cur == "-u" && i < argc-1) { if (arg_next_int < 0 || arg_next_int >= 99999) { usage(argc, argv); return 1; } dig_up_n = arg_next_int; i++; } else if(arg_cur == "-d" && i < argc-1) { if (arg_next_int < 0 || arg_next_int >= 99999) { usage(argc, argv); return 1; } dig_down_n = arg_next_int; i++; } else { usage(argc, argv); return 1; } } DFHack::ContextManager DFMgr("Memory.xml"); DFHack::Context * DF; try { DF = DFMgr.getSingleContext(); DF->Attach(); } catch (exception& e) { cerr << "Error getting context: " << e.what() << endl; if (!quiet) cin.ignore(); return 1; } uint32_t x_max,y_max,z_max; DFHack::Maps * Maps = DF->getMaps(); DFHack::Gui * Gui = DF->getGui(); // init the map if(!Maps->Start()) { cerr << "Can't init map. Make sure you have a map loaded in DF." << endl; DF->Detach(); if (!quiet) cin.ignore(); return 1; } int32_t cx, cy, cz; Maps->getSize(x_max,y_max,z_max); uint32_t tx_max = x_max * 16; uint32_t ty_max = y_max * 16; Gui->getCursorCoords(cx,cy,cz); if (cx == -30000) { cerr << "Cursor is not active. Point the cursor at the position to dig at." << endl; DF->Detach(); if (!quiet) { cin.ignore(); } return 1; } DFHack::DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz); if(xy.x == 0 || xy.x == tx_max - 1 || xy.y == 0 || xy.y == ty_max - 1) { cerr << "I won't dig the borders. That would be cheating!" << endl; DF->Detach(); if (!quiet) { cin.ignore(); } return 1; } MapCache * MCache = new MapCache(Maps); DFHack::t_designation des = MCache->designationAt(xy); int16_t tt = MCache->tiletypeAt(xy); int16_t veinmat = MCache->veinMaterialAt(xy); /* if( veinmat == -1 ) { cerr << "This tile is non-vein. Bye :)" << endl; delete MCache; DF->Detach(); if (!quiet) { cin.ignore(); } return 1; } */ printf("Digging at (%d/%d/%d), tiletype: %d, veinmat: %d, designation: 0x%x ... DIGGING!\n", cx,cy,cz, tt, veinmat, des.whole); // 1 < xy.x < tx_max - 1 // 1 < xy.y < ty_max - 1 // xy.z // X____ // X_XXX // XXXXX // __XXX // __XXX // _____ pos map[] = { { 0,0 } , { 0,1 } , { 0,2 } , { 2,2 }, { 3,2 }, { 4,2 } , { 0,3 }, { 1,3 }, { 2,3 }, { 3,3 }, { 4,3 } , { 2,4 }, { 3,4 }, { 4,4 } // this is mirrored, goes left instead of right , {-2,2 }, {-3,2 }, {-4,2 } , {-1,3 }, {-2,3 }, {-3,3 }, {-4,3 } , {-2,4 }, {-3,4 }, {-4,4 } }; DFHack::DFCoord npos = xy; if (dig_up_n > 0) { for (int j = 0; j < dig_up_n; j++) { for (int i = 0; i < sizeof(map)/sizeof(map[0]); i++) { npos=xy; npos.x += map[i].x; npos.y -= 4*j + map[i].y; printf("Digging at (%d/%d/%d)\n", npos.x, npos.y, npos.z); digat(MCache, npos); } } } if (dig_down_n > 0) { for (int j = 0; j < dig_down_n; j++) { for (int i = 0; i < sizeof(map)/sizeof(map[0]); i++) { npos=xy; npos.x += map[i].x; npos.y += 4*j + map[i].y; printf("Digging at (%d/%d/%d)\n", npos.x, npos.y, npos.z); digat(MCache, npos); } } } MCache->WriteAll(); delete MCache; DF->Detach(); if (!quiet) { cout << "Done. Press any key to continue" << endl; cin.ignore(); } return 0; }
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; } } uint32_t x_max,y_max,z_max; vector<DFHack::t_spattervein> splatter; DFHack::ContextManager DFMgr("Memory.xml"); DFHack::Context *DF = DFMgr.getSingleContext(); try { DF->Attach(); } catch (exception& e) { cerr << e.what() << endl; if(temporary_terminal) cin.ignore(); return 1; } DFHack::Maps *Mapz = DF->getMaps(); // init the map if(!Mapz->Start()) { cerr << "Can't init map." << endl; if(temporary_terminal) cin.ignore(); return 1; } Mapz->getSize(x_max,y_max,z_max); uint8_t zeroes [16][16] = {{0}}; DFHack::occupancies40d occ; // walk the map for(uint32_t x = 0; x< x_max;x++) { for(uint32_t y = 0; y< y_max;y++) { for(uint32_t z = 0; z< z_max;z++) { if(Mapz->isValidBlock(x,y,z)) { Mapz->ReadVeins(x,y,z,0,0,&splatter); Mapz->ReadOccupancy(x,y,z,&occ); for(int i = 0; i < 16; i++) for(int j = 0; j < 16; j++) { occ[i][j].bits.arrow_color = 0; occ[i][j].bits.broken_arrows_variant = 0; } Mapz->WriteOccupancy(x,y,z,&occ); for(uint32_t i = 0; i < splatter.size(); i++) { DFHack::t_spattervein & vein = splatter[i]; // filter snow if(vein.mat1 == water_idx && vein.matter_state == DFHack::state_powder) continue; // filter mud if(vein.mat1 == mud_idx && vein.matter_state == DFHack::state_solid) continue; uint32_t addr = vein.address_of; uint32_t offset = offsetof(DFHack::t_spattervein, intensity); // TODO: make this actually destroy the objects/remove them from the vector? // still, this is safe. DF->WriteRaw(addr + offset,sizeof(zeroes),(uint8_t *) zeroes); } } } } } DF->Detach(); if (!quiet && temporary_terminal) { cout << "Done. Press any key to continue" << endl; cin.ignore(); } return 0; }
DFhackCExport command_result tubefill(DFHack::Core * c, std::vector<std::string> & params) { uint32_t x_max,y_max,z_max; DFHack::designations40d designations; DFHack::tiletypes40d tiles; int32_t oldT, newT; uint64_t count = 0; int dirty=0; for(int i = 0; i < params.size();i++) { if(params[i] == "help" || params[i] == "?") { c->con.print("Replenishes mined out adamantine and hollow adamantine tubes.\n" "May cause !!FUN!!\n" ); return CR_OK; } } c->Suspend(); DFHack::Maps *Mapz = c->getMaps(); // init the map if (!Mapz->Start()) { c->con.printerr("Can't init map.\n"); c->Resume(); return CR_FAILURE; } Mapz->getSize(x_max,y_max,z_max); if(!Mapz->StartFeatures()) { c->con.printerr("Can't get map features.\n"); c->Resume(); return CR_FAILURE; } // walk the map for (uint32_t x = 0; x< x_max;x++) { for (uint32_t y = 0; y< y_max;y++) { for (uint32_t z = 0; z< z_max;z++) { DFHack::t_feature * locf = 0; DFHack::t_feature * glof = 0; if (Mapz->ReadFeatures(x,y,z,&locf,&glof)) { // we're looking for addy tubes if(!locf) continue; if(locf->type != DFHack::feature_Adamantine_Tube) continue; dirty=0; Mapz->ReadDesignations(x,y,z, &designations); Mapz->ReadTileTypes(x,y,z, &tiles); for (uint32_t ty=0;ty<16;++ty) { for (uint32_t tx=0;tx<16;++tx) { if(!designations[tx][ty].bits.feature_local) continue; oldT = tiles[tx][ty]; if ( DFHack::tileShape(oldT) != DFHack::WALL ) { //Current tile is not a wall. //Set current tile, as accurately as can be expected //newT = DFHack::findSimilarTileType(oldT,DFHack::WALL); newT = DFHack::findTileType( DFHack::WALL, DFHack::FEATSTONE, DFHack::tilevariant_invalid, DFHack::TILE_NORMAL, DFHack::TileDirection() ); //If no change, skip it (couldn't find a good tile type) if ( oldT == newT) continue; //Set new tile type, clear designation tiles[tx][ty] = newT; dirty=1; ++count; } } } //If anything was changed, write it all. if (dirty) { Mapz->WriteTileTypes(x,y,z, &tiles); } } } } } c->Resume(); c->con.print("Found and changed %d tiles.\n", count); return CR_OK; }
DFhackCExport command_result df_liquids (Core * c, vector <string> & parameters) { int32_t x,y,z; uint32_t x_max,y_max,z_max; DFHack::Maps * Maps; DFHack::Gui * Position; for(int i = 0; i < parameters.size();i++) { if(parameters[i] == "help" || parameters[i] == "?") { c->con.print("This tool allows placing magma, water and other similar things.\n" "It is interactive and further help is available when you run it.\n" ); return CR_OK; } } Brush * brush = new RectangleBrush(1,1); string brushname = "point"; bool end = false; c->con << "Welcome to the liquid spawner.\nType 'help' or '?' for a list of available commands, 'q' to quit.\nPress return after a command to confirm." << std::endl; string mode="magma"; string flowmode="f+"; string setmode ="s."; unsigned int amount = 7; int width = 1, height = 1, z_levels = 1; while(!end) { string command = ""; std::stringstream str; str <<"[" << mode << ":" << brushname << ":" << amount << ":" << flowmode << ":" << setmode << "]#"; if(c->con.lineedit(str.str(),command,liquids_hist) == -1) return CR_FAILURE; if(command=="help" || command == "?") { c->con << "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") { std::stringstream str; CommandHistory range_hist; str << " :set range width<" << width << "># "; c->con.lineedit(str.str(),command,range_hist); range_hist.add(command); width = command == "" ? width : atoi (command.c_str()); if(width < 1) width = 1; str.str(""); str << " :set range height<" << height << "># "; c->con.lineedit(str.str(),command,range_hist); range_hist.add(command); height = command == "" ? height : atoi (command.c_str()); if(height < 1) height = 1; str.str(""); str << " :set range z-levels<" << z_levels << "># "; c->con.lineedit(str.str(),command,range_hist); range_hist.add(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()) { c->Suspend(); Maps = c->getMaps(); Maps->Start(); Maps->getSize(x_max,y_max,z_max); Position = c->getGui(); do { if(!Maps->Start()) { c->con << "Can't see any DF map loaded." << endl; break; } if(!Position->getCursorCoords(x,y,z)) { c->con << "Can't get cursor coords! Make sure you have a cursor active in DF." << endl; break; } c->con << "cursor coords: " << x << "/" << y << "/" << z << endl; MapCache mcache(Maps); DFHack::DFCoord cursor(x,y,z); coord_vec all_tiles = brush->points(mcache,cursor); c->con << "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 <Block *> 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 <Block *> 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 <Block *>::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 { c->con << "flow bit 1 = " << bflags.bits.liquid_1 << endl; c->con << "flow bit 2 = " << bflags.bits.liquid_2 << endl; } biter ++; } } if(mcache.WriteAll()) c->con << "OK" << endl; else c->con << "Something failed horribly! RUN!" << endl; Maps->Finish(); } while (0); c->Resume(); } else { c->con << command << " : unknown command." << endl; } } return CR_OK; }
int main(int argc, char *argv[]) { /* initialize your non-curses data structures here */ signal(SIGINT, finish); /* arrange interrupts to terminate */ setlocale(LC_ALL,""); initscr(); /* initialize the curses library */ keypad(stdscr, TRUE); /* enable keyboard mapping */ nonl(); /* tell curses not to do NL->CR/NL on output */ cbreak(); /* take input chars one at a time, no wait for \n */ noecho(); /* don't echo input */ //nodelay(stdscr, true); keypad(stdscr, TRUE); scrollok(stdscr, TRUE); if (has_colors()) { start_color(); /* * Simple color assignment, often all we need. */ init_pair(COLOR_BLACK, COLOR_BLACK, COLOR_BLACK); init_pair(COLOR_GREEN, COLOR_GREEN, COLOR_BLACK); init_pair(COLOR_RED, COLOR_RED, COLOR_BLACK); init_pair(COLOR_BLUE, COLOR_BLUE, COLOR_BLACK); init_pair(COLOR_YELLOW, COLOR_YELLOW, COLOR_BLACK); init_color(COLOR_CYAN, 700, 700, 700); // lt grey init_color(COLOR_MAGENTA, 500, 500, 500); // dk grey init_pair(COLOR_WHITE, COLOR_WHITE, COLOR_BLACK); init_pair(COLOR_CYAN, COLOR_CYAN, COLOR_BLACK); init_pair(COLOR_MAGENTA, COLOR_MAGENTA, COLOR_BLACK); } int x_max,y_max,z_max; uint32_t x_max_a,y_max_a,z_max_a; /* uint16_t tiletypes[16][16]; DFHack::t_designation designations[16][16]; uint8_t regionoffsets[16]; */ map <int16_t, uint32_t> materials; materials.clear(); mapblock40d blocks[3][3]; vector<DFHack::t_effect_df40d> effects; vector< vector <uint16_t> > layerassign; vector<t_vein> veinVector; vector<t_frozenliquidvein> IceVeinVector; vector<t_spattervein> splatter; vector<t_grassvein> grass; vector<t_worldconstruction> wconstructs; t_temperatures b_temp1; t_temperatures b_temp2; DFHack::Materials * Mats = 0; DFHack::Maps * Maps = 0; DFHack::ContextManager DFMgr("Memory.xml"); DFHack::Context* DF; try { pDF = DF = DFMgr.getSingleContext(); DF->Attach(); Maps = DF->getMaps(); } catch (exception& e) { cerr << e.what() << endl; #ifndef LINUX_BUILD cin.ignore(); #endif finish(0); } bool hasmats = true; try { Mats = DF->getMaterials(); } catch (exception& e) { hasmats = false; } // init the map if(!Maps->Start()) { error = "Can't find a map to look at."; finish(0); } Maps->getSize(x_max_a,y_max_a,z_max_a); x_max = x_max_a; y_max = y_max_a; z_max = z_max_a; bool hasInorgMats = false; bool hasPlantMats = false; bool hasCreatureMats = false; if(hasmats) { // get stone matgloss mapping if(Mats->ReadInorganicMaterials()) { hasInorgMats = true; } if(Mats->ReadCreatureTypes()) { hasCreatureMats = true; } if(Mats->ReadOrganicMaterials()) { hasPlantMats = true; } } /* // get region geology if(!DF.ReadGeology( layerassign )) { error = "Can't read local geology."; pDF = 0; finish(0); } */ // FIXME: could fail on small forts int cursorX = x_max/2 - 1; int cursorY = y_max/2 - 1; int cursorZ = z_max/2 - 1; bool dig = false; bool dump = false; bool digbit = false; bool dotwiddle; unsigned char twiddle = 0; int vein = 0; int filenum = 0; bool dirtybit = false; uint32_t blockaddr = 0; uint32_t blockaddr2 = 0; t_blockflags bflags; bflags.whole = 0; enum e_tempmode { TEMP_NO, TEMP_1, TEMP_2, WATER_SALT, WATER_STAGNANT }; e_tempmode temperature = TEMP_NO; // resume so we don't block DF while we wait for input DF->Resume(); for (;;) { dig = false; dump = false; dotwiddle = false; digbit = false; int c = getch(); /* refresh, accept single keystroke of input */ flushinp(); clrscr(); /* process the command keystroke */ switch(c) { case KEY_DOWN: cursorY ++; break; case KEY_UP: cursorY --; break; case KEY_LEFT: cursorX --; break; case KEY_RIGHT: cursorX ++; break; case KEY_NPAGE: cursorZ --; break; case KEY_PPAGE: cursorZ ++; break; case '+': vein ++; break; case 'd': dig = true; break; case 'o': dump = true; break; case '-': vein --; break; case 'z': digbit = true; break; case '/': if(twiddle != 0) twiddle--; break; case '*': twiddle++; break; case 't': dotwiddle = true; break; case 'b': temperature = TEMP_NO; break; case 'n': temperature = TEMP_1; break; case 'm': temperature = TEMP_2; break; case 'c': temperature = WATER_SALT; break; case 'v': temperature = WATER_STAGNANT; break; case 27: // escape key DF->Detach(); return 0; break; default: break; } cursorX = max(cursorX, 0); cursorY = max(cursorY, 0); cursorZ = max(cursorZ, 0); cursorX = min(cursorX, x_max - 1); cursorY = min(cursorY, y_max - 1); cursorZ = min(cursorZ, z_max - 1); if(twiddle > 31) twiddle = 31; // clear data before we suspend memset(blocks,0,sizeof(blocks)); veinVector.clear(); IceVeinVector.clear(); effects.clear(); splatter.clear(); grass.clear(); dirtybit = 0; // Supend, read/write data DF->Suspend(); // restart cleared modules Maps->Start(); if(hasmats) { Mats->Start(); if(hasInorgMats) { Mats->ReadInorganicMaterials(); } if(hasPlantMats) { Mats->ReadOrganicMaterials(); } if(hasCreatureMats) { Mats->ReadCreatureTypes(); } } /* if(DF.InitReadEffects(effectnum)) { for(uint32_t i = 0; i < effectnum;i++) { t_effect_df40d effect; DF.ReadEffect(i,effect); effects.push_back(effect); } } */ for(int i = -1; i <= 1; i++) for(int j = -1; j <= 1; j++) { mapblock40d * Block = &blocks[i+1][j+1]; if(Maps->isValidBlock(cursorX+i,cursorY+j,cursorZ)) { Maps->ReadBlock40d(cursorX+i,cursorY+j,cursorZ, Block); // extra processing of the block in the middle if(i == 0 && j == 0) { if(hasInorgMats) do_features(DF, Block, cursorX, cursorY, 50,10, Mats->inorganic); // read veins Maps->ReadVeins(cursorX+i,cursorY+j,cursorZ,&veinVector,&IceVeinVector,&splatter,&grass, &wconstructs); // get pointer to block blockaddr = Maps->getBlockPtr(cursorX+i,cursorY+j,cursorZ); blockaddr2 = Block->origin; // dig all veins and trees if(dig) { for(int x = 0; x < 16; x++) for(int y = 0; y < 16; y++) { int16_t tiletype = Block->tiletypes[x][y]; TileShape tc = tileShape(tiletype); TileMaterial tm = tileMaterial(tiletype); if( tc == WALL && tm == VEIN || tc == TREE_OK || tc == TREE_DEAD) { Block->designation[x][y].bits.dig = designation_default; } } Maps->WriteDesignations(cursorX+i,cursorY+j,cursorZ, &(Block->designation)); } // read temperature data Maps->ReadTemperatures(cursorX+i,cursorY+j,cursorZ,&b_temp1, &b_temp2 ); if(dotwiddle) { bitset<32> bs = Block->designation[0][0].whole; bs.flip(twiddle); Block->designation[0][0].whole = bs.to_ulong(); Maps->WriteDesignations(cursorX+i,cursorY+j,cursorZ, &(Block->designation)); dotwiddle = false; } // do a dump of the block data if(dump) { hexdump(DF,blockaddr,0x1E00,filenum); filenum++; } // read/write dirty bit of the block Maps->ReadDirtyBit(cursorX+i,cursorY+j,cursorZ,dirtybit); Maps->ReadBlockFlags(cursorX+i,cursorY+j,cursorZ,bflags); if(digbit) { dirtybit = !dirtybit; Maps->WriteDirtyBit(cursorX+i,cursorY+j,cursorZ,dirtybit); } } } } // Resume, print stuff to the terminal DF->Resume(); for(int i = -1; i <= 1; i++) for(int j = -1; j <= 1; j++) { mapblock40d * Block = &blocks[i+1][j+1]; for(int x = 0; x < 16; x++) for(int y = 0; y < 16; y++) { int color = COLOR_BLACK; color = pickColor(Block->tiletypes[x][y]); /* if(!Block->designation[x][y].bits.hidden) { puttile(x+(i+1)*16,y+(j+1)*16,Block->tiletypes[x][y], color); } else*/ { attron(A_STANDOUT); puttile(x+(i+1)*16,y+(j+1)*16,Block->tiletypes[x][y], color); attroff(A_STANDOUT); } } // print effects for the center tile /* if(i == 0 && j == 0) { for(uint zz = 0; zz < effects.size();zz++) { if(effects[zz].z == cursorZ && !effects[zz].isHidden) { // block coords to tile coords uint16_t x = effects[zz].x - (cursorX * 16); uint16_t y = effects[zz].y - (cursorY * 16); if(x < 16 && y < 16) { putch(x + 16,y + 16,'@',COLOR_WHITE); } } } } */ } gotoxy(50,0); cprintf("arrow keys, PGUP, PGDN = navigate"); gotoxy(50,1); cprintf("+,- = switch vein"); gotoxy(50,2); uint32_t mineralsize = veinVector.size(); uint32_t icesize = IceVeinVector.size(); uint32_t splattersize = splatter.size(); uint32_t grasssize = grass.size(); uint32_t wconstrsize = wconstructs.size(); uint32_t totalVeinSize = mineralsize+ icesize + splattersize + grasssize + wconstrsize; if(vein == totalVeinSize) vein = totalVeinSize - 1; if(vein < -1) vein = -1; cprintf("X %d/%d, Y %d/%d, Z %d/%d. Vein %d of %d",cursorX+1,x_max,cursorY+1,y_max,cursorZ,z_max,vein+1,totalVeinSize); if(!veinVector.empty() || !IceVeinVector.empty() || !splatter.empty() || !grass.empty() || !wconstructs.empty()) { if(vein != -1 && vein < totalVeinSize) { uint32_t realvein = 0; if(vein < mineralsize) { realvein = vein; //iterate through vein rows for(uint32_t j = 0;j<16;j++) { //iterate through the bits for (uint32_t k = 0; k< 16;k++) { // and the bit array with a one-bit mask, check if the bit is set bool set = !!(((1 << k) & veinVector[realvein].assignment[j]) >> k); if(set) { putch(k+16,j+16,'$',COLOR_RED); } } } if(hasInorgMats) { gotoxy(50,3); cprintf("Mineral: %s",Mats->inorganic[veinVector[vein].type].id); } } else if (vein < mineralsize + icesize) { realvein = vein - mineralsize; t_frozenliquidvein &frozen = IceVeinVector[realvein]; for(uint32_t i = 0;i<16;i++) { for (uint32_t j = 0; j< 16;j++) { int color = COLOR_BLACK; int tile = frozen.tiles[i][j]; color = pickColor(tile); attron(A_STANDOUT); puttile(i+16,j+16,tile, color); attroff(A_STANDOUT); } } gotoxy(50,3); cprintf("ICE"); } else if(vein < mineralsize + icesize + splattersize) { realvein = vein - mineralsize - icesize; for(uint32_t yyy = 0; yyy < 16; yyy++) { for(uint32_t xxx = 0; xxx < 16; xxx++) { uint8_t intensity = splatter[realvein].intensity[xxx][yyy]; if(intensity) { attron(A_STANDOUT); putch(xxx+16,yyy+16,'*', COLOR_RED); attroff(A_STANDOUT); } } } if(hasCreatureMats) { gotoxy(50,3); cprintf("Spatter: %s",PrintSplatterType(splatter[realvein].mat1,splatter[realvein].mat2,Mats->race).c_str()); } } else if(vein < mineralsize + icesize + splattersize + grasssize) { realvein = vein - mineralsize - icesize - splattersize; t_grassvein & grassy =grass[realvein]; for(uint32_t yyy = 0; yyy < 16; yyy++) { for(uint32_t xxx = 0; xxx < 16; xxx++) { uint8_t intensity = grassy.intensity[xxx][yyy]; if(intensity) { attron(A_STANDOUT); putch(xxx+16,yyy+16,'X', COLOR_RED); attroff(A_STANDOUT); } } } if(hasPlantMats) { gotoxy(50,3); cprintf("Grass: 0x%x, %s",grassy.address_of, Mats->organic[grassy.material].id); } } else { realvein = vein - mineralsize - icesize - splattersize - grasssize; t_worldconstruction & wconstr=wconstructs[realvein]; for(uint32_t j = 0; j < 16; j++) { for(uint32_t k = 0; k < 16; k++) { bool set = !!(((1 << k) & wconstr.assignment[j]) >> k); if(set) { putch(k+16,j+16,'$',COLOR_RED); } } } if(hasInorgMats) { gotoxy(50,3); cprintf("Road: 0x%x, %d - %s", wconstr.address_of, wconstr.material,Mats->inorganic[wconstr.material].id); } } }
command_result df_tiles (Core * c, vector <string> & 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); Maps = c->getMaps(); Maps->Start(); Maps->getSize(x_max,y_max,z_max); Position = c->getGui(); string command = ""; if(command=="help" || command == "?") { c->con.print ( "Usage: This command sets the properties of the tile painter brush\n" " It is best used from the console, or as an alias bound to a hotkey\n" " After setting the brush\n" "\n" "Modes:\n" "none - nothing, the default" "magma [0-7] - magma, accepts depth\n" "water [0-7] - water\n" "obsidian - obsidian wall\n" "obsfloor - obsidian floors\n" "obsramp - obsidian ramp (forces 1 z-level brush)\n" "riversource - an endless source of water (floor tile)\n" "type ### - plain tiletype painter. For a list of tile types see:\n" " http://df.magmawiki.com/index.php/DF2010:Tile_types_in_DF_memory\n" "\n" "Set-Modes (only for magma/water):\n" "add - set liquid level everywhere\n" "keep - set liquid level only where liquids are already present\n" "\n" "Brush:\n" "point - single tile [p]\n" "#x#[x#] - block with cursor at bottom north-west [r]\n" " (any place, any size)\n" " Example:" " 3x3x2 = rectangle 3x3 x2 z-levels\n" " The z-level part is optional - ommiting it is\n" " the same as setting it to 1.\n" "h#x#[x#] - Same as previous, only the rectangle is 'hollow'.\n" "block - DF map block with cursor in it\n" " (regular spaced 16x16x1 blocks)\n" "column - Column from cursor, up through free space\n" "line - A line between two points.\n" "circle [#] - A filled circle, optional # specifies radius in tiles.\n" "hcircle [#,#] - A hollow circle (ring). First # specifies radius\n" " second # ring thickness in tiles.\n" "\n" "Other:\n" "help or ? - print this list of commands\n" "paint - same effect as if you also the 'paint' command at the same time.\n" "\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 <Block *> 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 <Block *> 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 <Block *>::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; }
int main (int argc, char* argv[]) { // Command line options bool updown = false; if(argc > 1 && strcmp(argv[1],"-x") == 0) updown = true; DFHack::ContextManager DFMgr("Memory.xml"); DFHack::Context * DF; try { DF = DFMgr.getSingleContext(); DF->Attach(); } catch (exception& e) { cerr << e.what() << endl; #ifndef LINUX_BUILD cin.ignore(); #endif return 1; } uint32_t x_max,y_max,z_max; DFHack::Maps * Maps = DF->getMaps(); DFHack::Gui * Gui = DF->getGui(); // init the map if(!Maps->Start()) { cerr << "Can't init map. Make sure you have a map loaded in DF." << endl; DF->Detach(); #ifndef LINUX_BUILD cin.ignore(); #endif return 1; } int32_t cx, cy, cz; Maps->getSize(x_max,y_max,z_max); uint32_t tx_max = x_max * 16; uint32_t ty_max = y_max * 16; Gui->getCursorCoords(cx,cy,cz); while(cx == -30000) { cerr << "Cursor is not active. Point the cursor at a vein." << endl; DF->Resume(); cin.ignore(); DF->Suspend(); Gui->getCursorCoords(cx,cy,cz); } DFHack::DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz); if(xy.x == 0 || xy.x == tx_max - 1 || xy.y == 0 || xy.y == ty_max - 1) { cerr << "I won't dig the borders. That would be cheating!" << endl; DF->Detach(); #ifndef LINUX_BUILD cin.ignore(); #endif return 1; } MapCache * MCache = new MapCache(Maps); DFHack::t_designation des = MCache->designationAt(xy); int16_t tt = MCache->tiletypeAt(xy); int16_t veinmat = MCache->veinMaterialAt(xy); if( veinmat == -1 ) { cerr << "This tile is non-vein. Bye :)" << endl; delete MCache; DF->Detach(); #ifndef LINUX_BUILD cin.ignore(); #endif return 1; } printf("%d/%d/%d tiletype: %d, veinmat: %d, designation: 0x%x ... DIGGING!\n", cx,cy,cz, tt, veinmat, des.whole); stack <DFHack::DFCoord> flood; flood.push(xy); while( !flood.empty() ) { DFHack::DFCoord current = flood.top(); flood.pop(); int16_t vmat2 = MCache->veinMaterialAt(current); tt = MCache->tiletypeAt(current); if(!DFHack::isWallTerrain(tt)) continue; if(vmat2!=veinmat) continue; // found a good tile, dig+unset material DFHack::t_designation des = MCache->designationAt(current); DFHack::t_designation des_minus; DFHack::t_designation des_plus; des_plus.whole = des_minus.whole = 0; int16_t vmat_minus = -1; int16_t vmat_plus = -1; bool below = 0; bool above = 0; if(updown) { if(MCache->testCoord(current-1)) { below = 1; des_minus = MCache->designationAt(current-1); vmat_minus = MCache->veinMaterialAt(current-1); } if(MCache->testCoord(current+1)) { above = 1; des_plus = MCache->designationAt(current+1); vmat_plus = MCache->veinMaterialAt(current+1); } } if(MCache->testCoord(current)) { MCache->clearMaterialAt(current); if(current.x < tx_max - 2) { flood.push(DFHack::DFCoord(current.x + 1, current.y, current.z)); if(current.y < ty_max - 2) { flood.push(DFHack::DFCoord(current.x + 1, current.y + 1,current.z)); flood.push(DFHack::DFCoord(current.x, current.y + 1,current.z)); } if(current.y > 1) { flood.push(DFHack::DFCoord(current.x + 1, current.y - 1,current.z)); flood.push(DFHack::DFCoord(current.x, current.y - 1,current.z)); } } if(current.x > 1) { flood.push(DFHack::DFCoord(current.x - 1, current.y,current.z)); if(current.y < ty_max - 2) { flood.push(DFHack::DFCoord(current.x - 1, current.y + 1,current.z)); flood.push(DFHack::DFCoord(current.x, current.y + 1,current.z)); } if(current.y > 1) { flood.push(DFHack::DFCoord(current.x - 1, current.y - 1,current.z)); flood.push(DFHack::DFCoord(current.x, current.y - 1,current.z)); } } if(updown) { if(current.z > 0 && below && vmat_minus == vmat2) { flood.push(current-1); if(des_minus.bits.dig == DFHack::designation_d_stair) des_minus.bits.dig = DFHack::designation_ud_stair; else des_minus.bits.dig = DFHack::designation_u_stair; MCache->setDesignationAt(current-1,des_minus); des.bits.dig = DFHack::designation_d_stair; } if(current.z < z_max - 1 && above && vmat_plus == vmat2) { flood.push(current+ 1); if(des_plus.bits.dig == DFHack::designation_u_stair) des_plus.bits.dig = DFHack::designation_ud_stair; else des_plus.bits.dig = DFHack::designation_d_stair; MCache->setDesignationAt(current+1,des_plus); if(des.bits.dig == DFHack::designation_d_stair) des.bits.dig = DFHack::designation_ud_stair; else des.bits.dig = DFHack::designation_u_stair; } } if(des.bits.dig == DFHack::designation_no) des.bits.dig = DFHack::designation_default; MCache->setDesignationAt(current,des); } } MCache->WriteAll(); delete MCache; DF->Detach(); #ifndef LINUX_BUILD cout << "Done. Press any key to continue" << endl; cin.ignore(); #endif return 0; }
//Helper function for writing new functions that check every tile on the map. //newTraffic is the traffic designation to set. //check takes a coordinate and the map cache as arguments, and returns true if the criteria is met. //minCoord and maxCoord can be used to specify a bounding cube. DFhackCExport command_result setAllMatching(DFHack::Core * c, checkTile checkProc, DFHack::DFCoord minCoord, DFHack::DFCoord maxCoord) { //Initialization. c->Suspend(); DFHack::Maps * Maps = c->getMaps(); DFHack::Gui * Gui = c->getGui(); // init the map if(!Maps->Start()) { c->con.printerr("Can't init map. Make sure you have a map loaded in DF.\n"); c->Resume(); return CR_FAILURE; } //Maximum map size. uint32_t x_max,y_max,z_max; Maps->getSize(x_max,y_max,z_max); uint32_t tx_max = x_max * 16; uint32_t ty_max = y_max * 16; //Ensure maximum coordinate is within map. Truncate to map edge. maxCoord.x = std::min((uint32_t) maxCoord.x, tx_max); maxCoord.y = std::min((uint32_t) maxCoord.y, ty_max); maxCoord.z = std::min(maxCoord.z, z_max); //Check minimum co-ordinates against maximum map size if (minCoord.x > maxCoord.x) { c->con.printerr("Minimum x coordinate is greater than maximum x coordinate.\n"); c->Resume(); return CR_FAILURE; } if (minCoord.y > maxCoord.y) { c->con.printerr("Minimum y coordinate is greater than maximum y coordinate.\n"); c->Resume(); return CR_FAILURE; } if (minCoord.z > maxCoord.y) { c->con.printerr("Minimum z coordinate is greater than maximum z coordinate.\n"); c->Resume(); return CR_FAILURE; } MapExtras::MapCache * MCache = new MapExtras::MapCache(Maps); c->con.print("Setting traffic...\n"); //Loop through every single tile for(uint32_t x = minCoord.x; x <= maxCoord.x; x++) { for(uint32_t y = minCoord.y; y <= maxCoord.y; y++) { for(uint32_t z = minCoord.z; z <= maxCoord.z; z++) { DFHack::DFCoord tile = DFHack::DFCoord(x, y, z); checkProc(tile, MCache); } } } MCache->WriteAll(); c->con.print("Complete!\n"); c->Resume(); return CR_OK; }
// FIXME: use block cache, break into manageable bits int main (void) { srand ( (unsigned int)time(NULL) ); //Message of intent cout << "DF Hole" << endl << "This tool will instantly dig a chasm, pit, pipe, etc through hell, wherever your cursor is." << endl << "This can not be undone! End program now if you don't want hellish fun." << endl ; //User selection of settings should have it own routine, a structure for settings, I know //sloppy mess, but this is just a demo utility. //Pit Types. e_pitType pittype = selectPitType(); //Here are all the settings. //Default values are set here. int pitdepth=0; int roof=-1; int holeradius=6; int wallthickness=1; int wallpillar=1; int holepillar=1; int exposehell = 0; int fillmagma=0; int fillwater=0; int stopatmagma=0; int exposemagma=0; int aquify=0; //The Tile Type to use for the walls lining the hole //263 is semi-molten rock, 331 is obsidian uint32_t whell=263, wmolten=263, wmagma=331, wcave=331; //The Tile Type to use for the hole's floor at bottom of the map //35 is chasm, 42 is eerie pit , 340 is obsidian floor, 344 is featstone floor, 264 is 'magma flow' floor uint32_t floor=35, cap=340; int floorvar=0; //Modify default settings based on pit type. switch ( pittype ) { case pitTypeChasm: floor=35; break; case pitTypeEerie: floor=42; break; case pitTypeFloor: floor=344; floorvar=3; break; case pitTypeSolid: holeradius=0; wallthickness=7; wallpillar=4; break; case pitTypeOasis: stopatmagma=-1; fillwater=-1; holeradius=5; wallthickness=2; //aquify=-1; floor=340; floorvar=3; break; case pitTypeOPool: pitdepth=5; fillwater=-1; holeradius=5; wallthickness=2; //aquify=-1; floor=340; floorvar=3; break; case pitTypeMagma: stopatmagma=-1; exposemagma=-1; wallthickness=2; fillmagma=-1; floor=264; break; case pitTypeMPool: pitdepth=5; wallthickness=2; fillmagma=-1; floor=340; floorvar=3; break; } //Should tiles be revealed? int reveal=0; int accept = getyesno("Use default settings?",1); while ( !accept ) { //Pit Depth pitdepth = getint( "Enter max depth (0 for bottom of map)", 0, INT_MAX, pitdepth ); //Hole Size holeradius = getint( "Enter hole radius, 0 to 16", 0, 16, holeradius ); //Wall thickness wallthickness = getint( "Enter wall thickness, 0 to 16", 0, 16, wallthickness ); //Obsidian Pillars holepillar = getint( "Number of Obsidian Pillars in hole, 0 to 255", 0, 255, holepillar ); wallpillar = getint( "Number of Obsidian Pillars in wall, 0 to 255", 0, 255, wallpillar ); //Open Hell? exposehell=getyesno("Expose the pit to hell (no walls in hell)?",exposehell); //Stop when magma sea is hit? stopatmagma=getyesno("Stop at magma sea?",stopatmagma); exposemagma=getyesno("Expose magma sea (no walls in magma)?",exposemagma); //Fill? fillmagma=getyesno("Fill with magma?",fillmagma); if (fillmagma) aquify=fillwater=0; fillwater=getyesno("Fill with water?",fillwater); //aquify=getyesno("Aquifer?",aquify); /////////////////////////////////////////////////////////////////////////////////////////////// //Print settings. //If a settings struct existed, this could be in a routine printf("Using Settings:\n"); printf("Pit Type......: %d = %s\n", pittype, pitTypeDesc[pittype]); printf("Depth.........: %d\n", pitdepth); printf("Hole Radius...: %d\n", holeradius); printf("Wall Thickness: %d\n", wallthickness); printf("Pillars, Hole.: %d\n", holepillar); printf("Pillars, Wall.: %d\n", wallpillar); printf("Expose Hell...: %c\n", (exposehell?'Y':'N') ); printf("Stop at Magma.: %c\n", (stopatmagma?'Y':'N') ); printf("Expose Magma..: %c\n", (exposemagma?'Y':'N') ); printf("Magma Fill....: %c\n", (fillmagma?'Y':'N') ); printf("Water Fill....: %c\n", (fillwater?'Y':'N') ); printf("Aquifer.......: %c\n", (aquify?'Y':'N') ); accept = getyesno("Accept these settings?",1); } int64_t n; uint32_t x_max,y_max,z_max; //Pattern to dig unsigned char pattern[16][16]; for (int regen=1;regen; ) { regen=0; memset(pattern,0,sizeof(pattern)); //Calculate a randomized circle. //These values found through experimentation. int x=0, y=0, n=0; //Two concentric irregular circles //Outer circle, solid. if ( wallthickness ) { drawcircle(holeradius+wallthickness, pattern, 2); } //Inner circle, hole. if ( holeradius ) { drawcircle(holeradius, pattern, 1); } //Post-process to be certain the wall totally encloses hole. if (wallthickness) { for (y=0;y<16;++y) { for (x=0;x<16;++x) { if ( 1==pattern[x][y] ) { //No hole at edges. if ( x<1 || x>14 || y<1 || y>14 ) { pattern[x][y]=2; } } else if ( 0==pattern[x][y] ) { //check neighbors checkneighbors( pattern , x,y, 1, 2); } } } } //Makes sure that somewhere random gets a vertical pillar of rock which is safe //to dig stairs down, to permit access to anywhere within the pit from the top. for (n=holepillar; n ; --n) { settileat( pattern , 1 , 3 , rand()&255 ); } for (n=wallpillar; n ; --n) { settileat( pattern , 2 , 3 , rand()&255 ); } //Note: //At this point, the pattern holds: //0 for all tiles which will be ignored. //1 for all tiles set to empty pit space. //2 for all normal walls. //3 for the straight obsidian top-to-bottom wall. //4 is randomized between wall or floor (!not implemented!) printf("\nPattern:\n"); const char patternkey[] = ".cW!?567890123"; //Print the pattern for (y=0;y<16;++y) { for (x=0;x<16;++x) { cout << patternkey[ pattern[x][y] ]; } cout << endl; } cout << endl; regen = !getyesno("Acceptable Pattern?",1); } //Post-process settings to fix problems here if (pitdepth<1) { pitdepth=INT_MAX; } /////////////////////////////////////////////////////////////////////////////////////////////// cerr << "Loading memory map..." << endl; //Connect to DF! DFHack::ContextManager DFMgr("Memory.xml"); DFHack::Context *DF = DFMgr.getSingleContext(); //Init cerr << "Attaching to DF..." << endl; try { DF->Attach(); } catch (exception& e) { cerr << e.what() << endl; #ifndef LINUX_BUILD cin.ignore(); #endif return 1; } // init the map DFHack::Maps *Mapz = DF->getMaps(); if (!Mapz->Start()) { cerr << "Can't init map. Exiting." << endl; #ifndef LINUX_BUILD cin.ignore(); #endif return 1; } Mapz->getSize(x_max,y_max,z_max); //Get cursor int32_t cursorX, cursorY, cursorZ; DFHack::Gui *Gui = DF->getGui(); Gui->getCursorCoords(cursorX,cursorY,cursorZ); if (-30000==cursorX) { cout << "No cursor position found. Exiting." << endl; #ifndef LINUX_BUILD cin.ignore(); #endif return 1; } //Block coordinates int32_t bx=cursorX/16, by=cursorY/16, bz=cursorZ; //Tile coordinates within block int32_t tx=cursorX%16, ty=cursorY%16, tz=cursorZ; /* //Access the DF interface to pause the game. //Copied from the reveal tool. DFHack::Gui *Gui =DF->getGui(); cout << "Pausing..." << endl; Gui->SetPauseState(true); DF->Resume(); waitmsec(1000); DF->Suspend(); */ //Verify that every z-level at this location exists. for (int32_t Z = 0; Z<= bz ;Z++) { if ( ! Mapz->isValidBlock(bx,by,Z) ) { cout << "This block does't exist! Exiting." << endl; #ifndef LINUX_BUILD cin.ignore(); #endif return 1; } } //Get all the map features. vector<DFHack::t_feature> global_features; if (!Mapz->ReadGlobalFeatures(global_features)) { cout << "Couldn't load global features! Probably a version problem." << endl; #ifndef LINUX_BUILD cin.ignore(); #endif return 1; } std::map <DFHack::DFCoord, std::vector<DFHack::t_feature *> > local_features; if (!Mapz->ReadLocalFeatures(local_features)) { cout << "Couldn't load local features! Probably a version problem." << endl; #ifndef LINUX_BUILD cin.ignore(); #endif return 1; } //Get info on current tile, to determine how to generate the pit mapblock40d topblock; Mapz->ReadBlock40d( bx, by, bz , &topblock ); //Related block info DFCoord pc(bx,by); mapblock40d block; const TileRow * tp; t_designation * d; ////////////////////////////////////// //From top to bottom, dig this thing. ////////////////////////////////////// //Top level, cap. //Might make this an option in the future //For now, no wall means no cap. if (wallthickness) { Mapz->ReadBlock40d( bx, by, bz , &block ); for (uint32_t x=0;x<16;++x) { for (uint32_t y=0;y<16;++y) { if ( (pattern[x][y]>1) || (roof && pattern[x][y]) ) { tp = getTileRow(block.tiletypes[x][y]); d = &block.designation[x][y]; //Only modify this level if it's 'empty' if ( EMPTY != tp->shape && RAMP_TOP != tp->shape && STAIR_DOWN != tp->shape && DFHack::TILE_STREAM_TOP != tp->special) { continue; } //Need a floor for empty space. if (reveal) { d->bits.hidden = 0; //topblock.designation[x][y].bits.hidden; } //Always clear the dig designation. d->bits.dig = designation_no; //unlock fluids, so they fall down the pit. d->bits.flow_forbid = d->bits.liquid_static=0; block.blockflags.bits.liquid_1 = block.blockflags.bits.liquid_2 = 1; //Remove aquifer, to prevent bugginess d->bits.water_table=0; //Set the tile. block.tiletypes[x][y] = cap + rand()%4; } } } //Write the block. Mapz->WriteBlockFlags(bx,by,bz, block.blockflags ); Mapz->WriteDesignations(bx,by,bz, &block.designation ); Mapz->WriteTileTypes(bx,by,bz, &block.tiletypes ); Mapz->WriteDirtyBit(bx,by,bz,1); } /////////////////////////////////////////////////////////////////////////////////////////////// //All levels in between. int done=0; uint32_t t,v; int32_t z = bz-1; int32_t bottom = max(0,bz-pitdepth-1); assert( bottom>=0 && bottom<=bz ); for ( ; !done && z>=bottom ; --z) { int watercount=0; int magmacount=0; int moltencount=0; int rockcount=0; int veincount=0; int emptycount=0; int hellcount=0; int templecount=0; int adamcount=0; int featcount=0; int tpat; cout << z << endl; assert( Mapz->isValidBlock(bx,by,z) ); if (!Mapz->ReadBlock40d( bx, by, z , &block )) { cout << "Bad block! " << bx << "," << by << "," << z << endl; } //Pre-process this z-level, to get some tile statistics. for (int32_t x=0;x<16;++x) { for (int32_t y=0;y<16;++y) { t=0; tp = getTileRow(block.tiletypes[x][y]); d = &block.designation[x][y]; tpat=pattern[x][y]; //Tile type material categories switch ( tp->material ) { case AIR: ++emptycount; break; case MAGMA: ++moltencount; break; case VEIN: ++veincount; break; case FEATSTONE: case HFS: case OBSIDIAN: //basicly, ignored. break; default: if ( EMPTY == tp->shape || RAMP_TOP == tp->shape || STAIR_DOWN == tp->shape ) { ++emptycount; } else { ++rockcount; } break; } //Magma and water if ( d->bits.flow_size ) { if (d->bits.liquid_type) { ++magmacount; } else { ++watercount; } } //Check for Features if ( block.local_feature > -1 || block.global_feature > -1 ) { //Count tiles which actually are in the feature. //It is possible for a block to have a feature, but no tiles to be feature. if ( d->bits.feature_global || d->bits.feature_local ) { //All features ++featcount; if ( d->bits.feature_global && d->bits.feature_local ) { cout << "warn:tile is global and local at same time!" << endl; } n=0; if ( block.global_feature > -1 && d->bits.feature_global ) { n=global_features[block.global_feature].type; switch ( n ) { case feature_Other: //no count break; case feature_Adamantine_Tube: ++adamcount; break; case feature_Underworld: ++hellcount; break; case feature_Hell_Temple: ++templecount; break; default: //something here. for debugging, it may be interesting to know. if (n) cout << '(' << n << ')'; } } n=0; if ( block.local_feature > -1 && d->bits.feature_local ) { n=local_features[pc][block.local_feature]->type; switch ( n ) { case feature_Other: //no count break; case feature_Adamantine_Tube: ++adamcount; break; case feature_Underworld: ++hellcount; break; case feature_Hell_Temple: ++templecount; break; default: //something here. for debugging, it may be interesting to know. if (n) cout << '[' << n << ']'; } } } } } } //If stopping at magma, and no no non-feature stone in this layer, and magma found, then we're either at //or below the magma sea / molten rock. if ( stopatmagma && (moltencount || magmacount) && (!exposemagma || !rockcount) ) { //If not exposing magma, quit at the first sign of magma. //If exposing magma, quite once magma is exposed. done=-1; } ///////////////////////////////////////////////////////////////////////////////////////////////// //Some checks, based on settings and stats collected //First check, are we at illegal depth? if ( !done && hellcount && stopatmagma ) { //Panic! done=-1; tpat=0; cout << "error: illegal breach of hell!" << endl; } ///////////////////////////////////////////////////////////////////////////////////////////////// //Actually process the current z-level. //These loops do the work. for (int32_t x=0;!done && x<16;++x) { for (int32_t y=0;!done && y<16;++y) { t=0; tp = getTileRow(block.tiletypes[x][y]); d = &block.designation[x][y]; tpat=pattern[x][y]; //Up front, remove aquifer, to prevent bugginess //It may be added back if aquify is set. d->bits.water_table=0; //Change behaviour based on settings and stats from this z-level //In hell? if ( tpat && tpat!=3 && isfeature(global_features, local_features,block,pc,x,y,feature_Underworld ) ) { if ( exposehell ) { tpat=0; } } //Expose magma? if ( tpat && tpat!=3 && exposemagma ) { //Leave certain tiles unchanged. switch ( tp->material ) { case HFS: case FEATSTONE: case MAGMA: tpat=0; default: break; } //Adamantine may be left unchanged... if ( isfeature(global_features, local_features,block,pc,x,y,feature_Adamantine_Tube ) ) { tpat=0; } //Leave magma sea unchanged. if ( d->bits.flow_size && d->bits.liquid_type) { tpat=0; } } //For all situations... //Special modification for walls, always for adamantine. if ( isfeature(global_features, local_features,block,pc,x,y,feature_Adamantine_Tube ) ) { if ( 2==pattern[x][y] || 3==pattern[x][y] ) { tpat=2; } } //Border or space? switch (tpat) { case 0: continue; break; case 1: //Empty Space t=32; //d->bits.light = topblock.designation[x][y].bits.light; //d->bits.skyview = topblock.designation[x][y].bits.skyview; //d->bits.subterranean = topblock.designation[x][y].bits.subterranean; //Erase special markers? //d->bits.feature_global = d->bits.feature_local = 0; //Water? Magma? if (fillmagma || fillwater) { d->bits.flow_size=7; d->bits.water_stagnant = false; d->bits.water_salt = false; if (fillmagma) { d->bits.liquid_type=liquid_magma; } else { d->bits.liquid_type=liquid_water; } } else { //Otherwise, remove all liquids. d->bits.flow_size=0; d->bits.water_stagnant = false; d->bits.water_salt = false; d->bits.liquid_type = liquid_water; } break; case 2: //Wall. //First guess based on current material switch ( tp->material ) { case OBSIDIAN: t=wmagma; break; case MAGMA: t=wmolten; break; case HFS: //t=whell; break; case VEIN: t=440; //Solid vein block break; case FEATSTONE: t=335; //Solid feature stone block break; default: t=wcave; } //Adamantine (a local feature) trumps veins. { //Local Feature? if ( block.local_feature > -1 ) { switch ( n=local_features[pc][block.local_feature]->type ) { case feature_Underworld: case feature_Hell_Temple: //Only adopt these if there is no global feature present if ( block.global_feature >-1 ) { break; } case feature_Adamantine_Tube: //Always for adamantine, sometimes for others //Whatever the feature is made of. "featstone wall" d->bits.feature_global = 0; d->bits.feature_local = 1; t=335; break; } } //Global Feature? else if (block.global_feature > -1 && !d->bits.feature_local ) { switch ( n=global_features[block.global_feature].type ) { case feature_Adamantine_Tube: case feature_Underworld: case feature_Hell_Temple: //Whatever the feature is made of. "featstone wall" d->bits.feature_global = 1; t=335; break; } } } //Erase any liquids, as they cause problems. d->bits.flow_size=0; d->bits.water_stagnant = false; d->bits.water_salt = false; d->bits.liquid_type=liquid_water; //Placing an aquifer? //(bugged, these aquifers don't generate water!) if ( aquify ) { //Only normal stone types can be aquified if ( tp->material!=MAGMA && tp->material!=FEATSTONE && tp->material!=HFS ) { //Only place next to the hole. //If no hole, place in middle. if ( checkneighbors(pattern,x,y,1) || (7==x && 7==y) ) { d->bits.water_table = 1; //t=265; //soil wall } } } break; case 3: ////No obsidian walls on bottom of map! //if(z<1 && (d->bits.feature_global || d->bits.feature_local) ) { // t=335; //} //Special wall, always sets to obsidian, to give a stairway t=331; //Erase special markers d->bits.feature_global = d->bits.feature_local = 0; //Erase any liquids, as they cause problems. d->bits.flow_size=0; d->bits.water_stagnant = false; d->bits.water_salt = false; d->bits.liquid_type=liquid_water; break; default: cout << ".error,bad pattern."; } //For all tiles. if (reveal) { d->bits.hidden = 0; //topblock.designation[x][y].bits.hidden; } //Always clear the dig designation. d->bits.dig=designation_no; //Make it underground, because it is capped d->bits.subterranean=1; d->bits.light=0; d->bits.skyview=0; //unlock fluids, so they fall down the pit. d->bits.flow_forbid = d->bits.liquid_static=0; block.blockflags.bits.liquid_1 = block.blockflags.bits.liquid_2 = 1; //Set the tile. block.tiletypes[x][y] = t; } } //Write the block. Mapz->WriteBlockFlags(bx,by,z, block.blockflags ); Mapz->WriteDesignations(bx,by,z, &block.designation ); Mapz->WriteTileTypes(bx,by,z, &block.tiletypes ); Mapz->WriteDirtyBit(bx,by,z,1); } //Re-process the last z-level handled above. z++; assert( z>=0 ); /////////////////////////////////////////////////////////////////////////////////////////////// //The bottom level is special. if (-1) { if (!Mapz->ReadBlock40d( bx, by, z , &block )) { cout << "Bad block! " << bx << "," << by << "," << z << endl; } for (uint32_t x=0;x<16;++x) { for (uint32_t y=0;y<16;++y) { t=floor; v=floorvar; tp = getTileRow(block.tiletypes[x][y]); d = &block.designation[x][y]; if ( exposehell ) { //Leave hell tiles unchanged when exposing hell. if ( isfeature(global_features,local_features,block,pc,x,y,feature_Underworld) ) { continue; } } //Does expose magma need anything at this level? if ( exposemagma && stopatmagma ) { continue; } switch (pattern[x][y]) { case 0: continue; break; case 1: //Empty becomes floor. //Base floor type on the z-level first, features, then tile type. if (!z) { //Bottom of map, use the floor specified, always. break; } ////Only place floor where ground is already solid when exposing //if( EMPTY == tp->c || RAMP_TOP == tp->c || STAIR_DOWN == tp->c ){ // continue; //} if ( d->bits.feature_global || d->bits.feature_global ) { //Feature Floor! t=344; break; } //Tile material check. switch ( tp->material ) { case OBSIDIAN: t=340; v=3; break; case MAGMA: v=0; t=264; //magma flow break; case HFS: //should only happen at bottom of map break; case VEIN: t=441; //vein floor v=3; break; case FEATSTONE: t=344; v=3; break; } break; case 2: case 3: //Walls already drawn. //Ignore. continue; break; } //For all tiles. if (reveal) d->bits.hidden = 0; //topblock.designation[x][y].bits.hidden; //Always clear the dig designation. d->bits.dig=designation_no; //unlock fluids d->bits.flow_forbid = d->bits.liquid_static=0; block.blockflags.bits.liquid_1 = block.blockflags.bits.liquid_2 = 1; //Set the tile. block.tiletypes[x][y] = t + ( v ? rand()&v : 0 ); } } //Write the block. Mapz->WriteBlockFlags(bx,by,z, block.blockflags ); Mapz->WriteDesignations(bx,by,z, &block.designation ); Mapz->WriteTileTypes(bx,by,z, &block.tiletypes ); Mapz->WriteDirtyBit(bx,by,z,1); } DF->Detach(); #ifndef LINUX_BUILD cout << "Done. Press any key to continue" << endl; cin.ignore(); #endif return 0; }
static command_result autodump_main(Core * c, vector <string> & parameters) { // Command line options bool destroy = false; bool here = false; if(parameters.size() > 0) { string & p = parameters[0]; if(p == "destroy") destroy = true; else if (p == "destroy-here") destroy = here = true; else if(p == "?" || p == "help") { c->con.print( "This utility lets you quickly move all items designated to be dumped.\n" "Items are instantly moved to the cursor position, the dump flag is unset,\n" "and the forbid flag is set, as if it had been dumped normally.\n" "Be aware that any active dump item tasks still point at the item.\n\n" "Options:\n" "destroy - instead of dumping, destroy the items instantly.\n" "destroy-here - only affect the tile under cursor.\n" ); return CR_OK; } } c->Suspend(); DFHack::VersionInfo *mem = c->vinfo; DFHack::Gui * Gui = c->getGui(); DFHack::Items * Items = c->getItems(); DFHack::Maps *Maps = c->getMaps(); vector <df_item*> p_items; if(!Items->readItemVector(p_items)) { c->con.printerr("Can't access the item vector.\n"); return CR_FAILURE; } std::size_t numItems = p_items.size(); // init the map if(!Maps->Start()) { c->con.printerr("Can't initialize map.\n"); return CR_FAILURE; } MapCache MC (Maps); int i = 0; int dumped_total = 0; int cx, cy, cz; DFCoord pos_cursor; if(!destroy || here) { if (!Gui->getCursorCoords(cx,cy,cz)) { c->con.printerr("Cursor position not found. Please enabled the cursor.\n"); return CR_FAILURE; } pos_cursor = DFCoord(cx,cy,cz); } if (!destroy) { { Block * b = MC.BlockAt(pos_cursor / 16); if(!b) { c->con.printerr("Cursor is in an invalid/uninitialized area. Place it over a floor.\n"); return CR_FAILURE; } uint16_t ttype = MC.tiletypeAt(pos_cursor); if(!DFHack::isFloorTerrain(ttype)) { c->con.printerr("Cursor should be placed over a floor.\n"); return CR_FAILURE; } } } coordmap counts; // proceed with the dumpification operation for(std::size_t i=0; i< numItems; i++) { df_item * itm = p_items[i]; DFCoord pos_item(itm->x, itm->y, itm->z); // keep track how many items are at places. all items. coordmap::iterator it = counts.find(pos_item); if(it == counts.end()) { std::pair< coordmap::iterator, bool > inserted = counts.insert(std::make_pair(pos_item,1)); it = inserted.first; } else { it->second ++; } // iterator is valid here, we use it later to decrement the pile counter if the item is moved // only dump the stuff marked for dumping and laying on the ground if ( !itm->flags.dump || !itm->flags.on_ground || itm->flags.construction || itm->flags.hidden || itm->flags.in_building || itm->flags.in_chest || itm->flags.in_inventory || itm->flags.artifact1 ) continue; if(!destroy) // move to cursor { // Change flags to indicate the dump was completed, as if by super-dwarfs itm->flags.dump = false; itm->flags.forbid = true; // Don't move items if they're already at the cursor if (pos_cursor == pos_item) continue; // Do we need to fix block-local item ID vector? if(pos_item/16 != pos_cursor/16) { // yes... cerr << "Moving from block to block!" << endl; df_block * bl_src = Maps->getBlock(itm->x /16, itm->y/16, itm->z); df_block * bl_tgt = Maps->getBlock(cx /16, cy/16, cz); if(bl_src) { std::remove(bl_src->items.begin(), bl_src->items.end(),itm->id); } else { cerr << "No source block" << endl; } if(bl_tgt) { bl_tgt->items.push_back(itm->id); } else { cerr << "No target block" << endl; } } // Move the item itm->x = pos_cursor.x; itm->y = pos_cursor.y; itm->z = pos_cursor.z; } else // destroy { if (here && pos_item != pos_cursor) continue; itm->flags.garbage_colect = true; // Cosmetic changes: make them disappear from view instantly itm->flags.forbid = true; itm->flags.hidden = true; } // keeping track of item pile sizes ;) it->second --; dumped_total++; } if(!destroy) // TODO: do we have to do any of this when destroying items? { // for each item pile, see if it reached zero. if so, unset item flag on the tile it's on coordmap::iterator it = counts.begin(); coordmap::iterator end = counts.end(); while(it != end) { if(it->second == 0) { t_occupancy occ = MC.occupancyAt(it->first); occ.bits.item = false; MC.setOccupancyAt(it->first, occ); } it++; } // Set "item here" flag on target tile, if we moved any items to the target tile. if (dumped_total > 0) { // assume there is a possibility the cursor points at some weird location with missing block data Block * b = MC.BlockAt(pos_cursor / 16); if(b) { t_occupancy occ = MC.occupancyAt(pos_cursor); occ.bits.item = 1; MC.setOccupancyAt(pos_cursor,occ); } } // write map changes back to DF. MC.WriteAll(); // Is this necessary? Is "forbid" a dirtyable attribute like "dig" is? Maps->WriteDirtyBit(cx/16, cy/16, cz, true); } c->con.print("Done. %d items %s.\n", dumped_total, destroy ? "marked for desctruction" : "quickdumped"); return CR_OK; }