Merge remote-tracking branch 'DFHack/develop' into develop

develop
Japa 2017-05-07 19:24:39 +05:30
commit de7ef79d76
29 changed files with 568 additions and 104 deletions

@ -94,6 +94,8 @@ IF(CMAKE_CROSSCOMPILING)
INCLUDE("${DFHACK_NATIVE_BUILD_DIR}/ImportExecutables.cmake")
ENDIF()
find_package(Perl REQUIRED)
# set up folder structures for IDE solutions
# MSVC Express won't load solutions that use this. It also doesn't include MFC supported
# Check for MFC!
@ -137,7 +139,7 @@ endif()
# set up versioning.
set(DF_VERSION "0.43.05")
SET(DFHACK_RELEASE "beta1")
SET(DFHACK_RELEASE "beta2")
SET(DFHACK_PRERELEASE TRUE)
set(DFHACK_VERSION "${DF_VERSION}-${DFHACK_RELEASE}")

@ -14,7 +14,7 @@
Internals
Lua
New [Internal Commands | Plugins | Scripts | Features]
New [Internal Commands | Plugins | Scripts | Tweaks | Features]
Fixes
Misc Improvements
Removed
@ -35,17 +35,21 @@ Changelog
.. contents::
:depth: 2
DFHack future
=============
DFHack 0.43.05-r1
=================
Internals
---------
- 64-bit support on all platforms
- Visual Studio 2015 now required on Windows instead of 2010
- GCC 4.8 or newer required on Linux and OS X (and now supported on OS X)
- Several structure fixes to match 64-bit DF's memory layout
- Added ``DFHack::Job::removeJob()`` function
- New module: ``Designations`` - handles designation creation (currently for plants only)
- Added ``Gui::getSelectedPlant()``
- Added ``Units::getMainSocialActivity()``, ``Units::getMainSocialEvent()``
- Visual Studio 2015 now required to build on Windows instead of 2010
- GCC 4.8 or newer required to build on Linux and OS X (and now supported on OS X)
- Updated TinyXML from 2.5.3 to 2.6.2
- Added the ability to download files manually before building
Lua
---
@ -56,6 +60,8 @@ Lua
- ``df.new()`` supports more types: ``char``, ``intptr_t``, ``uintptr_t``, ``long``, ``unsigned long``
- String representations of vectors and a few other containers now include their lengths
- Added a ``tile-material`` module
- Added a ``Painter:key_string()`` method
- Made ``dfhack.gui.revealInDwarfmodeMap()`` available
Ruby
----
@ -71,34 +77,63 @@ New Plugins
New Scripts
-----------
- `adv-rumors`: improves the "Bring up specific incident or rumor" menu in adventure mode
- `fix/tile-occupancy`: Clears bad occupancy flags on the selected tile.
- `install-info`: Logs basic troubleshooting information about the current DFHack installation
- `load-save`: loads a save non-interactively
- `modtools/change-build-menu`: Edit the build mode sidebar menus
- `modtools/if-entity`: Run a command if the current entity matches a given ID
- `season-palette`: Swap color palettes with the changes of the seasons
- `unforbid`: Unforbids all items
New Tweaks
----------
- `tweak condition-material <tweak>`: fixes a crash in the work order condition material list
- `tweak hotkey-clear <tweak>`: adds an option to clear bindings from DF hotkeys
Fixes
-----
- The DF path on OS X can now contain spaces and ``:`` characters
- Buildings::setOwner() changes now persist properly when saved
- ``ls`` now lists scripts in folders other than ``hack/scripts``, when applicable
- Fixed ``plug`` output alignment for plugins with long names
- `add-thought`: fixed support for emotion names
- `autofarm`: Made surface farms detect local biome
- `autochop`:
- fixed several issues with job creation and removal
- stopped designating the center tile (unreachable) for large trees
- stopped options from moving when enabling and disabling burrows
- fixed display of unnamed burrows
- `devel/find-offsets`: fixed a crash when vtables used by globals aren't available
- `getplants`:
- fixed several issues with job creation and removal
- stopped designating the center tile (unreachable) for large trees
- `gui/workflow`: added extra keybinding to work with `gui/extended-status`
- `manipulator`:
- Fixed crash when selecting a profession from an empty list
- Custom professions are now sorted alphabetically more reliably
- `modtools/create-unit`: stopped permanently overwriting the creature creation
menu in arena mode
- `modtools/create-unit`:
- stopped permanently overwriting the creature creation menu in arena mode
- now uses non-English names
- `modtools/item-trigger`: fixed errors with plant growths
- `remotefortressreader`: fixed a crash when serializing the local map
- `title-version`: now hidden when loading an arena
Misc Improvements
-----------------
- Documented all default keybindings (from :file:`dfhack.init-example`) in the
docs for the relevant commands; updates enforced by build system.
- `autounsuspend`: reduced update frequency to address potential performance issues
- `gui/extended-status`: added a feature to queue beds
- `lua` and `gui/gm-editor` now support the same aliases (``scr``, ``unit``, etc.)
- `manipulator`: added social activities to job column
- `remotefortressreader`: Added support for
- world map snow coverage
@ -106,8 +141,11 @@ Misc Improvements
- wall info
- site towers, world buildings
- surface material
- building items
- DF version info
- `title-version`: Added a prerelease indicator
- `workflow`: Re-added ``Alt-W`` keybindings
DFHack 0.43.03-r1
=================

