diff --git a/LUA_API.rst b/LUA_API.rst index b0f1a9f31..9fb37375d 100644 --- a/LUA_API.rst +++ b/LUA_API.rst @@ -726,7 +726,7 @@ Units module * ``dfhack.units.isDead(unit)`` - The unit is completely dead and passive. + The unit is completely dead and passive, or a ghost. * ``dfhack.units.isAlive(unit)`` @@ -734,7 +734,16 @@ Units module * ``dfhack.units.isSane(unit)`` - The unit is capable of rational action, i.e. not dead, insane or zombie. + The unit is capable of rational action, i.e. not dead, insane, zombie, or active werewolf. + +* ``dfhack.units.isDwarf(unit)`` + + The unit is of the correct race of the fortress. + +* ``dfhack.units.isCitizen(unit)`` + + The unit is an alive sane citizen of the fortress; wraps the + same checks the game uses to decide game-over by extinction. * ``dfhack.units.getAge(unit[,true_age])`` diff --git a/Lua API.html b/Lua API.html index 4b763af25..1576652d6 100644 --- a/Lua API.html +++ b/Lua API.html @@ -960,13 +960,20 @@ a lua list containing them.

Returns the nemesis record of the unit if it has one, or nil.

  • dfhack.units.isDead(unit)

    -

    The unit is completely dead and passive.

    +

    The unit is completely dead and passive, or a ghost.

  • dfhack.units.isAlive(unit)

    The unit isn't dead or undead.

  • dfhack.units.isSane(unit)

    -

    The unit is capable of rational action, i.e. not dead, insane or zombie.

    +

    The unit is capable of rational action, i.e. not dead, insane, zombie, or active werewolf.

    +
  • +
  • dfhack.units.isDwarf(unit)

    +

    The unit is of the correct race of the fortress.

    +
  • +
  • dfhack.units.isCitizen(unit)

    +

    The unit is an alive sane citizen of the fortress; wraps the +same checks the game uses to decide game-over by extinction.

  • dfhack.units.getAge(unit[,true_age])

    Returns the age of the unit in years as a floating-point value. diff --git a/depends/protobuf/CMakeLists.txt b/depends/protobuf/CMakeLists.txt index dddefb06b..570c77b18 100644 --- a/depends/protobuf/CMakeLists.txt +++ b/depends/protobuf/CMakeLists.txt @@ -200,7 +200,9 @@ google/protobuf/compiler/zip_writer.cc LIST(APPEND LIBPROTOBUF_FULL_SRCS ${LIBPROTOBUF_LITE_SRCS}) -SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -Wno-sign-compare") +IF(CMAKE_COMPILER_IS_GNUCC) + SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -Wno-sign-compare") +ENDIF() INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) SET(PROTOBUF_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/dfhack.init-example b/dfhack.init-example index 7bceda2d0..4af4246fc 100644 --- a/dfhack.init-example +++ b/dfhack.init-example @@ -13,6 +13,9 @@ keybinding add Ctrl-Shift-K autodump-destroy-here # any item: keybinding add Ctrl-K autodump-destroy-item +# quicksave, only in main dwarfmode screen and menu page +keybinding add Ctrl-Alt-S@dwarfmode/Default quicksave + ############################## # Generic adv mode bindings # ############################## diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 32b7d9dad..c49ac6884 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -208,6 +208,8 @@ IF(UNIX) SET_SOURCE_FILES_PROPERTIES(DataStatics.cpp DataStaticsCtor.cpp DataStaticsFields.cpp PROPERTIES COMPILE_FLAGS "-g0 -O1") ELSE(WIN32) + SET_SOURCE_FILES_PROPERTIES(DataStatics.cpp DataStaticsCtor.cpp DataStaticsFields.cpp + PROPERTIES COMPILE_FLAGS "/O1 /bigobj") ENDIF() diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 6a550db87..8e8a3c4e3 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -715,6 +715,8 @@ static const LuaWrapper::FunctionReg dfhack_units_module[] = { WRAPM(Units, isDead), WRAPM(Units, isAlive), WRAPM(Units, isSane), + WRAPM(Units, isDwarf), + WRAPM(Units, isCitizen), WRAPM(Units, getAge), WRAPM(Units, getProfessionName), WRAPM(Units, getCasteProfessionName), diff --git a/library/VersionInfoFactory.cpp b/library/VersionInfoFactory.cpp index 36dbd9aae..972ab31b4 100644 --- a/library/VersionInfoFactory.cpp +++ b/library/VersionInfoFactory.cpp @@ -107,7 +107,7 @@ void VersionInfoFactory::ParseVersion (TiXmlElement* entry, VersionInfo* mem) } else { - throw Error::SymbolsXmlBadAttribute("os-type"); + return; // ignore it if it's invalid } // process additional entries diff --git a/library/include/DataFuncs.h b/library/include/DataFuncs.h index aff04128c..637a532f8 100644 --- a/library/include/DataFuncs.h +++ b/library/include/DataFuncs.h @@ -160,6 +160,17 @@ INSTANTIATE_WRAPPERS(6, (OSTREAM_ARG,A1,A2,A3,A4,A5,A6), (out,vA1,vA2,vA3,vA4,vA #define FW_TARGS class A1, class A2, class A3, class A4, class A5, class A6, class A7 INSTANTIATE_RETURN_TYPE((A1,A2,A3,A4,A5,A6,A7)) +INSTANTIATE_WRAPPERS(7, (A1,A2,A3,A4,A5,A6,A7), (vA1,vA2,vA3,vA4,vA5,vA6,vA7), + LOAD_ARG(A1); LOAD_ARG(A2); LOAD_ARG(A3); + LOAD_ARG(A4); LOAD_ARG(A5); LOAD_ARG(A6); + LOAD_ARG(A7);) +INSTANTIATE_WRAPPERS(7, (OSTREAM_ARG,A1,A2,A3,A4,A5,A6,A7), (out,vA1,vA2,vA3,vA4,vA5,vA6,vA7), + LOAD_OSTREAM(out); LOAD_ARG(A1); LOAD_ARG(A2); LOAD_ARG(A3); + LOAD_ARG(A4); LOAD_ARG(A5); LOAD_ARG(A6); LOAD_ARG(A7);) +#undef FW_TARGS + +#define FW_TARGS class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 +INSTANTIATE_RETURN_TYPE((A1,A2,A3,A4,A5,A6,A7,A8)) #undef FW_TARGS #undef FW_TARGSC diff --git a/library/include/modules/World.h b/library/include/modules/World.h index e7b17ce41..81ebfbd60 100644 --- a/library/include/modules/World.h +++ b/library/include/modules/World.h @@ -37,16 +37,6 @@ distribution. namespace DFHack { - /** - * \ingroup grp_world - */ - enum WeatherType - { - CLEAR, - RAINING, - SNOWING - }; - typedef unsigned char weather_map [5][5]; /** * \ingroup grp_world */ @@ -113,7 +103,6 @@ namespace DFHack class DFHACK_EXPORT World : public Module { public: - weather_map * wmap; World(); ~World(); bool Start(); diff --git a/library/modules/Gui.cpp b/library/modules/Gui.cpp index 2290110a8..63ba811c1 100644 --- a/library/modules/Gui.cpp +++ b/library/modules/Gui.cpp @@ -58,12 +58,14 @@ using namespace DFHack; #include "df/viewscreen_layer_overall_healthst.h" #include "df/viewscreen_layer_assigntradest.h" #include "df/viewscreen_layer_militaryst.h" +#include "df/viewscreen_layer_stockpilest.h" #include "df/viewscreen_petst.h" #include "df/viewscreen_tradegoodsst.h" #include "df/viewscreen_storesst.h" #include "df/ui_unit_view_mode.h" #include "df/ui_sidebar_menus.h" #include "df/ui_look_list.h" +#include "df/ui_advmode.h" #include "df/job.h" #include "df/ui_build_selector.h" #include "df/building_workshopst.h" @@ -273,7 +275,9 @@ DEFINE_GET_FOCUS_STRING_HANDLER(dwarfmode) break; case Burrows: - if (ui->burrows.in_add_units_mode) + if (ui->burrows.in_confirm_delete) + focus += "/ConfirmDelete"; + else if (ui->burrows.in_add_units_mode) focus += "/AddUnits"; else if (ui->burrows.in_edit_name_mode) focus += "/EditName"; @@ -288,6 +292,16 @@ DEFINE_GET_FOCUS_STRING_HANDLER(dwarfmode) } } +DEFINE_GET_FOCUS_STRING_HANDLER(dungeonmode) +{ + using df::global::ui_advmode; + + if (!ui_advmode) + return; + + focus += "/" + enum_item_key(ui_advmode->menu); +} + DEFINE_GET_FOCUS_STRING_HANDLER(unitlist) { focus += "/" + enum_item_key(screen->page); @@ -407,6 +421,35 @@ DEFINE_GET_FOCUS_STRING_HANDLER(stores) focus += "/Items"; } +DEFINE_GET_FOCUS_STRING_HANDLER(layer_stockpile) +{ + auto list1 = getLayerList(screen, 0); + auto list2 = getLayerList(screen, 1); + auto list3 = getLayerList(screen, 2); + if (!list1 || !list2 || !list3 || !screen->settings) return; + + auto group = screen->cur_group; + if (group != vector_get(screen->group_ids, list1->cursor)) + return; + + focus += "/" + enum_item_key(group); + + auto bits = vector_get(screen->group_bits, list1->cursor); + if (bits.whole && !(bits.whole & screen->settings->flags.whole)) + { + focus += "/Off"; + return; + } + + focus += "/On"; + + if (list2->bright || list3->bright || screen->list_ids.empty()) { + focus += "/" + enum_item_key(screen->cur_list); + + if (list3->bright) + focus += (screen->item_names.empty() ? "/None" : "/Item"); + } +} std::string Gui::getFocusString(df::viewscreen *top) { @@ -998,16 +1041,29 @@ bool Gui::setDesignationCoords (const int32_t x, const int32_t y, const int32_t bool Gui::getMousePos (int32_t & x, int32_t & y) { - x = gps->mouse_x; - y = gps->mouse_y; + if (gps) { + x = gps->mouse_x; + y = gps->mouse_y; + } + else { + x = -1; + y = -1; + } return (x == -1) ? false : true; } bool Gui::getWindowSize (int32_t &width, int32_t &height) { - width = gps->dimx; - height = gps->dimy; - return true; + if (gps) { + width = gps->dimx; + height = gps->dimy; + return true; + } + else { + width = 80; + height = 25; + return false; + } } bool Gui::getMenuWidth(uint8_t &menu_width, uint8_t &area_map_width) diff --git a/library/modules/Materials.cpp b/library/modules/Materials.cpp index f49dd82e2..f8f99f81e 100644 --- a/library/modules/Materials.cpp +++ b/library/modules/Materials.cpp @@ -761,8 +761,8 @@ bool Materials::ReadCreatureTypesEx (void) { df::body_part_raw *bp = ca->body_info.body_parts[k]; t_bodypart part; - part.id = bp->part_code; - part.category = bp->part_name; + part.id = bp->token; + part.category = bp->category; caste.bodypart.push_back(part); } using namespace df::enums::mental_attribute_type; diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index dd26109e7..ee383cc07 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -613,12 +613,45 @@ df::nemesis_record *Units::getNemesis(df::unit *unit) return NULL; } +static bool casteFlagSet(int race, int caste, df::caste_raw_flags flag) +{ + auto creature = df::creature_raw::find(race); + if (!creature) + return false; + + auto craw = vector_get(creature->caste, caste); + if (!craw) + return false; + + return craw->flags.is_set(flag); +} + +static bool isCrazed(df::unit *unit) +{ + if (unit->flags3.bits.scuttle) + return false; + if (unit->curse.rem_tags1.bits.CRAZED) + return false; + if (unit->curse.add_tags1.bits.CRAZED) + return true; + return casteFlagSet(unit->race, unit->caste, caste_raw_flags::CRAZED); +} + +static bool isOpposedToLife(df::unit *unit) +{ + if (unit->curse.rem_tags1.bits.OPPOSED_TO_LIFE) + return false; + if (unit->curse.add_tags1.bits.OPPOSED_TO_LIFE) + return true; + return casteFlagSet(unit->race, unit->caste, caste_raw_flags::CANNOT_UNDEAD); +} bool DFHack::Units::isDead(df::unit *unit) { CHECK_NULL_POINTER(unit); - return unit->flags1.bits.dead; + return unit->flags1.bits.dead || + unit->flags3.bits.ghostly; } bool DFHack::Units::isAlive(df::unit *unit) @@ -636,8 +669,11 @@ bool DFHack::Units::isSane(df::unit *unit) if (unit->flags1.bits.dead || unit->flags3.bits.ghostly || - unit->curse.add_tags1.bits.OPPOSED_TO_LIFE || - unit->curse.add_tags1.bits.CRAZED) + isOpposedToLife(unit) || + unit->unknown8.unk2) + return false; + + if (unit->unknown8.normal_race == unit->unknown8.were_race && isCrazed(unit)) return false; switch (unit->mood) @@ -657,19 +693,38 @@ bool DFHack::Units::isCitizen(df::unit *unit) { CHECK_NULL_POINTER(unit); + // Copied from the conditions used to decide game over, + // except that the game appears to let melancholy/raving + // dwarves count as citizens. + + if (!isDwarf(unit) || !isSane(unit)) + return false; + + if (unit->flags1.bits.marauder || + unit->flags1.bits.invader_origin || + unit->flags1.bits.active_invader || + unit->flags1.bits.forest || + unit->flags1.bits.merchant || + unit->flags1.bits.diplomat) + return false; + + if (unit->flags1.bits.tame) + return true; + return unit->civ_id == ui->civ_id && - !unit->flags1.bits.merchant && - !unit->flags1.bits.diplomat && + unit->civ_id != -1 && + !unit->flags2.bits.underworld && !unit->flags2.bits.resident && - !unit->flags1.bits.dead && - !unit->flags3.bits.ghostly; + !unit->flags2.bits.visitor_uninvited && + !unit->flags2.bits.visitor; } bool DFHack::Units::isDwarf(df::unit *unit) { CHECK_NULL_POINTER(unit); - return unit->race == ui->race_id; + return unit->race == ui->race_id || + unit->unknown8.normal_race == ui->race_id; } double DFHack::Units::getAge(df::unit *unit, bool true_age) diff --git a/library/modules/Windows.cpp b/library/modules/Windows.cpp index e069d964e..218b6f7e0 100644 --- a/library/modules/Windows.cpp +++ b/library/modules/Windows.cpp @@ -34,10 +34,12 @@ distribution. #include "modules/Windows.h" using namespace DFHack; +using df::global::gps; Windows::df_screentile *Windows::getScreenBuffer() { - return (df_screentile *) df::global::gps->screen; + if (!gps) return NULL; + return (df_screentile *) gps->screen; } Windows::df_window::df_window(int x, int y, unsigned int width, unsigned int height) @@ -79,7 +81,7 @@ bool Windows::df_window::unlock (painter * painter) return false; } -Windows::top_level_window::top_level_window(): df_window(0,0,df::global::gps->dimx,df::global::gps->dimy) +Windows::top_level_window::top_level_window() : df_window(0,0,gps ? gps->dimx : 80,gps ? gps->dimy : 25) { buffer = 0; } diff --git a/library/modules/World.cpp b/library/modules/World.cpp index 6f6a69a59..4b50b44ca 100644 --- a/library/modules/World.cpp +++ b/library/modules/World.cpp @@ -63,15 +63,8 @@ struct World::Private bool Inited; bool PauseInited; - void * pause_state_offset; - bool StartedWeather; - char * weather_offset; - bool StartedMode; - void * gamemode_offset; - void * controlmode_offset; - void * controlmodecopy_offset; int next_persistent_id; std::multimap persistent_index; @@ -86,21 +79,14 @@ World::World() Core & c = Core::getInstance(); d = new Private; d->owner = c.p; - wmap = 0; - d->pause_state_offset = (void *) c.vinfo->getAddress ("pause_state"); - if(d->pause_state_offset) + if(df::global::pause_state) d->PauseInited = true; - d->weather_offset = (char *) c.vinfo->getAddress( "current_weather" ); - if(d->weather_offset) - { - wmap = (weather_map *) d->weather_offset; + if(df::global::current_weather) d->StartedWeather = true; - } - d->gamemode_offset = (void *) c.vinfo->getAddress( "game_mode" ); - d->controlmode_offset = (void *) c.vinfo->getAddress( "control_mode" ); - d->StartedMode = true; + if (df::global::game_mode && df::global::control_mode) + d->StartedMode = true; d->Inited = true; } @@ -123,14 +109,13 @@ bool World::Finish() bool World::ReadPauseState() { if(!d->PauseInited) return false; - uint8_t pauseState = d->owner->readByte (d->pause_state_offset); - return pauseState & 1; + return *df::global::pause_state; } void World::SetPauseState(bool paused) { - if(!d->PauseInited) return; - d->owner->writeByte (d->pause_state_offset, paused); + if (d->PauseInited) + *df::global::pause_state = paused; } uint32_t World::ReadCurrentYear() @@ -147,8 +132,8 @@ bool World::ReadGameMode(t_gamemodes& rd) { if(d->Inited && d->StartedMode) { - rd.g_mode = (GameMode) d->owner->readDWord( d->controlmode_offset); - rd.g_type = (GameType) d->owner->readDWord(d->gamemode_offset); + rd.g_mode = (DFHack::GameMode)*df::global::control_mode; + rd.g_type = (DFHack::GameType)*df::global::game_mode; return true; } return false; @@ -157,8 +142,8 @@ bool World::WriteGameMode(const t_gamemodes & wr) { if(d->Inited && d->StartedMode) { - d->owner->writeDWord(d->gamemode_offset,wr.g_type); - d->owner->writeDWord(d->controlmode_offset,wr.g_mode); + *df::global::control_mode = wr.g_mode; + *df::global::game_mode = wr.g_type; return true; } return false; @@ -199,18 +184,14 @@ uint32_t World::ReadCurrentDay() uint8_t World::ReadCurrentWeather() { if (d->Inited && d->StartedWeather) - return(d->owner->readByte(d->weather_offset + 12)); + return (*df::global::current_weather)[2][2]; return 0; } void World::SetCurrentWeather(uint8_t weather) { if (d->Inited && d->StartedWeather) - { - uint8_t buf[25]; - memset(&buf,weather, sizeof(buf)); - d->owner->write(d->weather_offset,sizeof(buf),buf); - } + memset(df::global::current_weather, weather, 25); } string World::ReadWorldFolder() diff --git a/library/xml b/library/xml index 234d0f57a..0a0dc568d 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 234d0f57a927f306f2052fc2f45d38b3201ddee6 +Subproject commit 0a0dc568dff80396efd1b2c9a6ef1614df5786f7 diff --git a/plugins/autolabor.cpp b/plugins/autolabor.cpp index d89ddd7c6..de1a1aef6 100644 --- a/plugins/autolabor.cpp +++ b/plugins/autolabor.cpp @@ -706,7 +706,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out ) { static int step_count = 0; // check run conditions - if(!world->map.block_index || !enable_autolabor) + if(!world || !world->map.block_index || !enable_autolabor) { // give up if we shouldn't be running' return CR_OK; diff --git a/plugins/devel/counters.cpp b/plugins/devel/counters.cpp index 66d8c63a4..332945677 100644 --- a/plugins/devel/counters.cpp +++ b/plugins/devel/counters.cpp @@ -25,7 +25,7 @@ command_result df_counters (color_ostream &out, vector & parameters) for (size_t i = 0; i < counters.size(); i++) { auto counter = counters[i]; - out.print("%i (%s): %i\n", counter->id, ENUM_KEY_STR(unit_misc_trait::T_id, counter->id).c_str(), counter->value); + out.print("%i (%s): %i\n", counter->id, ENUM_KEY_STR(misc_trait_type, counter->id).c_str(), counter->value); } return CR_OK; diff --git a/plugins/dwarfexport/dwarfexport.cpp b/plugins/dwarfexport/dwarfexport.cpp index 5db1bf226..64fbcd653 100644 --- a/plugins/dwarfexport/dwarfexport.cpp +++ b/plugins/dwarfexport/dwarfexport.cpp @@ -89,13 +89,13 @@ static void element(const char* name, const uint32_t content, ostream& out, cons static void printAttributes(color_ostream &con, df::unit* cre, ostream& out) { out << " " << endl; for (int i = 0; i < NUM_CREATURE_PHYSICAL_ATTRIBUTES; i++) { - element(physicals[i], cre->body.physical_attrs[i].unk1, out, " "); + element(physicals[i], cre->body.physical_attrs[i].value, out, " "); } df::unit_soul * s = cre->status.current_soul; if (s) { for (int i = 0; i < NUM_CREATURE_MENTAL_ATTRIBUTES; i++) { - element(mentals[i], s->mental_attrs[i].unk1, out, " "); + element(mentals[i], s->mental_attrs[i].value, out, " "); } } out << " " << endl; diff --git a/plugins/fastdwarf.cpp b/plugins/fastdwarf.cpp index 643a097c4..5a2e2f206 100644 --- a/plugins/fastdwarf.cpp +++ b/plugins/fastdwarf.cpp @@ -28,7 +28,7 @@ static int enable_fastdwarf = false; DFhackCExport command_result plugin_onupdate ( color_ostream &out ) { // check run conditions - if(!world->map.block_index || !enable_fastdwarf) + if(!world || !world->map.block_index || !enable_fastdwarf) { // give up if we shouldn't be running' return CR_OK; diff --git a/plugins/forceequip.cpp b/plugins/forceequip.cpp index 0d493143b..abf4a95db 100644 --- a/plugins/forceequip.cpp +++ b/plugins/forceequip.cpp @@ -28,7 +28,7 @@ using namespace std; #include "df/body_part_raw.h" #include "MiscUtils.h" #include "df/unit_inventory_item.h" -#include "df/body_part_template_flags.h" +#include "df/body_part_raw_flags.h" #include "df/creature_raw.h" #include "df/caste_raw.h" #include "df/body_detail_plan.h" @@ -292,7 +292,7 @@ static bool moveToInventory(MapExtras::MapCache &mc, df::item *item, df::unit *u else if (bpIndex < unit->body.body_plan->body_parts.size()) { // The current body part is not the one that was specified in the function call, but we can keep searching - if (verbose) { Core::printerr("Found bodypart %s; not a match; continuing search.\n", currPart->part_code.c_str()); } + if (verbose) { Core::printerr("Found bodypart %s; not a match; continuing search.\n", currPart->token.c_str()); } continue; } else @@ -302,35 +302,35 @@ static bool moveToInventory(MapExtras::MapCache &mc, df::item *item, df::unit *u return false; } - if (verbose) { Core::print("Inspecting bodypart %s.\n", currPart->part_code.c_str()); } + if (verbose) { Core::print("Inspecting bodypart %s.\n", currPart->token.c_str()); } // Inspect the current bodypart - if (item->getType() == df::enums::item_type::GLOVES && currPart->flags.is_set(df::body_part_template_flags::GRASP) && - ((item->getGloveHandedness() == const_GloveLeftHandedness && currPart->flags.is_set(df::body_part_template_flags::LEFT)) || - (item->getGloveHandedness() == const_GloveRightHandedness && currPart->flags.is_set(df::body_part_template_flags::RIGHT)))) + if (item->getType() == df::enums::item_type::GLOVES && currPart->flags.is_set(df::body_part_raw_flags::GRASP) && + ((item->getGloveHandedness() == const_GloveLeftHandedness && currPart->flags.is_set(df::body_part_raw_flags::LEFT)) || + (item->getGloveHandedness() == const_GloveRightHandedness && currPart->flags.is_set(df::body_part_raw_flags::RIGHT)))) { - if (verbose) { Core::print("Hand found (%s)...", currPart->part_code.c_str()); } + if (verbose) { Core::print("Hand found (%s)...", currPart->token.c_str()); } } - else if (item->getType() == df::enums::item_type::HELM && currPart->flags.is_set(df::body_part_template_flags::HEAD)) + else if (item->getType() == df::enums::item_type::HELM && currPart->flags.is_set(df::body_part_raw_flags::HEAD)) { - if (verbose) { Core::print("Head found (%s)...", currPart->part_code.c_str()); } + if (verbose) { Core::print("Head found (%s)...", currPart->token.c_str()); } } - else if (item->getType() == df::enums::item_type::ARMOR && currPart->flags.is_set(df::body_part_template_flags::UPPERBODY)) + else if (item->getType() == df::enums::item_type::ARMOR && currPart->flags.is_set(df::body_part_raw_flags::UPPERBODY)) { - if (verbose) { Core::print("Upper body found (%s)...", currPart->part_code.c_str()); } + if (verbose) { Core::print("Upper body found (%s)...", currPart->token.c_str()); } } - else if (item->getType() == df::enums::item_type::PANTS && currPart->flags.is_set(df::body_part_template_flags::LOWERBODY)) + else if (item->getType() == df::enums::item_type::PANTS && currPart->flags.is_set(df::body_part_raw_flags::LOWERBODY)) { - if (verbose) { Core::print("Lower body found (%s)...", currPart->part_code.c_str()); } + if (verbose) { Core::print("Lower body found (%s)...", currPart->token.c_str()); } } - else if (item->getType() == df::enums::item_type::SHOES && currPart->flags.is_set(df::body_part_template_flags::STANCE)) + else if (item->getType() == df::enums::item_type::SHOES && currPart->flags.is_set(df::body_part_raw_flags::STANCE)) { - if (verbose) { Core::print("Foot found (%s)...", currPart->part_code.c_str()); } + if (verbose) { Core::print("Foot found (%s)...", currPart->token.c_str()); } } else if (targetBodyPart && ignoreRestrictions) { // The BP in question would normally be considered ineligible for equipment. But since it was deliberately specified by the user, we'll proceed anyways. - if (verbose) { Core::print("Non-standard bodypart found (%s)...", targetBodyPart->part_code.c_str()); } + if (verbose) { Core::print("Non-standard bodypart found (%s)...", targetBodyPart->token.c_str()); } } else if (targetBodyPart) { @@ -538,16 +538,16 @@ command_result df_forceequip(color_ostream &out, vector & parameters) { // Tentatively assume that the part is a match targetBodyPart = targetUnit->body.body_plan->body_parts.at(bpIndex); - if (targetBodyPart->part_code.compare(targetBodyPartCode) == 0) + if (targetBodyPart->token.compare(targetBodyPartCode) == 0) { // It is indeed a match; exit the loop (while leaving the variable populated) - if (verbose) { out.print("Matching bodypart (%s) found.\n", targetBodyPart->part_name.c_str()); } + if (verbose) { out.print("Matching bodypart (%s) found.\n", targetBodyPart->token.c_str()); } break; } else { // Not a match; nullify the variable (it will get re-populated on the next pass through the loop) - if (verbose) { out.printerr("Bodypart \"%s\" does not match \"%s\".\n", targetBodyPart->part_code.c_str(), targetBodyPartCode.c_str()); } + if (verbose) { out.printerr("Bodypart \"%s\" does not match \"%s\".\n", targetBodyPart->token.c_str(), targetBodyPartCode.c_str()); } targetBodyPart = NULL; } } diff --git a/plugins/showmood.cpp b/plugins/showmood.cpp index 7407e6af1..7926e2ac5 100644 --- a/plugins/showmood.cpp +++ b/plugins/showmood.cpp @@ -100,37 +100,37 @@ command_result df_showmood (color_ostream &out, vector & parameters) switch (job->job_type) { case job_type::StrangeMoodCrafter: - out.print("become a Craftsdwarf (or Engraver)"); + out.print("claim a Craftsdwarf's Workshop"); break; case job_type::StrangeMoodJeweller: - out.print("become a Jeweler"); + out.print("claim a Jeweler's Workshop"); break; case job_type::StrangeMoodForge: - out.print("become a Metalworker"); + out.print("claim a Metalsmith's Forge"); break; case job_type::StrangeMoodMagmaForge: - out.print("become a Metalworker using a Magma Forge"); + out.print("claim a Magma Forge"); break; case job_type::StrangeMoodCarpenter: - out.print("become a Carpenter"); + out.print("claim a Carpenter's Workshop"); break; case job_type::StrangeMoodMason: - out.print("become a Mason (or Miner)"); + out.print("claim a Mason's Workshop"); break; case job_type::StrangeMoodBowyer: - out.print("become a Bowyer"); + out.print("claim a Boywer's Workshop"); break; case job_type::StrangeMoodTanner: - out.print("become a Leatherworker (or Tanner)"); + out.print("claim a Leather Works"); break; case job_type::StrangeMoodWeaver: - out.print("become a Clothier (or Weaver)"); + out.print("claim a Clothier's Shop"); break; case job_type::StrangeMoodGlassmaker: - out.print("become a Glassmaker"); + out.print("claim a Glass Furnace"); break; case job_type::StrangeMoodMechanics: - out.print("become a Mechanic"); + out.print("claim a Mechanic's Workshop"); break; case job_type::StrangeMoodBrooding: out.print("enter a macabre mood?"); @@ -142,20 +142,28 @@ command_result df_showmood (color_ostream &out, vector & parameters) out.print("do something else..."); break; } + out.print(" and become a legendary %s", ENUM_ATTR_STR(job_skill, caption_noun, unit->job.mood_skill)); + if (unit->mood == mood_type::Possessed) + out.print(" (but not really)"); break; - default: out.print("insane?"); break; } + out.print(".\n"); + if (unit->sex) + out.print("He has "); + else + out.print("She has "); if (building) { string name; building->getName(&name); - out.print(" and has claimed a %s\n", name.c_str()); + out.print("claimed a %s and wants", name.c_str()); } else - out.print(" and has not yet claimed a workshop\n"); + out.print("not yet claimed a workshop but will want"); + out.print(" the following items:\n"); for (size_t i = 0; i < job->job_items.size(); i++) { diff --git a/plugins/weather.cpp b/plugins/weather.cpp index 68eb078ad..33fa45fd3 100644 --- a/plugins/weather.cpp +++ b/plugins/weather.cpp @@ -5,10 +5,13 @@ #include #include #include "modules/World.h" +#include "DataDefs.h" +#include "df/weather_type.h" using std::vector; using std::string; using namespace DFHack; +using namespace df::enums; bool locked = false; unsigned char locked_data[25]; @@ -82,7 +85,7 @@ command_result weather (color_ostream &con, vector & parameters) CoreSuspender suspend; DFHack::World * w = Core::getInstance().getWorld(); - if(!w->wmap) + if(!df::global::current_weather) { con << "Weather support seems broken :(" << std::endl; return CR_FAILURE; @@ -95,19 +98,19 @@ command_result weather (color_ostream &con, vector & parameters) { for(int x = 0; x<5;x++) { - switch((*w->wmap)[x][y]) + switch((*df::global::current_weather)[x][y]) { - case CLEAR: + case weather_type::None: con << "C "; break; - case RAINING: + case weather_type::Rain: con << "R "; break; - case SNOWING: + case weather_type::Snow: con << "S "; break; default: - con << (int) (*w->wmap)[x][y] << " "; + con << (int) (*df::global::current_weather)[x][y] << " "; break; } } @@ -120,17 +123,17 @@ command_result weather (color_ostream &con, vector & parameters) if(rain) { con << "Here comes the rain." << std::endl; - w->SetCurrentWeather(RAINING); + w->SetCurrentWeather(weather_type::Rain); } if(snow) { con << "Snow everywhere!" << std::endl; - w->SetCurrentWeather(SNOWING); + w->SetCurrentWeather(weather_type::Snow); } if(clear) { con << "Suddenly, sunny weather!" << std::endl; - w->SetCurrentWeather(CLEAR); + w->SetCurrentWeather(weather_type::None); } if(val_override != -1) { diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp index 1092c86ae..dbf546070 100644 --- a/plugins/workflow.cpp +++ b/plugins/workflow.cpp @@ -965,6 +965,9 @@ static void compute_job_outputs(color_ostream &out, ProtectedJob *pj) mat.decode(mat.plant->material_defs.type_##tag, \ mat.plant->material_defs.idx_##tag); \ else mat.decode(-1); + case BrewDrink: + PLANT_PROCESS_MAT(DRINK, drink); + break; case MillPlants: PLANT_PROCESS_MAT(MILL, mill); break; diff --git a/scripts/fix/fat-dwarves.lua b/scripts/fix/fat-dwarves.lua new file mode 100644 index 000000000..5394f6770 --- /dev/null +++ b/scripts/fix/fat-dwarves.lua @@ -0,0 +1,24 @@ +-- Makes fat dwarves non-fat. +-- +-- See for more info: +-- http://www.bay12games.com/dwarves/mantisbt/view.php?id=5971 + +local num_fat = 0 +local num_lagging = 0 + +for _,v in ipairs(df.global.world.units.all) do + local fat = v.counters2.stored_fat + if fat > 850000 then + v.counters2.stored_fat = 500000 + if v.race == df.global.ui.race_id then + print(fat,dfhack.TranslateName(dfhack.units.getVisibleName(v))) + num_fat = num_fat + 1 + if fat > 999990 then + num_lagging = num_lagging + 1 + end + end + end +end + +print("Fat dwarves cured: "..num_fat) +print("Lag sources: "..num_lagging)