Merge branch 'master' of github.com/quietust/dfhack

develop
jj 2013-12-24 14:07:08 +01:00
commit ce33973f0f
19 changed files with 344 additions and 143 deletions

@ -565,7 +565,7 @@ static int dfhack_matinfo_find(lua_State *state)
{
std::vector<std::string> tokens;
for (int i = 1; i < argc; i++)
for (int i = 1; i <= argc; i++)
tokens.push_back(luaL_checkstring(state, i));
info.find(tokens);

@ -42,11 +42,14 @@ using namespace std;
#include "MiscUtils.h"
#include "VTableInterpose.h"
#include "DataDefs.h"
#include "df/world.h"
#include "df/historical_figure.h"
#include "df/map_block.h"
#include "df/block_square_event_world_constructionst.h"
#include "df/viewscreen_legendsst.h"
using namespace DFHack;
using namespace df::enums;
@ -154,14 +157,51 @@ static PersistentDataItem dataFromHFig(df::historical_figure *hfig)
return PersistentDataItem(hfig->id, hfig->name.first_name, &hfig->name.nickname, hfig->name.words);
}
// Hide fake histfigs from legends xml export
static bool in_export_xml = false;
struct hide_fake_histfigs_hook : df::viewscreen_legendsst {
typedef df::viewscreen_legendsst interpose_base;
DEFINE_VMETHOD_INTERPOSE(void, feed, (set<df::interface_key> *input))
{
if (input->count(interface_key::LEGENDS_EXPORT_XML))
{
auto &figs = df::historical_figure::get_vector();
auto it = figs.begin();
while (it != figs.end() && (*it)->id <= -100)
++it;
// Move our histfigs to a temporary vector
std::vector<df::historical_figure*> fakes(figs.begin(), it);
figs.erase(figs.begin(), it);
in_export_xml = true;
INTERPOSE_NEXT(feed)(input);
in_export_xml = false;
figs.insert(figs.begin(), fakes.begin(), fakes.end());
}
else
INTERPOSE_NEXT(feed)(input);
}
};
IMPLEMENT_VMETHOD_INTERPOSE_PRIO(hide_fake_histfigs_hook, feed, -10000);
void World::ClearPersistentCache()
{
next_persistent_id = 0;
persistent_index.clear();
INTERPOSE_HOOK(hide_fake_histfigs_hook, feed).apply(Core::getInstance().isWorldLoaded());
}
static bool BuildPersistentCache()
{
if (in_export_xml)
return false;
if (next_persistent_id)
return true;
if (!Core::getInstance().isWorldLoaded())

@ -1 +1 @@
Subproject commit e62d498e68e3a87929b144220d03e691016f7aae
Subproject commit d6bcaa991cfe9ab5a8031b1721d548a73258d7ed

@ -377,6 +377,7 @@ struct GeoLayer
int16_t material;
bool is_soil;
bool is_soil_layer;
// World-global origin coordinates in blocks
df::coord world_pos;
@ -489,6 +490,7 @@ GeoLayer::GeoLayer(GeoBiome *parent, int index, df::world_geo_layer *info)
tiles = unmined_tiles = mineral_tiles = 0;
material = info->mat_index;
is_soil = isSoilInorganic(material);
is_soil_layer = (info->type == geo_layer_type::SOIL || info->type == geo_layer_type::SOIL_SAND);
}
const unsigned NUM_INCLUSIONS = 1+(int)ENUM_LAST_ITEM(inclusion_type);
@ -721,14 +723,17 @@ bool VeinGenerator::scan_layer_depth(Block *b, df::coord2d column, int z)
auto &top_solid = col_info.top_solid_z[x][y];
auto &bottom = col_info.bottom_layer[x][y];
if (top_solid < 0 && isWallTerrain(b->baseTiletypeAt(tile)))
auto ttype = b->baseTiletypeAt(tile);
bool obsidian = (tileMaterial(ttype) == tiletype_material::LAVA_STONE);
if (top_solid < 0 && !obsidian && isWallTerrain(ttype))
top_solid = z;
if (max_level[idx] < 0)
{
// Do not start the layer stack in open air.
// Those tiles can be very weird.
if (bottom < 0 && isOpenTerrain(b->baseTiletypeAt(tile)))
if (bottom < 0 && (isOpenTerrain(ttype) || obsidian))
continue;
max_level[idx] = min_level[idx] = z;
@ -777,9 +782,14 @@ bool VeinGenerator::adjust_layer_depth(df::coord2d column)
if (max_defined < 0)
continue;
int last_top = min_defined;
// Verify assumptions
for (int i = min_defined; i < max_defined; i++)
{
if (max_level[i] >= top_solid)
last_top = i;
if (max_level[i+1] < 0 && min_level[i] > top_solid)
max_level[i+1] = min_level[i+1] = min_level[i];
@ -815,6 +825,22 @@ bool VeinGenerator::adjust_layer_depth(df::coord2d column)
continue;
}
// If below a thick soil layer, allow thickness to pass from prev to current.
// This accounts for a probable bug in worldgen soil placement code.
if (i > min_defined && i-1 <= last_top)
{
auto prev = biome->layers[i-1];
if (size > layer->thickness &&
prev->is_soil_layer && prev->thickness > 1 &&
size <= layer->thickness+prev->thickness-1)
{
max_level[i] += layer->thickness - size;
layer->setZBias(size - layer->thickness);
continue;
}
}
out.printerr(
"Layer height change in layer %d at (%d,%d,%d): %d instead of %d.\n",
i, x+column.x*16, y+column.y*16, max_level[i],

@ -626,7 +626,7 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
commands.push_back(
PluginCommand(
"autotrade", "Automatically send items in marked stockpiles to trade depot, when trading is possible.",
autotrade_cmd, false, ""));
autotrade_cmd, false, "Run 'autotrade version' to query the plugin version."));
return CR_OK;
}