@ -18,4 +18,4 @@ if (-f $out_file and !exists($args{'--force'})) {
die "output file exists, not overwriting: \"$out_file\"";
}
gunzip $in_file => $out_file or die "gunzip failed: $GunzipError\n";
gunzip $in_file => $out_file, BinModeOut => 1 or die "gunzip failed: $GunzipError\n";

@ -135,6 +135,12 @@ keybinding add Alt-P@dwarfmode/Hauling/DefineStop/Cond/Guide gui/guide-path
# workshop job details
keybinding add Alt-A@dwarfmode/QueryBuilding/Some/Workshop/Job gui/workshop-job
# workflow front-end
keybinding add Alt-W@dwarfmode/QueryBuilding/Some/Workshop/Job gui/workflow
keybinding add Alt-W@overallstatus "gui/workflow status"
# equivalent to the one above when gui/extended-status is enabled
keybinding add Alt-W@dfhack/lua/status_overlay "gui/workflow status"
# autobutcher front-end
keybinding add Shift-B@pet/List/Unit "gui/autobutcher"
@ -184,6 +190,9 @@ tweak import-priority-category
# Fixes a crash in the work order contition material list (bug 9905).
tweak condition-material
# Adds an option to clear currently-bound hotkeys
tweak hotkey-clear
# Misc. UI tweaks
tweak block-labors # Prevents labors that can't be used from being toggled
tweak civ-view-agreement

@ -12,6 +12,7 @@ Name Github Other
8Z 8Z
acwatkins acwatkins
Alexander Gavrilov angavrilov ag
Amostubal Amostubal
AndreasPK AndreasPK
Angus Mezick amezick
Antalia tamarakorr
@ -75,6 +76,7 @@ Nick Rart nickrart comestible
Nikolay Amiantov abbradar
nocico nocico
Omniclasm
Paul Fenwick pjf
PeridexisErrant PeridexisErrant
Petr Mrázek peterix
potato
@ -87,7 +89,9 @@ rampaging-poet
Raoul van Putten
Raoul XQ raoulxq
reverb
Rich Rauenzahn rrauenza
Rinin Rinin
rndmvar rndmvar
Robert Heinrich rh73
Robert Janetzko robertjanetzko
rofl0r rofl0r
@ -107,6 +111,7 @@ Simon Jackson sizeak
stolencatkarma
sv-esk sv-esk
Tacomagic
TheHologram TheHologram
Tim Walberg twalberg
Timothy Collett danaris
Tom Jobbins TheBloke

@ -921,6 +921,10 @@ Gui module
Returns the building selected via :kbd:`q`, :kbd:`t`, :kbd:`k` or :kbd:`i`.
* ``dfhack.gui.getSelectedPlant([silent])``
Returns the plant selected via :kbd:`k`.
* ``dfhack.gui.writeToGamelog(text)``
Writes a string to :file:`gamelog.txt` without doing an announcement.

@ -37,6 +37,57 @@ Development Changelog
.. contents::
:depth: 2
DFHack 0.43.05-beta2
====================
Fixes
-----
- Fixed Buildings::updateBuildings(), along with building creation/deletion events
- Fixed ``plug`` output alignment for plugins with long names
- Fixed a crash that happened when a ``LUA_PATH`` environment variable was set
- `add-thought`: fixed number conversion
- `gui/workflow`: fixed range editing producing the wrong results for certain numbers
- `modtools/create-unit`: now uses non-English names
- `modtools/item-trigger`: fixed errors with plant growths
- `remotefortressreader`: fixed a crash when serializing the local map
- `stockflow`: fixed an issue with non-integer manager order limits
- `title-folder`: fixed compatibility issues with certain SDL libraries on macOS
Structures
----------
- Added some missing renderer VTable addresses on macOS
- ``entity.resources.organic``: identified ``parchment``
- ``entity_sell_category``: added ``Parchment`` and ``CupsMugsGoblets``
- ``ui_advmode_menu``: added ``Build``
- ``ui_unit_view_mode``: added ``PrefOccupation``
- ``unit_skill``: identified ``natural_skill_lvl`` (was ``unk_1c``)
- ``viewscreen_jobmanagementst``: identified ``max_workshops``
- ``viewscreen_overallstatusst``: made ``visible_pages`` an enum
- ``viewscreen_pricest``: identified fields
- ``viewscreen_workquota_conditionst``: gave some fields ``unk`` names
API Changes
-----------
- Allowed the Lua API to accept integer-like floats and strings when expecting an integer
- Lua: New ``Painter:key_string()`` method
- Lua: Added ``dfhack.getArchitecture()`` and ``dfhack.getArchitectureName()``
Additions/Removals:
-------------------
- Added `adv-rumors` script: improves the "Bring up specific incident or rumor" menu in adventure mode
- Added `install-info` script for basic troubleshooting
- Added `tweak condition-material <tweak>`: fixes a crash in the work order condition material list
- Added `tweak hotkey-clear <tweak>`: adds an option to clear bindings from DF hotkeys
- `autofarm`: reverted local biome detection (from 0.43.05-alpha3)
Other Changes
-------------
- Added a DOWNLOAD_RUBY CMake option, to allow use of a system/external ruby library
- Added the ability to download files manually before building
- `gui/extended-status`: added a feature to queue beds
- `remotefortressreader`: added building items, DF version info
- `stonesense`: Added support for 64-bit macOS and Linux
DFHack 0.43.05-beta1
====================

