From 97de21357c96076ea605c5df7a0721226c30ba50 Mon Sep 17 00:00:00 2001
From: Quietust
Date: Mon, 21 Jul 2014 13:18:29 -0500
Subject: [PATCH 01/22] First pass for 0.40 compatibility; still lots left to
do, but this will at least build
---
CMakeLists.txt | 4 +--
library/modules/Items.cpp | 1 -
library/modules/MapCache.cpp | 9 -------
library/modules/Maps.cpp | 2 +-
library/modules/Materials.cpp | 1 -
library/modules/Translation.cpp | 2 +-
library/xml | 2 +-
plugins/CMakeLists.txt | 48 ++++++++++++++++-----------------
plugins/automaterial.cpp | 3 ---
plugins/devel/dumpmats.cpp | 2 +-
plugins/embark-tools.cpp | 34 +++++++++++------------
plugins/feature.cpp | 12 ++++-----
plugins/infiniteSky.cpp | 6 ++---
plugins/manipulator.cpp | 3 ++-
plugins/prospector.cpp | 6 ++---
plugins/reveal.cpp | 14 +++++++---
plugins/search.cpp | 9 -------
plugins/sort.cpp | 1 -
plugins/tweak.cpp | 5 +++-
19 files changed, 76 insertions(+), 88 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index df5943a31..231cef16c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -58,8 +58,8 @@ if (NOT EXISTS ${dfhack_SOURCE_DIR}/library/xml/codegen.pl OR NOT EXISTS ${dfhac
endif()
# set up versioning.
-set(DF_VERSION "0.34.11")
-SET(DFHACK_RELEASE "r5" CACHE STRING "Current release revision.")
+set(DF_VERSION "0.40.04")
+SET(DFHACK_RELEASE "r0" CACHE STRING "Current release revision.")
set(DFHACK_VERSION "${DF_VERSION}-${DFHACK_RELEASE}")
add_definitions(-DDFHACK_VERSION="${DFHACK_VERSION}")
diff --git a/library/modules/Items.cpp b/library/modules/Items.cpp
index 31640dbb5..dbce89576 100644
--- a/library/modules/Items.cpp
+++ b/library/modules/Items.cpp
@@ -1158,7 +1158,6 @@ int Items::getItemBaseValue(int16_t item_type, int16_t item_subtype, int16_t mat
case item_type::MEAT:
case item_type::PLANT:
- case item_type::LEAVES:
case item_type::CHEESE:
value = 2;
break;
diff --git a/library/modules/MapCache.cpp b/library/modules/MapCache.cpp
index da7683351..133ebedf9 100644
--- a/library/modules/MapCache.cpp
+++ b/library/modules/MapCache.cpp
@@ -845,15 +845,6 @@ t_matpair MapExtras::BlockInfo::getBaseMaterial(df::tiletype tt, df::coord2d pos
case ROOT:
case TREE:
case PLANT:
- rv.mat_type = MaterialInfo::PLANT_BASE;
- if (auto plant = plants[block->map_pos + df::coord(x,y,0)])
- {
- if (auto raw = df::plant_raw::find(plant->material))
- {
- rv.mat_type = raw->material_defs.type_basic_mat;
- rv.mat_index = raw->material_defs.idx_basic_mat;
- }
- }
break;
case GRASS_LIGHT:
diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp
index 2ad1f7821..89eae64ed 100644
--- a/library/modules/Maps.cpp
+++ b/library/modules/Maps.cpp
@@ -253,7 +253,7 @@ void Maps::enableBlockUpdates(df::map_block *blk, bool flow, bool temperature)
blk->flags.bits.update_liquid_twice = true;
}
- auto z_flags = world->map.z_level_flags;
+ auto z_flags = world->map_extras.z_level_flags;
int z_level = blk->map_pos.z;
if (z_flags && z_level >= 0 && z_level < world->map.z_count_block)
diff --git a/library/modules/Materials.cpp b/library/modules/Materials.cpp
index 60a35fa2b..20b5a913c 100644
--- a/library/modules/Materials.cpp
+++ b/library/modules/Materials.cpp
@@ -479,7 +479,6 @@ void MaterialInfo::getMatchBits(df::job_item_flags1 &ok, df::job_item_flags1 &ma
TEST(extract_bearing_fish, false);
TEST(extract_bearing_vermin, false);
TEST(processable_to_vial, structural && FLAG(plant, plant_raw_flags::EXTRACT_VIAL));
- TEST(processable_to_bag, structural && FLAG(plant, plant_raw_flags::LEAVES));
TEST(processable_to_barrel, structural && FLAG(plant, plant_raw_flags::EXTRACT_BARREL));
TEST(solid, !(MAT_FLAG(ALCOHOL_PLANT) ||
MAT_FLAG(ALCOHOL_CREATURE) ||
diff --git a/library/modules/Translation.cpp b/library/modules/Translation.cpp
index 90f8bbb81..b42cf4d2d 100644
--- a/library/modules/Translation.cpp
+++ b/library/modules/Translation.cpp
@@ -153,7 +153,7 @@ string Translation::TranslateName(const df::language_name * name, bool inEnglish
if (!name->nickname.empty())
{
word = "`" + name->nickname + "'";
- switch (d_init ? d_init->nickname_dwarf : d_init_nickname::CENTRALIZE)
+ switch (d_init ? d_init->nickname[*df::global::gametype] : d_init_nickname::CENTRALIZE)
{
case d_init_nickname::REPLACE_ALL:
out = word;
diff --git a/library/xml b/library/xml
index c66ab3307..ad20c0e25 160000
--- a/library/xml
+++ b/library/xml
@@ -1 +1 @@
-Subproject commit c66ab33071842bcfb7d37c3993f6a024923ca358
+Subproject commit ad20c0e2598df0599954c0ff09df982d60c006dd
diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt
index f2983a2ca..bcae09442 100644
--- a/plugins/CMakeLists.txt
+++ b/plugins/CMakeLists.txt
@@ -13,16 +13,16 @@ endif()
OPTION(BUILD_ISOWORLD "Build isoworld (needs a checkout first)." OFF)
if(BUILD_ISOWORLD)
- add_subdirectory (isoworld)
- IF(UNIX)
- if (APPLE)
- #TODO: add an OSX runner script
- else()
- # On linux, copy our version of the df launch script which sets LD_PRELOAD
- install(PROGRAMS ${dfhack_SOURCE_DIR}/package/linux/runisoworld
- DESTINATION .)
- endif()
- ENDIF()
+ add_subdirectory (isoworld)
+ IF(UNIX)
+ if (APPLE)
+ #TODO: add an OSX runner script
+ else()
+ # On linux, copy our version of the df launch script which sets LD_PRELOAD
+ install(PROGRAMS ${dfhack_SOURCE_DIR}/package/linux/runisoworld
+ DESTINATION .)
+ endif()
+ ENDIF()
endif()
OPTION(BUILD_DEV_PLUGINS "Build developer plugins." OFF)
@@ -38,12 +38,12 @@ endif()
OPTION(BUILD_MAPEXPORT "Build map exporter." ON)
if (BUILD_MAPEXPORT)
- add_subdirectory (mapexport)
+# add_subdirectory (mapexport)
endif()
OPTION(BUILD_DWARFEXPORT "Build dwarf exporter." ON)
if (BUILD_DWARFEXPORT)
- add_subdirectory (dwarfexport)
+# add_subdirectory (dwarfexport)
endif()
OPTION(BUILD_RUBY "Build ruby binding." ON)
@@ -84,7 +84,7 @@ OPTION(BUILD_SUPPORTED "Build the supported plugins (reveal, probe, etc.)." ON)
if (BUILD_SUPPORTED)
DFHACK_PLUGIN(3dveins 3dveins.cpp)
DFHACK_PLUGIN(add-spatter add-spatter.cpp)
- DFHACK_PLUGIN(advtools advtools.cpp)
+# DFHACK_PLUGIN(advtools advtools.cpp)
DFHACK_PLUGIN(autodump autodump.cpp)
DFHACK_PLUGIN(autolabor autolabor.cpp)
DFHACK_PLUGIN(automaterial automaterial.cpp)
@@ -104,23 +104,23 @@ if (BUILD_SUPPORTED)
DFHACK_PLUGIN(createitem createitem.cpp)
DFHACK_PLUGIN(cursecheck cursecheck.cpp)
DFHACK_PLUGIN(deramp deramp.cpp)
- DFHACK_PLUGIN(dig dig.cpp)
+# DFHACK_PLUGIN(dig dig.cpp)
DFHACK_PLUGIN(digFlood digFlood.cpp)
- add_subdirectory(diggingInvaders)
+# add_subdirectory(diggingInvaders)
DFHACK_PLUGIN(drybuckets drybuckets.cpp)
- DFHACK_PLUGIN(dwarfmonitor dwarfmonitor.cpp)
+# DFHACK_PLUGIN(dwarfmonitor dwarfmonitor.cpp)
DFHACK_PLUGIN(embark-tools embark-tools.cpp)
DFHACK_PLUGIN(eventful eventful.cpp LINK_LIBRARIES lua)
DFHACK_PLUGIN(fastdwarf fastdwarf.cpp)
DFHACK_PLUGIN(feature feature.cpp)
DFHACK_PLUGIN(filltraffic filltraffic.cpp)
- DFHACK_PLUGIN(fix-armory fix-armory.cpp)
+# DFHACK_PLUGIN(fix-armory fix-armory.cpp)
DFHACK_PLUGIN(fixpositions fixpositions.cpp)
DFHACK_PLUGIN(fixveins fixveins.cpp)
DFHACK_PLUGIN(flows flows.cpp)
DFHACK_PLUGIN(follow follow.cpp)
DFHACK_PLUGIN(forceequip forceequip.cpp)
- DFHACK_PLUGIN(getplants getplants.cpp)
+# DFHACK_PLUGIN(getplants getplants.cpp)
DFHACK_PLUGIN(infiniteSky infiniteSky.cpp)
DFHACK_PLUGIN(initflags initflags.cpp)
DFHACK_PLUGIN(isoworldremote isoworldremote.cpp PROTOBUFS isoworldremote)
@@ -132,20 +132,20 @@ if (BUILD_SUPPORTED)
DFHACK_PLUGIN(misery misery.cpp)
DFHACK_PLUGIN(mousequery mousequery.cpp)
DFHACK_PLUGIN(petcapRemover petcapRemover.cpp)
- DFHACK_PLUGIN(plants plants.cpp)
+# DFHACK_PLUGIN(plants plants.cpp)
DFHACK_PLUGIN(probe probe.cpp)
- DFHACK_PLUGIN(prospector prospector.cpp)
+# DFHACK_PLUGIN(prospector prospector.cpp)
DFHACK_PLUGIN(power-meter power-meter.cpp LINK_LIBRARIES lua)
DFHACK_PLUGIN(regrass regrass.cpp)
- DFHACK_PLUGIN(remotefortressreader remotefortressreader.cpp PROTOBUFS RemoteFortressReader)
+ DFHACK_PLUGIN(remotefortressreader remotefortressreader.cpp PROTOBUFS RemoteFortressReader)
DFHACK_PLUGIN(rename rename.cpp LINK_LIBRARIES lua PROTOBUFS rename)
- add_subdirectory(rendermax)
+# add_subdirectory(rendermax)
DFHACK_PLUGIN(resume resume.cpp)
DFHACK_PLUGIN(reveal reveal.cpp)
DFHACK_PLUGIN(search search.cpp)
DFHACK_PLUGIN(seedwatch seedwatch.cpp)
DFHACK_PLUGIN(showmood showmood.cpp)
- DFHACK_PLUGIN(siege-engine siege-engine.cpp LINK_LIBRARIES lua)
+# DFHACK_PLUGIN(siege-engine siege-engine.cpp LINK_LIBRARIES lua)
DFHACK_PLUGIN(sort sort.cpp LINK_LIBRARIES lua)
DFHACK_PLUGIN(steam-engine steam-engine.cpp)
DFHACK_PLUGIN(stockflow stockflow.cpp LINK_LIBRARIES lua)
@@ -153,7 +153,7 @@ if (BUILD_SUPPORTED)
DFHACK_PLUGIN(stocks stocks.cpp)
DFHACK_PLUGIN(strangemood strangemood.cpp)
DFHACK_PLUGIN(tiletypes tiletypes.cpp Brushes.h)
- DFHACK_PLUGIN(treefarm treefarm.cpp)
+# DFHACK_PLUGIN(treefarm treefarm.cpp)
DFHACK_PLUGIN(tubefill tubefill.cpp)
DFHACK_PLUGIN(tweak tweak.cpp)
DFHACK_PLUGIN(weather weather.cpp)
diff --git a/plugins/automaterial.cpp b/plugins/automaterial.cpp
index b8021aaf2..69df2d279 100644
--- a/plugins/automaterial.cpp
+++ b/plugins/automaterial.cpp
@@ -476,9 +476,6 @@ static bool is_valid_building_site(building_site &site, bool orthogonal_check, b
return false;
}
- if (shape == tiletype_shape::TREE)
- return false;
-
if (material == tiletype_material::FIRE ||
material == tiletype_material::POOL ||
material == tiletype_material::BROOK ||
diff --git a/plugins/devel/dumpmats.cpp b/plugins/devel/dumpmats.cpp
index 0af1fce50..5aabf807a 100644
--- a/plugins/devel/dumpmats.cpp
+++ b/plugins/devel/dumpmats.cpp
@@ -231,7 +231,7 @@ command_result df_dumpmats (color_ostream &out, vector ¶meters)
for (int i = 0; i < mat->reaction_class.size(); i++)
out.print("\t[REACTION_CLASS:%s]\n", mat->reaction_class[i]->c_str());
for (int i = 0; i < mat->reaction_product.id.size(); i++)
- out.print("\t[MATERIAL_REACTION_PRODUCT:%s:%s:%s%s%s]\n", mat->reaction_product.id[i]->c_str(), mat->reaction_product.str[0][i]->c_str(), mat->reaction_product.str[1][i]->c_str(), mat->reaction_product.str[2][i]->size() ? ":" : "", mat->reaction_product.str[2][i]->c_str());
+ out.print("\t[MATERIAL_REACTION_PRODUCT:%s:%s:%s%s%s]\n", mat->reaction_product.id[i]->c_str(), mat->reaction_product.str[2][i]->c_str(), mat->reaction_product.str[3][i]->c_str(), mat->reaction_product.str[4][i]->size() ? ":" : "", mat->reaction_product.str[4][i]->c_str());
if (mat->hardens_with_water.mat_type != -1)
out.print("\t[HARDENS_WITH_WATER:%s:%s%s%s]\n", mat->hardens_with_water.str[0].c_str(), mat->hardens_with_water.str[1].c_str(), mat->hardens_with_water.str[2].size() ? ":" : "", mat->hardens_with_water.str[2].c_str());
diff --git a/plugins/embark-tools.cpp b/plugins/embark-tools.cpp
index 6c888ee7e..a93625038 100644
--- a/plugins/embark-tools.cpp
+++ b/plugins/embark-tools.cpp
@@ -106,7 +106,7 @@ public:
void update_embark_sidebar (df::viewscreen_choose_start_sitest * screen)
{
bool is_top = false;
- if (screen->embark_pos_min.y == 0)
+ if (screen->location.embark_pos_min.y == 0)
is_top = true;
std::set keys;
keys.insert(df::interface_key::SETUP_LOCAL_Y_MUP);
@@ -123,10 +123,10 @@ void resize_embark (df::viewscreen_choose_start_sitest * screen, int dx, int dy)
/* Reproduces DF's embark resizing functionality
* Local area resizes up and to the right, unless it's already touching the edge
*/
- int x1 = screen->embark_pos_min.x,
- x2 = screen->embark_pos_max.x,
- y1 = screen->embark_pos_min.y,
- y2 = screen->embark_pos_max.y,
+ int x1 = screen->location.embark_pos_min.x,
+ x2 = screen->location.embark_pos_max.x,
+ y1 = screen->location.embark_pos_min.y,
+ y2 = screen->location.embark_pos_max.y,
width = x2 - x1 + dx,
height = y2 - y1 + dy;
if (x1 == x2 && dx == -1)
@@ -150,10 +150,10 @@ void resize_embark (df::viewscreen_choose_start_sitest * screen, int dx, int dy)
}
y2 = std::min(15, y2);
- screen->embark_pos_min.x = x1;
- screen->embark_pos_max.x = x2;
- screen->embark_pos_min.y = y1;
- screen->embark_pos_max.y = y2;
+ screen->location.embark_pos_min.x = x1;
+ screen->location.embark_pos_max.x = x2;
+ screen->location.embark_pos_min.y = y1;
+ screen->location.embark_pos_max.y = y2;
update_embark_sidebar(screen);
}
@@ -183,10 +183,10 @@ int sticky_pos[] = {0, 0, 3, 3};
bool sticky_moved = false;
void sticky_save (df::viewscreen_choose_start_sitest * screen)
{
- sticky_pos[0] = screen->embark_pos_min.x;
- sticky_pos[1] = screen->embark_pos_max.x;
- sticky_pos[2] = screen->embark_pos_min.y;
- sticky_pos[3] = screen->embark_pos_max.y;
+ sticky_pos[0] = screen->location.embark_pos_min.x;
+ sticky_pos[1] = screen->location.embark_pos_max.x;
+ sticky_pos[2] = screen->location.embark_pos_min.y;
+ sticky_pos[3] = screen->location.embark_pos_max.y;
}
void sticky_apply (df::viewscreen_choose_start_sitest * screen)
@@ -196,10 +196,10 @@ void sticky_apply (df::viewscreen_choose_start_sitest * screen)
// Site finder is active - don't override default local position
return;
}
- screen->embark_pos_min.x = sticky_pos[0];
- screen->embark_pos_max.x = sticky_pos[1];
- screen->embark_pos_min.y = sticky_pos[2];
- screen->embark_pos_max.y = sticky_pos[3];
+ screen->location.embark_pos_min.x = sticky_pos[0];
+ screen->location.embark_pos_max.x = sticky_pos[1];
+ screen->location.embark_pos_min.y = sticky_pos[2];
+ screen->location.embark_pos_max.y = sticky_pos[3];
update_embark_sidebar(screen);
}
diff --git a/plugins/feature.cpp b/plugins/feature.cpp
index e2ee9d4f1..cbfd7b5e0 100644
--- a/plugins/feature.cpp
+++ b/plugins/feature.cpp
@@ -33,9 +33,9 @@ static command_result feature(color_ostream &out, vector ¶meters)
{
if (parameters.size() != 1)
return CR_WRONG_USAGE;
- for (size_t i = 0; i < world->cur_savegame.map_features.size(); i++)
+ for (size_t i = 0; i < world->features.map_features.size(); i++)
{
- df::feature_init *feature_init = world->cur_savegame.map_features[i];
+ df::feature_init *feature_init = world->features.map_features[i];
string name;
feature_init->getName(&name);
out.print("Feature #%i (\"%s\", type %s) is %s\n",
@@ -48,12 +48,12 @@ static command_result feature(color_ostream &out, vector ¶meters)
if (parameters.size() != 2)
return CR_WRONG_USAGE;
size_t i = atoi(parameters[1].c_str());
- if ((i < 0) || (i >= world->cur_savegame.map_features.size()))
+ if ((i < 0) || (i >= world->features.map_features.size()))
{
out.print("No such feature!\n");
return CR_FAILURE;
}
- df::feature_init *feature_init = world->cur_savegame.map_features[i];
+ df::feature_init *feature_init = world->features.map_features[i];
if (feature_init->flags.is_set(feature_init_flags::Discovered))
{
out.print("Selected feature is already discovered!\n");
@@ -70,12 +70,12 @@ static command_result feature(color_ostream &out, vector ¶meters)
if (parameters.size() != 2)
return CR_WRONG_USAGE;
size_t i = atoi(parameters[1].c_str());
- if ((i < 0) || (i >= world->cur_savegame.map_features.size()))
+ if ((i < 0) || (i >= world->features.map_features.size()))
{
out.print("No such feature!\n");
return CR_FAILURE;
}
- df::feature_init *feature_init = world->cur_savegame.map_features[i];
+ df::feature_init *feature_init = world->features.map_features[i];
if (!feature_init->flags.is_set(feature_init_flags::Discovered))
{
out.print("Selected feature is already hidden!\n");
diff --git a/plugins/infiniteSky.cpp b/plugins/infiniteSky.cpp
index 6405a5cf0..7dc986fca 100644
--- a/plugins/infiniteSky.cpp
+++ b/plugins/infiniteSky.cpp
@@ -144,13 +144,13 @@ void doInfiniteSky(color_ostream& out, int32_t howMany) {
}
}
df::z_level_flags* flags = new df::z_level_flags[z_count_block+1];
- memcpy(flags, world->map.z_level_flags, z_count_block*sizeof(df::z_level_flags));
+ memcpy(flags, world->map_extras.z_level_flags, z_count_block*sizeof(df::z_level_flags));
flags[z_count_block].whole = 0;
flags[z_count_block].bits.update = 1;
world->map.z_count_block++;
world->map.z_count++;
- delete[] world->map.z_level_flags;
- world->map.z_level_flags = flags;
+ delete[] world->map_extras.z_level_flags;
+ world->map_extras.z_level_flags = flags;
}
}
diff --git a/plugins/manipulator.cpp b/plugins/manipulator.cpp
index 5d36dcd5b..79a8476d0 100644
--- a/plugins/manipulator.cpp
+++ b/plugins/manipulator.cpp
@@ -180,7 +180,7 @@ const SkillColumn columns[] = {
{11, 3, profession::NONE, unit_labor::HAUL_REFUSE, job_skill::NONE, "Re"},
{11, 3, profession::NONE, unit_labor::HAUL_FURNITURE, job_skill::NONE, "Fu"},
{11, 3, profession::NONE, unit_labor::HAUL_ANIMAL, job_skill::NONE, "An"},
- {11, 3, profession::NONE, unit_labor::PUSH_HAUL_VEHICLE, job_skill::NONE, "Ve"},
+ {11, 3, profession::NONE, unit_labor::HANDLE_VEHICLES, job_skill::NONE, "Ve"},
// Other Jobs
{12, 4, profession::ARCHITECT, unit_labor::ARCHITECT, job_skill::DESIGNBUILDING, "Ar"},
{12, 4, profession::ALCHEMIST, unit_labor::ALCHEMIST, job_skill::ALCHEMY, "Al"},
@@ -217,6 +217,7 @@ const SkillColumn columns[] = {
{15, 8, profession::NONE, unit_labor::NONE, job_skill::SITUATIONAL_AWARENESS, "Ob"},
{15, 8, profession::NONE, unit_labor::NONE, job_skill::COORDINATION, "Cr"},
{15, 8, profession::NONE, unit_labor::NONE, job_skill::BALANCE, "Ba"},
+ {15, 8, profession::NONE, unit_labor::NONE, job_skill::CLIMBING, "Cl"},
// Social
{16, 3, profession::NONE, unit_labor::NONE, job_skill::PERSUASION, "Pe"},
{16, 3, profession::NONE, unit_labor::NONE, job_skill::NEGOTIATION, "Ne"},
diff --git a/plugins/prospector.cpp b/plugins/prospector.cpp
index cec6c3bcb..8f1cd91d9 100644
--- a/plugins/prospector.cpp
+++ b/plugins/prospector.cpp
@@ -489,7 +489,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;
+ coord2d cur_region = screen->location.region_pos;
auto cur_details = get_details(data, cur_region);
if (!cur_details)
@@ -512,9 +512,9 @@ static command_result embark_prospector(color_ostream &out, df::viewscreen_choos
biomes[screen->biome_rgn[screen->biome_idx]]++;
}*/
- for (int x = screen->embark_pos_min.x; x <= screen->embark_pos_max.x; x++)
+ for (int x = screen->location.embark_pos_min.x; x <= screen->location.embark_pos_max.x; x++)
{
- for (int y = screen->embark_pos_min.y; y <= screen->embark_pos_max.y; y++)
+ for (int y = screen->location.embark_pos_min.y; y <= screen->location.embark_pos_max.y; y++)
{
EmbarkTileLayout tile;
if (!estimate_underground(out, tile, cur_details, x, y) ||
diff --git a/plugins/reveal.cpp b/plugins/reveal.cpp
index 9bd63e47e..73c8f7be8 100644
--- a/plugins/reveal.cpp
+++ b/plugins/reveal.cpp
@@ -147,8 +147,8 @@ void revealAdventure(color_ostream &out)
{
df::map_block *block = world->map.map_blocks[i];
// in 'no-hell'/'safe' mode, don't reveal blocks with hell and adamantine
- if (!isSafe(block->map_pos))
- continue;
+// if (!isSafe(block->map_pos))
+// continue;
designations40d & designations = block->designation;
// for each tile in block
for (uint32_t x = 0; x < 16; x++) for (uint32_t y = 0; y < 16; y++)
@@ -430,7 +430,9 @@ command_result revflood(color_ostream &out, vector & params)
case tiletype_shape::STAIR_UP:
case tiletype_shape::RAMP:
case tiletype_shape::FLOOR:
- case tiletype_shape::TREE:
+ case tiletype_shape::BRANCH:
+ case tiletype_shape::TRUNK_BRANCH:
+ case tiletype_shape::TWIG:
case tiletype_shape::SAPLING:
case tiletype_shape::SHRUB:
case tiletype_shape::BOULDER:
@@ -442,6 +444,12 @@ command_result revflood(color_ostream &out, vector & params)
above = sides = true;
break;
}
+ if (tileMaterial(tt) == tiletype_material::PLANT || tileMaterial(tt) == tiletype_material::MUSHROOM)
+ {
+ if(from_below)
+ unhide = 0;
+ above = sides = true;
+ }
if(unhide)
{
des.bits.hidden = false;
diff --git a/plugins/search.cpp b/plugins/search.cpp
index 72001275c..7bb5cbd62 100644
--- a/plugins/search.cpp
+++ b/plugins/search.cpp
@@ -741,7 +741,6 @@ private:
virtual void do_post_init()
{
is_vermin = &viewscreen->is_vermin;
- pet_info = &viewscreen->pet_info;
is_tame = &viewscreen->is_tame;
is_adopting = &viewscreen->is_adopting;
}
@@ -764,7 +763,6 @@ private:
void save_secondary_values()
{
is_vermin_s = *is_vermin;
- pet_info_s = *pet_info;
is_tame_s = *is_tame;
is_adopting_s = *is_adopting;
}
@@ -772,7 +770,6 @@ private:
void reset_secondary_viewscreen_vectors()
{
is_vermin = NULL;
- pet_info = NULL;
is_tame = NULL;
is_adopting = NULL;
}
@@ -780,7 +777,6 @@ private:
void update_saved_secondary_list_item(size_t i, size_t j)
{
is_vermin_s[i] = (*is_vermin)[j];
- pet_info_s[i] = (*pet_info)[j];
is_tame_s[i] = (*is_tame)[j];
is_adopting_s[i] = (*is_adopting)[j];
}
@@ -788,7 +784,6 @@ private:
void clear_secondary_viewscreen_vectors()
{
is_vermin->clear();
- pet_info->clear();
is_tame->clear();
is_adopting->clear();
}
@@ -796,7 +791,6 @@ private:
void add_to_filtered_secondary_lists(size_t i)
{
is_vermin->push_back(is_vermin_s[i]);
- pet_info->push_back(pet_info_s[i]);
is_tame->push_back(is_tame_s[i]);
is_adopting->push_back(is_adopting_s[i]);
}
@@ -804,7 +798,6 @@ private:
void clear_secondary_saved_lists()
{
is_vermin_s.clear();
- pet_info_s.clear();
is_tame_s.clear();
is_adopting_s.clear();
}
@@ -812,7 +805,6 @@ private:
void restore_secondary_values()
{
*is_vermin = is_vermin_s;
- *pet_info = pet_info_s;
*is_tame = is_tame_s;
*is_adopting = is_adopting_s;
}
@@ -834,7 +826,6 @@ private:
}
std::vector *is_vermin, is_vermin_s;
- std::vector *pet_info, pet_info_s;
std::vector *is_tame, is_tame_s;
std::vector *is_adopting, is_adopting_s;
};
diff --git a/plugins/sort.cpp b/plugins/sort.cpp
index 95ae109a8..e4aad61e2 100644
--- a/plugins/sort.cpp
+++ b/plugins/sort.cpp
@@ -363,7 +363,6 @@ DEFINE_SORT_HANDLER(unit_sorters, pet, "/List", animals)
reorder_cursor(&animals->cursor, order);
reorder_vector(&animals->animal, order);
reorder_vector(&animals->is_vermin, order);
- reorder_vector(&animals->pet_info, order);
reorder_vector(&animals->is_tame, order);
reorder_vector(&animals->is_adopting, order);
}
diff --git a/plugins/tweak.cpp b/plugins/tweak.cpp
index 8154b473e..98e97cb0a 100644
--- a/plugins/tweak.cpp
+++ b/plugins/tweak.cpp
@@ -980,6 +980,7 @@ struct military_training_ct_hook : df::activity_event_combat_trainingst {
}
};
+/*
IMPLEMENT_VMETHOD_INTERPOSE(military_training_ct_hook, process);
struct military_training_sd_hook : df::activity_event_skill_demonstrationst {
@@ -1040,6 +1041,7 @@ struct military_training_id_hook : df::activity_event_individual_skill_drillst {
};
IMPLEMENT_VMETHOD_INTERPOSE(military_training_id_hook, process);
+*/
struct hive_crash_hook : df::building_hivest {
typedef df::building_hivest interpose_base;
@@ -1357,13 +1359,14 @@ static command_result tweak(color_ostream &out, vector ¶meters)
{
enable_hook(out, INTERPOSE_HOOK(military_assign_hook, render), parameters);
}
+/*
else if (cmd == "military-training")
{
enable_hook(out, INTERPOSE_HOOK(military_training_ct_hook, process), parameters);
enable_hook(out, INTERPOSE_HOOK(military_training_sd_hook, process), parameters);
enable_hook(out, INTERPOSE_HOOK(military_training_sp_hook, process), parameters);
enable_hook(out, INTERPOSE_HOOK(military_training_id_hook, process), parameters);
- }
+ }*/
else if (cmd == "hive-crash")
{
enable_hook(out, INTERPOSE_HOOK(hive_crash_hook, updateAction), parameters);
From e71160541352f3b7047b9d50b79772cafcbac1b7 Mon Sep 17 00:00:00 2001
From: Quietust
Date: Mon, 21 Jul 2014 13:26:34 -0500
Subject: [PATCH 02/22] Some minor corrections
---
library/modules/Items.cpp | 1 +
library/modules/MapCache.cpp | 9 +++++++++
library/modules/Translation.cpp | 3 ++-
plugins/reveal.cpp | 4 ++--
4 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/library/modules/Items.cpp b/library/modules/Items.cpp
index dbce89576..253e09468 100644
--- a/library/modules/Items.cpp
+++ b/library/modules/Items.cpp
@@ -1158,6 +1158,7 @@ int Items::getItemBaseValue(int16_t item_type, int16_t item_subtype, int16_t mat
case item_type::MEAT:
case item_type::PLANT:
+ case item_type::PLANT_GROWTH:
case item_type::CHEESE:
value = 2;
break;
diff --git a/library/modules/MapCache.cpp b/library/modules/MapCache.cpp
index 133ebedf9..da7683351 100644
--- a/library/modules/MapCache.cpp
+++ b/library/modules/MapCache.cpp
@@ -845,6 +845,15 @@ t_matpair MapExtras::BlockInfo::getBaseMaterial(df::tiletype tt, df::coord2d pos
case ROOT:
case TREE:
case PLANT:
+ rv.mat_type = MaterialInfo::PLANT_BASE;
+ if (auto plant = plants[block->map_pos + df::coord(x,y,0)])
+ {
+ if (auto raw = df::plant_raw::find(plant->material))
+ {
+ rv.mat_type = raw->material_defs.type_basic_mat;
+ rv.mat_index = raw->material_defs.idx_basic_mat;
+ }
+ }
break;
case GRASS_LIGHT:
diff --git a/library/modules/Translation.cpp b/library/modules/Translation.cpp
index b42cf4d2d..48ec646eb 100644
--- a/library/modules/Translation.cpp
+++ b/library/modules/Translation.cpp
@@ -46,6 +46,7 @@ using namespace df::enums;
using df::global::world;
using df::global::d_init;
+using df::global::gametype;
bool Translation::IsValid ()
{
@@ -153,7 +154,7 @@ string Translation::TranslateName(const df::language_name * name, bool inEnglish
if (!name->nickname.empty())
{
word = "`" + name->nickname + "'";
- switch (d_init ? d_init->nickname[*df::global::gametype] : d_init_nickname::CENTRALIZE)
+ switch ((d_init && gametype) ? d_init->nickname[*gametype] : d_init_nickname::CENTRALIZE)
{
case d_init_nickname::REPLACE_ALL:
out = word;
diff --git a/plugins/reveal.cpp b/plugins/reveal.cpp
index 73c8f7be8..1cafc3ca6 100644
--- a/plugins/reveal.cpp
+++ b/plugins/reveal.cpp
@@ -147,8 +147,8 @@ void revealAdventure(color_ostream &out)
{
df::map_block *block = world->map.map_blocks[i];
// in 'no-hell'/'safe' mode, don't reveal blocks with hell and adamantine
-// if (!isSafe(block->map_pos))
-// continue;
+ if (!isSafe(block->map_pos))
+ continue;
designations40d & designations = block->designation;
// for each tile in block
for (uint32_t x = 0; x < 16; x++) for (uint32_t y = 0; y < 16; y++)
From 38cdb37433f751f1334a0650c33445a97ba13067 Mon Sep 17 00:00:00 2001
From: Quietust
Date: Mon, 21 Jul 2014 14:46:51 -0500
Subject: [PATCH 03/22] Update plant_tree_info field names
---
library/modules/MapCache.cpp | 17 +++++++++--------
library/xml | 2 +-
2 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/library/modules/MapCache.cpp b/library/modules/MapCache.cpp
index da7683351..4d77ccb35 100644
--- a/library/modules/MapCache.cpp
+++ b/library/modules/MapCache.cpp
@@ -747,12 +747,12 @@ void MapExtras::BlockInfo::prepare(Block *mblock)
// tree_info contains vertical slices of the tree. This ensures there's a slice for our Z-level.
df::plant_tree_info * info = pp->tree_info;
- if(!((pp->pos.z-1 <= block->map_pos.z) && ((pp->pos.z+info->z_dim) > block->map_pos.z)))
+ if(!((pp->pos.z-1 <= block->map_pos.z) && ((pp->pos.z+info->body_height) > block->map_pos.z)))
continue;
// Parse through a single horizontal slice of the tree.
- for(int xx = 0; xx < info->x_dim;xx++)
- for(int yy = 0; yy < info->y_dim;yy++)
+ for(int xx = 0; xx < info->dim_x;xx++)
+ for(int yy = 0; yy < info->dim_y;yy++)
{
// Any non-zero value here other than blocked means there's some sort of branch here.
// If the block is at or above the plant's base level, we use the body array
@@ -760,14 +760,15 @@ void MapExtras::BlockInfo::prepare(Block *mblock)
// TODO: verify that the tree bounds intersect the block.
df::plant_tree_tile tile;
int z_diff = block->map_pos.z-pp->pos.z;
- if(z_diff >= 0)
- tile = info->body[z_diff][xx+(yy*info->x_dim)];
- else tile = info->roots[0][xx+(yy*info->x_dim)];
+ if ((z_diff >= 0) && (z_diff < info->body_height))
+ tile = info->body[z_diff][xx+(yy*info->dim_x)];
+ else if ((z_diff < 0) && (z_diff >= -info->roots_depth))
+ tile = info->roots[0][xx+(yy*info->dim_x)];
if(tile.whole && !(tile.bits.blocked))
{
df::coord pos=pp->pos;
- pos.x = pos.x - (info->x_dim/2) + xx;
- pos.y = pos.y - (info->y_dim/2) + yy;
+ pos.x = pos.x - (info->dim_x/2) + xx;
+ pos.y = pos.y - (info->dim_y/2) + yy;
pos.z = block->map_pos.z;
plants[pos] = pp;
}
diff --git a/library/xml b/library/xml
index ad20c0e25..e8e415684 160000
--- a/library/xml
+++ b/library/xml
@@ -1 +1 @@
-Subproject commit ad20c0e2598df0599954c0ff09df982d60c006dd
+Subproject commit e8e415684e9d8a2fdf1c69f5283889f6a2595157
From 9435d8f4d9d3152777470e85558ea2c2be078e58 Mon Sep 17 00:00:00 2001
From: Quietust
Date: Mon, 21 Jul 2014 19:14:43 -0500
Subject: [PATCH 04/22] Fix crashes caused by missing globals
---
library/Core.cpp | 18 +++++++-----
library/modules/EventManager.cpp | 47 ++++++++++++++++++++++++++++++++
scripts/devel/find-offsets.lua | 2 +-
3 files changed, 59 insertions(+), 8 deletions(-)
diff --git a/library/Core.cpp b/library/Core.cpp
index 175610700..d2e2d347e 100644
--- a/library/Core.cpp
+++ b/library/Core.cpp
@@ -394,12 +394,14 @@ static bool try_autocomplete(color_ostream &con, const std::string &first, std::
}
string findScript(string path, string name) {
- //first try the save folder if it exists
- string save = World::ReadWorldFolder();
- if ( save != "" ) {
- string file = path + "/data/save/" + save + "/raw/scripts/" + name;
- if (fileExists(file)) {
- return file;
+ if (df::global::world) {
+ //first try the save folder if it exists
+ string save = World::ReadWorldFolder();
+ if ( save != "" ) {
+ string file = path + "/data/save/" + save + "/raw/scripts/" + name;
+ if (fileExists(file)) {
+ return file;
+ }
}
}
string file = path + "/raw/scripts/" + name;
@@ -1407,7 +1409,9 @@ void Core::onUpdate(color_ostream &out)
}
static void handleLoadAndUnloadScripts(Core* core, color_ostream& out, state_change_event event) {
- //TODO: use different separators for windows
+ if (!df::global::world)
+ return;
+ //TODO: use different separators for windows
#ifdef _WIN32
static const std::string separator = "\\";
#else
diff --git a/library/modules/EventManager.cpp b/library/modules/EventManager.cpp
index 3dfe89822..86736d646 100644
--- a/library/modules/EventManager.cpp
+++ b/library/modules/EventManager.cpp
@@ -237,6 +237,16 @@ void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event
//out.print("%s,%d: on load, frame_counter = %d\n", __FILE__, __LINE__, tick);
*/
//tickQueue.clear();
+ if (!df::global::item_next_id)
+ return;
+ if (!df::global::building_next_id)
+ return;
+ if (!df::global::job_next_id)
+ return;
+ if (!df::global::ui)
+ return;
+ if (!df::global::world)
+ return;
nextItem = *df::global::item_next_id;
nextBuilding = *df::global::building_next_id;
@@ -291,6 +301,9 @@ void DFHack::EventManager::manageEvents(color_ostream& out) {
if ( !gameLoaded ) {
return;
}
+ if (!df::global::world)
+ return;
+
CoreSuspender suspender;
int32_t tick = df::global::world->frame_counter;
@@ -316,6 +329,8 @@ void DFHack::EventManager::manageEvents(color_ostream& out) {
}
static void manageTickEvent(color_ostream& out) {
+ if (!df::global::world)
+ return;
unordered_set toRemove;
int32_t tick = df::global::world->frame_counter;
while ( !tickQueue.empty() ) {
@@ -342,6 +357,10 @@ static void manageTickEvent(color_ostream& out) {
}
static void manageJobInitiatedEvent(color_ostream& out) {
+ if (!df::global::world)
+ return;
+ if (!df::global::job_next_id)
+ return;
if ( lastJobId == -1 ) {
lastJobId = *df::global::job_next_id - 1;
return;
@@ -375,6 +394,8 @@ static int32_t getWorkerID(df::job* job) {
TODO: consider checking item creation / experience gain just in case
*/
static void manageJobCompletedEvent(color_ostream& out) {
+ if (!df::global::world)
+ return;
int32_t tick0 = eventLastTick[EventType::JOB_COMPLETED];
int32_t tick1 = df::global::world->frame_counter;
@@ -500,6 +521,8 @@ static void manageJobCompletedEvent(color_ostream& out) {
}
static void manageUnitDeathEvent(color_ostream& out) {
+ if (!df::global::world)
+ return;
multimap copy(handlers[EventType::UNIT_DEATH].begin(), handlers[EventType::UNIT_DEATH].end());
for ( size_t a = 0; a < df::global::world->units.all.size(); a++ ) {
df::unit* unit = df::global::world->units.all[a];
@@ -520,6 +543,10 @@ static void manageUnitDeathEvent(color_ostream& out) {
}
static void manageItemCreationEvent(color_ostream& out) {
+ if (!df::global::world)
+ return;
+ if (!df::global::item_next_id)
+ return;
if ( nextItem >= *df::global::item_next_id ) {
return;
}
@@ -552,6 +579,10 @@ static void manageItemCreationEvent(color_ostream& out) {
}
static void manageBuildingEvent(color_ostream& out) {
+ if (!df::global::world)
+ return;
+ if (!df::global::building_next_id)
+ return;
/*
* TODO: could be faster
* consider looking at jobs: building creation / destruction
@@ -591,6 +622,8 @@ static void manageBuildingEvent(color_ostream& out) {
}
static void manageConstructionEvent(color_ostream& out) {
+ if (!df::global::world)
+ return;
//unordered_set constructionsNow(df::global::world->constructions.begin(), df::global::world->constructions.end());
multimap copy(handlers[EventType::CONSTRUCTION].begin(), handlers[EventType::CONSTRUCTION].end());
@@ -626,6 +659,8 @@ static void manageConstructionEvent(color_ostream& out) {
}
static void manageSyndromeEvent(color_ostream& out) {
+ if (!df::global::world)
+ return;
multimap copy(handlers[EventType::SYNDROME].begin(), handlers[EventType::SYNDROME].end());
int32_t highestTime = -1;
for ( auto a = df::global::world->units.all.begin(); a != df::global::world->units.all.end(); a++ ) {
@@ -653,6 +688,8 @@ static void manageSyndromeEvent(color_ostream& out) {
}
static void manageInvasionEvent(color_ostream& out) {
+ if (!df::global::ui)
+ return;
multimap copy(handlers[EventType::INVASION].begin(), handlers[EventType::INVASION].end());
if ( df::global::ui->invasions.next_id <= nextInvasion )
@@ -666,6 +703,8 @@ static void manageInvasionEvent(color_ostream& out) {
}
static void manageEquipmentEvent(color_ostream& out) {
+ if (!df::global::world)
+ return;
multimap copy(handlers[EventType::INVENTORY_CHANGE].begin(), handlers[EventType::INVENTORY_CHANGE].end());
unordered_map itemIdToInventoryItem;
@@ -747,6 +786,8 @@ static void manageEquipmentEvent(color_ostream& out) {
}
static void updateReportToRelevantUnits() {
+ if (!df::global::world)
+ return;
if ( df::global::world->frame_counter <= reportToRelevantUnitsTime )
return;
reportToRelevantUnitsTime = df::global::world->frame_counter;
@@ -767,6 +808,8 @@ static void updateReportToRelevantUnits() {
}
static void manageReportEvent(color_ostream& out) {
+ if (!df::global::world)
+ return;
multimap copy(handlers[EventType::REPORT].begin(), handlers[EventType::REPORT].end());
std::vector& reports = df::global::world->status.reports;
size_t a = df::report::binsearch_index(reports, lastReport, false);
@@ -795,6 +838,8 @@ static df::unit_wound* getWound(df::unit* attacker, df::unit* defender) {
}
static void manageUnitAttackEvent(color_ostream& out) {
+ if (!df::global::world)
+ return;
multimap copy(handlers[EventType::UNIT_ATTACK].begin(), handlers[EventType::UNIT_ATTACK].end());
std::vector& reports = df::global::world->status.reports;
size_t a = df::report::binsearch_index(reports, lastReportUnitAttack, false);
@@ -929,6 +974,8 @@ static std::string getVerb(df::unit* unit, std::string reportStr) {
}
static void manageInteractionEvent(color_ostream& out) {
+ if (!df::global::world)
+ return;
multimap copy(handlers[EventType::INTERACTION].begin(), handlers[EventType::INTERACTION].end());
std::vector& reports = df::global::world->status.reports;
size_t a = df::report::binsearch_index(reports, lastReportInteraction, false);
diff --git a/scripts/devel/find-offsets.lua b/scripts/devel/find-offsets.lua
index 1ce7a4425..f33b0124a 100644
--- a/scripts/devel/find-offsets.lua
+++ b/scripts/devel/find-offsets.lua
@@ -488,7 +488,7 @@ local function is_valid_world(world)
if not ms.is_valid_vector(world.units.all, 4)
or not ms.is_valid_vector(world.units.bad, 4)
or not ms.is_valid_vector(world.history.figures, 4)
- or not ms.is_valid_vector(world.cur_savegame.map_features, 4)
+ or not ms.is_valid_vector(world.features.map_features, 4)
then
dfhack.printerr('Vector layout check failed.')
return false
From 34ce7f61de44175b623b21b9b61220ff81f94513 Mon Sep 17 00:00:00 2001
From: Quietust
Date: Tue, 22 Jul 2014 16:38:18 -0500
Subject: [PATCH 05/22] Update find-offsets, find gview properly even if INTRO
is enabled
---
scripts/devel/find-offsets.lua | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/scripts/devel/find-offsets.lua b/scripts/devel/find-offsets.lua
index f33b0124a..505400ffd 100644
--- a/scripts/devel/find-offsets.lua
+++ b/scripts/devel/find-offsets.lua
@@ -400,6 +400,12 @@ local function find_gview()
return
end
+ idx, addr = data.uint32_t:find_one{100, vs_vtable}
+ if idx then
+ ms.found_offset('gview', addr)
+ return
+ end
+
dfhack.printerr('Could not find gview')
end
From 4902c577b360fe1b77259d6066ee68a0148c7378 Mon Sep 17 00:00:00 2001
From: Alexander Gavrilov
Date: Thu, 24 Jul 2014 23:10:37 +0400
Subject: [PATCH 06/22] Fix some crashes when running without globals and
update structures.
---
library/Core.cpp | 6 ++++++
library/lua/memscan.lua | 2 +-
library/modules/Gui.cpp | 3 +++
library/xml | 2 +-
scripts/devel/find-offsets.lua | 13 ++++++++++++-
5 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/library/Core.cpp b/library/Core.cpp
index d2e2d347e..6cc47292f 100644
--- a/library/Core.cpp
+++ b/library/Core.cpp
@@ -841,6 +841,12 @@ bool Core::loadScriptFile(color_ostream &out, string fname, bool silent)
static void run_dfhack_init(color_ostream &out, Core *core)
{
+ if (!df::global::world || !df::global::ui || !df::global::gview)
+ {
+ out.printerr("Key globals are missing, skipping loading dfhack.init.\n");
+ return;
+ }
+
if (!core->loadScriptFile(out, "dfhack.init", true))
{
core->runCommand(out, "gui/no-dfhack-init");
diff --git a/library/lua/memscan.lua b/library/lua/memscan.lua
index ce7d2f1e5..00a80cc48 100644
--- a/library/lua/memscan.lua
+++ b/library/lua/memscan.lua
@@ -268,7 +268,7 @@ function found_offset(name,val)
if cval then
if cval ~= val then
- error(string.format('Mismatch with the current value: %x',val))
+ error(string.format('Mismatch with the current value: %x != %x',val,cval))
end
else
dfhack.internal.setAddress(name, val)
diff --git a/library/modules/Gui.cpp b/library/modules/Gui.cpp
index bb9ce6676..fedb95954 100644
--- a/library/modules/Gui.cpp
+++ b/library/modules/Gui.cpp
@@ -1310,6 +1310,9 @@ void Gui::showAutoAnnouncement(
df::viewscreen *Gui::getCurViewscreen(bool skip_dismissed)
{
+ if (!gview)
+ return NULL;
+
df::viewscreen * ws = &gview->view;
while (ws && ws->child)
ws = ws->child;
diff --git a/library/xml b/library/xml
index e8e415684..996c51902 160000
--- a/library/xml
+++ b/library/xml
@@ -1 +1 @@
-Subproject commit e8e415684e9d8a2fdf1c69f5283889f6a2595157
+Subproject commit 996c5190247607a39da51b8b412fe11ed890d842
diff --git a/scripts/devel/find-offsets.lua b/scripts/devel/find-offsets.lua
index 505400ffd..e907fe5de 100644
--- a/scripts/devel/find-offsets.lua
+++ b/scripts/devel/find-offsets.lua
@@ -4,6 +4,17 @@ local utils = require 'utils'
local ms = require 'memscan'
local gui = require 'gui'
+--[[
+
+Arguments:
+
+ * global names to force finding them
+ * 'all' to force all globals
+ * 'nofeed' to block automated fake input searches
+ * 'nozoom' to disable neighboring object heuristics
+
+]]
+
local is_known = dfhack.internal.getAddress
local os_type = dfhack.getOSType()
@@ -1415,7 +1426,7 @@ local function find_process_jobs()
Searching for process_jobs. Please do as instructed below:]],
'int8_t',
{ 1, 0 },
- { [1] = 'designate a building to be constructed, e.g a bed',
+ { [1] = 'designate a building to be constructed, e.g a bed or a wall',
[0] = 'step or unpause the game to reset the flag' }
)
ms.found_offset('process_jobs', addr)
From 1c409975de1a3756fe1ef872d0cb9a7383a4bcaf Mon Sep 17 00:00:00 2001
From: Alexander Gavrilov
Date: Mon, 28 Jul 2014 08:15:03 +0400
Subject: [PATCH 07/22] Update the version to v0.40.05
---
CMakeLists.txt | 2 +-
library/xml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 231cef16c..04c9ab215 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -58,7 +58,7 @@ if (NOT EXISTS ${dfhack_SOURCE_DIR}/library/xml/codegen.pl OR NOT EXISTS ${dfhac
endif()
# set up versioning.
-set(DF_VERSION "0.40.04")
+set(DF_VERSION "0.40.05")
SET(DFHACK_RELEASE "r0" CACHE STRING "Current release revision.")
set(DFHACK_VERSION "${DF_VERSION}-${DFHACK_RELEASE}")
diff --git a/library/xml b/library/xml
index 996c51902..ac936b06b 160000
--- a/library/xml
+++ b/library/xml
@@ -1 +1 @@
-Subproject commit 996c5190247607a39da51b8b412fe11ed890d842
+Subproject commit ac936b06bd0a69c84c4e0a94a4f22b3b1402b23b
From 0182e0c980d7ee384944272fee5504b5a6ac2cd8 Mon Sep 17 00:00:00 2001
From: Alexander Gavrilov
Date: Mon, 28 Jul 2014 08:57:55 +0400
Subject: [PATCH 08/22] Fix SC_WORLD_LOADED/UNLOADED now that loading and
saving takes many frames.
During the loading or saving screen, consider the map and world as not
loaded, because they are likely only partially valid. This fixes errors
from the log-region script.
---
library/Core.cpp | 29 +++++++++++++++++++----------
library/xml | 2 +-
2 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/library/Core.cpp b/library/Core.cpp
index 6cc47292f..01964139c 100644
--- a/library/Core.cpp
+++ b/library/Core.cpp
@@ -61,6 +61,8 @@ using namespace DFHack;
#include "df/world_data.h"
#include "df/interfacest.h"
#include "df/viewscreen_dwarfmodest.h"
+#include "df/viewscreen_loadgamest.h"
+#include "df/viewscreen_savegamest.h"
#include
#include
@@ -1268,10 +1270,23 @@ void Core::doUpdate(color_ostream &out, bool first_update)
if (first_update)
onStateChange(out, SC_CORE_INITIALIZED);
+ // find the current viewscreen
+ df::viewscreen *screen = NULL;
+ if (df::global::gview)
+ {
+ screen = &df::global::gview->view;
+ while (screen->child)
+ screen = screen->child;
+ }
+
+ bool is_load_save =
+ strict_virtual_cast(screen) ||
+ strict_virtual_cast(screen);
+
// detect if the game was loaded or unloaded in the meantime
void *new_wdata = NULL;
void *new_mapdata = NULL;
- if (df::global::world)
+ if (df::global::world && !is_load_save)
{
df::world_data *wdata = df::global::world->world_data;
// when the game is unloaded, world_data isn't deleted, but its contents are
@@ -1313,16 +1328,10 @@ void Core::doUpdate(color_ostream &out, bool first_update)
}
// detect if the viewscreen changed
- if (df::global::gview)
+ if (screen != top_viewscreen)
{
- df::viewscreen *screen = &df::global::gview->view;
- while (screen->child)
- screen = screen->child;
- if (screen != top_viewscreen)
- {
- top_viewscreen = screen;
- onStateChange(out, SC_VIEWSCREEN_CHANGED);
- }
+ top_viewscreen = screen;
+ onStateChange(out, SC_VIEWSCREEN_CHANGED);
}
if (df::global::pause_state)
diff --git a/library/xml b/library/xml
index ac936b06b..cb4c883d4 160000
--- a/library/xml
+++ b/library/xml
@@ -1 +1 @@
-Subproject commit ac936b06bd0a69c84c4e0a94a4f22b3b1402b23b
+Subproject commit cb4c883d4f4f46fc9b4856d7e91f55e1b39b56c5
From d6162cd1892d880d0681a962d4f9791695a6ed34 Mon Sep 17 00:00:00 2001
From: Quietust
Date: Tue, 29 Jul 2014 16:26:14 -0500
Subject: [PATCH 09/22] death_info -> incident
---
library/RemoteTools.cpp | 8 ++++----
plugins/cursecheck.cpp | 4 ++--
plugins/tweak.cpp | 4 ++--
scripts/gui/unit-info-viewer.lua | 14 +++++++-------
4 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/library/RemoteTools.cpp b/library/RemoteTools.cpp
index 17f5258e1..ae352a6f9 100644
--- a/library/RemoteTools.cpp
+++ b/library/RemoteTools.cpp
@@ -1,4 +1,4 @@
-/*
+/*
https://github.com/peterix/dfhack
Copyright (c) 2011 Petr Mrázek
@@ -76,7 +76,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "df/historical_entity.h"
#include "df/squad.h"
#include "df/squad_position.h"
-#include "df/death_info.h"
+#include "df/incident.h"
#include "BasicApi.pb.h"
@@ -283,7 +283,7 @@ void DFHack::describeUnit(BasicUnitInfo *info, df::unit *unit,
if (unit->counters.death_id >= 0)
{
info->set_death_id(unit->counters.death_id);
- if (auto death = df::death_info::find(unit->counters.death_id))
+ if (auto death = df::incident::find(unit->counters.death_id))
info->set_death_flags(death->flags.whole);
}
@@ -455,7 +455,7 @@ static command_result ListEnums(color_ostream &stream,
BITFIELD(cie_add_tag_mask1);
BITFIELD(cie_add_tag_mask2);
- describe_bitfield(out->mutable_death_info_flags());
+ describe_bitfield(out->mutable_incident_flags());
ENUM(profession);
diff --git a/plugins/cursecheck.cpp b/plugins/cursecheck.cpp
index d4005d3d0..5dbc872c9 100644
--- a/plugins/cursecheck.cpp
+++ b/plugins/cursecheck.cpp
@@ -42,7 +42,7 @@ using namespace std;
#include "df/language_name.h"
#include "df/world.h"
#include "df/world_raws.h"
-#include "df/death_info.h"
+#include "df/incident.h"
using std::vector;
using std::string;
@@ -260,7 +260,7 @@ command_result cursecheck (color_ostream &out, vector & parameters)
out.print("Unnamed creature ");
}
- auto death = df::death_info::find(unit->counters.death_id);
+ auto death = df::incident::find(unit->counters.death_id);
bool missing = false;
if (death && !death->flags.bits.discovered)
{
diff --git a/plugins/tweak.cpp b/plugins/tweak.cpp
index 98e97cb0a..9c5999ca5 100644
--- a/plugins/tweak.cpp
+++ b/plugins/tweak.cpp
@@ -27,7 +27,7 @@
#include "df/historical_figure_info.h"
#include "df/assumed_identity.h"
#include "df/language_name.h"
-#include "df/death_info.h"
+#include "df/incident.h"
#include "df/criminal_case.h"
#include "df/unit_inventory_item.h"
#include "df/viewscreen_dwarfmodest.h"
@@ -1211,7 +1211,7 @@ static command_result tweak(color_ostream &out, vector ¶meters)
if (!unit)
return CR_FAILURE;
- auto death = df::death_info::find(unit->counters.death_id);
+ auto death = df::incident::find(unit->counters.death_id);
if (death)
{
diff --git a/scripts/gui/unit-info-viewer.lua b/scripts/gui/unit-info-viewer.lua
index 029db28d5..aa8cb3a20 100644
--- a/scripts/gui/unit-info-viewer.lua
+++ b/scripts/gui/unit-info-viewer.lua
@@ -417,16 +417,16 @@ function Identity:init(args)
end
end
if u.counters.death_id > -1 then -- if undead/ghostly dead or dead-dead
- self.death_info = df.global.world.deaths.all[u.counters.death_id]
- if not self.death_info.flags.discovered then
+ self.incident = df.global.world.incidents.all[u.counters.death_id]
+ if not self.incident.flags.discovered then
self.missing = true
end
end
-- slaughtered?
if self.death_event then
self.death_date = Time{year = self.death_event.year, ticks = self.death_event.seconds}
- elseif self.death_info then
- self.death_date = Time{year = self.death_info.event_year, ticks = self.death_info.event_time}
+ elseif self.incident then
+ self.death_date = Time{year = self.incident.event_year, ticks = self.incident.event_time}
end
-- age now or age death?
if self.dead and self.death_date then -- if cursed with no age? -- if hacked a ressurection, such that they aren't dead anymore, don't use the death date
@@ -753,14 +753,14 @@ function UnitInfoViewer:chunk_Dead()
--str << ", shot by a #{df.world.raws.itemdefs.weapons[e.weapon.bow_item_subtype].name}" if e.weapon.bow_item_type == :WEAPON
str = DEATH_TYPES[i.death_event.death_cause]..PERIOD
pen = pens.MAGENTA
- elseif i.death_info then
+ elseif i.incident then
--str = "The #{u.race_tg.name[0]}"
--str << " #{u.name}" if u.name.has_name
--str << " died"
- --str << " in year #{death_info.event_year}" if death_info
+ --str << " in year #{incident.event_year}" if incident
--str << " (cause: #{u.counters.death_cause.to_s.downcase})," if u.counters.death_cause != -1
--str << " killed by the #{killer.race_tg.name[0]} #{killer.name}" if killer
- str = DEATH_TYPES[i.death_info.death_cause]..PERIOD
+ str = DEATH_TYPES[i.incident.death_cause]..PERIOD
pen = pens.MAGENTA
elseif i.unit.flags2.slaughter and i.unit.flags2.killed then
str = ' was slaughtered.'
From 88dfb1faef3bbd175ca35efa931cb903276bacf8 Mon Sep 17 00:00:00 2001
From: Quietust
Date: Tue, 29 Jul 2014 16:27:16 -0500
Subject: [PATCH 10/22] criminal_case -> crime
---
plugins/tweak.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/plugins/tweak.cpp b/plugins/tweak.cpp
index 9c5999ca5..25b56d9dc 100644
--- a/plugins/tweak.cpp
+++ b/plugins/tweak.cpp
@@ -28,7 +28,7 @@
#include "df/assumed_identity.h"
#include "df/language_name.h"
#include "df/incident.h"
-#include "df/criminal_case.h"
+#include "df/crime.h"
#include "df/unit_inventory_item.h"
#include "df/viewscreen_dwarfmodest.h"
#include "df/viewscreen_layer_unit_actionst.h"
@@ -1217,7 +1217,7 @@ static command_result tweak(color_ostream &out, vector ¶meters)
{
death->flags.bits.discovered = true;
- auto crime = df::criminal_case::find(death->crime_id);
+ auto crime = df::crime::find(death->crime_id);
if (crime)
crime->flags.bits.discovered = true;
}
From 14502984847e6a4a7fcbefeda792a15a54eb11ab Mon Sep 17 00:00:00 2001
From: Quietust
Date: Tue, 29 Jul 2014 16:30:22 -0500
Subject: [PATCH 11/22] assumed_identity -> identity
---
library/LuaApi.cpp | 2 +-
library/include/modules/Units.h | 4 ++--
library/modules/Units.cpp | 8 ++++----
plugins/cursecheck.cpp | 4 ++--
plugins/rename.cpp | 2 +-
plugins/siege-engine.cpp | 2 +-
plugins/tweak.cpp | 2 +-
scripts/devel/export-dt-ini.lua | 10 +++++-----
8 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp
index aebe8e5c1..711e0e38a 100644
--- a/library/LuaApi.cpp
+++ b/library/LuaApi.cpp
@@ -66,7 +66,7 @@ distribution.
#include "df/item.h"
#include "df/material.h"
#include "df/viewscreen.h"
-#include "df/assumed_identity.h"
+#include "df/identity.h"
#include "df/nemesis_record.h"
#include "df/historical_figure.h"
#include "df/historical_entity.h"
diff --git a/library/include/modules/Units.h b/library/include/modules/Units.h
index 5380d82aa..6462b166c 100644
--- a/library/include/modules/Units.h
+++ b/library/include/modules/Units.h
@@ -41,7 +41,7 @@ namespace df
{
struct nemesis_record;
struct burrow;
- struct assumed_identity;
+ struct identity;
struct historical_entity;
struct entity_position_assignment;
struct entity_position;
@@ -213,7 +213,7 @@ DFHACK_EXPORT df::item *getContainer(df::unit *unit);
DFHACK_EXPORT void setNickname(df::unit *unit, std::string nick);
DFHACK_EXPORT df::language_name *getVisibleName(df::unit *unit);
-DFHACK_EXPORT df::assumed_identity *getIdentity(df::unit *unit);
+DFHACK_EXPORT df::identity *getIdentity(df::unit *unit);
DFHACK_EXPORT df::nemesis_record *getNemesis(df::unit *unit);
DFHACK_EXPORT bool isHidingCurse(df::unit *unit);
diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp
index 72c61b3d0..9d2ebf2dd 100644
--- a/library/modules/Units.cpp
+++ b/library/modules/Units.cpp
@@ -61,7 +61,7 @@ using namespace std;
#include "df/entity_position.h"
#include "df/entity_position_assignment.h"
#include "df/histfig_entity_link_positionst.h"
-#include "df/assumed_identity.h"
+#include "df/identity.h"
#include "df/burrow.h"
#include "df/creature_raw.h"
#include "df/caste_raw.h"
@@ -544,15 +544,15 @@ df::item *Units::getContainer(df::unit *unit)
return findItemRef(unit->general_refs, general_ref_type::CONTAINED_IN_ITEM);
}
-static df::assumed_identity *getFigureIdentity(df::historical_figure *figure)
+static df::identity *getFigureIdentity(df::historical_figure *figure)
{
if (figure && figure->info && figure->info->reputation)
- return df::assumed_identity::find(figure->info->reputation->cur_identity);
+ return df::identity::find(figure->info->reputation->cur_identity);
return NULL;
}
-df::assumed_identity *Units::getIdentity(df::unit *unit)
+df::identity *Units::getIdentity(df::unit *unit)
{
CHECK_NULL_POINTER(unit);
diff --git a/plugins/cursecheck.cpp b/plugins/cursecheck.cpp
index 5dbc872c9..f7c6d2fd9 100644
--- a/plugins/cursecheck.cpp
+++ b/plugins/cursecheck.cpp
@@ -38,7 +38,7 @@ using namespace std;
#include "df/historical_entity.h"
#include "df/historical_figure.h"
#include "df/historical_figure_info.h"
-#include "df/assumed_identity.h"
+#include "df/identity.h"
#include "df/language_name.h"
#include "df/world.h"
#include "df/world_raws.h"
@@ -104,7 +104,7 @@ void setUnitNickname(df::unit *unit, const std::string &nick)
// v0.34.01: added the vampire's assumed identity
if (figure->info && figure->info->reputation)
{
- auto identity = df::assumed_identity::find(figure->info->reputation->cur_identity);
+ auto identity = df::identity::find(figure->info->reputation->cur_identity);
if (identity)
{
diff --git a/plugins/rename.cpp b/plugins/rename.cpp
index fdebad1d3..383066b5e 100644
--- a/plugins/rename.cpp
+++ b/plugins/rename.cpp
@@ -22,7 +22,7 @@
#include "df/historical_entity.h"
#include "df/historical_figure.h"
#include "df/historical_figure_info.h"
-#include "df/assumed_identity.h"
+#include "df/identity.h"
#include "df/language_name.h"
#include "df/building_stockpilest.h"
#include "df/building_workshopst.h"
diff --git a/plugins/siege-engine.cpp b/plugins/siege-engine.cpp
index 124f464cc..6898b79e6 100644
--- a/plugins/siege-engine.cpp
+++ b/plugins/siege-engine.cpp
@@ -42,7 +42,7 @@
#include "df/creature_raw.h"
#include "df/caste_raw.h"
#include "df/caste_raw_flags.h"
-#include "df/assumed_identity.h"
+#include "df/identity.h"
#include "df/game_mode.h"
#include "df/unit_misc_trait.h"
#include "df/job.h"
diff --git a/plugins/tweak.cpp b/plugins/tweak.cpp
index 25b56d9dc..f6ecee913 100644
--- a/plugins/tweak.cpp
+++ b/plugins/tweak.cpp
@@ -25,7 +25,7 @@
#include "df/historical_entity.h"
#include "df/historical_figure.h"
#include "df/historical_figure_info.h"
-#include "df/assumed_identity.h"
+#include "df/identity.h"
#include "df/language_name.h"
#include "df/incident.h"
#include "df/crime.h"
diff --git a/scripts/devel/export-dt-ini.lua b/scripts/devel/export-dt-ini.lua
index 90776f1e2..a5a067c08 100644
--- a/scripts/devel/export-dt-ini.lua
+++ b/scripts/devel/export-dt-ini.lua
@@ -87,9 +87,9 @@ offset('dwarf_civ_index',globals,'ui','civ_id')
vector('races_vector',globals,'world','raws','creatures','all')
vector('reactions_vector',globals,'world','raws','reactions')
vector('historical_figures',globals,'world','history','figures')
-vector('fake_identities',globals,'world','assumed_identities','all')
+vector('fake_identities',globals,'world','identities','all')
vector('historical_figures_vector',globals,'world','history','figures')
-vector('fake_identities_vector',globals,'world','assumed_identities','all')
+vector('fake_identities_vector',globals,'world','identities','all')
offset('fortress_entity',globals,'ui','main','fortress_entity')
vector('historical_entities_vector',globals,'world','entities','all')
vector('weapons_vector',globals,'world','raws','itemdefs','weapons')
@@ -178,9 +178,9 @@ offset('id',df.historical_figure,'id')
offset('hist_fig_info',df.historical_figure,'info')
offset('reputation',df.historical_figure_info,'reputation')
offset('current_ident',df.historical_figure_info.T_reputation,'cur_identity')
-offset('fake_name',df.assumed_identity,'name')
-offset('fake_birth_year',df.assumed_identity,'birth_year')
-offset('fake_birth_time',df.assumed_identity,'birth_second')
+offset('fake_name',df.identity,'name')
+offset('fake_birth_year',df.identity,'birth_year')
+offset('fake_birth_time',df.identity,'birth_second')
header('weapon_offsets')
offset('name_plural',df.itemdef_weaponst,'name_plural')
From 612bcc65c8875c16701b14804775bcb92f89e084 Mon Sep 17 00:00:00 2001
From: Quietust
Date: Tue, 29 Jul 2014 16:43:29 -0500
Subject: [PATCH 12/22] Fix build, update XML
---
library/RemoteTools.cpp | 4 ++--
library/xml | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/library/RemoteTools.cpp b/library/RemoteTools.cpp
index ae352a6f9..f1887c9a7 100644
--- a/library/RemoteTools.cpp
+++ b/library/RemoteTools.cpp
@@ -1,4 +1,4 @@
-/*
+/*
https://github.com/peterix/dfhack
Copyright (c) 2011 Petr Mrázek
@@ -455,7 +455,7 @@ static command_result ListEnums(color_ostream &stream,
BITFIELD(cie_add_tag_mask1);
BITFIELD(cie_add_tag_mask2);
- describe_bitfield(out->mutable_incident_flags());
+ describe_bitfield(out->mutable_death_info_flags());
ENUM(profession);
diff --git a/library/xml b/library/xml
index cb4c883d4..1d8e07095 160000
--- a/library/xml
+++ b/library/xml
@@ -1 +1 @@
-Subproject commit cb4c883d4f4f46fc9b4856d7e91f55e1b39b56c5
+Subproject commit 1d8e0709572b2adb69ee99025b6c227d687773c9
From 2928f156291963c3db368fe1dae107ddeb5a9420 Mon Sep 17 00:00:00 2001
From: Quietust
Date: Fri, 1 Aug 2014 08:45:23 -0500
Subject: [PATCH 13/22] Update fastdwarf to work properly in 0.40
---
library/xml | 2 +-
plugins/fastdwarf.cpp | 97 +++++++++++++++++++++++++++++++++----------
2 files changed, 75 insertions(+), 24 deletions(-)
diff --git a/library/xml b/library/xml
index 1d8e07095..60ae817c4 160000
--- a/library/xml
+++ b/library/xml
@@ -1 +1 @@
-Subproject commit 1d8e0709572b2adb69ee99025b6c227d687773c9
+Subproject commit 60ae817c40fb366460412b6b659bb1228836f8bf
diff --git a/plugins/fastdwarf.cpp b/plugins/fastdwarf.cpp
index 587280385..b03fda561 100644
--- a/plugins/fastdwarf.cpp
+++ b/plugins/fastdwarf.cpp
@@ -8,13 +8,17 @@
#include "DataDefs.h"
#include "df/world.h"
#include "df/unit.h"
+#include "df/unit_action.h"
#include "df/map_block.h"
using std::string;
using std::vector;
+
using namespace DFHack;
+using namespace df::enums;
using df::global::world;
+using df::global::debug_turbospeed;
// dfhack interface
DFHACK_PLUGIN("fastdwarf");
@@ -26,8 +30,8 @@ static bool enable_teledwarf = false;
DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{
- if (df::global::debug_turbospeed)
- *df::global::debug_turbospeed = false;
+ if (debug_turbospeed)
+ *debug_turbospeed = false;
return CR_OK;
}
@@ -51,22 +55,8 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
if (!Units::isCitizen(unit))
continue;
- if (enable_fastdwarf && !enable_teledwarf )
- {
- if (unit->counters.job_counter > 0)
- unit->counters.job_counter = 0;
- // could also patch the unit->job.current_job->completion_timer
- }
-
if (enable_teledwarf) do
{
- // don't do anything if the dwarf isn't going anywhere
- if (!unit->pos.isValid() || !unit->path.dest.isValid() || unit->pos == unit->path.dest) {
- if ( enable_fastdwarf && unit->counters.job_counter > 0 )
- unit->counters.job_counter = 0;
- break;
- }
-
// skip dwarves that are dragging creatures or being dragged
if ((unit->relations.draggee_id != -1) || (unit->relations.dragger_id != -1))
break;
@@ -79,6 +69,11 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
if (unit->counters.unconscious > 0)
break;
+ // don't do anything if the dwarf isn't going anywhere
+ if (!unit->pos.isValid() || !unit->path.dest.isValid() || unit->pos == unit->path.dest) {
+ break;
+ }
+
// make sure source and dest map blocks are valid
auto old_occ = Maps::getTileOccupancy(unit->pos);
auto new_occ = Maps::getTileOccupancy(unit->path.dest);
@@ -106,6 +101,62 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
unit->pos = unit->path.dest;
unit->path.path.clear();
} while (0);
+
+ if (enable_fastdwarf)
+ {
+ for (size_t i = 0; i < unit->actions.size(); i++)
+ {
+ df::unit_action *action = unit->actions[i];
+ switch (action->type)
+ {
+ case unit_action_type::Move:
+ action->data.move.timer = 1;
+ break;
+ case unit_action_type::Attack:
+ action->data.attack.timer1 = 1;
+ action->data.attack.timer2 = 1;
+ break;
+ case unit_action_type::Hold:
+ action->data.hold.timer = 1;
+ break;
+ case unit_action_type::Climb:
+ action->data.climb.timer = 1;
+ break;
+ case unit_action_type::Job:
+ action->data.job.timer = 1;
+ // could also patch the unit->job.current_job->completion_timer
+ break;
+ case unit_action_type::Talk:
+ action->data.talk.timer = 1;
+ break;
+ case unit_action_type::Unsteady:
+ action->data.unsteady.timer = 1;
+ break;
+ case unit_action_type::Dodge:
+ action->data.dodge.timer = 1;
+ break;
+ case unit_action_type::Recover:
+ action->data.recover.timer = 1;
+ break;
+ case unit_action_type::StandUp:
+ action->data.standup.timer = 1;
+ break;
+ case unit_action_type::LieDown:
+ action->data.liedown.timer = 1;
+ break;
+ case unit_action_type::Job2:
+ action->data.job2.timer = 1;
+ // could also patch the unit->job.current_job->completion_timer
+ break;
+ case unit_action_type::PushObject:
+ action->data.pushobject.timer = 1;
+ break;
+ case unit_action_type::SuckBlood:
+ action->data.suckblood.timer = 1;
+ break;
+ }
+ }
+ }
}
return CR_OK;
}
@@ -131,21 +182,21 @@ static command_result fastdwarf (color_ostream &out, vector & parameter
if (parameters[0] == "0")
{
enable_fastdwarf = false;
- if (df::global::debug_turbospeed)
- *df::global::debug_turbospeed = false;
+ if (debug_turbospeed)
+ *debug_turbospeed = false;
}
else if (parameters[0] == "1")
{
enable_fastdwarf = true;
- if (df::global::debug_turbospeed)
- *df::global::debug_turbospeed = false;
+ if (debug_turbospeed)
+ *debug_turbospeed = false;
}
else if (parameters[0] == "2")
{
- if (df::global::debug_turbospeed)
+ if (debug_turbospeed)
{
enable_fastdwarf = false;
- *df::global::debug_turbospeed = true;
+ *debug_turbospeed = true;
}
else
{
@@ -160,7 +211,7 @@ static command_result fastdwarf (color_ostream &out, vector & parameter
active = enable_fastdwarf || enable_teledwarf;
out.print("Current state: fast = %d, teleport = %d.\n",
- (df::global::debug_turbospeed && *df::global::debug_turbospeed) ? 2 : (enable_fastdwarf ? 1 : 0),
+ (debug_turbospeed && *debug_turbospeed) ? 2 : (enable_fastdwarf ? 1 : 0),
enable_teledwarf ? 1 : 0);
return CR_OK;
From 14208577dd52513a533d1bcb623476792bdd7f06 Mon Sep 17 00:00:00 2001
From: lethosor
Date: Sun, 3 Aug 2014 22:02:15 -0400
Subject: [PATCH 14/22] Display all found offsets on completion
---
scripts/devel/find-offsets.lua | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/scripts/devel/find-offsets.lua b/scripts/devel/find-offsets.lua
index e907fe5de..2e1d5cf9c 100644
--- a/scripts/devel/find-offsets.lua
+++ b/scripts/devel/find-offsets.lua
@@ -130,12 +130,14 @@ local function zoomed_searcher(startn, end_or_sz)
end
end
+local finder_searches = {}
local function exec_finder(finder, names)
if type(names) ~= 'table' then
names = { names }
end
local search = force_scan['all']
for _,v in ipairs(names) do
+ table.insert(finder_searches, v)
if force_scan[v] or not is_known(v) then
search = true
end
@@ -1544,5 +1546,14 @@ exec_finder(find_process_jobs, 'process_jobs')
exec_finder(find_process_dig, 'process_dig')
exec_finder(find_pause_state, 'pause_state')
-print('\nDone. Now add newly-found globals to symbols.xml.')
+print('\nDone. Now add newly-found globals to symbols.xml.\n')
+
+for _, global in ipairs(finder_searches) do
+ local addr = dfhack.internal.getAddress(global)
+ if addr ~= nil then
+ local ival = addr - dfhack.internal.getRebaseDelta()
+ print(string.format("", global, ival))
+ end
+end
+
searcher:reset()
From fa26aa79eadded88062598a1cc4618868975aabb Mon Sep 17 00:00:00 2001
From: lethosor
Date: Fri, 25 Jul 2014 21:49:46 -0400
Subject: [PATCH 15/22] Make some plugins compile for 0.40
dwarfmonitor: remove StoreItemInChest, StoreItemInCabinet, ProcessPlantsBag, and BrewDrink
dig/diggingInvaders/siege-engine: update special cases for trees to handle roots/branches/trunks
---
plugins/CMakeLists.txt | 8 ++++----
plugins/dig.cpp | 4 +++-
plugins/diggingInvaders/edgeCost.cpp | 4 +++-
plugins/dwarfmonitor.cpp | 4 ----
plugins/siege-engine.cpp | 5 ++++-
5 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt
index bcae09442..595a73a19 100644
--- a/plugins/CMakeLists.txt
+++ b/plugins/CMakeLists.txt
@@ -104,11 +104,11 @@ if (BUILD_SUPPORTED)
DFHACK_PLUGIN(createitem createitem.cpp)
DFHACK_PLUGIN(cursecheck cursecheck.cpp)
DFHACK_PLUGIN(deramp deramp.cpp)
-# DFHACK_PLUGIN(dig dig.cpp)
+ DFHACK_PLUGIN(dig dig.cpp)
DFHACK_PLUGIN(digFlood digFlood.cpp)
-# add_subdirectory(diggingInvaders)
+ add_subdirectory(diggingInvaders)
DFHACK_PLUGIN(drybuckets drybuckets.cpp)
-# DFHACK_PLUGIN(dwarfmonitor dwarfmonitor.cpp)
+ DFHACK_PLUGIN(dwarfmonitor dwarfmonitor.cpp)
DFHACK_PLUGIN(embark-tools embark-tools.cpp)
DFHACK_PLUGIN(eventful eventful.cpp LINK_LIBRARIES lua)
DFHACK_PLUGIN(fastdwarf fastdwarf.cpp)
@@ -145,7 +145,7 @@ if (BUILD_SUPPORTED)
DFHACK_PLUGIN(search search.cpp)
DFHACK_PLUGIN(seedwatch seedwatch.cpp)
DFHACK_PLUGIN(showmood showmood.cpp)
-# DFHACK_PLUGIN(siege-engine siege-engine.cpp LINK_LIBRARIES lua)
+ DFHACK_PLUGIN(siege-engine siege-engine.cpp LINK_LIBRARIES lua)
DFHACK_PLUGIN(sort sort.cpp LINK_LIBRARIES lua)
DFHACK_PLUGIN(steam-engine steam-engine.cpp)
DFHACK_PLUGIN(stockflow stockflow.cpp LINK_LIBRARIES lua)
diff --git a/plugins/dig.cpp b/plugins/dig.cpp
index bbfc15058..082e6a04a 100644
--- a/plugins/dig.cpp
+++ b/plugins/dig.cpp
@@ -134,7 +134,9 @@ bool dig (MapExtras::MapCache & MCache,
}
if (tsb == tiletype_shape_basic::Floor
&& (type == tile_dig_designation::DownStair || type == tile_dig_designation::Channel)
- && ts != tiletype_shape::TREE
+ && ts != tiletype_shape::BRANCH
+ && ts != tiletype_shape::TRUNK_BRANCH
+ && ts != tiletype_shape::TWIG
)
{
std::cerr << "allowing tt" << (int)tt << ", is floor\n";
diff --git a/plugins/diggingInvaders/edgeCost.cpp b/plugins/diggingInvaders/edgeCost.cpp
index 785c55922..66f2810e2 100644
--- a/plugins/diggingInvaders/edgeCost.cpp
+++ b/plugins/diggingInvaders/edgeCost.cpp
@@ -73,7 +73,9 @@ cost_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2, DigAbilitie
return -1;
}
- if ( shape2 == df::enums::tiletype_shape::TREE )
+ if ( shape2 == df::enums::tiletype_shape::BRANCH ||
+ shape2 == df::enums::tiletype_shape::TRUNK_BRANCH ||
+ shape2 == df::enums::tiletype_shape::TWIG )
return -1;
/*
diff --git a/plugins/dwarfmonitor.cpp b/plugins/dwarfmonitor.cpp
index be271750a..4f23e5199 100644
--- a/plugins/dwarfmonitor.cpp
+++ b/plugins/dwarfmonitor.cpp
@@ -524,8 +524,6 @@ public:
case job_type::StoreItemInStockpile:
case job_type::StoreItemInBag:
case job_type::StoreItemInHospital:
- case job_type::StoreItemInChest:
- case job_type::StoreItemInCabinet:
case job_type::StoreWeapon:
case job_type::StoreArmor:
case job_type::StoreItemInBarrel:
@@ -575,7 +573,6 @@ public:
case job_type::MakeHelm:
case job_type::MakePants:
case job_type::StudWith:
- case job_type::ProcessPlantsBag:
case job_type::ProcessPlantsVial:
case job_type::ProcessPlantsBarrel:
case job_type::WeaveCloth:
@@ -699,7 +696,6 @@ public:
case job_type::MakeCheese:
case job_type::PrepareMeal:
case job_type::ProcessPlants:
- case job_type::BrewDrink:
case job_type::CollectHiveProducts:
real_activity = JOB_FOOD_PROD;
break;
diff --git a/plugins/siege-engine.cpp b/plugins/siege-engine.cpp
index 6898b79e6..9a4ee2054 100644
--- a/plugins/siege-engine.cpp
+++ b/plugins/siege-engine.cpp
@@ -900,7 +900,10 @@ static bool isTreeTile(df::coord pos)
{
auto ptile = Maps::getTileType(pos);
- return ptile && tileShape(*ptile) == tiletype_shape::TREE;
+ return ptile &&
+ (tileShape(*ptile) == tiletype_shape::BRANCH ||
+ tileShape(*ptile) == tiletype_shape::TRUNK_BRANCH ||
+ tileShape(*ptile) == tiletype_shape::TWIG);
}
static bool adjustToTarget(EngineInfo *engine, df::coord *pos)
From 1bcfcd36f64ea3470a812e2afed1ead947158a57 Mon Sep 17 00:00:00 2001
From: Quietust
Date: Tue, 5 Aug 2014 19:59:53 -0500
Subject: [PATCH 16/22] Avoid buffer overrun on mouse clicks
---
plugins/manipulator.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugins/manipulator.cpp b/plugins/manipulator.cpp
index 79a8476d0..36ab7e218 100644
--- a/plugins/manipulator.cpp
+++ b/plugins/manipulator.cpp
@@ -769,7 +769,7 @@ void viewscreen_unitlaborsst::feed(set *events)
if ((gps->mouse_x >= col_offsets[DISP_COLUMN_LABORS]) &&
(gps->mouse_x < col_offsets[DISP_COLUMN_LABORS] + col_widths[DISP_COLUMN_LABORS]))
click_labor = gps->mouse_x - col_offsets[DISP_COLUMN_LABORS] + first_column;
- if ((gps->mouse_y >= 4) && (gps->mouse_y <= 4 + num_rows))
+ if ((gps->mouse_y >= 4) && (gps->mouse_y < 4 + num_rows))
click_unit = gps->mouse_y - 4 + first_row;
switch (click_header)
From 86c036b7d336e81c41246312b4a69f0f9d4f9307 Mon Sep 17 00:00:00 2001
From: Quietust
Date: Tue, 5 Aug 2014 20:19:31 -0500
Subject: [PATCH 17/22] Add an extra check that was missing
---
plugins/manipulator.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/plugins/manipulator.cpp b/plugins/manipulator.cpp
index 36ab7e218..19327c6b1 100644
--- a/plugins/manipulator.cpp
+++ b/plugins/manipulator.cpp
@@ -772,6 +772,9 @@ void viewscreen_unitlaborsst::feed(set *events)
if ((gps->mouse_y >= 4) && (gps->mouse_y < 4 + num_rows))
click_unit = gps->mouse_y - 4 + first_row;
+ if (click_unit == -1)
+ click_body = DISP_COLUMN_MAX;
+
switch (click_header)
{
case DISP_COLUMN_HAPPINESS:
From f34d68e567209289c07b891563d6b007781914a3 Mon Sep 17 00:00:00 2001
From: Quietust
Date: Tue, 5 Aug 2014 20:28:09 -0500
Subject: [PATCH 18/22] Actual correct fix here
---
plugins/manipulator.cpp | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/plugins/manipulator.cpp b/plugins/manipulator.cpp
index 19327c6b1..98d3181e7 100644
--- a/plugins/manipulator.cpp
+++ b/plugins/manipulator.cpp
@@ -761,7 +761,7 @@ void viewscreen_unitlaborsst::feed(set *events)
{
if ((gps->mouse_y >= 1) && (gps->mouse_y <= 2))
click_header = i;
- if ((gps->mouse_y >= 4) && (gps->mouse_y <= 4 + num_rows))
+ if ((gps->mouse_y >= 4) && (gps->mouse_y < 4 + num_rows))
click_body = i;
}
}
@@ -772,9 +772,6 @@ void viewscreen_unitlaborsst::feed(set *events)
if ((gps->mouse_y >= 4) && (gps->mouse_y < 4 + num_rows))
click_unit = gps->mouse_y - 4 + first_row;
- if (click_unit == -1)
- click_body = DISP_COLUMN_MAX;
-
switch (click_header)
{
case DISP_COLUMN_HAPPINESS:
From 17b19bfcdcf91fc0d17d0b70d804d21b54849812 Mon Sep 17 00:00:00 2001
From: Quietust
Date: Wed, 6 Aug 2014 08:28:02 -0500
Subject: [PATCH 19/22] Update structures
---
library/xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/library/xml b/library/xml
index 60ae817c4..fc3c5ce33 160000
--- a/library/xml
+++ b/library/xml
@@ -1 +1 @@
-Subproject commit 60ae817c40fb366460412b6b659bb1228836f8bf
+Subproject commit fc3c5ce3329edcdca5dadb4c1f8b03b0c98f0472
From 9956b4a5ef874e8ff6e4530dadd3438609217f3f Mon Sep 17 00:00:00 2001
From: Quietust
Date: Wed, 6 Aug 2014 09:31:42 -0500
Subject: [PATCH 20/22] Update getplants, plants, and prospector, and isolate
autochop
---
plugins/CMakeLists.txt | 7 +-
plugins/autochop.cpp | 722 +++++++++++++++++++++++++++++++++++++++
plugins/getplants.cpp | 750 ++---------------------------------------
plugins/plants.cpp | 65 ++--
plugins/prospector.cpp | 4 +-
5 files changed, 791 insertions(+), 757 deletions(-)
create mode 100644 plugins/autochop.cpp
diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt
index 595a73a19..823b9aa75 100644
--- a/plugins/CMakeLists.txt
+++ b/plugins/CMakeLists.txt
@@ -85,6 +85,7 @@ if (BUILD_SUPPORTED)
DFHACK_PLUGIN(3dveins 3dveins.cpp)
DFHACK_PLUGIN(add-spatter add-spatter.cpp)
# DFHACK_PLUGIN(advtools advtools.cpp)
+ DFHACK_PLUGIN(autochop autochop.cpp)
DFHACK_PLUGIN(autodump autodump.cpp)
DFHACK_PLUGIN(autolabor autolabor.cpp)
DFHACK_PLUGIN(automaterial automaterial.cpp)
@@ -120,7 +121,7 @@ if (BUILD_SUPPORTED)
DFHACK_PLUGIN(flows flows.cpp)
DFHACK_PLUGIN(follow follow.cpp)
DFHACK_PLUGIN(forceequip forceequip.cpp)
-# DFHACK_PLUGIN(getplants getplants.cpp)
+ DFHACK_PLUGIN(getplants getplants.cpp)
DFHACK_PLUGIN(infiniteSky infiniteSky.cpp)
DFHACK_PLUGIN(initflags initflags.cpp)
DFHACK_PLUGIN(isoworldremote isoworldremote.cpp PROTOBUFS isoworldremote)
@@ -132,9 +133,9 @@ if (BUILD_SUPPORTED)
DFHACK_PLUGIN(misery misery.cpp)
DFHACK_PLUGIN(mousequery mousequery.cpp)
DFHACK_PLUGIN(petcapRemover petcapRemover.cpp)
-# DFHACK_PLUGIN(plants plants.cpp)
+ DFHACK_PLUGIN(plants plants.cpp)
DFHACK_PLUGIN(probe probe.cpp)
-# DFHACK_PLUGIN(prospector prospector.cpp)
+ DFHACK_PLUGIN(prospector prospector.cpp)
DFHACK_PLUGIN(power-meter power-meter.cpp LINK_LIBRARIES lua)
DFHACK_PLUGIN(regrass regrass.cpp)
DFHACK_PLUGIN(remotefortressreader remotefortressreader.cpp PROTOBUFS RemoteFortressReader)
diff --git a/plugins/autochop.cpp b/plugins/autochop.cpp
new file mode 100644
index 000000000..5dab8f69b
--- /dev/null
+++ b/plugins/autochop.cpp
@@ -0,0 +1,722 @@
+// automatically chop trees
+
+#include "uicommon.h"
+
+#include "Core.h"
+#include "Console.h"
+#include "Export.h"
+#include "PluginManager.h"
+#include "DataDefs.h"
+#include "TileTypes.h"
+
+#include "df/world.h"
+#include "df/map_block.h"
+#include "df/tile_dig_designation.h"
+#include "df/plant_raw.h"
+#include "df/plant.h"
+#include "df/ui.h"
+#include "df/burrow.h"
+#include "df/item_flags.h"
+#include "df/item.h"
+#include "df/items_other_id.h"
+#include "df/viewscreen_dwarfmodest.h"
+
+#include "modules/Screen.h"
+#include "modules/Maps.h"
+#include "modules/Burrows.h"
+#include "modules/World.h"
+#include "modules/MapCache.h"
+#include "modules/Gui.h"
+
+#include
+
+using std::string;
+using std::vector;
+using std::set;
+using namespace DFHack;
+using namespace df::enums;
+
+using df::global::world;
+using df::global::ui;
+
+#define PLUGIN_VERSION 0.3
+DFHACK_PLUGIN("autochop");
+
+
+static bool autochop_enabled = false;
+static int min_logs, max_logs;
+static bool wait_for_threshold;
+
+static PersistentDataItem config_autochop;
+
+struct WatchedBurrow
+{
+ int32_t id;
+ df::burrow *burrow;
+
+ WatchedBurrow(df::burrow *burrow) : burrow(burrow)
+ {
+ id = burrow->id;
+ }
+};
+
+class WatchedBurrows
+{
+public:
+ string getSerialisedIds()
+ {
+ validate();
+ stringstream burrow_ids;
+ bool append_started = false;
+ for (auto it = burrows.begin(); it != burrows.end(); it++)
+ {
+ if (append_started)
+ burrow_ids << " ";
+ burrow_ids << it->id;
+ append_started = true;
+ }
+
+ return burrow_ids.str();
+ }
+
+ void clear()
+ {
+ burrows.clear();
+ }
+
+ void add(const int32_t id)
+ {
+ if (!isValidBurrow(id))
+ return;
+
+ WatchedBurrow wb(getBurrow(id));
+ burrows.push_back(wb);
+ }
+
+ void add(const string burrow_ids)
+ {
+ istringstream iss(burrow_ids);
+ int id;
+ while (iss >> id)
+ {
+ add(id);
+ }
+ }
+
+ bool isValidPos(const df::coord &plant_pos)
+ {
+ validate();
+ if (!burrows.size())
+ return true;
+
+ for (auto it = burrows.begin(); it != burrows.end(); it++)
+ {
+ df::burrow *burrow = it->burrow;
+ if (Burrows::isAssignedTile(burrow, plant_pos))
+ return true;
+ }
+
+ return false;
+ }
+
+ bool isBurrowWatched(const df::burrow *burrow)
+ {
+ validate();
+ for (auto it = burrows.begin(); it != burrows.end(); it++)
+ {
+ if (it->burrow == burrow)
+ return true;
+ }
+
+ return false;
+ }
+
+private:
+ static bool isValidBurrow(const int32_t id)
+ {
+ return getBurrow(id);
+ }
+
+ static df::burrow *getBurrow(const int32_t id)
+ {
+ return df::burrow::find(id);
+ }
+
+ void validate()
+ {
+ for (auto it = burrows.begin(); it != burrows.end();)
+ {
+ if (!isValidBurrow(it->id))
+ it = burrows.erase(it);
+ else
+ ++it;
+ }
+ }
+
+ vector burrows;
+};
+
+static WatchedBurrows watchedBurrows;
+
+static void save_config()
+{
+ config_autochop.val() = watchedBurrows.getSerialisedIds();
+ config_autochop.ival(0) = autochop_enabled;
+ config_autochop.ival(1) = min_logs;
+ config_autochop.ival(2) = max_logs;
+ config_autochop.ival(3) = wait_for_threshold;
+}
+
+static void initialize()
+{
+ watchedBurrows.clear();
+ autochop_enabled = false;
+ min_logs = 80;
+ max_logs = 100;
+ wait_for_threshold = false;
+
+ config_autochop = World::GetPersistentData("autochop/config");
+ if (config_autochop.isValid())
+ {
+ watchedBurrows.add(config_autochop.val());
+ autochop_enabled = config_autochop.ival(0);
+ min_logs = config_autochop.ival(1);
+ max_logs = config_autochop.ival(2);
+ wait_for_threshold = config_autochop.ival(3);
+ }
+ else
+ {
+ config_autochop = World::AddPersistentData("autochop/config");
+ if (config_autochop.isValid())
+ save_config();
+ }
+}
+
+static int do_chop_designation(bool chop, bool count_only)
+{
+ int count = 0;
+ for (size_t i = 0; i < world->plants.all.size(); i++)
+ {
+ const df::plant *plant = world->plants.all[i];
+ df::map_block *cur = Maps::getTileBlock(plant->pos);
+ if (!cur)
+ continue;
+ int x = plant->pos.x % 16;
+ int y = plant->pos.y % 16;
+
+ if (plant->flags.bits.is_shrub)
+ continue;
+ if (cur->designation[x][y].bits.hidden)
+ continue;
+
+ df::tiletype_material material = tileMaterial(cur->tiletype[x][y]);
+ if (material != tiletype_material::TREE)
+ continue;
+
+ if (!count_only && !watchedBurrows.isValidPos(plant->pos))
+ continue;
+
+ bool dirty = false;
+ if (chop && cur->designation[x][y].bits.dig == tile_dig_designation::No)
+ {
+ if (count_only)
+ {
+ ++count;
+ }
+ else
+ {
+ cur->designation[x][y].bits.dig = tile_dig_designation::Default;
+ dirty = true;
+ }
+ }
+
+ if (!chop && cur->designation[x][y].bits.dig == tile_dig_designation::Default)
+ {
+ if (count_only)
+ {
+ ++count;
+ }
+ else
+ {
+ cur->designation[x][y].bits.dig = tile_dig_designation::No;
+ dirty = true;
+ }
+ }
+
+ if (dirty)
+ {
+ cur->flags.bits.designated = true;
+ ++count;
+ }
+ }
+
+ return count;
+}
+
+static bool is_valid_item(df::item *item)
+{
+ for (size_t i = 0; i < item->general_refs.size(); i++)
+ {
+ df::general_ref *ref = item->general_refs[i];
+
+ switch (ref->getType())
+ {
+ case general_ref_type::CONTAINED_IN_ITEM:
+ return false;
+
+ case general_ref_type::UNIT_HOLDER:
+ return false;
+
+ case general_ref_type::BUILDING_HOLDER:
+ return false;
+
+ default:
+ break;
+ }
+ }
+
+ for (size_t i = 0; i < item->specific_refs.size(); i++)
+ {
+ df::specific_ref *ref = item->specific_refs[i];
+
+ if (ref->type == specific_ref_type::JOB)
+ {
+ // Ignore any items assigned to a job
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static int get_log_count()
+{
+ std::vector &items = world->items.other[items_other_id::IN_PLAY];
+
+ // Pre-compute a bitmask with the bad flags
+ df::item_flags bad_flags;
+ bad_flags.whole = 0;
+
+#define F(x) bad_flags.bits.x = true;
+ F(dump); F(forbid); F(garbage_collect);
+ F(hostile); F(on_fire); F(rotten); F(trader);
+ F(in_building); F(construction); F(artifact);
+ F(spider_web); F(owned); F(in_job);
+#undef F
+
+ size_t valid_count = 0;
+ for (size_t i = 0; i < items.size(); i++)
+ {
+ df::item *item = items[i];
+
+ if (item->getType() != item_type::WOOD)
+ continue;
+
+ if (item->flags.whole & bad_flags.whole)
+ continue;
+
+ if (!is_valid_item(item))
+ continue;
+
+ ++valid_count;
+ }
+
+ return valid_count;
+}
+
+static void set_threshold_check(bool state)
+{
+ wait_for_threshold = state;
+ save_config();
+}
+
+static void do_autochop()
+{
+ int log_count = get_log_count();
+ if (wait_for_threshold)
+ {
+ if (log_count < min_logs)
+ {
+ set_threshold_check(false);
+ do_chop_designation(true, false);
+ }
+ }
+ else
+ {
+ if (log_count >= max_logs)
+ {
+ set_threshold_check(true);
+ do_chop_designation(false, false);
+ }
+ else
+ {
+ do_chop_designation(true, false);
+ }
+ }
+}
+
+class ViewscreenAutochop : public dfhack_viewscreen
+{
+public:
+ ViewscreenAutochop()
+ {
+ burrows_column.multiselect = true;
+ burrows_column.setTitle("Burrows");
+ burrows_column.bottom_margin = 3;
+ burrows_column.allow_search = false;
+ burrows_column.text_clip_at = 30;
+
+ populateBurrowsColumn();
+ message.clear();
+ }
+
+ void populateBurrowsColumn()
+ {
+ selected_column = 0;
+
+ auto last_selected_index = burrows_column.highlighted_index;
+ burrows_column.clear();
+
+ for (auto iter = ui->burrows.list.begin(); iter != ui->burrows.list.end(); iter++)
+ {
+ df::burrow* burrow = *iter;
+ auto elem = ListEntry(burrow->name, burrow);
+ elem.selected = watchedBurrows.isBurrowWatched(burrow);
+ burrows_column.add(elem);
+ }
+
+ burrows_column.fixWidth();
+ burrows_column.filterDisplay();
+
+ current_log_count = get_log_count();
+ marked_tree_count = do_chop_designation(false, true);
+ }
+
+ void change_min_logs(int delta)
+ {
+ if (!autochop_enabled)
+ return;
+
+ min_logs += delta;
+ if (min_logs < 0)
+ min_logs = 0;
+ if (min_logs > max_logs)
+ max_logs = min_logs;
+ }
+
+ void change_max_logs(int delta)
+ {
+ if (!autochop_enabled)
+ return;
+
+ max_logs += delta;
+ if (max_logs < min_logs)
+ min_logs = max_logs;
+ }
+
+ void feed(set *input)
+ {
+ bool key_processed = false;
+ message.clear();
+ switch (selected_column)
+ {
+ case 0:
+ key_processed = burrows_column.feed(input);
+ break;
+ }
+
+ if (key_processed)
+ {
+ if (input->count(interface_key::SELECT))
+ updateAutochopBurrows();
+ return;
+ }
+
+ if (input->count(interface_key::LEAVESCREEN))
+ {
+ save_config();
+ input->clear();
+ Screen::dismiss(this);
+ if (autochop_enabled)
+ do_autochop();
+ return;
+ }
+ else if (input->count(interface_key::CUSTOM_A))
+ {
+ autochop_enabled = !autochop_enabled;
+ }
+ else if (input->count(interface_key::CUSTOM_D))
+ {
+ int count = do_chop_designation(true, false);
+ message = "Trees marked for chop: " + int_to_string(count);
+ marked_tree_count = do_chop_designation(false, true);
+ }
+ else if (input->count(interface_key::CUSTOM_U))
+ {
+ int count = do_chop_designation(false, false);
+ message = "Trees unmarked: " + int_to_string(count);
+ marked_tree_count = do_chop_designation(false, true);
+ }
+ else if (input->count(interface_key::CUSTOM_H))
+ {
+ change_min_logs(-1);
+ }
+ else if (input->count(interface_key::CUSTOM_SHIFT_H))
+ {
+ change_min_logs(-10);
+ }
+ else if (input->count(interface_key::CUSTOM_J))
+ {
+ change_min_logs(1);
+ }
+ else if (input->count(interface_key::CUSTOM_SHIFT_J))
+ {
+ change_min_logs(10);
+ }
+ else if (input->count(interface_key::CUSTOM_K))
+ {
+ change_max_logs(-1);
+ }
+ else if (input->count(interface_key::CUSTOM_SHIFT_K))
+ {
+ change_max_logs(-10);
+ }
+ else if (input->count(interface_key::CUSTOM_L))
+ {
+ change_max_logs(1);
+ }
+ else if (input->count(interface_key::CUSTOM_SHIFT_L))
+ {
+ change_max_logs(10);
+ }
+ else if (enabler->tracking_on && enabler->mouse_lbut)
+ {
+ if (burrows_column.setHighlightByMouse())
+ {
+ selected_column = 0;
+ }
+
+ enabler->mouse_lbut = enabler->mouse_rbut = 0;
+ }
+ }
+
+ void render()
+ {
+ if (Screen::isDismissed(this))
+ return;
+
+ dfhack_viewscreen::render();
+
+ Screen::clear();
+ Screen::drawBorder(" Autochop ");
+
+ burrows_column.display(selected_column == 0);
+
+ int32_t y = gps->dimy - 3;
+ int32_t x = 2;
+ OutputHotkeyString(x, y, "Leave", "Esc");
+ x += 3;
+ OutputString(COLOR_YELLOW, x, y, message);
+
+ y = 3;
+ int32_t left_margin = burrows_column.getMaxItemWidth() + 3;
+ x = left_margin;
+ if (burrows_column.getSelectedElems().size() > 0)
+ {
+ OutputString(COLOR_GREEN, x, y, "Will chop in selected burrows", true, left_margin);
+ }
+ else
+ {
+ OutputString(COLOR_YELLOW, x, y, "Will chop from whole map", true, left_margin);
+ OutputString(COLOR_YELLOW, x, y, "Select from left to chop in specific burrows", true, left_margin);
+ }
+
+ ++y;
+ OutputToggleString(x, y, "Autochop", "a", autochop_enabled, true, left_margin);
+ OutputHotkeyString(x, y, "Designate Now", "d", true, left_margin);
+ OutputHotkeyString(x, y, "Undesignate Now", "u", true, left_margin);
+ OutputHotkeyString(x, y, "Toggle Burrow", "Enter", true, left_margin);
+ if (autochop_enabled)
+ {
+ OutputLabelString(x, y, "Min Logs", "hjHJ", int_to_string(min_logs), true, left_margin);
+ OutputLabelString(x, y, "Max Logs", "klKL", int_to_string(max_logs), true, left_margin);
+ }
+
+ ++y;
+ OutputString(COLOR_BROWN, x, y, "Current Counts", true, left_margin);
+ OutputString(COLOR_WHITE, x, y, "Current Logs: ");
+ OutputString(COLOR_GREEN, x, y, int_to_string(current_log_count), true, left_margin);
+ OutputString(COLOR_WHITE, x, y, "Marked Trees: ");
+ OutputString(COLOR_GREEN, x, y, int_to_string(marked_tree_count), true, left_margin);
+ }
+
+ std::string getFocusString() { return "autochop"; }
+
+ void updateAutochopBurrows()
+ {
+ watchedBurrows.clear();
+ vector v = burrows_column.getSelectedElems();
+ for_each_(v, [] (df::burrow *b) { watchedBurrows.add(b->id); });
+ }
+
+private:
+ ListColumn burrows_column;
+ int selected_column;
+ int current_log_count;
+ int marked_tree_count;
+ MapExtras::MapCache mcache;
+ string message;
+
+ void validateColumn()
+ {
+ set_to_limit(selected_column, 0);
+ }
+
+ void resize(int32_t x, int32_t y)
+ {
+ dfhack_viewscreen::resize(x, y);
+ burrows_column.resize();
+ }
+};
+
+struct autochop_hook : public df::viewscreen_dwarfmodest
+{
+ typedef df::viewscreen_dwarfmodest interpose_base;
+
+ bool isInDesignationMenu()
+ {
+ using namespace df::enums::ui_sidebar_mode;
+ return (ui->main.mode == DesignateChopTrees);
+ }
+
+ void sendKey(const df::interface_key &key)
+ {
+ set tmp;
+ tmp.insert(key);
+ INTERPOSE_NEXT(feed)(&tmp);
+ }
+
+ DEFINE_VMETHOD_INTERPOSE(void, feed, (set *input))
+ {
+ if (isInDesignationMenu() && input->count(interface_key::CUSTOM_C))
+ {
+ sendKey(interface_key::LEAVESCREEN);
+ Screen::show(new ViewscreenAutochop());
+ }
+ else
+ {
+ INTERPOSE_NEXT(feed)(input);
+ }
+ }
+
+ DEFINE_VMETHOD_INTERPOSE(void, render, ())
+ {
+ INTERPOSE_NEXT(render)();
+
+ auto dims = Gui::getDwarfmodeViewDims();
+ if (dims.menu_x1 <= 0)
+ return;
+
+ df::ui_sidebar_mode d = ui->main.mode;
+ if (!isInDesignationMenu())
+ return;
+
+ int left_margin = dims.menu_x1 + 1;
+ int x = left_margin;
+ int y = 26;
+ OutputHotkeyString(x, y, "Autochop Dashboard", "c");
+ }
+};
+
+IMPLEMENT_VMETHOD_INTERPOSE_PRIO(autochop_hook, feed, 100);
+IMPLEMENT_VMETHOD_INTERPOSE_PRIO(autochop_hook, render, 100);
+
+
+command_result df_autochop (color_ostream &out, vector & parameters)
+{
+ for (size_t i = 0; i < parameters.size(); i++)
+ {
+ if (parameters[i] == "help" || parameters[i] == "?")
+ return CR_WRONG_USAGE;
+ if (parameters[i] == "debug")
+ save_config();
+ else
+ return CR_WRONG_USAGE;
+ }
+ if (Maps::IsValid())
+ Screen::show(new ViewscreenAutochop());
+ return CR_OK;
+}
+
+DFhackCExport command_result plugin_onupdate (color_ostream &out)
+{
+ if (!autochop_enabled)
+ return CR_OK;
+
+ if(!Maps::IsValid())
+ return CR_OK;
+
+ static decltype(world->frame_counter) last_frame_count = 0;
+
+ if (DFHack::World::ReadPauseState())
+ return CR_OK;
+
+ if (world->frame_counter - last_frame_count < 1200) // Check every day
+ return CR_OK;
+
+ last_frame_count = world->frame_counter;
+
+ do_autochop();
+
+ return CR_OK;
+}
+
+DFHACK_PLUGIN_IS_ENABLED(is_enabled);
+
+DFhackCExport command_result plugin_enable(color_ostream &out, bool enable)
+{
+ if (!gps)
+ return CR_FAILURE;
+
+ if (enable != is_enabled)
+ {
+ if (!INTERPOSE_HOOK(autochop_hook, feed).apply(enable) ||
+ !INTERPOSE_HOOK(autochop_hook, render).apply(enable))
+ return CR_FAILURE;
+
+ is_enabled = enable;
+ initialize();
+ }
+
+ return CR_OK;
+}
+
+DFhackCExport command_result plugin_init ( color_ostream &out, vector &commands)
+{
+ commands.push_back(PluginCommand(
+ "autochop", "Allows automatic harvesting of trees based on the number of stockpiled logs",
+ df_autochop, false,
+ "Opens the automated chopping control screen. Specify 'debug' to forcibly save settings.\n"
+ ));
+
+ initialize();
+ return CR_OK;
+}
+
+DFhackCExport command_result plugin_shutdown ( color_ostream &out )
+{
+ return CR_OK;
+}
+
+DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event)
+{
+ switch (event) {
+ case SC_MAP_LOADED:
+ initialize();
+ break;
+ default:
+ break;
+ }
+
+ return CR_OK;
+}
diff --git a/plugins/getplants.cpp b/plugins/getplants.cpp
index 5a5337f45..f4771b58b 100644
--- a/plugins/getplants.cpp
+++ b/plugins/getplants.cpp
@@ -1,7 +1,5 @@
// (un)designate matching plants for gathering/cutting
-#include "uicommon.h"
-
#include "Core.h"
#include "Console.h"
#include "Export.h"
@@ -14,20 +12,8 @@
#include "df/tile_dig_designation.h"
#include "df/plant_raw.h"
#include "df/plant.h"
-#include "df/ui.h"
-#include "df/burrow.h"
-#include "df/item_flags.h"
-#include "df/item.h"
-#include "df/items_other_id.h"
-#include "df/viewscreen_dwarfmodest.h"
-#include "modules/Screen.h"
#include "modules/Maps.h"
-#include "modules/Burrows.h"
-#include "modules/World.h"
-#include "modules/MapCache.h"
-#include "modules/Gui.h"
-
#include
using std::string;
@@ -37,601 +23,6 @@ using namespace DFHack;
using namespace df::enums;
using df::global::world;
-using df::global::ui;
-
-#define PLUGIN_VERSION 0.3
-DFHACK_PLUGIN("getplants");
-
-
-static bool autochop_enabled = false;
-static int min_logs, max_logs;
-static bool wait_for_threshold;
-
-static PersistentDataItem config_autochop;
-
-struct WatchedBurrow
-{
- int32_t id;
- df::burrow *burrow;
-
- WatchedBurrow(df::burrow *burrow) : burrow(burrow)
- {
- id = burrow->id;
- }
-};
-
-class WatchedBurrows
-{
-public:
- string getSerialisedIds()
- {
- validate();
- stringstream burrow_ids;
- bool append_started = false;
- for (auto it = burrows.begin(); it != burrows.end(); it++)
- {
- if (append_started)
- burrow_ids << " ";
- burrow_ids << it->id;
- append_started = true;
- }
-
- return burrow_ids.str();
- }
-
- void clear()
- {
- burrows.clear();
- }
-
- void add(const int32_t id)
- {
- if (!isValidBurrow(id))
- return;
-
- WatchedBurrow wb(getBurrow(id));
- burrows.push_back(wb);
- }
-
- void add(const string burrow_ids)
- {
- istringstream iss(burrow_ids);
- int id;
- while (iss >> id)
- {
- add(id);
- }
- }
-
- bool isValidPos(const df::coord &plant_pos)
- {
- validate();
- if (!burrows.size())
- return true;
-
- for (auto it = burrows.begin(); it != burrows.end(); it++)
- {
- df::burrow *burrow = it->burrow;
- if (Burrows::isAssignedTile(burrow, plant_pos))
- return true;
- }
-
- return false;
- }
-
- bool isBurrowWatched(const df::burrow *burrow)
- {
- validate();
- for (auto it = burrows.begin(); it != burrows.end(); it++)
- {
- if (it->burrow == burrow)
- return true;
- }
-
- return false;
- }
-
-private:
- static bool isValidBurrow(const int32_t id)
- {
- return getBurrow(id);
- }
-
- static df::burrow *getBurrow(const int32_t id)
- {
- return df::burrow::find(id);
- }
-
- void validate()
- {
- for (auto it = burrows.begin(); it != burrows.end();)
- {
- if (!isValidBurrow(it->id))
- it = burrows.erase(it);
- else
- ++it;
- }
- }
-
- vector burrows;
-};
-
-static WatchedBurrows watchedBurrows;
-
-static void save_config()
-{
- config_autochop.val() = watchedBurrows.getSerialisedIds();
- config_autochop.ival(0) = autochop_enabled;
- config_autochop.ival(1) = min_logs;
- config_autochop.ival(2) = max_logs;
- config_autochop.ival(3) = wait_for_threshold;
-}
-
-static void initialize()
-{
- watchedBurrows.clear();
- autochop_enabled = false;
- min_logs = 80;
- max_logs = 100;
- wait_for_threshold = false;
-
- config_autochop = World::GetPersistentData("autochop/config");
- if (config_autochop.isValid())
- {
- watchedBurrows.add(config_autochop.val());
- autochop_enabled = config_autochop.ival(0);
- min_logs = config_autochop.ival(1);
- max_logs = config_autochop.ival(2);
- wait_for_threshold = config_autochop.ival(3);
- }
- else
- {
- config_autochop = World::AddPersistentData("autochop/config");
- if (config_autochop.isValid())
- save_config();
- }
-}
-
-static int do_chop_designation(bool chop, bool count_only)
-{
- int count = 0;
- for (size_t i = 0; i < world->map.map_blocks.size(); i++)
- {
- df::map_block *cur = world->map.map_blocks[i];
- for (size_t j = 0; j < cur->plants.size(); j++)
- {
- const df::plant *plant = cur->plants[j];
- int x = plant->pos.x % 16;
- int y = plant->pos.y % 16;
-
- if (plant->flags.bits.is_shrub)
- continue;
- if (cur->designation[x][y].bits.hidden)
- continue;
-
- df::tiletype_shape shape = tileShape(cur->tiletype[x][y]);
- if (shape != tiletype_shape::TREE)
- continue;
-
- if (!count_only && !watchedBurrows.isValidPos(plant->pos))
- continue;
-
- bool dirty = false;
- if (chop && cur->designation[x][y].bits.dig == tile_dig_designation::No)
- {
- if (count_only)
- {
- ++count;
- }
- else
- {
- cur->designation[x][y].bits.dig = tile_dig_designation::Default;
- dirty = true;
- }
- }
-
- if (!chop && cur->designation[x][y].bits.dig == tile_dig_designation::Default)
- {
- if (count_only)
- {
- ++count;
- }
- else
- {
- cur->designation[x][y].bits.dig = tile_dig_designation::No;
- dirty = true;
- }
- }
-
- if (dirty)
- {
- cur->flags.bits.designated = true;
- ++count;
- }
- }
- }
-
- return count;
-}
-
-static bool is_valid_item(df::item *item)
-{
- for (size_t i = 0; i < item->general_refs.size(); i++)
- {
- df::general_ref *ref = item->general_refs[i];
-
- switch (ref->getType())
- {
- case general_ref_type::CONTAINED_IN_ITEM:
- return false;
-
- case general_ref_type::UNIT_HOLDER:
- return false;
-
- case general_ref_type::BUILDING_HOLDER:
- return false;
-
- default:
- break;
- }
- }
-
- for (size_t i = 0; i < item->specific_refs.size(); i++)
- {
- df::specific_ref *ref = item->specific_refs[i];
-
- if (ref->type == specific_ref_type::JOB)
- {
- // Ignore any items assigned to a job
- return false;
- }
- }
-
- return true;
-}
-
-static int get_log_count()
-{
- std::vector &items = world->items.other[items_other_id::IN_PLAY];
-
- // Pre-compute a bitmask with the bad flags
- df::item_flags bad_flags;
- bad_flags.whole = 0;
-
-#define F(x) bad_flags.bits.x = true;
- F(dump); F(forbid); F(garbage_collect);
- F(hostile); F(on_fire); F(rotten); F(trader);
- F(in_building); F(construction); F(artifact);
- F(spider_web); F(owned); F(in_job);
-#undef F
-
- size_t valid_count = 0;
- for (size_t i = 0; i < items.size(); i++)
- {
- df::item *item = items[i];
-
- if (item->getType() != item_type::WOOD)
- continue;
-
- if (item->flags.whole & bad_flags.whole)
- continue;
-
- if (!is_valid_item(item))
- continue;
-
- ++valid_count;
- }
-
- return valid_count;
-}
-
-static void set_threshold_check(bool state)
-{
- wait_for_threshold = state;
- save_config();
-}
-
-static void do_autochop()
-{
- int log_count = get_log_count();
- if (wait_for_threshold)
- {
- if (log_count < min_logs)
- {
- set_threshold_check(false);
- do_chop_designation(true, false);
- }
- }
- else
- {
- if (log_count >= max_logs)
- {
- set_threshold_check(true);
- do_chop_designation(false, false);
- }
- else
- {
- do_chop_designation(true, false);
- }
- }
-}
-
-class ViewscreenAutochop : public dfhack_viewscreen
-{
-public:
- ViewscreenAutochop()
- {
- burrows_column.multiselect = true;
- burrows_column.setTitle("Burrows");
- burrows_column.bottom_margin = 3;
- burrows_column.allow_search = false;
- burrows_column.text_clip_at = 30;
-
- populateBurrowsColumn();
- message.clear();
- }
-
- void populateBurrowsColumn()
- {
- selected_column = 0;
-
- auto last_selected_index = burrows_column.highlighted_index;
- burrows_column.clear();
-
- for (auto iter = ui->burrows.list.begin(); iter != ui->burrows.list.end(); iter++)
- {
- df::burrow* burrow = *iter;
- auto elem = ListEntry(burrow->name, burrow);
- elem.selected = watchedBurrows.isBurrowWatched(burrow);
- burrows_column.add(elem);
- }
-
- burrows_column.fixWidth();
- burrows_column.filterDisplay();
-
- current_log_count = get_log_count();
- marked_tree_count = do_chop_designation(false, true);
- }
-
- void change_min_logs(int delta)
- {
- if (!autochop_enabled)
- return;
-
- min_logs += delta;
- if (min_logs < 0)
- min_logs = 0;
- if (min_logs > max_logs)
- max_logs = min_logs;
- }
-
- void change_max_logs(int delta)
- {
- if (!autochop_enabled)
- return;
-
- max_logs += delta;
- if (max_logs < min_logs)
- min_logs = max_logs;
- }
-
- void feed(set *input)
- {
- bool key_processed = false;
- message.clear();
- switch (selected_column)
- {
- case 0:
- key_processed = burrows_column.feed(input);
- break;
- }
-
- if (key_processed)
- {
- if (input->count(interface_key::SELECT))
- updateAutochopBurrows();
- return;
- }
-
- if (input->count(interface_key::LEAVESCREEN))
- {
- save_config();
- input->clear();
- Screen::dismiss(this);
- if (autochop_enabled)
- do_autochop();
- return;
- }
- else if (input->count(interface_key::CUSTOM_A))
- {
- autochop_enabled = !autochop_enabled;
- }
- else if (input->count(interface_key::CUSTOM_D))
- {
- int count = do_chop_designation(true, false);
- message = "Trees marked for chop: " + int_to_string(count);
- marked_tree_count = do_chop_designation(false, true);
- }
- else if (input->count(interface_key::CUSTOM_U))
- {
- int count = do_chop_designation(false, false);
- message = "Trees unmarked: " + int_to_string(count);
- marked_tree_count = do_chop_designation(false, true);
- }
- else if (input->count(interface_key::CUSTOM_H))
- {
- change_min_logs(-1);
- }
- else if (input->count(interface_key::CUSTOM_SHIFT_H))
- {
- change_min_logs(-10);
- }
- else if (input->count(interface_key::CUSTOM_J))
- {
- change_min_logs(1);
- }
- else if (input->count(interface_key::CUSTOM_SHIFT_J))
- {
- change_min_logs(10);
- }
- else if (input->count(interface_key::CUSTOM_K))
- {
- change_max_logs(-1);
- }
- else if (input->count(interface_key::CUSTOM_SHIFT_K))
- {
- change_max_logs(-10);
- }
- else if (input->count(interface_key::CUSTOM_L))
- {
- change_max_logs(1);
- }
- else if (input->count(interface_key::CUSTOM_SHIFT_L))
- {
- change_max_logs(10);
- }
- else if (enabler->tracking_on && enabler->mouse_lbut)
- {
- if (burrows_column.setHighlightByMouse())
- {
- selected_column = 0;
- }
-
- enabler->mouse_lbut = enabler->mouse_rbut = 0;
- }
- }
-
- void render()
- {
- if (Screen::isDismissed(this))
- return;
-
- dfhack_viewscreen::render();
-
- Screen::clear();
- Screen::drawBorder(" Autochop ");
-
- burrows_column.display(selected_column == 0);
-
- int32_t y = gps->dimy - 3;
- int32_t x = 2;
- OutputHotkeyString(x, y, "Leave", "Esc");
- x += 3;
- OutputString(COLOR_YELLOW, x, y, message);
-
- y = 3;
- int32_t left_margin = burrows_column.getMaxItemWidth() + 3;
- x = left_margin;
- if (burrows_column.getSelectedElems().size() > 0)
- {
- OutputString(COLOR_GREEN, x, y, "Will chop in selected burrows", true, left_margin);
- }
- else
- {
- OutputString(COLOR_YELLOW, x, y, "Will chop from whole map", true, left_margin);
- OutputString(COLOR_YELLOW, x, y, "Select from left to chop in specific burrows", true, left_margin);
- }
-
- ++y;
- OutputToggleString(x, y, "Autochop", "a", autochop_enabled, true, left_margin);
- OutputHotkeyString(x, y, "Designate Now", "d", true, left_margin);
- OutputHotkeyString(x, y, "Undesignate Now", "u", true, left_margin);
- OutputHotkeyString(x, y, "Toggle Burrow", "Enter", true, left_margin);
- if (autochop_enabled)
- {
- OutputLabelString(x, y, "Min Logs", "hjHJ", int_to_string(min_logs), true, left_margin);
- OutputLabelString(x, y, "Max Logs", "klKL", int_to_string(max_logs), true, left_margin);
- }
-
- ++y;
- OutputString(COLOR_BROWN, x, y, "Current Counts", true, left_margin);
- OutputString(COLOR_WHITE, x, y, "Current Logs: ");
- OutputString(COLOR_GREEN, x, y, int_to_string(current_log_count), true, left_margin);
- OutputString(COLOR_WHITE, x, y, "Marked Trees: ");
- OutputString(COLOR_GREEN, x, y, int_to_string(marked_tree_count), true, left_margin);
- }
-
- std::string getFocusString() { return "autochop"; }
-
- void updateAutochopBurrows()
- {
- watchedBurrows.clear();
- vector v = burrows_column.getSelectedElems();
- for_each_(v, [] (df::burrow *b) { watchedBurrows.add(b->id); });
- }
-
-private:
- ListColumn burrows_column;
- int selected_column;
- int current_log_count;
- int marked_tree_count;
- MapExtras::MapCache mcache;
- string message;
-
- void validateColumn()
- {
- set_to_limit(selected_column, 0);
- }
-
- void resize(int32_t x, int32_t y)
- {
- dfhack_viewscreen::resize(x, y);
- burrows_column.resize();
- }
-};
-
-struct autochop_hook : public df::viewscreen_dwarfmodest
-{
- typedef df::viewscreen_dwarfmodest interpose_base;
-
- bool isInDesignationMenu()
- {
- using namespace df::enums::ui_sidebar_mode;
- return (ui->main.mode == DesignateChopTrees);
- }
-
- void sendKey(const df::interface_key &key)
- {
- set tmp;
- tmp.insert(key);
- INTERPOSE_NEXT(feed)(&tmp);
- }
-
- DEFINE_VMETHOD_INTERPOSE(void, feed, (set *input))
- {
- if (isInDesignationMenu() && input->count(interface_key::CUSTOM_C))
- {
- sendKey(interface_key::LEAVESCREEN);
- Screen::show(new ViewscreenAutochop());
- }
- else
- {
- INTERPOSE_NEXT(feed)(input);
- }
- }
-
- DEFINE_VMETHOD_INTERPOSE(void, render, ())
- {
- INTERPOSE_NEXT(render)();
-
- auto dims = Gui::getDwarfmodeViewDims();
- if (dims.menu_x1 <= 0)
- return;
-
- df::ui_sidebar_mode d = ui->main.mode;
- if (!isInDesignationMenu())
- return;
-
- int left_margin = dims.menu_x1 + 1;
- int x = left_margin;
- int y = 26;
- OutputHotkeyString(x, y, "Autochop Dashboard", "c");
- }
-};
-
-IMPLEMENT_VMETHOD_INTERPOSE_PRIO(autochop_hook, feed, 100);
-IMPLEMENT_VMETHOD_INTERPOSE_PRIO(autochop_hook, render, 100);
-
command_result df_getplants (color_ostream &out, vector & parameters)
{
@@ -655,17 +46,6 @@ command_result df_getplants (color_ostream &out, vector & parameters)
exclude = true;
else if(parameters[i] == "-a")
all = true;
- else if(parameters[i] == "debug")
- {
- save_config();
- }
- else if(parameters[i] == "autochop")
- {
- if(Maps::IsValid())
- Screen::show(new ViewscreenAutochop());
-
- return CR_OK;
- }
else
plantNames.insert(parameters[i]);
}
@@ -721,45 +101,44 @@ command_result df_getplants (color_ostream &out, vector & parameters)
}
count = 0;
- for (size_t i = 0; i < world->map.map_blocks.size(); i++)
+ for (size_t i = 0; i < world->plants.all.size(); i++)
{
- df::map_block *cur = world->map.map_blocks[i];
+ const df::plant *plant = world->plants.all[i];
+ df::map_block *cur = Maps::getTileBlock(plant->pos);
bool dirty = false;
- for (size_t j = 0; j < cur->plants.size(); j++)
+
+ int x = plant->pos.x % 16;
+ int y = plant->pos.y % 16;
+ if (plantIDs.find(plant->material) != plantIDs.end())
{
- const df::plant *plant = cur->plants[j];
- int x = plant->pos.x % 16;
- int y = plant->pos.y % 16;
- if (plantIDs.find(plant->material) != plantIDs.end())
- {
- if (exclude)
- continue;
- }
- else
- {
- if (!exclude)
- continue;
- }
- df::tiletype_shape shape = tileShape(cur->tiletype[x][y]);
- df::tiletype_special special = tileSpecial(cur->tiletype[x][y]);
- if (plant->flags.bits.is_shrub && (treesonly || !(shape == tiletype_shape::SHRUB && special != tiletype_special::DEAD)))
- continue;
- if (!plant->flags.bits.is_shrub && (shrubsonly || !(shape == tiletype_shape::TREE)))
+ if (exclude)
continue;
- if (cur->designation[x][y].bits.hidden)
+ }
+ else
+ {
+ if (!exclude)
continue;
- if (deselect && cur->designation[x][y].bits.dig == tile_dig_designation::Default)
- {
- cur->designation[x][y].bits.dig = tile_dig_designation::No;
- dirty = true;
- ++count;
- }
- if (!deselect && cur->designation[x][y].bits.dig == tile_dig_designation::No)
- {
- cur->designation[x][y].bits.dig = tile_dig_designation::Default;
- dirty = true;
- ++count;
- }
+ }
+ df::tiletype_shape shape = tileShape(cur->tiletype[x][y]);
+ df::tiletype_material material = tileMaterial(cur->tiletype[x][y]);
+ df::tiletype_special special = tileSpecial(cur->tiletype[x][y]);
+ if (plant->flags.bits.is_shrub && (treesonly || !(shape == tiletype_shape::SHRUB && special != tiletype_special::DEAD)))
+ continue;
+ if (!plant->flags.bits.is_shrub && (shrubsonly || !(material == tiletype_material::TREE)))
+ continue;
+ if (cur->designation[x][y].bits.hidden)
+ continue;
+ if (deselect && cur->designation[x][y].bits.dig == tile_dig_designation::Default)
+ {
+ cur->designation[x][y].bits.dig = tile_dig_designation::No;
+ dirty = true;
+ ++count;
+ }
+ if (!deselect && cur->designation[x][y].bits.dig == tile_dig_designation::No)
+ {
+ cur->designation[x][y].bits.dig = tile_dig_designation::Default;
+ dirty = true;
+ ++count;
}
if (dirty)
cur->flags.bits.designated = true;
@@ -769,48 +148,7 @@ command_result df_getplants (color_ostream &out, vector & parameters)
return CR_OK;
}
-DFhackCExport command_result plugin_onupdate (color_ostream &out)
-{
- if (!autochop_enabled)
- return CR_OK;
-
- if(!Maps::IsValid())
- return CR_OK;
-
- static decltype(world->frame_counter) last_frame_count = 0;
-
- if (DFHack::World::ReadPauseState())
- return CR_OK;
-
- if (world->frame_counter - last_frame_count < 1200) // Check every day
- return CR_OK;
-
- last_frame_count = world->frame_counter;
-
- do_autochop();
-
- return CR_OK;
-}
-
-DFHACK_PLUGIN_IS_ENABLED(is_enabled);
-
-DFhackCExport command_result plugin_enable(color_ostream &out, bool enable)
-{
- if (!gps)
- return CR_FAILURE;
-
- if (enable != is_enabled)
- {
- if (!INTERPOSE_HOOK(autochop_hook, feed).apply(enable) ||
- !INTERPOSE_HOOK(autochop_hook, render).apply(enable))
- return CR_FAILURE;
-
- is_enabled = enable;
- initialize();
- }
-
- return CR_OK;
-}
+DFHACK_PLUGIN("getplants");
DFhackCExport command_result plugin_init ( color_ostream &out, vector &commands)
{
@@ -826,28 +164,12 @@ DFhackCExport command_result plugin_init ( color_ostream &out, vector *alltrees = block ? &block->plants : NULL;
- if(alltrees)
+ bool didit = false;
+ for(size_t i = 0; i < world->plants.all.size(); i++)
{
- bool didit = false;
- for(size_t i = 0 ; i < alltrees->size(); i++)
- {
- df::plant * tree = alltrees->at(i);
- if(tree->pos.x == x && tree->pos.y == y && tree->pos.z == z)
- {
- if(what == do_immolate)
- tree->damage_flags.bits.is_burning = true;
- tree->hitpoints = 0;
- didit = true;
- break;
- }
- }
- /*
- if(!didit)
+ df::plant *tree = world->plants.all[i];
+ if(tree->pos.x == x && tree->pos.y == y && tree->pos.z == z)
{
- cout << "----==== There's NOTHING there! ====----" << endl;
+ if(what == do_immolate)
+ tree->damage_flags.bits.is_burning = true;
+ tree->hitpoints = 0;
+ didit = true;
+ break;
}
- */
}
+ /*
+ if(!didit)
+ {
+ cout << "----==== There's NOTHING there! ====----" << endl;
+ }
+ */
}
else
{
@@ -182,22 +177,17 @@ command_result df_grow (color_ostream &out, vector & parameters)
int32_t x,y,z;
if(Gui::getCursorCoords(x,y,z))
{
- auto block = Maps::getTileBlock(x,y,z);
- vector *alltrees = block ? &block->plants : NULL;
- if(alltrees)
+ for(size_t i = 0; i < world->plants.all.size(); i++)
{
- for(size_t i = 0 ; i < alltrees->size(); i++)
+ df::plant * tree = world->plants.all[i];
+ if(tree->pos.x == x && tree->pos.y == y && tree->pos.z == z)
{
- df::plant * tree = alltrees->at(i);
- if(tree->pos.x == x && tree->pos.y == y && tree->pos.z == z)
+ if(tileShape(map.tiletypeAt(DFCoord(x,y,z))) == tiletype_shape::SAPLING &&
+ tileSpecial(map.tiletypeAt(DFCoord(x,y,z))) != tiletype_special::DEAD)
{
- if(tileShape(map.tiletypeAt(DFCoord(x,y,z))) == tiletype_shape::SAPLING &&
- tileSpecial(map.tiletypeAt(DFCoord(x,y,z))) != tiletype_special::DEAD)
- {
- tree->grow_counter = sapling_to_tree_threshold;
- }
- break;
+ tree->grow_counter = sapling_to_tree_threshold;
}
+ break;
}
}
}
@@ -244,7 +234,8 @@ command_result df_createplant (color_ostream &out, vector & parameters)
return CR_FAILURE;
}
df::map_block *map = Maps::getTileBlock(x, y, z);
- if (!map)
+ df::map_block_column *col = Maps::getBlockColumn((x / 48) * 3, (y / 48) * 3);
+ if (!map || !col)
{
out.printerr("Invalid location selected!\n");
return CR_FAILURE;
@@ -296,10 +287,6 @@ command_result df_createplant (color_ostream &out, vector & parameters)
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)
@@ -309,7 +296,7 @@ command_result df_createplant (color_ostream &out, vector & parameters)
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);
+ col->plants.push_back(plant);
if (plant->flags.bits.is_shrub)
map->tiletype[tx][ty] = tiletype::Shrub;
else
diff --git a/plugins/prospector.cpp b/plugins/prospector.cpp
index 8f1cd91d9..2f9f5b5d3 100644
--- a/plugins/prospector.cpp
+++ b/plugins/prospector.cpp
@@ -737,13 +737,15 @@ command_result prospector (color_ostream &con, vector & parameters)
// and we can check visibility more easily here
if (showPlants)
{
- auto block = Maps::getBlock(b_x,b_y,z);
+ auto block = Maps::getBlockColumn(b_x,b_y);
vector *plants = block ? &block->plants : NULL;
if(plants)
{
for (PlantList::const_iterator it = plants->begin(); it != plants->end(); it++)
{
const df::plant & plant = *(*it);
+ if (plant.pos.z != z)
+ continue;
df::coord2d loc(plant.pos.x, plant.pos.y);
loc = loc % 16;
if (showHidden || !b->DesignationAt(loc).bits.hidden)
From 55ebca4a7a455c3cd7fac3246fe60691c10ef46a Mon Sep 17 00:00:00 2001
From: Quietust
Date: Wed, 6 Aug 2014 10:03:34 -0500
Subject: [PATCH 21/22] Plant immolate/extirpate no longer work, but
create/grow are still good
---
plugins/plants.cpp | 50 +++++++++++++++++++++++++++-------------------
1 file changed, 29 insertions(+), 21 deletions(-)
diff --git a/plugins/plants.cpp b/plugins/plants.cpp
index 658b84321..9509e07f8 100644
--- a/plugins/plants.cpp
+++ b/plugins/plants.cpp
@@ -24,6 +24,7 @@ const uint32_t sapling_to_tree_threshold = 120 * 28 * 12 * 3 - 1; // 3 years min
DFHACK_PLUGIN("plants");
+/* Immolate/Extirpate no longer work in 0.40
enum do_what
{
do_immolate,
@@ -59,12 +60,13 @@ static bool getoptions( vector & parameters, bool & shrubs, bool & tree
return true;
}
-/**
- * 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.
- */
+//
+// 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 (color_ostream &out, do_what what, bool shrubs, bool trees)
{
CoreSuspender suspend;
@@ -90,7 +92,7 @@ static command_result immolations (color_ostream &out, do_what what, bool shrubs
destroyed ++;
}
}
- out.print("Praise Armok!\n");
+ out.print("Praise Armok! %i plants destroyed.\n", destroyed);
}
else
{
@@ -110,12 +112,10 @@ static command_result immolations (color_ostream &out, do_what what, bool shrubs
break;
}
}
- /*
- if(!didit)
- {
- cout << "----==== There's NOTHING there! ====----" << endl;
- }
- */
+ if(didit)
+ out.print("Praise Armok! Selected plant destroyed.\n");
+ else
+ out.printerr("No plant found at specified location!\n");
}
else
{
@@ -152,16 +152,16 @@ command_result df_immolate (color_ostream &out, vector & parameters, do
return CR_OK;
}
-
+*/
command_result df_grow (color_ostream &out, vector & parameters)
{
for(size_t i = 0; i < parameters.size();i++)
{
if(parameters[i] == "help" || parameters[i] == "?")
{
- out << "Usage:\n"
+ out.print("Usage:\n"
"This command turns all living saplings on the map into full-grown trees.\n"
- "With active cursor, work on the targetted one only.\n";
+ "With active cursor, work on the targetted one only.\n");
return CR_OK;
}
}
@@ -175,6 +175,7 @@ command_result df_grow (color_ostream &out, vector & parameters)
}
MapExtras::MapCache map;
int32_t x,y,z;
+ int grown = 0;
if(Gui::getCursorCoords(x,y,z))
{
for(size_t i = 0; i < world->plants.all.size(); i++)
@@ -186,6 +187,7 @@ command_result df_grow (color_ostream &out, vector & parameters)
tileSpecial(map.tiletypeAt(DFCoord(x,y,z))) != tiletype_special::DEAD)
{
tree->grow_counter = sapling_to_tree_threshold;
+ grown++;
}
break;
}
@@ -193,7 +195,6 @@ command_result df_grow (color_ostream &out, vector & parameters)
}
else
{
- int grown = 0;
for(size_t i = 0 ; i < world->plants.all.size(); i++)
{
df::plant *p = world->plants.all[i];
@@ -201,9 +202,14 @@ command_result df_grow (color_ostream &out, vector & parameters)
if(!p->flags.bits.is_shrub && tileShape(ttype) == tiletype_shape::SAPLING && tileSpecial(ttype) != tiletype_special::DEAD)
{
p->grow_counter = sapling_to_tree_threshold;
+ grown++;
}
}
}
+ if (grown)
+ out.print("%i plants grown.\n", grown);
+ else
+ out.printerr("No plant(s) found!\n");
return CR_OK;
}
@@ -212,10 +218,10 @@ command_result df_createplant (color_ostream &out, vector & parameters)
{
if ((parameters.size() != 1) || (parameters[0] == "help" || parameters[0] == "?"))
{
- out << "Usage:\n"
+ out.print("Usage:\n"
"Create a new plant at the cursor.\n"
"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";
+ "Only shrubs and saplings can be placed, and they must be located on a dirt or grass floor.\n");
return CR_OK;
}
@@ -313,6 +319,7 @@ command_result df_plant (color_ostream &out, vector & parameters)
parameters.erase(parameters.begin());
return df_grow(out, parameters);
} else
+/*
if (parameters[0] == "immolate") {
parameters.erase(parameters.begin());
return df_immolate(out, parameters, do_immolate);
@@ -321,6 +328,7 @@ command_result df_plant (color_ostream &out, vector & parameters)
parameters.erase(parameters.begin());
return df_immolate(out, parameters, do_extirpate);
} else
+*/
if (parameters[0] == "create") {
parameters.erase(parameters.begin());
return df_createplant(out, parameters);
@@ -334,8 +342,8 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector
Date: Wed, 6 Aug 2014 13:55:22 -0500
Subject: [PATCH 22/22] Update compile instructions - Strawberry Perl includes
all of the necessary dependencies, so you don't need to install them too
---
Compile.html | 24 +++++++++---------------
Compile.rst | 23 +++++++++--------------
2 files changed, 18 insertions(+), 29 deletions(-)
diff --git a/Compile.html b/Compile.html
index e031fd87a..4471278cb 100644
--- a/Compile.html
+++ b/Compile.html
@@ -382,10 +382,10 @@ ul.auto-toc {
DFHack doesn't have any kind of system of code snapshots in place, so you will have to get code from the github repository using git.
Having a 'git' package installed is the minimal requirement, but some sort of git gui or git integration for your favorite text editor/IDE will certainly help.
-The code resides here: https://github.com/peterix/dfhack
+The code resides here: https://github.com/DFHack/dfhack
If you just want to compile DFHack or work on it by contributing patches, it's quite enough to clone from the read-only address:
-git clone git://github.com/peterix/dfhack.git
+git clone git://github.com/DFHack/dfhack.git
cd dfhack
git submodule init
git submodule update
@@ -553,14 +553,14 @@ make install
You will need some sort of Windows port of git, or a GUI. Some examples:
-The code resides here: https://github.com/peterix/dfhack
+The code resides here: https://github.com/DFHack/dfhack
If you just want to compile DFHack or work on it by contributing patches, it's quite enough to clone from the read-only address:
-git clone git://github.com/peterix/dfhack.git
+git clone git://github.com/DFHack/dfhack.git
cd dfhack
git submodule init
git submodule update
@@ -577,13 +577,7 @@ to your binary search PATH so the tool can be later run from anywhere.
You'll need a copy of Microsoft Visual C++ 2010. The Express version is sufficient.
Grab it from Microsoft's site.
You'll also need the Visual Studio 2010 SP1 update.
-For the code generation parts, you'll need perl and XML::LibXML. You can install them like this:
-
-- download and install strawberry perl from http://strawberryperl.com/
-- reboot so that the system can pick up the new binary path
-- open a cmd.exe window and run "cpan XML::LibXML" (obviously without the quotes). This can take a while to complete.
-- Same with "cpan XML::LibXSLT".
-
+For the code generation parts, you'll need perl with XML::LibXML and XML::LibXSLT. Strawberry Perl works nicely for this: http://strawberryperl.com/
If you already have a different version of perl (for example the one from cygwin), you can run into some trouble. Either remove the other perl install from PATH, or install libxml and libxslt for it instead. Strawberry perl works though and has all the required packages.
@@ -666,7 +660,7 @@ I'll make
you fix it ;)
the IRC channel to pull your code in. I'll review it and see if there
are any problems. I'll fix them if they are minor.
Fixes are higher in priority. If you want to work on something, but
-don't know what, check out http://github.com/peterix/dfhack/issues --
+don't know what, check out http://github.com/DFHack/dfhack/issues --
this is also a good place to dump new ideas and/or bugs that need
fixing.
@@ -678,13 +672,13 @@ to look at machine code without getting crazy :)
Good windows tools include:
- Cheat Engine
-- IDA Pro (the free version)
+- IDA Pro 5.0 (freely available for non-commercial use)
Good linux tools:
- angavrilov's df-structures gui (visit us on IRC for details).
- edb (Evan's Debugger)
-- IDA Pro running under wine.
+- IDA Pro 5.0 running under Wine
- Some of the tools residing in the legacy dfhack branch.
Using publicly known information and analyzing the game's data is preferred.
diff --git a/Compile.rst b/Compile.rst
index 63686d663..eb15b2c8b 100644
--- a/Compile.rst
+++ b/Compile.rst
@@ -16,11 +16,11 @@ How to get the code
DFHack doesn't have any kind of system of code snapshots in place, so you will have to get code from the github repository using git.
Having a 'git' package installed is the minimal requirement, but some sort of git gui or git integration for your favorite text editor/IDE will certainly help.
-The code resides here: https://github.com/peterix/dfhack
+The code resides here: https://github.com/DFHack/dfhack
If you just want to compile DFHack or work on it by contributing patches, it's quite enough to clone from the read-only address::
- git clone git://github.com/peterix/dfhack.git
+ git clone git://github.com/DFHack/dfhack.git
cd dfhack
git submodule init
git submodule update
@@ -165,14 +165,14 @@ How to get the code
DFHack doesn't have any kind of system of code snapshots in place, so you will have to get code from the github repository using git.
You will need some sort of Windows port of git, or a GUI. Some examples:
- * http://code.google.com/p/msysgit/ - this is a command line version of git for windows. Most tutorials on git usage will apply.
+ * http://msysgit.github.io/ - this is a command line version of git for windows. Most tutorials on git usage will apply.
* http://code.google.com/p/tortoisegit/ - this puts a pretty, graphical face on top of msysgit :)
-The code resides here: https://github.com/peterix/dfhack
+The code resides here: https://github.com/DFHack/dfhack
If you just want to compile DFHack or work on it by contributing patches, it's quite enough to clone from the read-only address::
- git clone git://github.com/peterix/dfhack.git
+ git clone git://github.com/DFHack/dfhack.git
cd dfhack
git submodule init
git submodule update
@@ -194,12 +194,7 @@ Grab it from Microsoft's site.
You'll also need the Visual Studio 2010 SP1 update.
-For the code generation parts, you'll need perl and XML::LibXML. You can install them like this:
-
-* download and install strawberry perl from http://strawberryperl.com/
-* reboot so that the system can pick up the new binary path
-* open a cmd.exe window and run "cpan XML::LibXML" (obviously without the quotes). This can take a while to complete.
-* Same with "cpan XML::LibXSLT".
+For the code generation parts, you'll need perl with XML::LibXML and XML::LibXSLT. Strawberry Perl works nicely for this: http://strawberryperl.com/
If you already have a different version of perl (for example the one from cygwin), you can run into some trouble. Either remove the other perl install from PATH, or install libxml and libxslt for it instead. Strawberry perl works though and has all the required packages.
@@ -307,7 +302,7 @@ the IRC channel to pull your code in. I'll review it and see if there
are any problems. I'll fix them if they are minor.
Fixes are higher in priority. If you want to work on something, but
-don't know what, check out http://github.com/peterix/dfhack/issues --
+don't know what, check out http://github.com/DFHack/dfhack/issues --
this is also a good place to dump new ideas and/or bugs that need
fixing.
@@ -321,13 +316,13 @@ to look at machine code without getting crazy :)
Good windows tools include:
* Cheat Engine
-* IDA Pro (the free version)
+* IDA Pro 5.0 (freely available for non-commercial use)
Good linux tools:
* angavrilov's df-structures gui (visit us on IRC for details).
* edb (Evan's Debugger)
-* IDA Pro running under wine.
+* IDA Pro 5.0 running under Wine
* Some of the tools residing in the ``legacy`` dfhack branch.
Using publicly known information and analyzing the game's data is preferred.