@ -1183,7 +1183,7 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
commands.push_back(
PluginCommand(
"buildingplan", "Place furniture before it's built",
buildingplan_cmd, false, ""));
buildingplan_cmd, false, "Run 'buildingplan debug [on|off]' to toggle debugging, or 'buildingplan version' to query the plugin version."));
planner.initialize();
return CR_OK;

@ -37,7 +37,14 @@ command_result df_createitem (color_ostream &out, vector <string> & parameters);
DFhackCExport command_result plugin_init (color_ostream &out, std::vector<PluginCommand> &commands)
{
commands.push_back(PluginCommand("createitem", "Create arbitrary item at the selected unit's feet.", df_createitem));
commands.push_back(PluginCommand("createitem", "Create arbitrary item at the selected unit's feet.", df_createitem, false,
"Syntax: createitem <item> <material> [count]\n"
" <item> - Item token for what you wish to create, as specified in custom\n"
" reactions. If the item has no subtype, omit the :NONE.\n"
" <material> - The material you want the item to be made of, as specified\n"
" in custom reactions. For REMAINS, FISH, FISH_RAW, VERMIN,\n"
" PET, and EGG, replace this with a creature ID and caste.\n"
" [count] - How many of the item you wish to create.\n"));
return CR_OK;
}
@ -91,17 +98,7 @@ command_result df_createitem (color_ostream &out, vector <string> & parameters)
int count = 1;
if ((parameters.size() < 2) || (parameters.size() > 3))
{
out.print("Syntax: createitem <item> <material> [count]\n"
" <item> - Item token for what you wish to create, as specified in custom\n"
" reactions. If the item has no subtype, omit the :NONE.\n"
" <material> - The material you want the item to be made of, as specified\n"
" in custom reactions. For REMAINS, FISH, FISH_RAW, VERMIN,\n"
" PET, and EGG, replace this with a creature ID and caste.\n"
" [count] - How many of the item you wish to create.\n"
);
return CR_WRONG_USAGE;
}
item_str = parameters[0];
material_str = parameters[1];