@ -287,6 +287,7 @@ Subcommands that persist until disabled or DF quits:
the current item (fully, in case of a stack), and scroll down one line.
:fps-min: Fixes the in-game minimum FPS setting
:hide-priority: Adds an option to hide designation priority indicators
:hotkey-clear: Adds an option to clear currently-bound hotkeys (in the :kbd:`H` menu)
:import-priority-category:
Allows changing the priority of all goods in a
category when discussing an import agreement with the liaison
@ -1656,13 +1657,14 @@ quotas.
Open the dashboard by running::
getplants autochop
enable autochop
The plugin must be activated (with ``c``) before it can be used. You can then set logging quotas
and restrict designations to specific burrows (with 'Enter') if desired. The plugin's activity
cycle runs once every in game day.
The plugin must be activated (with :kbd:`d`-:kbd:`t`-:kbd:`c`-:kbd:`a`) before
it can be used. You can then set logging quotas and restrict designations to
specific burrows (with 'Enter') if desired. The plugin's activity cycle runs
once every in game day.
If you add ``enable getplants`` to your dfhack.init there will be a hotkey to
If you add ``enable autochop`` to your dfhack.init there will be a hotkey to
open the dashboard from the chop designation menu.

@ -16,8 +16,6 @@ ENDIF()
include_directories (proto)
include_directories (include)
SET(PERL_EXECUTABLE "perl" CACHE FILEPATH "This is the perl executable to run in the codegen step. Tweak it if you need to run a specific one.")
execute_process(COMMAND ${PERL_EXECUTABLE} xml/list.pl xml ${dfapi_SOURCE_DIR}/include/df ";"
WORKING_DIRECTORY ${dfapi_SOURCE_DIR}
OUTPUT_VARIABLE GENERATED_HDRS)
@ -115,36 +113,39 @@ SET(MODULE_HEADERS
include/modules/Buildings.h
include/modules/Burrows.h
include/modules/Constructions.h
include/modules/Units.h
include/modules/Designations.h
include/modules/Engravings.h
include/modules/EventManager.h
include/modules/Filesystem.h
include/modules/Graphic.h
include/modules/Gui.h
include/modules/GuiHooks.h
include/modules/Items.h
include/modules/Job.h
include/modules/kitchen.h
include/modules/Maps.h
include/modules/MapCache.h
include/modules/Maps.h
include/modules/Materials.h
include/modules/Notes.h
include/modules/Once.h
include/modules/Random.h
include/modules/Renderer.h
include/modules/Screen.h
include/modules/Translation.h
include/modules/Units.h
include/modules/Vermin.h
include/modules/World.h
include/modules/Graphic.h
include/modules/Once.h
include/modules/Filesystem.h
)
SET( MODULE_SOURCES
modules/Buildings.cpp
modules/Burrows.cpp
modules/Constructions.cpp
modules/Units.cpp
modules/Designations.cpp
modules/Engravings.cpp
modules/EventManager.cpp
modules/Filesystem.cpp
modules/Graphic.cpp
modules/Gui.cpp
modules/Items.cpp
modules/Job.cpp
@ -153,16 +154,15 @@ modules/MapCache.cpp
modules/Maps.cpp
modules/Materials.cpp
modules/Notes.cpp
modules/Once.cpp
modules/Random.cpp
modules/Renderer.cpp
modules/Screen.cpp
modules/Translation.cpp
modules/Units.cpp
modules/Vermin.cpp
modules/World.cpp
modules/Graphic.cpp
modules/Windows.cpp
modules/Once.cpp
modules/Filesystem.cpp
modules/World.cpp
)
SET(STATIC_FIELDS_FILES)

