diff --git a/docs/Authors.rst b/docs/Authors.rst index dd0f691f3..fa315677a 100644 --- a/docs/Authors.rst +++ b/docs/Authors.rst @@ -56,7 +56,9 @@ IndigoFenix James Logsdon jlogsdon Japa JapaMala Jared Adams +Jeremy Apthorp nornagon Jim Lisi stonetoad +Jimbo Whales jimbowhales jimcarreer jimcarreer jj jjyg jj`` Joel Meador janxious diff --git a/docs/changelog.txt b/docs/changelog.txt index 46f71cf6c..41405a53a 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -52,6 +52,8 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: - `embark-assistant`: - fixed bug causing crash on worlds without generated metals (as well as pruning vectors as originally intended). - fixed bug causing mineral matching to fail to cut off at the magma sea, reporting presence of things that aren't (like DF does currently). + - fixed bug causing half of the river tiles not to be recognized. + - added logic to detect some river tiles DF doesn't generate data for (but are definitely present). - `getplants`: fixed designation of plants out of season and added verbose flag, but failed to identify picked plants (which are still designated incorrectly) - `gui/autogems`: fixed error when no world is loaded - `gui/companion-order`: diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 2840aa5b9..7c3ef965d 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -1611,6 +1611,7 @@ static const LuaWrapper::FunctionReg dfhack_units_module[] = { WRAPM(Units, isOwnCiv), WRAPM(Units, isOwnGroup), WRAPM(Units, isOwnRace), + WRAPM(Units, getPhysicalDescription), WRAPM(Units, getRaceName), WRAPM(Units, getRaceNamePlural), WRAPM(Units, getRaceBabyName), diff --git a/library/include/MiscUtils.h b/library/include/MiscUtils.h index ec2c7be58..35f8be73b 100644 --- a/library/include/MiscUtils.h +++ b/library/include/MiscUtils.h @@ -45,6 +45,17 @@ using std::endl; #define DFHACK_FUNCTION_SIG __func__ #endif +#ifdef _WIN32 +// On x86 MSVC, __thiscall passes |this| in ECX. On x86_64, __thiscall is the +// same as the standard calling convention. +// See https://docs.microsoft.com/en-us/cpp/cpp/thiscall for more info. +#define THISCALL __thiscall +#else +// On other platforms, there's no special calling convention for calling member +// functions. +#define THISCALL +#endif + namespace DFHack { class color_ostream; } diff --git a/library/include/modules/Units.h b/library/include/modules/Units.h index 09c39be55..f5995583b 100644 --- a/library/include/modules/Units.h +++ b/library/include/modules/Units.h @@ -120,6 +120,7 @@ DFHACK_EXPORT bool isVisible(df::unit* unit); DFHACK_EXPORT std::string getRaceNameById(int32_t race_id); DFHACK_EXPORT std::string getRaceName(df::unit* unit); +DFHACK_EXPORT std::string getPhysicalDescription(df::unit* unit); DFHACK_EXPORT std::string getRaceNamePluralById(int32_t race_id); DFHACK_EXPORT std::string getRaceNamePlural(df::unit* unit); DFHACK_EXPORT std::string getRaceBabyNameById(int32_t race_id); diff --git a/library/lua/dfhack.lua b/library/lua/dfhack.lua index 93ab48dca..049297385 100644 --- a/library/lua/dfhack.lua +++ b/library/lua/dfhack.lua @@ -765,14 +765,15 @@ function dfhack.run_command_silent(...) end function dfhack.run_command(...) - local output, status = _run_command(...) - for i, fragment in pairs(output) do - if type(fragment) == 'table' then - dfhack.color(fragment[1]) - dfhack.print(fragment[2]) + local result = _run_command(...) + for i, f in pairs(result) do + if type(f) == 'table' then + dfhack.color(f[1]) + dfhack.print(f[2]) end end dfhack.color(COLOR_RESET) + return result.status end -- Per-save init file diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index 861c25ce9..1907b1641 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -541,6 +541,25 @@ string Units::getRaceName(df::unit* unit) return getRaceNameById(unit->race); } +void df_unit_get_physical_description(df::unit* unit, string* out_str) +{ + static auto* const fn = + reinterpret_cast( + Core::getInstance().vinfo->getAddress("unit_get_physical_description")); + if (fn) + fn(unit, out_str); + else + *out_str = ""; +} + +string Units::getPhysicalDescription(df::unit* unit) +{ + CHECK_NULL_POINTER(unit); + string str; + df_unit_get_physical_description(unit, &str); + return str; +} + // get plural of race name (used for display in autobutcher UI and for sorting the watchlist) string Units::getRaceNamePluralById(int32_t id) { @@ -1549,8 +1568,8 @@ bool Units::isGay(df::unit* unit) if (!unit->status.current_soul) return false; df::orientation_flags orientation = unit->status.current_soul->orientation_flags; - return (Units::isFemale(unit) && ! (orientation.whole & (orientation.mask_marry_male | orientation.mask_romance_male))) - || (!Units::isFemale(unit) && ! (orientation.whole & (orientation.mask_marry_female | orientation.mask_romance_female))); + return (!Units::isFemale(unit) || !(orientation.whole & (orientation.mask_marry_male | orientation.mask_romance_male))) + && (!Units::isMale(unit) || !(orientation.whole & (orientation.mask_marry_female | orientation.mask_romance_female))); } bool Units::isNaked(df::unit* unit) diff --git a/library/xml b/library/xml index abdcb2e17..779de2311 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit abdcb2e17ff29e754a8a7661b697035a0ee702ba +Subproject commit 779de23111409635b5644daae5338ba0199945e4 diff --git a/package/linux/dfhack b/package/linux/dfhack index d0c70765b..1bd3e8d92 100755 --- a/package/linux/dfhack +++ b/package/linux/dfhack @@ -69,6 +69,16 @@ fi PRELOAD_LIB="${PRELOAD_LIB:+$PRELOAD_LIB:}${LIBSAN}${LIB}" setarch_arch=$(cat hack/dfhack_setarch.txt || printf i386) +if ! setarch "$setarch_arch" -R true 2>/dev/null; then + echo "warn: architecture '$setarch_arch' not supported by setarch" >&2 + if [ "$setarch_arch" = "i386" ]; then + setarch_arch=linux32 + else + setarch_arch=linux64 + fi + echo "using '$setarch_arch' instead. To silence this warning, edit" >&2 + echo "hack/dfhack_setarch.txt to contain an architecture that works on your system." >&2 +fi case "$1" in -g | --gdb) diff --git a/plugins/embark-assistant/matcher.cpp b/plugins/embark-assistant/matcher.cpp index 2033d7758..106cc6090 100644 --- a/plugins/embark-assistant/matcher.cpp +++ b/plugins/embark-assistant/matcher.cpp @@ -2077,7 +2077,7 @@ namespace embark_assist { uint32_t preliminary_world_match(embark_assist::defs::world_tile_data *survey_results, embark_assist::defs::finders *finder, embark_assist::defs::match_results *match_results) { - // color_ostream_proxy out(Core::getInstance().getConsole()); +// color_ostream_proxy out(Core::getInstance().getConsole()); uint32_t count = 0; for (uint16_t i = 0; i < world->worldgen.worldgen_parms.dim_x; i++) { for (uint16_t k = 0; k < world->worldgen.worldgen_parms.dim_y; k++) { diff --git a/plugins/embark-assistant/survey.cpp b/plugins/embark-assistant/survey.cpp index 5e9e44b5f..a2fb648f2 100644 --- a/plugins/embark-assistant/survey.cpp +++ b/plugins/embark-assistant/survey.cpp @@ -1043,11 +1043,11 @@ void embark_assist::survey::survey_mid_level_tile(embark_assist::defs::geo_data mlt->at(i).at(k).river_present = false; mlt->at(i).at(k).river_elevation = 100; - if (details->rivers_vertical.active[i][k] == 1) { + if (details->rivers_vertical.active[i][k] != 0) { mlt->at(i).at(k).river_present = true; mlt->at(i).at(k).river_elevation = details->rivers_vertical.elevation[i][k]; } - else if (details->rivers_horizontal.active[i][k] == 1) { + else if (details->rivers_horizontal.active[i][k] != 0) { mlt->at(i).at(k).river_present = true; mlt->at(i).at(k).river_elevation = details->rivers_horizontal.elevation[i][k]; } @@ -1179,6 +1179,51 @@ void embark_assist::survey::survey_mid_level_tile(embark_assist::defs::geo_data } } + // This is messy. DF has some weird logic to leave out river bends with a South and an East connection, as well + // as river sources (and presumably sinks) that are to the North or the West of the connecting river. + // Experiments indicate these implicit river bends inherit their River Elevation from the lower of the two + // "parents", and it's assumed river sources and sinks similarly inherit it from their sole "parent". + // Two issues are known: + // - Lake and Ocean tiles may be marked as having a river when DF doesn't. However, DF does allow for rivers to + // exist in Ocean/Lake tiles, as well as sources/sinks. + // - DF generates rivers on/under glaciers, but does not display them (as they're frozen), nor are their names + // displayed. + // + for (uint8_t i = 1; i < 16; i++) { + for (uint8_t k = 0; k < 15; k++) { + if (details->rivers_horizontal.active[i][k] != 0 && + details->rivers_vertical.active[i - 1][k + 1] != 0 && + !mlt->at(i - 1).at(k).river_present) { // Probably never true + mlt->at(i - 1).at(k).river_present = true; + mlt->at(i - 1).at(k).river_elevation = mlt->at(i).at(k).river_elevation; + + if (mlt->at(i - 1).at(k).river_elevation > mlt->at(i - 1).at(k + 1).river_elevation) { + mlt->at(i - 1).at(k).river_elevation = mlt->at(i - 1).at(k + 1).river_elevation; + } + } + } + } + + for (uint8_t i = 0; i < 16; i++) { + for (uint8_t k = 1; k < 16; k++) { + if (details->rivers_vertical.active[i][k] != 0 && + !mlt->at(i).at(k - 1).river_present) { + mlt->at(i).at(k - 1).river_present = true; + mlt->at(i).at(k - 1).river_elevation = mlt->at(i).at(k).river_elevation; + } + } + } + + for (uint8_t i = 1; i < 16; i++) { + for (uint8_t k = 0; k < 16; k++) { + if (details->rivers_horizontal.active[i][k] != 0 && + !mlt->at(i - 1).at(k).river_present) { + mlt->at(i - 1).at(k).river_present = true; + mlt->at(i - 1).at(k).river_elevation = mlt->at(i).at(k).river_elevation; + } + } + } + survey_results->at(x).at(y).aquifer_count = 0; survey_results->at(x).at(y).clay_count = 0; survey_results->at(x).at(y).sand_count = 0; diff --git a/plugins/proto/RemoteFortressReader.proto b/plugins/proto/RemoteFortressReader.proto index ed7557a2f..a54a0397f 100644 --- a/plugins/proto/RemoteFortressReader.proto +++ b/plugins/proto/RemoteFortressReader.proto @@ -457,6 +457,7 @@ message UnitAppearance optional Hair beard = 6; optional Hair moustache = 7; optional Hair sideburns = 8; + optional string physical_description = 9; } message InventoryItem diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index e3cfc2e1f..f63ae5b2c 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -1734,6 +1734,8 @@ static command_result GetUnitListInside(color_ostream &stream, const BlockReques appearance->add_colors(unit->appearance.colors[j]); appearance->set_size_modifier(unit->appearance.size_modifier); + appearance->set_physical_description(Units::getPhysicalDescription(unit)); + send_unit->set_profession_id(unit->profession); std::vector pvec; diff --git a/scripts b/scripts index abcb0cffb..5d0f00eae 160000 --- a/scripts +++ b/scripts @@ -1 +1 @@ -Subproject commit abcb0cffbbcaaeefc7effca25ff947ab8ea91c43 +Subproject commit 5d0f00eae3bd8eef41c860369550e05f95a1282a