@ -1,4 +1,5 @@
#include "Core.h"
#include "Error.h"
#include <Console.h>
#include <Export.h>
#include <PluginManager.h>
@ -228,8 +229,8 @@ static void enableEvent(int evType,int freq)
{
if (freq < 0)
return;
if (evType < 0 || evType >= EventManager::EventType::EVENT_MAX || evType == EventManager::EventType::TICK)
throw std::runtime_error("invalid event type to enable");
CHECK_INVALID_ARGUMENT(evType >= 0 && evType < EventManager::EventType::EVENT_MAX &&
evType != EventManager::EventType::TICK);
EventManager::EventHandler::callback_t fun_ptr = eventHandlers[evType];
EventManager::EventType::EventType typeToEnable=static_cast<EventManager::EventType::EventType>(evType);

@ -58,6 +58,7 @@ command_result lair(color_ostream &out, std::vector<std::string> & params)
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{
commands.push_back(PluginCommand("lair","Mark the map as a monster lair, preventing item scatter ('lair reset' reverts that).",lair));
commands.push_back(PluginCommand("lair","Mark the map as a monster lair, preventing item scatter.",lair, false,
"Usage: 'lair' to mark entire map as monster lair, 'lair reset' to undo the operation.\n"));
return CR_OK;
}

@ -59,12 +59,16 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
liquids_hist.load("liquids.history");
commands.push_back(PluginCommand(
"liquids", "Place magma, water or obsidian.",
df_liquids, true)); // interactive, needs console for prompt
df_liquids, true,
"This tool allows placing magma, water and other similar things.\n"
"It is interactive and further help is available when you run it.\n"
"The settings will be remembered until dfhack is closed and you can call\n"
"'liquids-here' (mapped to a hotkey) to paint liquids at the cursor position\n"
"without the need to go back to the dfhack console.\n")); // interactive, needs console for prompt
commands.push_back(PluginCommand(
"liquids-here", "Use settings from liquids at cursor position.",
df_liquids_here, Gui::cursor_hotkey, // non-interactive, needs ingame cursor
" Identical to pressing enter in liquids, intended for use as keybinding.\n"
" Can (but doesn't need to) be called while liquids is running in the console."));
" This command is intended to be mapped to a hotkey and is identical to pressing Enter in liquids with the current parameters.\n"));
return CR_OK;
}
@ -157,14 +161,7 @@ command_result df_liquids (color_ostream &out_, vector <string> & parameters)
for(size_t i = 0; i < parameters.size();i++)
{
if(parameters[i] == "help" || parameters[i] == "?")
{
out.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"
"The settings will be remembered until dfhack is closed and you can call\n"
"'liquids-here' (mapped to a hotkey) to paint liquids at the cursor position\n"
"without the need to go back to the dfhack console.\n");
return CR_OK;
}
return CR_WRONG_USAGE;
}
if (!Maps::IsValid())
@ -375,11 +372,7 @@ command_result df_liquids_here (color_ostream &out, vector <string> & parameters
for(size_t i = 0; i < parameters.size();i++)
{
if(parameters[i] == "help" || parameters[i] == "?")
{
out << "This command is supposed to be mapped to a hotkey." << endl;
out << "It will use the current/last parameters set in liquids." << endl;
return CR_OK;
}
return CR_WRONG_USAGE;
}
out.print("Run liquids-here with these parameters: ");

@ -22,25 +22,8 @@ using df::global::world;
const uint32_t sapling_to_tree_threshold = 120 * 28 * 12 * 3; // 3 years
command_result df_grow (color_ostream &out, vector <string> & parameters);
command_result df_immolate (color_ostream &out, vector <string> & parameters);
command_result df_extirpate (color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("plants");
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{
commands.push_back(PluginCommand("grow", "Grows saplings into trees (with active cursor, only the targetted one).", df_grow));
commands.push_back(PluginCommand("immolate", "Set plants on fire (under cursor, 'shrubs', 'trees' or 'all').", df_immolate));
commands.push_back(PluginCommand("extirpate", "Kill plants (same mechanics as immolate).", df_extirpate));
return CR_OK;
}
DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{
return CR_OK;
}
enum do_what
{
do_immolate,
@ -84,19 +67,8 @@ static bool getoptions( vector <string> & parameters, bool & shrubs, bool & tree
*/
static command_result immolations (color_ostream &out, do_what what, bool shrubs, bool trees, bool help)
{
static const char * what1 = "destroys";
static const char * what2 = "burns";
if(help)
{
out.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;
}
return CR_WRONG_USAGE;
CoreSuspender suspend;
if (!Maps::IsValid())
{
@ -165,26 +137,26 @@ command_result df_immolate (color_ostream &out, vector <string> & parameters)
bool shrubs = false, trees = false, help = false;
if(getoptions(parameters,shrubs,trees,help))
{
return immolations(out,do_immolate,shrubs,trees, help);
return immolations(out,do_immolate,shrubs,trees,help);
}
else
{
out.printerr("Invalid parameter!\n");
return CR_FAILURE;
return CR_WRONG_USAGE;
}
}
command_result df_extirpate (color_ostream &out, vector <string> & parameters)
{
bool shrubs = false, trees = false, help = false;
if(getoptions(parameters,shrubs,trees, help))
if(getoptions(parameters,shrubs,trees,help))
{
return immolations(out,do_extirpate,shrubs,trees, help);
return immolations(out,do_extirpate,shrubs,trees,help);
}
else
{
out.printerr("Invalid parameter!\n");
return CR_FAILURE;
return CR_WRONG_USAGE;
}
}
@ -193,10 +165,7 @@ command_result df_grow (color_ostream &out, vector <string> & parameters)
for(size_t i = 0; i < parameters.size();i++)
{
if(parameters[i] == "help" || parameters[i] == "?")
{
out.print("This command turns all living saplings into full-grown trees.\n");
return CR_OK;
}
return CR_WRONG_USAGE;
}
CoreSuspender suspend;
@ -245,3 +214,123 @@ command_result df_grow (color_ostream &out, vector <string> & parameters)
return CR_OK;
}
command_result df_createplant (color_ostream &out, vector <string> & parameters)
{
if ((parameters.size() != 1) || (parameters[0] == "help" || parameters[0] == "?"))
return CR_WRONG_USAGE;
CoreSuspender suspend;
if (!Maps::IsValid())
{
out.printerr("Map is not available!\n");
return CR_FAILURE;
}
int32_t x,y,z;
if(!Gui::getCursorCoords(x,y,z))
{
out.printerr("No cursor detected - please place the cursor over the location in which you wish to create a new plant.\n");
return CR_FAILURE;
}
df::map_block *map = Maps::getTileBlock(x, y, z);
if (!map)
{
out.printerr("Invalid location selected!\n");
return CR_FAILURE;
}
int tx = x & 15, ty = y & 15;
int mat = tileMaterial(map->tiletype[tx][ty]);
if ((tileShape(map->tiletype[tx][ty]) != tiletype_shape::FLOOR) || ((mat != tiletype_material::SOIL) && (mat != tiletype_material::GRASS_DARK) && (mat != tiletype_material::GRASS_LIGHT)))
{
out.printerr("Plants can only be placed on dirt or grass floors!\n");
return CR_FAILURE;
}
int plant_id = -1;
df::plant_raw *plant_raw = NULL;
for (size_t i = 0; i < world->raws.plants.all.size(); i++)
{
plant_raw = world->raws.plants.all[i];
if (plant_raw->id == parameters[0])
{
plant_id = i;
break;
}
}
if (plant_id == -1)
{
out.printerr("Invalid plant ID specified!\n");
return CR_FAILURE;
}
if (plant_raw->flags.is_set(plant_raw_flags::GRASS))
{
out.printerr("You cannot plant grass using this command.\n");
return CR_FAILURE;
}
df::plant *plant = df::allocate<df::plant>();
if (plant_raw->flags.is_set(plant_raw_flags::TREE))
plant->hitpoints = 400000;
else
{
plant->hitpoints = 100000;
plant->flags.bits.is_shrub = 1;
}
// for now, always set "watery" for WET-permitted plants, even if they're spawned away from water
// the proper method would be to actually look for nearby water features, but it's not clear exactly how that works
if (plant_raw->flags.is_set(plant_raw_flags::WET))
plant->flags.bits.watery = 1;
plant->material = plant_id;
plant->pos.x = x;
plant->pos.y = y;
plant->pos.z = z;
plant->update_order = rand() % 10;
plant->temperature_tile_tick = -1;
plant->temperature_tile = 60001;
plant->min_safe_temp = 9900;
plant->max_safe_temp = 60001;
world->plants.all.push_back(plant);
switch (plant->flags.whole & 3)
{
case 0: world->plants.tree_dry.push_back(plant); break;
case 1: world->plants.tree_wet.push_back(plant); break;
case 2: world->plants.shrub_dry.push_back(plant); break;
case 3: world->plants.shrub_wet.push_back(plant); break;
}
map->plants.push_back(plant);
if (plant->flags.bits.is_shrub)
map->tiletype[tx][ty] = tiletype::Shrub;
else
map->tiletype[tx][ty] = tiletype::Sapling;
return CR_OK;
}
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{
commands.push_back(PluginCommand("grow", "Grows saplings into trees (with active cursor, only the targetted one).", df_grow, false,
"This command turns all living saplings on the map into full-grown trees.\n"));
commands.push_back(PluginCommand("immolate", "Set plants on fire (under cursor, 'shrubs', 'trees' or 'all').", df_immolate, false,
"Without any options, this command burns a plant under the cursor.\n"
"Options:\n"
"shrubs - affect all shrubs\n"
"trees - affect all trees\n"
"all - affect all plants\n"));
commands.push_back(PluginCommand("extirpate", "Kill plants (same mechanics as immolate).", df_extirpate, false,
"Without any options, this command destroys a plant under the cursor.\n"
"Options:\n"
"shrubs - affect all shrubs\n"
"trees - affect all trees\n"
"all - affect all plants\n"));
commands.push_back(PluginCommand("createplant", "Create a new plant at the cursor.", df_createplant, false,
"Specify the type of plant to create by its raw ID (e.g. TOWER_CAP or MUSHROOM_HELMET_PLUMP).\n"
"Only shrubs and saplings can be placed, and they must be located on a dirt or grass floor.\n"));
return CR_OK;
}
DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{
return CR_OK;
}

@ -46,13 +46,19 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
{
commands.push_back(PluginCommand("probe",
"A tile probe",
df_probe));
df_probe,
false,
"Hover the cursor over a tile to view its properties.\n"));
commands.push_back(PluginCommand("cprobe",
"A creature probe",
df_cprobe));
df_cprobe,
false,
"Select a creature to view its properties.\n"));
commands.push_back(PluginCommand("bprobe",
"A simple building probe",
df_bprobe));
df_bprobe,
false,
"Select a building to view its properties.\n"));
return CR_OK;
}