@ -56,12 +56,15 @@ distribution.
#include "modules/Constructions.h"
#include "modules/Random.h"
#include "modules/Filesystem.h"
#include "modules/Designations.h"
#include "LuaWrapper.h"
#include "LuaTools.h"
#include "MiscUtils.h"
#include "df/activity_entry.h"
#include "df/activity_event.h"
#include "df/job.h"
#include "df/job_item.h"
#include "df/building.h"
@ -90,6 +93,7 @@ distribution.
#include "df/itemdef.h"
#include "df/enabler.h"
#include "df/feature_init.h"
#include "df/plant.h"
#include <lua.h>
#include <lauxlib.h>
@ -1449,6 +1453,7 @@ static const LuaWrapper::FunctionReg dfhack_gui_module[] = {
WRAPM(Gui, getSelectedUnit),
WRAPM(Gui, getSelectedItem),
WRAPM(Gui, getSelectedBuilding),
WRAPM(Gui, getSelectedPlant),
WRAPM(Gui, writeToGamelog),
WRAPM(Gui, makeAnnouncement),
WRAPM(Gui, addCombatReport),
@ -1457,6 +1462,7 @@ static const LuaWrapper::FunctionReg dfhack_gui_module[] = {
WRAPM(Gui, showZoomAnnouncement),
WRAPM(Gui, showPopupAnnouncement),
WRAPM(Gui, showAutoAnnouncement),
WRAPM(Gui, revealInDwarfmodeMap),
{ NULL, NULL }
};
@ -1580,6 +1586,8 @@ static const LuaWrapper::FunctionReg dfhack_units_module[] = {
WRAPM(Units, isUndead),
WRAPM(Units, isGelded),
WRAPM(Units, isDomesticated),
WRAPM(Units, getMainSocialActivity),
WRAPM(Units, getMainSocialEvent),
{ NULL, NULL }
};
@ -2309,6 +2317,27 @@ static const luaL_Reg dfhack_filesystem_funcs[] = {
{NULL, NULL}
};
/***** Designations module *****/
static const LuaWrapper::FunctionReg dfhack_designations_module[] = {
WRAPM(Designations, markPlant),
WRAPM(Designations, unmarkPlant),
WRAPM(Designations, canMarkPlant),
WRAPM(Designations, canUnmarkPlant),
WRAPM(Designations, isPlantMarked),
{NULL, NULL}
};
static int designations_getPlantDesignationTile(lua_State *state)
{
return Lua::PushPosXYZ(state, Designations::getPlantDesignationTile(Lua::CheckDFObject<df::plant>(state, 1)));
}
static const luaL_Reg dfhack_designations_funcs[] = {
{"getPlantDesignationTile", designations_getPlantDesignationTile},
{NULL, NULL}
};
/***** Internal module *****/
static void *checkaddr(lua_State *L, int idx, bool allow_null = false)
@ -2787,5 +2816,6 @@ void OpenDFHackApi(lua_State *state)
OpenModule(state, "constructions", dfhack_constructions_module);
OpenModule(state, "screen", dfhack_screen_module, dfhack_screen_funcs);
OpenModule(state, "filesystem", dfhack_filesystem_module, dfhack_filesystem_funcs);
OpenModule(state, "designations", dfhack_designations_module, dfhack_designations_funcs);
OpenModule(state, "internal", dfhack_internal_module, dfhack_internal_funcs);
}

@ -1,10 +1,10 @@
execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --long
execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --abbrev=8 --long
WORKING_DIRECTORY "${dfhack_SOURCE_DIR}"
OUTPUT_VARIABLE DFHACK_GIT_DESCRIPTION)
execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
WORKING_DIRECTORY "${dfhack_SOURCE_DIR}"
OUTPUT_VARIABLE DFHACK_GIT_COMMIT)
execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --exact-match
execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --abbrev=8 --exact-match
WORKING_DIRECTORY "${dfhack_SOURCE_DIR}"
RESULT_VARIABLE DFHACK_GIT_TAGGED_RESULT
OUTPUT_QUIET ERROR_QUIET)

@ -0,0 +1,21 @@
#pragma once
namespace df {
struct plant;
}
namespace DFHack {
namespace Designations {
// Mark or un-mark a plant (e.g. fell trees, gather plants)
// Return value indicates whether the plant's designation was changed or not
// (This can be false if markPlant() is called on an already-designated plant, for example)
DFHACK_EXPORT bool markPlant(const df::plant *plant);
DFHACK_EXPORT bool unmarkPlant(const df::plant *plant);
DFHACK_EXPORT bool canMarkPlant(const df::plant *plant);
DFHACK_EXPORT bool canUnmarkPlant(const df::plant *plant);
DFHACK_EXPORT bool isPlantMarked(const df::plant *plant);
// Return the tile that should be designated for this plant
DFHACK_EXPORT df::coord getPlantDesignationTile(const df::plant *plant);
}
}

