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; }
command_result df_liquids_execute(color_ostream &out) { // create brush type depending on old parameters Brush * brush; if (brushname == "point") { brush = new RectangleBrush(1,1,1,0,0,0); //width = 1; //height = 1; //z_levels = 1; } else if (brushname == "range") { brush = new RectangleBrush(width,height,z_levels,0,0,0); } else if(brushname == "block") { brush = new BlockBrush(); } else if(brushname == "column") { brush = new ColumnBrush(); } else if(brushname == "flood") { brush = new FloodBrush(&Core::getInstance()); } else { // this should never happen! out << "Old brushtype is invalid! Resetting to point brush.\n"; brushname = "point"; width = 1; height = 1; z_levels = 1; brush = new RectangleBrush(width,height,z_levels,0,0,0); } CoreSuspender suspend; do { if (!Maps::IsValid()) { out << "Can't see any DF map loaded." << endl; break;; } int32_t x,y,z; if(!Gui::getCursorCoords(x,y,z)) { out << "Can't get cursor coords! Make sure you have a cursor active in DF." << endl; break; } out << "cursor coords: " << x << "/" << y << "/" << z << endl; MapCache mcache; DFHack::DFCoord cursor(x,y,z); coord_vec all_tiles = brush->points(mcache,cursor); out << "working..." << endl; // Force the game to recompute its walkability cache df::global::world->reindex_pathfinding = true; if(mode == "obsidian") { coord_vec::iterator iter = all_tiles.begin(); while (iter != all_tiles.end()) { mcache.setTiletypeAt(*iter, tiletype::LavaWall); mcache.setTemp1At(*iter,10015); mcache.setTemp2At(*iter,10015); df::tile_designation des = mcache.designationAt(*iter); des.bits.flow_size = 0; des.bits.flow_forbid = false; mcache.setDesignationAt(*iter, des); iter ++; } } if(mode == "obsidian_floor") { coord_vec::iterator iter = all_tiles.begin(); while (iter != all_tiles.end()) { mcache.setTiletypeAt(*iter, findRandomVariant(tiletype::LavaFloor1)); iter ++; } } else if(mode == "riversource") { coord_vec::iterator iter = all_tiles.begin(); while (iter != all_tiles.end()) { mcache.setTiletypeAt(*iter, tiletype::RiverSource); df::tile_designation a = mcache.designationAt(*iter); a.bits.liquid_type = tile_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.update_liquid = true; bf.bits.update_liquid_twice = true; b->setBlockFlags(bf); iter++; } } else if(mode=="wclean") { coord_vec::iterator iter = all_tiles.begin(); while (iter != all_tiles.end()) { DFHack::DFCoord current = *iter; df::tile_designation des = mcache.designationAt(current); des.bits.water_salt = false; des.bits.water_stagnant = false; mcache.setDesignationAt(current,des); 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; // current tile coord DFHack::DFCoord curblock = current /16; // current block coord // check if the block is actually there if(!mcache.BlockAt(curblock)) { iter ++; continue; } df::tile_designation des = mcache.designationAt(current); df::tiletype tt = mcache.tiletypeAt(current); // don't put liquids into places where they don't belong... if(!DFHack::FlowPassable(tt)) { iter++; continue; } if(mode != "flowbits") { if(setmode == "s.") { des.bits.flow_size = amount; } else if(setmode == "s+") { if(des.bits.flow_size < amount) des.bits.flow_size = amount; } else if(setmode == "s-") { if (des.bits.flow_size > amount) des.bits.flow_size = amount; } if(amount != 0 && mode == "magma") { des.bits.liquid_type = tile_liquid::Magma; mcache.setTemp1At(current,12000); mcache.setTemp2At(current,12000); } else if(amount != 0 && mode == "water") { des.bits.liquid_type = tile_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); } // mark the tile passable or impassable like the game does des.bits.flow_forbid = des.bits.flow_size && (des.bits.liquid_type == tile_liquid::Magma || des.bits.flow_size > 3); mcache.setDesignationAt(current,des); } seen_blocks.insert(mcache.BlockAt(current / 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.update_liquid = true; bflags.bits.update_liquid_twice = true; (*biter)->setBlockFlags(bflags); } else if(flowmode == "f-") { bflags.bits.update_liquid = false; bflags.bits.update_liquid_twice = false; (*biter)->setBlockFlags(bflags); } else { out << "flow bit 1 = " << bflags.bits.update_liquid << endl; out << "flow bit 2 = " << bflags.bits.update_liquid_twice << endl; } biter ++; } } if(mcache.WriteAll()) out << "OK" << endl; else out << "Something failed horribly! RUN!" << endl; } while (0); // cleanup delete brush; 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; }