@ -234,11 +234,18 @@ static coord2d biome_delta[] = {
struct EmbarkTileLayout {
coord2d biome_off, biome_pos;
df::region_map_entry *biome;
df::world_geo_biome *geo_biome;
int elevation, max_soil_depth;
int min_z, base_z;
std::map<int, float> penalty;
};
static df::world_region_details *get_details(df::world_data *data, df::coord2d pos)
{
int d_idx = linear_index(data->region_details, &df::world_region_details::pos, pos);
return vector_get(data->region_details, d_idx);
}
bool estimate_underground(color_ostream &out, EmbarkTileLayout &tile, df::world_region_details *details, int x, int y)
{
// Find actual biome
@ -251,15 +258,37 @@ bool estimate_underground(color_ostream &out, EmbarkTileLayout &tile, df::world_
tile.biome_pos = coord2d(bx, by);
tile.biome = &data->region_map[bx][by];
tile.geo_biome = df::world_geo_biome::find(tile.biome->geo_index);
// Compute surface elevation
tile.elevation = (
details->elevation[x][y] + details->elevation[x][y+1] +
details->elevation[x+1][y] + details->elevation[x+1][y+1]
) / 4;
tile.max_soil_depth = std::max((154-tile.biome->elevation)/5,0);
tile.base_z = tile.elevation;
tile.elevation = details->elevation[x][y];
tile.max_soil_depth = std::max((154-tile.elevation)/5,1);
tile.penalty.clear();
// Special biome adjustments
if (!tile.biome->flags.is_set(region_map_entry_flags::is_lake))
{
// Mountain biome
if (tile.biome->elevation >= 150)
tile.max_soil_depth = 0;
// Ocean biome
else if (tile.biome->elevation < 100)
{
if (tile.elevation == 99)
tile.elevation = 98;
if (tile.geo_biome && (tile.geo_biome->unk1 == 4 || tile.geo_biome->unk1 == 5))
{
auto b_details = get_details(data, tile.biome_pos);
if (b_details && b_details->unk12e8 < 500)
tile.max_soil_depth = 0;
}
}
}
tile.base_z = tile.elevation-1;
auto &features = details->features[x][y];
// Collect global feature layer depths and apply penalties
@ -301,8 +330,8 @@ bool estimate_underground(color_ostream &out, EmbarkTileLayout &tile, df::world_
if (!sea_found)
{
out.printerr("Could not find magma sea.\n");
return false;
out.printerr("Could not find magma sea; depth may be incorrect.\n");
tile.min_z = tile.base_z;
}
// Scan for big local features and apply their penalties
@ -340,7 +369,7 @@ bool estimate_materials(color_ostream &out, EmbarkTileLayout &tile, MatMap &laye
{
using namespace geo_layer_type;
df::world_geo_biome *geo_biome = df::world_geo_biome::find(tile.biome->geo_index);
df::world_geo_biome *geo_biome = tile.geo_biome;
if (!geo_biome)
{
@ -350,35 +379,58 @@ bool estimate_materials(color_ostream &out, EmbarkTileLayout &tile, MatMap &laye
}
// soil depth increases by 1 every 5 levels below 150
int top_z_level = tile.elevation - tile.max_soil_depth;
unsigned nlayers = std::min<unsigned>(16, geo_biome->layers.size());
int soil_size = 0;
for (unsigned i = 0; i < geo_biome->layers.size(); i++)
for (unsigned i = 0; i < nlayers; i++)
{
auto layer = geo_biome->layers[i];
switch (layer->type)
if (layer->type == SOIL || layer->type == SOIL_SAND)
soil_size += layer->top_height - layer->bottom_height + 1;
}
// Compute shifts for layers in the stack
int soil_erosion = soil_size - std::min(soil_size,tile.max_soil_depth);
int layer_shift[16];
int cur_shift = tile.elevation+soil_erosion-1;
for (unsigned i = 0; i < nlayers; i++)
{
case SOIL:
case SOIL_OCEAN:
case SOIL_SAND:
top_z_level += layer->top_height - layer->bottom_height + 1;
break;
default:;
auto layer = geo_biome->layers[i];
layer_shift[i] = cur_shift;
if (layer->type == SOIL || layer->type == SOIL_SAND)
{
int size = layer->top_height - layer->bottom_height + 1;
// This is to replicate the behavior of a probable bug in the
// map generation code: if a layer is partially eroded, the
// removed levels are in fact transferred to the layer below,
// because unlike the case of removing the whole layer, the code
// does not execute a loop to shift the lower part of the stack up.
if (size > soil_erosion)
cur_shift -= soil_erosion;
soil_erosion -= std::min(soil_erosion, size);
}
}
top_z_level = std::max(top_z_level, tile.elevation)-1;
// Estimate amounts
int last_bottom = tile.elevation;
for (unsigned i = 0; i < geo_biome->layers.size(); i++)
for (unsigned i = 0; i < nlayers; i++)
{
auto layer = geo_biome->layers[i];
int top_z = std::min(layer->top_height + top_z_level, tile.elevation-1);
int bottom_z = std::max(layer->bottom_height + top_z_level, tile.min_z);
if (i+1 == geo_biome->layers.size()) // stretch layer if needed
int top_z = last_bottom-1;
int bottom_z = std::max(layer->bottom_height + layer_shift[i], tile.min_z);
if (i+1 == nlayers) // stretch layer if needed
bottom_z = tile.min_z;
if (top_z < bottom_z)
continue;
last_bottom = bottom_z;
float layer_size = 48*48;
int sums[ENUM_LAST_ITEM(inclusion_type)+1] = { 0 };
@ -438,8 +490,7 @@ static command_result embark_prospector(color_ostream &out, df::viewscreen_choos
df::world_data *data = world->world_data;
coord2d cur_region = screen->region_pos;
int d_idx = linear_index(data->region_details, &df::world_region_details::pos, cur_region);
auto cur_details = vector_get(data->region_details, d_idx);
auto cur_details = get_details(data, cur_region);
if (!cur_details)
{

@ -30,7 +30,8 @@ command_result df_regrass (color_ostream &out, vector <string> & parameters);
DFhackCExport command_result plugin_init (color_ostream &out, std::vector<PluginCommand> &commands)
{
commands.push_back(PluginCommand("regrass", "Regrows surface grass.", df_regrass));
commands.push_back(PluginCommand("regrass", "Regrows surface grass.", df_regrass, false,
"Specify parameter 'max' to set all grass types to full density, otherwise only one type of grass will be restored per tile.\n"));
return CR_OK;
}

@ -76,12 +76,23 @@ DFHACK_PLUGIN("reveal");
DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCommand> &commands)
{
commands.push_back(PluginCommand("reveal","Reveal the map. 'reveal hell' will also reveal hell. 'reveal demon' won't pause.",reveal));
commands.push_back(PluginCommand("unreveal","Revert the map to its previous state.",unreveal));
commands.push_back(PluginCommand("revtoggle","Reveal/unreveal depending on state.",revtoggle));
commands.push_back(PluginCommand("revflood","Hide all, reveal all tiles reachable from cursor position.",revflood));
commands.push_back(PluginCommand("revforget", "Forget the current reveal data, allowing to use reveal again.",revforget));
commands.push_back(PluginCommand("nopause","Disable pausing (doesn't affect pause forced by reveal).",nopause));
commands.push_back(PluginCommand("reveal","Reveal the map. 'reveal hell' will also reveal hell. 'reveal demon' won't pause.",reveal,false,
"Reveals the map, by default ignoring hell.\n"
"Options:\n"
"hell - also reveal hell, while forcing the game to pause.\n"
"demon - reveal hell, do not pause.\n"));
commands.push_back(PluginCommand("unreveal","Revert the map to its previous state.",unreveal,false,
"Reverts the previous reveal operation, hiding the map again.\n"));
commands.push_back(PluginCommand("revtoggle","Reveal/unreveal depending on state.",revtoggle,false,
"Toggles between reveal and unreveal.\n"));
commands.push_back(PluginCommand("revflood","Hide all, reveal all tiles reachable from cursor position.",revflood,false,
"This command hides the whole map. Then, starting from the cursor,\n"
"reveals all accessible tiles. Allows repairing parma-revealed maps.\n"));
commands.push_back(PluginCommand("revforget", "Forget the current reveal data, allowing to use reveal again.",revforget,false,
"Forget the current reveal data, allowing to use reveal again.\n"));
commands.push_back(PluginCommand("nopause","Disable pausing (doesn't affect pause forced by reveal).",nopause,false,
"Disable pausing (doesn't affect pause forced by reveal).\n"
"Activate with 'nopause 1', deactivate with 'nopause 0'.\n"));
return CR_OK;
}
@ -160,14 +171,7 @@ command_result reveal(color_ostream &out, vector<string> & params)
if(params[i]=="hell")
no_hell = false;
else if(params[i] == "help" || params[i] == "?")
{
out.print("Reveals the map, by default ignoring hell.\n"
"Options:\n"
"hell - also reveal hell, while forcing the game to pause.\n"
"demon - reveal hell, do not pause.\n"
);
return CR_OK;
}
return CR_WRONG_USAGE;
}
if(params.size() && params[0] == "hell")
{
@ -254,10 +258,7 @@ command_result unreveal(color_ostream &out, vector<string> & params)
for(size_t i = 0; i < params.size();i++)
{
if(params[i] == "help" || params[i] == "?")
{
out.print("Reverts the previous reveal operation, hiding the map again.\n");
return CR_OK;
}
return CR_WRONG_USAGE;
}
if(!revealed)
{
@ -330,12 +331,7 @@ command_result revflood(color_ostream &out, vector<string> & params)
for(size_t i = 0; i < params.size();i++)
{
if(params[i] == "help" || params[i] == "?")
{
out.print("This command hides the whole map. Then, starting from the cursor,\n"
"reveals all accessible tiles. Allows repairing parma-revealed maps.\n"
);
return CR_OK;
}
return CR_WRONG_USAGE;
}
CoreSuspender suspend;
uint32_t x_max,y_max,z_max;
@ -482,10 +478,7 @@ command_result revforget(color_ostream &out, vector<string> & params)
for(size_t i = 0; i < params.size();i++)
{
if(params[i] == "help" || params[i] == "?")
{
out.print("Forget the current reveal data, allowing to use reveal again.\n");
return CR_OK;
}
return CR_WRONG_USAGE;
}
if(!revealed)
{

@ -130,11 +130,15 @@ command_result df_seedwatch(color_ostream &out, vector<string>& parameters)
{
case 0:
printHelp(out);
break;
return CR_WRONG_USAGE;
case 1:
par = parameters[0];
if(par == "help") printHelp(out);
else if(par == "?") printHelp(out);
if ((par == "help") || (par == "?"))
{
printHelp(out);
return CR_WRONG_USAGE;
}
else if(par == "start")
{
running = true;
@ -239,6 +243,7 @@ command_result df_seedwatch(color_ostream &out, vector<string>& parameters)
break;
default:
printHelp(out);
return CR_WRONG_USAGE;
break;
}

@ -292,7 +292,8 @@ DFHACK_PLUGIN("showmood");
DFhackCExport command_result plugin_init (color_ostream &out, std::vector<PluginCommand> &commands)
{
commands.push_back(PluginCommand("showmood", "Shows items needed for current strange mood.", df_showmood));
commands.push_back(PluginCommand("showmood", "Shows items needed for current strange mood.", df_showmood, false,
"Run this command without any parameters to display information on the currently active Strange Mood."));
return CR_OK;
}

@ -1002,7 +1002,7 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
commands.push_back(
PluginCommand(
"stocks", "An improved stocks display screen",
stocks_cmd, false, ""));
stocks_cmd, false, "Run 'stocks show' open the stocks display screen, or 'stocks version' to query the plugin version."));
ViewscreenStocks::reset();

@ -23,7 +23,9 @@ DFHACK_PLUGIN("tubefill");
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{
commands.push_back(PluginCommand("tubefill","Fill in all the adamantine tubes again.",tubefill));
commands.push_back(PluginCommand("tubefill","Fill in all the adamantine tubes again.",tubefill, false,
"Replenishes mined out adamantine and hollow adamantine tubes.\n"
"May cause !!FUN!!\n"));
return CR_OK;
}
@ -39,12 +41,7 @@ command_result tubefill(color_ostream &out, std::vector<std::string> & params)
for(size_t i = 0; i < params.size();i++)
{
if(params[i] == "help" || params[i] == "?")
{
out.print("Replenishes mined out adamantine and hollow adamantine tubes.\n"
"May cause !!FUN!!\n"
);
return CR_OK;
}
return CR_WRONG_USAGE;
}
CoreSuspender suspend;