@ -45,6 +45,7 @@ namespace df {
struct job;
struct unit;
struct item;
struct plant;
};
/**
@ -104,6 +105,11 @@ namespace DFHack
DFHACK_EXPORT df::building *getAnyBuilding(df::viewscreen *top);
DFHACK_EXPORT df::building *getSelectedBuilding(color_ostream &out, bool quiet = false);
// A plant is selected, e.g. via 'k'
DFHACK_EXPORT bool any_plant_hotkey(df::viewscreen *top);
DFHACK_EXPORT df::plant *getAnyPlant(df::viewscreen *top);
DFHACK_EXPORT df::plant *getSelectedPlant(color_ostream &out, bool quiet = false);
// Low-level API that gives full control over announcements and reports
DFHACK_EXPORT void writeToGamelog(std::string message);

@ -44,6 +44,7 @@ namespace df
struct item;
struct unit;
struct building;
struct plant;
}
/**
@ -326,10 +327,11 @@ namespace DFHack
virtual std::string getFocusString() = 0;
virtual void onShow() {};
virtual void onDismiss() {};
virtual df::unit *getSelectedUnit() { return NULL; }
virtual df::item *getSelectedItem() { return NULL; }
virtual df::job *getSelectedJob() { return NULL; }
virtual df::building *getSelectedBuilding() { return NULL; }
virtual df::unit *getSelectedUnit() { return nullptr; }
virtual df::item *getSelectedItem() { return nullptr; }
virtual df::job *getSelectedJob() { return nullptr; }
virtual df::building *getSelectedBuilding() { return nullptr; }
virtual df::plant *getSelectedPlant() { return nullptr; }
};
class DFHACK_EXPORT dfhack_lua_viewscreen : public dfhack_viewscreen {
@ -369,5 +371,6 @@ namespace DFHack
virtual df::item *getSelectedItem();
virtual df::job *getSelectedJob();
virtual df::building *getSelectedBuilding();
virtual df::plant *getSelectedPlant();
};
}

@ -41,6 +41,8 @@ distribution.
namespace df
{
struct activity_entry;
struct activity_event;
struct nemesis_record;
struct burrow;
struct identity;
@ -301,6 +303,10 @@ DFHACK_EXPORT int8_t getProfessionColor(df::unit *unit, bool ignore_noble = fals
DFHACK_EXPORT int8_t getCasteProfessionColor(int race, int caste, df::profession pid);
DFHACK_EXPORT std::string getSquadName(df::unit *unit);
DFHACK_EXPORT df::activity_entry *getMainSocialActivity(df::unit *unit);
DFHACK_EXPORT df::activity_event *getMainSocialEvent(df::unit *unit);
}
}
#endif

@ -144,14 +144,14 @@ function make_citizen(unit)
hf.caste = unit.caste
hf.sex = unit.sex
hf.appeared_year = dfg.cur_year
hf.born_year = unit.relations.birth_year
hf.born_seconds = unit.relations.birth_time
hf.curse_year = unit.relations.curse_year
hf.curse_seconds = unit.relations.curse_time
hf.anon_1 = unit.relations.anon_2
hf.anon_2 = unit.relations.anon_3
hf.old_year = unit.relations.old_year
hf.old_seconds = unit.relations.old_time
hf.born_year = unit.birth_year
hf.born_seconds = unit.birth_time
hf.curse_year = unit.curse_year
hf.curse_seconds = unit.curse_time
hf.birth_year_bias=unit.bias_birth_bias
hf.birth_time_bias=unit.birth_time_bias
hf.old_year = unit.old_year
hf.old_seconds = unit.old_time
hf.died_year = -1
hf.died_seconds = -1
hf.name:assign(unit.name)
@ -299,4 +299,4 @@ end
return _ENV
return _ENV

@ -635,6 +635,8 @@ function df_shortcut_var(k)
return dfhack.gui.getSelectedWorkshopJob()
elseif k == 'unit' then
return dfhack.gui.getSelectedUnit()
elseif k == 'plant' then
return dfhack.gui.getSelectedPlant()
else
for g in pairs(df.global) do
if g == k then

@ -0,0 +1,153 @@
#include "DataDefs.h"
#include "Error.h"
#include "modules/Designations.h"
#include "modules/Job.h"
#include "modules/Maps.h"
#include "df/job.h"
#include "df/map_block.h"
#include "df/plant.h"
#include "df/plant_tree_info.h"
#include "df/plant_tree_tile.h"
#include "df/tile_dig_designation.h"
#include "df/world.h"
using namespace DFHack;
using namespace df::enums;
using df::global::world;
static df::map_block *getPlantBlock(const df::plant *plant)
{
if (!world)
return nullptr;
return Maps::getTileBlock(Designations::getPlantDesignationTile(plant));
}
df::coord Designations::getPlantDesignationTile(const df::plant *plant)
{
CHECK_NULL_POINTER(plant);
if (!plant->tree_info)
return plant->pos;
int dimx = plant->tree_info->dim_x;
int dimy = plant->tree_info->dim_y;
int cx = dimx / 2;
int cy = dimy / 2;
// Find the southeast trunk tile
int x = cx;
int y = cy;
while (x + 1 < dimx && y + 1 < dimy)
{
if (plant->tree_info->body[0][(y * dimx) + (x + 1)].bits.trunk)
++x;
else if (plant->tree_info->body[0][((y + 1) * dimx) + x].bits.trunk)
++y;
else
break;
}
return df::coord(plant->pos.x - cx + x, plant->pos.y - cy + y, plant->pos.z);
}
bool Designations::isPlantMarked(const df::plant *plant)
{
CHECK_NULL_POINTER(plant);
df::coord des_pos = getPlantDesignationTile(plant);
df::map_block *block = Maps::getTileBlock(des_pos);
if (!block)
return false;
if (block->designation[des_pos.x % 16][des_pos.y % 16].bits.dig == tile_dig_designation::Default)
return true;
for (auto *link = world->job_list.next; link; link = link->next)
{
df::job *job = link->item;
if (!job)
continue;
if (job->job_type != job_type::FellTree && job->job_type != job_type::GatherPlants)
continue;
if (job->pos == des_pos)
return true;
}
return false;
}
bool Designations::canMarkPlant(const df::plant *plant)
{
CHECK_NULL_POINTER(plant);
if (!getPlantBlock(plant))
return false;
return !isPlantMarked(plant);
}
bool Designations::markPlant(const df::plant *plant)
{
CHECK_NULL_POINTER(plant);
if (canMarkPlant(plant))
{
df::coord des_pos = getPlantDesignationTile(plant);
df::map_block *block = Maps::getTileBlock(des_pos);
block->designation[des_pos.x % 16][des_pos.y % 16].bits.dig = tile_dig_designation::Default;
block->flags.bits.designated = true;
return true;
}
else
{
return false;
}
}
bool Designations::canUnmarkPlant(const df::plant *plant)
{
CHECK_NULL_POINTER(plant);
if (!getPlantBlock(plant))
return false;
return isPlantMarked(plant);
}
bool Designations::unmarkPlant(const df::plant *plant)
{
CHECK_NULL_POINTER(plant);
if (canUnmarkPlant(plant))
{
df::coord des_pos = getPlantDesignationTile(plant);
df::map_block *block = Maps::getTileBlock(des_pos);
block->designation[des_pos.x % 16][des_pos.y % 16].bits.dig = tile_dig_designation::No;
block->flags.bits.designated = true;
auto *link = world->job_list.next;
while (link)
{
auto *next = link->next;
df::job *job = link->item;
if (job &&
(job->job_type == job_type::FellTree || job->job_type == job_type::GatherPlants) &&
job->pos == des_pos)
{
Job::removeJob(job);
}
link = next;
}
return true;
}
else
{
return false;
}
}

@ -92,6 +92,7 @@ using namespace DFHack;
#include "df/game_mode.h"
#include "df/unit.h"
#include "df/occupation.h"
#include "df/plant.h"
using namespace df::enums;
using df::global::gview;
@ -1120,6 +1121,50 @@ df::building *Gui::getSelectedBuilding(color_ostream &out, bool quiet)
return building;
}
df::plant *Gui::getAnyPlant(df::viewscreen *top)
{
using df::global::cursor;
using df::global::ui;
using df::global::world;
if (auto dfscreen = dfhack_viewscreen::try_cast(top))
return dfscreen->getSelectedPlant();
if (Gui::dwarfmode_hotkey(top))
{
if (!cursor || !ui || !world)
return nullptr;
if (ui->main.mode == ui_sidebar_mode::LookAround)
{
for (df::plant *plant : world->plants.all)
{
if (plant->pos.x == cursor->x && plant->pos.y == cursor->y && plant->pos.z == cursor->z)
{
return plant;
}
}
}
}
return nullptr;
}
bool Gui::any_plant_hotkey(df::viewscreen *top)
{
return getAnyPlant(top) != nullptr;
}
df::plant *Gui::getSelectedPlant(color_ostream &out, bool quiet)
{
df::plant *plant = getAnyPlant(Core::getTopViewscreen());
if (!plant && !quiet)
out.printerr("No plant is selected in the UI.\n");
return plant;
}
//
DFHACK_EXPORT void Gui::writeToGamelog(std::string message)

@ -57,6 +57,7 @@ using namespace DFHack;
#include "df/job.h"
#include "df/building.h"
#include "df/renderer.h"
#include "df/plant.h"
using namespace df::enums;
using df::global::init;
@ -934,3 +935,11 @@ df::building *dfhack_lua_viewscreen::getSelectedBuilding()
safe_call_lua(do_notify, 1, 1);
return Lua::GetDFObject<df::building>(Lua::Core::State, -1);
}
df::plant *dfhack_lua_viewscreen::getSelectedPlant()
{
Lua::StackUnwinder frame(Lua::Core::State);
lua_pushstring(Lua::Core::State, "onGetSelectedPlant");
safe_call_lua(do_notify, 1, 1);
return Lua::GetDFObject<df::plant>(Lua::Core::State, -1);
}

@ -48,6 +48,7 @@ using namespace std;
#include "Core.h"
#include "MiscUtils.h"
#include "df/activity_entry.h"
#include "df/burrow.h"
#include "df/caste_raw.h"
#include "df/creature_raw.h"
@ -1831,6 +1832,24 @@ std::string Units::getSquadName(df::unit *unit)
return Translation::TranslateName(&squad->name, true);
}
df::activity_entry *Units::getMainSocialActivity(df::unit *unit)
{
CHECK_NULL_POINTER(unit);
if (unit->social_activities.empty())
return nullptr;
return df::activity_entry::find(unit->social_activities[unit->social_activities.size() - 1]);
}
df::activity_event *Units::getMainSocialEvent(df::unit *unit)
{
CHECK_NULL_POINTER(unit);
df::activity_entry *entry = getMainSocialActivity(unit);
if (!entry || entry->events.empty())
return nullptr;
return entry->events[entry->events.size() - 1];
}
bool Units::isMerchant(df::unit* unit)
{
CHECK_NULL_POINTER(unit);

@ -1 +1 @@
Subproject commit 9b834c089efb4657d43a8fa4f8f0822e8224e576
Subproject commit b48397cf5b4c954a098151943f7314a1a6eacf90

@ -10,24 +10,26 @@
#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/item_flags.h"
#include "df/items_other_id.h"
#include "df/job.h"
#include "df/map_block.h"
#include "df/plant.h"
#include "df/plant_raw.h"
#include "df/tile_dig_designation.h"
#include "df/ui.h"
#include "df/viewscreen_dwarfmodest.h"
#include "df/world.h"
#include "modules/Screen.h"
#include "modules/Maps.h"
#include "modules/Burrows.h"
#include "modules/World.h"
#include "modules/MapCache.h"
#include "modules/Designations.h"
#include "modules/Gui.h"
#include "modules/MapCache.h"
#include "modules/Maps.h"
#include "modules/Screen.h"
#include "modules/World.h"
#include <set>
@ -228,38 +230,33 @@ static int do_chop_designation(bool chop, bool count_only)
if (!count_only && !watchedBurrows.isValidPos(plant->pos))
continue;
bool dirty = false;
if (chop && cur->designation[x][y].bits.dig == tile_dig_designation::No)
if (chop && !Designations::isPlantMarked(plant))
{
if (count_only)
{
++count;
if (Designations::canMarkPlant(plant))
count++;
}
else
{
cur->designation[x][y].bits.dig = tile_dig_designation::Default;
dirty = true;
if (Designations::markPlant(plant))
count++;
}
}
if (!chop && cur->designation[x][y].bits.dig == tile_dig_designation::Default)
if (!chop && Designations::isPlantMarked(plant))
{
if (count_only)
{
++count;
if (Designations::canUnmarkPlant(plant))
count++;
}
else
{
cur->designation[x][y].bits.dig = tile_dig_designation::No;
dirty = true;
if (Designations::unmarkPlant(plant))
count++;
}
}
if (dirty)
{
cur->flags.bits.designated = true;
++count;
}
}
return count;
@ -390,10 +387,12 @@ public:
auto last_selected_index = burrows_column.highlighted_index;
burrows_column.clear();
for (auto iter = ui->burrows.list.begin(); iter != ui->burrows.list.end(); iter++)
for (df::burrow *burrow : ui->burrows.list)
{
df::burrow* burrow = *iter;
auto elem = ListEntry<df::burrow *>(burrow->name, burrow);
string name = burrow->name;
if (name.empty())
name = "Burrow " + int_to_string(burrow->id + 1);
auto elem = ListEntry<df::burrow *>(name, burrow);
elem.selected = watchedBurrows.isBurrowWatched(burrow);
burrows_column.add(elem);
}
@ -590,6 +589,7 @@ public:
if (burrows_column.getSelectedElems().size() > 0)
{
OutputString(COLOR_GREEN, x, y, "Will chop in selected burrows", true, left_margin);
++y;
}
else
{

@ -1,5 +1,7 @@
// (un)designate matching plants for gathering/cutting
#include <set>
#include "Core.h"
#include "Console.h"
#include "Export.h"
@ -7,18 +9,19 @@
#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/plant_raw.h"
#include "df/tile_dig_designation.h"
#include "df/world.h"
#include "modules/Designations.h"
#include "modules/Maps.h"
#include <set>
using std::string;
using std::vector;
using std::set;
using namespace DFHack;
using namespace df::enums;
@ -129,20 +132,14 @@ command_result df_getplants (color_ostream &out, vector <string> & parameters)
continue;
if (cur->designation[x][y].bits.hidden)
continue;
if (deselect && cur->designation[x][y].bits.dig == tile_dig_designation::Default)
if (deselect && Designations::unmarkPlant(plant))
{
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)
if (!deselect && Designations::markPlant(plant))
{
cur->designation[x][y].bits.dig = tile_dig_designation::Default;
dirty = true;
++count;
}
if (dirty)
cur->flags.bits.designated = true;
}
if (count)
out.print("Updated %d plant designations.\n", count);
@ -171,4 +168,4 @@ DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCom
DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{
return CR_OK;
}
}

@ -15,8 +15,9 @@
#include <set>
#include <algorithm>
#include <tuple>
#include <VTableInterpose.h>
#include "df/activity_event.h"
#include "df/world.h"
#include "df/ui.h"
#include "df/graphic.h"
@ -289,7 +290,8 @@ struct UnitInfo
int active_index;
string squad_effective_name;
string squad_info;
string job_info;
string job_desc;
enum { IDLE, SOCIAL, JOB } job_mode;
bool selected;
struct {
// Used for custom professions, 1-indexed
@ -363,16 +365,18 @@ bool sortBySquad (const UnitInfo *d1, const UnitInfo *d2)
bool sortByJob (const UnitInfo *d1, const UnitInfo *d2)
{
bool gt = false;
if (d1->job_mode != d2->job_mode)
{
if (descending)
return int(d1->job_mode) < int(d2->job_mode);
else
return int(d1->job_mode) > int(d2->job_mode);
}
if (d1->job_info == "Idle")
gt = false;
else if (d2->job_info == "Idle")
gt = true;
if (descending)
return d1->job_desc > d2->job_desc;
else
gt = (d1->job_info > d2->job_info);
return descending ? gt : !gt;
return d1->job_desc < d2->job_desc;
}
bool sortByStress (const UnitInfo *d1, const UnitInfo *d2)
@ -1234,9 +1238,18 @@ void viewscreen_unitlaborsst::refreshNames()
cur->profession = Units::getProfessionName(unit);
if (unit->job.current_job == NULL) {
cur->job_info = "Idle";
df::activity_event *event = Units::getMainSocialEvent(unit);
if (event) {
event->getName(unit->id, &cur->job_desc);
cur->job_mode = UnitInfo::SOCIAL;
}
else {
cur->job_desc = "Idle";
cur->job_mode = UnitInfo::IDLE;
}
} else {
cur->job_info = DFHack::Job::getName(unit->job.current_job);
cur->job_desc = DFHack::Job::getName(unit->job.current_job);
cur->job_mode = UnitInfo::JOB;
}
if (unit->military.squad_id > -1) {
cur->squad_effective_name = Units::getSquadName(unit);
@ -1283,7 +1296,7 @@ void viewscreen_unitlaborsst::calcSize()
if (detail_mode == DETAIL_MODE_SQUAD) {
detail_cmp = units[i]->squad_info.size();
} else if (detail_mode == DETAIL_MODE_JOB) {
detail_cmp = units[i]->job_info.size();
detail_cmp = units[i]->job_desc.size();
} else {
detail_cmp = units[i]->profession.size();
}
@ -1954,11 +1967,13 @@ void viewscreen_unitlaborsst::render()
fg = 11;
detail_str = cur->squad_info;
} else if (detail_mode == DETAIL_MODE_JOB) {
detail_str = cur->job_info;
if (detail_str == "Idle") {
fg = 14;
detail_str = cur->job_desc;
if (cur->job_mode == UnitInfo::IDLE) {
fg = COLOR_YELLOW;
} else if (cur->job_mode == UnitInfo::SOCIAL) {
fg = COLOR_LIGHTGREEN;
} else {
fg = 10;
fg = COLOR_LIGHTCYAN;
}
} else {
fg = cur->color;

@ -1 +1 @@
Subproject commit 1925760b2f611d246d1715a2e3cfb591a02ef00b
Subproject commit 1ffdc984d0c3d50e790b9ff5991c02fb21dec463

@ -90,6 +90,7 @@
#include "tweaks/fast-trade.h"
#include "tweaks/fps-min.h"
#include "tweaks/hide-priority.h"
#include "tweaks/hotkey-clear.h"
#include "tweaks/import-priority-category.h"
#include "tweaks/kitchen-keys.h"
#include "tweaks/kitchen-prefs-color.h"
@ -205,6 +206,8 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector <Plugi
" Fixes the in-game minimum FPS setting (bug 6277)\n"
" tweak hide-priority [disable]\n"
" Adds an option to hide designation priority indicators\n"
" tweak hotkey-clear [disable] \n"
" Adds an option to clear currently-bound hotkeys\n"
" tweak import-priority-category [disable]\n"
" When meeting with a liaison, makes Shift+Left/Right arrow adjust\n"
" the priority of an entire category of imports.\n"
@ -272,6 +275,9 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector <Plugi
TWEAK_HOOK("hide-priority", hide_priority_hook, feed);
TWEAK_HOOK("hide-priority", hide_priority_hook, render);
TWEAK_HOOK("hotkey-clear", hotkey_clear_hook, feed);
TWEAK_HOOK("hotkey-clear", hotkey_clear_hook, render);
TWEAK_HOOK("import-priority-category", takerequest_hook, feed);
TWEAK_HOOK("import-priority-category", takerequest_hook, render);

@ -0,0 +1,41 @@
#include "df/viewscreen_dwarfmodest.h"
using df::global::ui;
struct hotkey_clear_hook : df::viewscreen_dwarfmodest {
typedef df::viewscreen_dwarfmodest interpose_base;
DEFINE_VMETHOD_INTERPOSE(void, render, ())
{
INTERPOSE_NEXT(render)();
if (ui->main.mode == df::ui_sidebar_mode::Hotkeys)
{
int x = 26, y = 19;
OutputHotkeyString(x, y, "Clear", df::interface_key::CUSTOM_C, false, 0, COLOR_WHITE, COLOR_LIGHTRED);
}
}
DEFINE_VMETHOD_INTERPOSE(void, feed, (set<df::interface_key> *input))
{
if (ui->main.mode == df::ui_sidebar_mode::Hotkeys &&
input->count(df::interface_key::CUSTOM_C) &&
!ui->main.in_rename_hotkey)
{
auto &hotkey = ui->main.hotkeys[ui->main.selected_hotkey];
hotkey.name = "";
hotkey.cmd = df::ui_hotkey::T_cmd::None;
hotkey.x = 0;
hotkey.y = 0;
hotkey.z = 0;
hotkey.unit_id = 0;
hotkey.item_id = 0;
}
else
{
INTERPOSE_NEXT(feed)(input);
}
}
};
IMPLEMENT_VMETHOD_INTERPOSE(hotkey_clear_hook, feed);
IMPLEMENT_VMETHOD_INTERPOSE(hotkey_clear_hook, render);

@ -1 +1 @@
Subproject commit cf367974b5e1513d454b2988d45122e98cd28f52
Subproject commit e9c3119e751c3e2073eb02bbcda01d140cc6ae4a