Merge branch 'develop' into myk_docs

develop
Myk Taylor 2023-01-06 15:22:03 -08:00
commit 91df585bf8
No known key found for this signature in database
GPG Key ID: 8A39CA0FA0C16E78
161 changed files with 2268 additions and 1630 deletions

@ -195,8 +195,8 @@ if(NOT EXISTS ${dfhack_SOURCE_DIR}/library/xml/codegen.pl
endif()
# set up versioning.
set(DF_VERSION "0.50.03")
set(DFHACK_RELEASE "alpha0pre1")
set(DF_VERSION "50.05")
set(DFHACK_RELEASE "alpha0")
set(DFHACK_PRERELEASE TRUE)
set(DFHACK_VERSION "${DF_VERSION}-${DFHACK_RELEASE}")
@ -258,6 +258,7 @@ if(UNIX)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32 -march=i686")
endif()
string(REPLACE "-DNDEBUG" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
set(CMAKE_INSTALL_RPATH "hack")
elseif(MSVC)
# for msvc, tell it to always use 8-byte pointers to member functions to avoid confusion
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /vmg /vmm /MP")
@ -447,8 +448,6 @@ endif()
file(WRITE "${CMAKE_BINARY_DIR}/dfhack_setarch.txt" ${DFHACK_SETARCH})
install(FILES "${CMAKE_BINARY_DIR}/dfhack_setarch.txt" DESTINATION "${DFHACK_DATA_DESTINATION}")
install(DIRECTORY dfhack-config/ DESTINATION dfhack-config/default)
# build the plugins
if(BUILD_PLUGINS)
add_subdirectory(plugins)

@ -1,20 +1,23 @@
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/dfhack-config/
DESTINATION "${DFHACK_DATA_DESTINATION}/data/dfhack-config-defaults")
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/init/
DESTINATION "${DFHACK_DATA_DESTINATION}/init")
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/base_command_counts.json
DESTINATION "${DFHACK_DATA_DESTINATION}/data/base_command_counts.json")
DESTINATION "${DFHACK_DATA_DESTINATION}/data")
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/quickfort/
DESTINATION "${DFHACK_DATA_DESTINATION}/data/quickfort")
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/orders/
DESTINATION dfhack-config/orders/library)
DESTINATION "${DFHACK_DATA_DESTINATION}/data/orders")
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/examples/
DESTINATION "${DFHACK_DATA_DESTINATION}/examples")
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/art/
DESTINATION "${DFHACK_DATA_DESTINATION}/data/art")
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/professions/
DESTINATION dfhack-config/professions/library)
DESTINATION "${DFHACK_DATA_DESTINATION}/data/professions")
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/blueprints/
DESTINATION blueprints

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

@ -0,0 +1,8 @@
{
"hotkeys.menu": {
"enabled": true
},
"unsuspend.overlay": {
"enabled": true
}
}

@ -0,0 +1,7 @@
You can put scripts you write or download in this folder and DFHack will find
them.
If a script in this directory has the same name as a default DFHack script, the
script in this directory will take precedence.
Everything you add to this folder will be kept safe when you upgrade DFHack.

@ -1,9 +0,0 @@
# The DFHack Example Configuration File Library
This folder contains ready-to-use examples of various DFHack configuration
files. You can use them by copying them to appropriate folders where DFHack
and its plugins can find them. You can use them unmodified, or you can
customize them to better suit your preferences.
For information on each of the files in this library, see the
[DFHack Example Configuration File Guide](https://docs.dfhack.org/en/stable/docs/guides/examples-guide.html).

@ -20,7 +20,7 @@ keybinding add Ctrl-Shift-C hotkeys
keybinding add Ctrl-Shift-K gui/cp437-table
# an in-game init file editor
keybinding add Alt-S@title|dwarfmode/Default|dungeonmode gui/settings-manager
#keybinding add Alt-S@title|dwarfmode/Default|dungeonmode gui/settings-manager
######################
@ -28,142 +28,142 @@ keybinding add Alt-S@title|dwarfmode/Default|dungeonmode gui/settings-manager
######################
# quicksave, only in main dwarfmode screen and menu page
keybinding add Ctrl-Alt-S@dwarfmode/Default quicksave
#keybinding add Ctrl-Alt-S@dwarfmode/Default quicksave
# toggle the display of water level as 1-7 tiles
keybinding add Ctrl-W@dwarfmode|dungeonmode twaterlvl
# designate the whole vein for digging
keybinding add Ctrl-V@dwarfmode digv
keybinding add Ctrl-Shift-V@dwarfmode "digv x"
#keybinding add Ctrl-V@dwarfmode digv
#keybinding add Ctrl-Shift-V@dwarfmode "digv x"
# clean the selected tile of blood etc
keybinding add Ctrl-C spotclean
#keybinding add Ctrl-C spotclean
# destroy the selected item
keybinding add Ctrl-K@dwarfmode autodump-destroy-item
#keybinding add Ctrl-K@dwarfmode autodump-destroy-item
# destroy items designated for dump in the selected tile
keybinding add Ctrl-Shift-K@dwarfmode autodump-destroy-here
#keybinding add Ctrl-Shift-K@dwarfmode autodump-destroy-here
# apply blueprints to the map (Alt-F for compatibility with LNP Quickfort)
keybinding add Ctrl-Shift-Q@dwarfmode gui/quickfort
keybinding add Alt-F@dwarfmode gui/quickfort
#keybinding add Ctrl-Shift-Q@dwarfmode gui/quickfort
#keybinding add Alt-F@dwarfmode gui/quickfort
# show information collected by dwarfmonitor
keybinding add Alt-M@dwarfmode/Default "dwarfmonitor prefs"
keybinding add Ctrl-F@dwarfmode/Default "dwarfmonitor stats"
#keybinding add Alt-M@dwarfmode/Default "dwarfmonitor prefs"
#keybinding add Ctrl-F@dwarfmode/Default "dwarfmonitor stats"
# set the zone or cage under the cursor as the default
keybinding add Alt-Shift-I@dwarfmode/Zones "zone set"
#keybinding add Alt-Shift-I@dwarfmode/Zones "zone set"
# Stocks plugin
keybinding add Ctrl-Shift-Z@dwarfmode/Default "stocks show"
#keybinding add Ctrl-Shift-Z@dwarfmode/Default "stocks show"
# open an overview window summarising some stocks (dfstatus)
keybinding add Ctrl-Shift-I@dwarfmode/Default|dfhack/lua/dfstatus gui/dfstatus
#keybinding add Ctrl-Shift-I@dwarfmode/Default|dfhack/lua/dfstatus gui/dfstatus
# change quantity of manager orders
keybinding add Alt-Q@jobmanagement/Main gui/manager-quantity
#keybinding add Alt-Q@jobmanagement/Main gui/manager-quantity
# re-check manager orders
keybinding add Alt-R@jobmanagement/Main workorder-recheck
#keybinding add Alt-R@jobmanagement/Main workorder-recheck
# set workorder item details (on workorder details screen press D again)
keybinding add D@workquota_details gui/workorder-details
#keybinding add D@workquota_details gui/workorder-details
# view combat reports for the selected unit/corpse/spatter
keybinding add Ctrl-Shift-R@dwarfmode|unit|unitlist|joblist|dungeon_monsterstatus|layer_unit_relationship|item|workshop_profile|layer_noblelist|locations|pets|layer_overall_health|textviewer|reportlist|announcelist|layer_military|layer_unit_health|customize_unit|buildinglist|workshop_profile view-unit-reports
#keybinding add Ctrl-Shift-R@dwarfmode|unit|unitlist|joblist|dungeon_monsterstatus|layer_unit_relationship|item|workshop_profile|layer_noblelist|locations|pets|layer_overall_health|textviewer|reportlist|announcelist|layer_military|layer_unit_health|customize_unit|buildinglist|workshop_profile view-unit-reports
# view extra unit information
keybinding add Alt-I@dwarfmode/ViewUnits|unitlist gui/unit-info-viewer
#keybinding add Alt-I@dwarfmode/ViewUnits|unitlist gui/unit-info-viewer
# boost priority of jobs related to the selected entity
keybinding add Alt-N@dwarfmode|job|joblist|unit|unitlist|joblist|dungeon_monsterstatus|layer_unit_relationship|item|layer_noblelist|locations|pets|layer_overall_health|textviewer|reportlist|announcelist|layer_military|layer_unit_health|customize_unit|buildinglist|textviewer|item|layer_assigntrade|tradegoods|store|assign_display_item|treasurelist do-job-now
#keybinding add Alt-N@dwarfmode|job|joblist|unit|unitlist|joblist|dungeon_monsterstatus|layer_unit_relationship|item|layer_noblelist|locations|pets|layer_overall_health|textviewer|reportlist|announcelist|layer_military|layer_unit_health|customize_unit|buildinglist|textviewer|item|layer_assigntrade|tradegoods|store|assign_display_item|treasurelist do-job-now
# export a Dwarf's preferences screen in BBCode to post to a forum
keybinding add Ctrl-Shift-F@textviewer forum-dwarves
#keybinding add Ctrl-Shift-F@textviewer forum-dwarves
# q->stockpile - copy & paste stockpiles
keybinding add Alt-P@dwarfmode/QueryBuilding/Some/Stockpile copystock
#keybinding add Alt-P@dwarfmode/QueryBuilding/Some/Stockpile copystock
# q->stockpile - load and save stockpile settings out of game
keybinding add Alt-L@dwarfmode/QueryBuilding/Some/Stockpile "gui/stockpiles -load"
keybinding add Alt-S@dwarfmode/QueryBuilding/Some/Stockpile "gui/stockpiles -save"
#keybinding add Alt-L@dwarfmode/QueryBuilding/Some/Stockpile "gui/stockpiles -load"
#keybinding add Alt-S@dwarfmode/QueryBuilding/Some/Stockpile "gui/stockpiles -save"
# q->workshop - duplicate the selected job
keybinding add Ctrl-D job-duplicate
#keybinding add Ctrl-D job-duplicate
# materials: q->workshop; b->select items
keybinding add Shift-A "job-material ALUNITE"
keybinding add Shift-M "job-material MICROCLINE"
keybinding add Shift-D "job-material DACITE"
keybinding add Shift-R "job-material RHYOLITE"
keybinding add Shift-I "job-material CINNABAR"
keybinding add Shift-B "job-material COBALTITE"
keybinding add Shift-O "job-material OBSIDIAN"
keybinding add Shift-T "job-material ORTHOCLASE"
keybinding add Shift-G "job-material GLASS_GREEN"
#keybinding add Shift-A "job-material ALUNITE"
#keybinding add Shift-M "job-material MICROCLINE"
#keybinding add Shift-D "job-material DACITE"
#keybinding add Shift-R "job-material RHYOLITE"
#keybinding add Shift-I "job-material CINNABAR"
#keybinding add Shift-B "job-material COBALTITE"
#keybinding add Shift-O "job-material OBSIDIAN"
#keybinding add Shift-T "job-material ORTHOCLASE"
#keybinding add Shift-G "job-material GLASS_GREEN"
# sort units and items in the on-screen list
keybinding add Alt-Shift-N "sort-units name" "sort-items description"
keybinding add Alt-Shift-R "sort-units arrival"
keybinding add Alt-Shift-T "sort-units profession" "sort-items type material"
keybinding add Alt-Shift-Q "sort-units squad_position" "sort-items quality"
#keybinding add Alt-Shift-N "sort-units name" "sort-items description"
#keybinding add Alt-Shift-R "sort-units arrival"
#keybinding add Alt-Shift-T "sort-units profession" "sort-items type material"
#keybinding add Alt-Shift-Q "sort-units squad_position" "sort-items quality"
# browse linked mechanisms
keybinding add Ctrl-M@dwarfmode/QueryBuilding/Some gui/mechanisms
#keybinding add Ctrl-M@dwarfmode/QueryBuilding/Some gui/mechanisms
# browse rooms of same owner
keybinding add Alt-R@dwarfmode/QueryBuilding/Some gui/room-list
#keybinding add Alt-R@dwarfmode/QueryBuilding/Some gui/room-list
# interface for the liquids plugin - spawn water/magma/obsidian
keybinding add Alt-L@dwarfmode/LookAround gui/liquids
#keybinding add Alt-L@dwarfmode/LookAround gui/liquids
# machine power sensitive pressure plate construction
keybinding add Ctrl-Shift-M@dwarfmode/Build/Position/Trap gui/power-meter
#keybinding add Ctrl-Shift-M@dwarfmode/Build/Position/Trap gui/power-meter
# siege engine control
keybinding add Alt-A@dwarfmode/QueryBuilding/Some/SiegeEngine gui/siege-engine
#keybinding add Alt-A@dwarfmode/QueryBuilding/Some/SiegeEngine gui/siege-engine
# military weapon auto-select
keybinding add Ctrl-W@layer_military/Equip/Customize/View gui/choose-weapons
#keybinding add Ctrl-W@layer_military/Equip/Customize/View gui/choose-weapons
# military copy uniform
keybinding add Ctrl-C@layer_military/Uniforms gui/clone-uniform
#keybinding add Ctrl-C@layer_military/Uniforms gui/clone-uniform
# minecart Guide path
keybinding add Alt-P@dwarfmode/Hauling/DefineStop/Cond/Guide gui/guide-path
#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
#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"
#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"
#keybinding add Alt-W@dfhack/lua/status_overlay "gui/workflow status"
# autobutcher front-end
keybinding add Shift-B@pet/List/Unit gui/autobutcher
#keybinding add Shift-B@pet/List/Unit gui/autobutcher
# view pathable tiles from active cursor
keybinding add Alt-Shift-P@dwarfmode/LookAround gui/pathable
#keybinding add Alt-Shift-P@dwarfmode/LookAround gui/pathable
# gui/rename script - rename units and buildings
keybinding add Ctrl-Shift-N@dwarfmode|unit|unitlist|joblist|dungeon_monsterstatus|layer_unit_relationship|item|workshop_profile|layer_noblelist|locations|pets|layer_overall_health|textviewer|reportlist|announcelist|layer_military|layer_unit_health|customize_unit|buildinglist gui/rename
keybinding add Ctrl-Shift-T@dwarfmode|unit|unitlist|joblist|dungeon_monsterstatus|layer_unit_relationship|item|workshop_profile|layer_noblelist|locations|pets|layer_overall_health|textviewer|reportlist|announcelist|layer_military|layer_unit_health|customize_unit "gui/rename unit-profession"
#keybinding add Ctrl-Shift-N@dwarfmode|unit|unitlist|joblist|dungeon_monsterstatus|layer_unit_relationship|item|workshop_profile|layer_noblelist|locations|pets|layer_overall_health|textviewer|reportlist|announcelist|layer_military|layer_unit_health|customize_unit|buildinglist gui/rename
#keybinding add Ctrl-Shift-T@dwarfmode|unit|unitlist|joblist|dungeon_monsterstatus|layer_unit_relationship|item|workshop_profile|layer_noblelist|locations|pets|layer_overall_health|textviewer|reportlist|announcelist|layer_military|layer_unit_health|customize_unit "gui/rename unit-profession"
#####################
# adv mode bindings #
#####################
keybinding add Ctrl-A@dungeonmode/ConversationSpeak adv-rumors
keybinding add Ctrl-B@dungeonmode adv-bodyswap
keybinding add Ctrl-Shift-B@dungeonmode "adv-bodyswap force"
keybinding add Shift-O@dungeonmode gui/companion-order
keybinding add Ctrl-T@dungeonmode gui/advfort
#keybinding add Ctrl-A@dungeonmode/ConversationSpeak adv-rumors
#keybinding add Ctrl-B@dungeonmode adv-bodyswap
#keybinding add Ctrl-Shift-B@dungeonmode "adv-bodyswap force"
#keybinding add Shift-O@dungeonmode gui/companion-order
#keybinding add Ctrl-T@dungeonmode gui/advfort
#########################
@ -171,4 +171,4 @@ keybinding add Ctrl-T@dungeonmode gui/advfort
#########################
# export all information, or just the detailed maps (doesn't handle site maps)
keybinding add Ctrl-A@legends "exportlegends all"
#keybinding add Ctrl-A@legends "exportlegends all"

@ -9,7 +9,7 @@
############################
# stabilize the cursor of dwarfmode when switching menus
tweak stable-cursor
#tweak stable-cursor
# stop stacked liquid/bar/thread/cloth items from lasting forever
# if used in reactions that use only a fraction of the dimension.
@ -18,114 +18,116 @@ tweak stable-cursor
# make reactions requiring containers usable in advmode - the issue is
# that the screen asks for those reagents to be selected directly
tweak advmode-contained
#tweak advmode-contained
# support Shift-Enter in Trade and Move Goods to Depot screens for faster
# selection; it selects the current item or stack and scrolls down one line
tweak fast-trade
#tweak fast-trade
# stop the right list in military->positions from resetting to top all the time
tweak military-stable-assign
#tweak military-stable-assign
# in same list, color units already assigned to squads in brown & green
tweak military-color-assigned
#tweak military-color-assigned
# make crafted cloth items wear out with time like in old versions (bug 6003)
tweak craft-age-wear
#tweak craft-age-wear
# stop adamantine clothing from wearing out (bug 6481)
#tweak adamantine-cloth-wear
# Add "Select all" and "Deselect all" options to farm plot menus
tweak farm-plot-select
#tweak farm-plot-select
# Add Shift-Left/Right controls to import agreement screen
tweak import-priority-category
#tweak import-priority-category
# Fixes a crash in the work order contition material list (bug 9905).
tweak condition-material
#tweak condition-material
# Adds an option to clear currently-bound hotkeys
tweak hotkey-clear
#tweak hotkey-clear
# Allows lowercase letters in embark profile names, and allows exiting the name prompt without saving
tweak embark-profile-name
#tweak embark-profile-name
# Reduce performance impact of temperature changes
tweak fast-heat 100
#tweak fast-heat 100
# Misc. UI tweaks
tweak block-labors # Prevents labors that can't be used from being toggled
tweak burrow-name-cancel
tweak cage-butcher
tweak civ-view-agreement
tweak do-job-now
tweak eggs-fertile
tweak fps-min
tweak hide-priority
tweak kitchen-prefs-all
tweak kitchen-prefs-empty
tweak max-wheelbarrow
tweak partial-items
tweak shift-8-scroll
tweak stone-status-all
tweak title-start-rename
tweak tradereq-pet-gender
#tweak block-labors # Prevents labors that can't be used from being toggled
#tweak burrow-name-cancel
#tweak cage-butcher
#tweak civ-view-agreement
#tweak do-job-now
#tweak eggs-fertile
#tweak fps-min
#tweak hide-priority
#tweak kitchen-prefs-all
#tweak kitchen-prefs-empty
#tweak max-wheelbarrow
#tweak partial-items
#tweak shift-8-scroll
#tweak stone-status-all
#tweak title-start-rename
#tweak tradereq-pet-gender
###########################
# Globally acting plugins #
###########################
# Display DFHack version on title screen
enable title-version
#enable title-version
# Allow DFHack tools to overlay functionality and information on the DF screen
enable overlay
# Dwarf Manipulator (simple in-game Dwarf Therapist replacement)
enable manipulator
#enable manipulator
# Search tool in various screens (by falconne)
enable search
#enable search
# Improved build material selection interface (by falconne)
enable automaterial
#enable automaterial
# Other interface improvement tools
enable \
overlay \
confirm \
dwarfmonitor \
mousequery \
autogems \
autodump \
automelt \
autotrade \
buildingplan \
trackstop \
zone \
stocks \
autochop \
stockpiles
#enable \
# confirm \
# dwarfmonitor \
# mousequery \
# autogems \
# autodump \
# automelt \
# autotrade \
# buildingplan \
# trackstop \
# zone \
# stocks \
# autochop \
# stockpiles
#end a line with a backslash to make it continue to the next line. The \ is deleted for the final command.
# Multiline commands are ONLY supported for scripts like dfhack.init. You cannot do multiline command manually on the DFHack console.
# You cannot extend a commented line.
# You can comment out the extension of a line.
# enable mouse controls and sand indicator in embark screen
embark-tools enable sticky sand mouse
#embark-tools enable sticky sand mouse
# enable option to enter embark assistant
enable embark-assistant
#enable embark-assistant
###########
# Scripts #
###########
# write extra information to the gamelog
modtools/extra-gamelog enable
#modtools/extra-gamelog enable
# extended status screen (bedrooms page)
enable gui/extended-status
#enable gui/extended-status
# add information to item viewscreens
view-item-info enable
#view-item-info enable
# a replacement for the "load game" screen
gui/load-screen enable
#gui/load-screen enable

@ -1,17 +0,0 @@
{
"dwarfmonitor.date": {
"enabled": true
},
"dwarfmonitor.misery": {
"enabled": true
},
"dwarfmonitor.weather": {
"enabled": true
},
"hotkeys.menu": {
"enabled": true
},
"unsuspend.overlay": {
"enabled": true
}
}

@ -21,10 +21,11 @@ DFHack commands can be implemented in any of three ways:
same version of DFHack. They are less flexible than scripts,
but used for complex or ongoing tasks because they run faster.
:scripts: are Ruby or Lua scripts stored in ``hack/scripts/``.
Because they don't need to be compiled, scripts are
more flexible about versions, and easier to distribute.
Most third-party DFHack addons are scripts.
:scripts: are Ruby or Lua scripts stored in ``hack/scripts/`` or other
directories in the `script-paths`. Because they don't need to
be compiled, scripts are more flexible about versions, and
they are easier to distribute. Most third-party DFHack addons
are scripts.
All tools distributed with DFHack are documented `here <tools>`.
@ -37,6 +38,8 @@ DFHack commands can be executed in a number of ways:
#. Pressing a key combination set up with `keybinding`
#. From one of several `init-files`, automatically
#. Using `script` to run a batch of commands from a file
#. From an in-game command launcher interface like `gui/launcher`, the
`hotkeys` overlay widget, or `gui/quickcmd`.
The DFHack console
------------------
@ -144,7 +147,7 @@ save-specific init files in the save folders.
DFHack looks for init files in three places each time they could be run:
#. The :file:`dfhack-config/init` subdirectory in the main DF directory
#. :file:`data/save/{world}/raw`, where ``world`` is the current save, and
#. :file:`data/save/{world}/raw`, where ``{world}`` is the current save, and
#. :file:`data/save/{world}/raw/objects`
For each of those directories, all matching init files will be executed in
@ -171,7 +174,7 @@ dfhack\*.init
On startup, DFHack looks for files of the form ``dfhack*.init`` (where ``*`` is
a placeholder for any string, including the empty string).
These files are best used for keybindings and enabling persistent plugins
These files are best used for keybindings and enabling persistent tools
which do not require a world to be loaded.
@ -230,9 +233,10 @@ Script paths are folders that DFHack searches to find a script when a command is
run. By default, the following folders are searched, in order (relative to the
root DF folder):
1. :file:`data/save/{<region folder>}/raw/scripts` (only if a save is loaded)
2. :file:`raw/scripts`
3. :file:`hack/scripts`
#. :file:`dfhack-config/scripts`
#. :file:`data/save/{<region folder>}/raw/scripts` (only if a save is loaded)
#. :file:`raw/scripts`
#. :file:`hack/scripts`
For example, if ``teleport`` is run, these folders are searched in order for
``teleport.lua`` or ``teleport.rb``, and the first matching file is run.

@ -38,17 +38,24 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
## Fixes
## Misc Improvements
- Scrollable widgets now react to mouse wheel events when the mouse is over the widget
- the ``dfhack-config/scripts/`` folder is now searched for scripts by default
- `hotkeys`: overlay hotspot widget now shows the DFHack logo in graphics mode and "DFHack" in text mode
## Documentation
- `overlay-dev-guide`: added troubleshooting tips and common development workflows
- added DFHack architecture diagrams to the dev intro
## API
- ``Gui::getDwarfmodeDims``: now only returns map viewport dimensions; menu dimensions are obsolete
- ``Gui::getDFViewscreen``: returns the topmost underlying DF viewscreen
## Lua
- ``gui.View``: ``visible`` and ``active`` can now be functions that return a boolean
- ``widgets.Panel``: new attributes to control window dragging and resizing with mouse or keyboard
- ``widgets.Window``: Panel subclass with attributes preset for top-level windows
- `overlay`: ``OverlayWidget`` now inherits from ``Panel`` instead of ``Widget`` to get all the frame and mouse integration goodies
- ``dfhack.gui.getDFViewscreen()``: returns the topmost underlying DF viewscreen
## Internals

@ -965,6 +965,11 @@ Screens
the specified type (e.g. ``df.viewscreen_titlest``), or ``nil`` if none match.
If ``depth`` is not specified or is less than 1, all viewscreens are checked.
* ``dfhack.gui.getDFViewscreen([skip_dismissed])``
Returns the topmost viewscreen not owned by DFHack. If ``skip_dismissed`` is
``true``, ignores screens already marked to be removed.
General-purpose selections
~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -1011,7 +1016,7 @@ Fortress mode
* ``dfhack.gui.getDwarfmodeViewDims()``
Returns dimensions of the main fortress mode screen. See ``getPanelLayout()``
Returns dimensions of the displayed map viewport. See ``getPanelLayout()``
in the ``gui.dwarfmode`` module for a more Lua-friendly version.
* ``dfhack.gui.resetDwarfmodeView([pause])``
@ -1121,7 +1126,8 @@ Other
* ``dfhack.gui.getDepthAt(x, y)``
Returns the distance from the z-level of the tile at map coordinates (x, y) to
the closest ground z-level below. Defaults to 0, unless overridden by plugins.
the closest rendered ground z-level below. Defaults to 0, unless overridden by
plugins.
Job module
----------
@ -2161,7 +2167,14 @@ Functions:
* ``dfhack.screen.getMousePos()``
Returns *x,y* of the tile the mouse is over.
Returns *x,y* of the UI interface tile the mouse is over, with the upper left
corner being ``0,0``. To get the map tile coordinate that the mouse is over,
see ``dfhack.gui.getMousePos()``.
* ``dfhack.screen.getMousePixels()``
Returns *x,y* of the screen coordinates the mouse is over in pixels, with the
upper left corner being ``0,0``.
* ``dfhack.screen.inGraphicsMode()``
@ -2355,7 +2368,14 @@ Supported callbacks and fields are:
where the above painting functions work correctly.
If omitted, the screen is cleared; otherwise it should do that itself.
In order to make a see-through dialog, call ``self._native.parent:render()``.
In order to make a dialog where portions of the parent viewscreen are still
visible in the background, call ``screen:renderParent()``.
If artifacts are left on the parent even after this function is called, such
as when the window is dragged or is resized, any code can set
``gui.Screen.request_full_screen_refresh`` to ``true``. Then when
``screen.renderParent()`` is next called, it will do a full flush of the
graphics and clear the screen of artifacts.
* ``function screen:onIdle()``
@ -2377,13 +2397,13 @@ Supported callbacks and fields are:
``_STRING``
Maps to an integer in range 0-255. Duplicates a separate "STRING_A???" code for convenience.
``_MOUSE_L, _MOUSE_R``
If the left or right mouse button is being pressed.
``_MOUSE_L, _MOUSE_R, _MOUSE_M``
If the left, right, and/or middle mouse button is being pressed.
``_MOUSE_L_DOWN, _MOUSE_R_DOWN``
If the left or right mouse button was just pressed.
``_MOUSE_L_DOWN, _MOUSE_R_DOWN, _MOUSE_M_DOWN``
If the left, right, and/or middle mouse button was just pressed.
If this method is omitted, the screen is dismissed on receival of the ``LEAVESCREEN`` key.
If this method is omitted, the screen is dismissed on reception of the ``LEAVESCREEN`` key.
* ``function screen:onGetSelectedUnit()``
* ``function screen:onGetSelectedItem()``
@ -2614,8 +2634,8 @@ and are only documented here for completeness:
Registers ``path`` as a `script path <script-paths>`.
If ``search_before`` is passed and ``true``, the path will be searched before
the default paths (e.g. ``raw/scripts``, ``hack/scripts``); otherwise, it will
be searched after.
the default paths (e.g. ``dfhack-config/scripts``, ``hack/scripts``); otherwise,
it will be searched after.
Returns ``true`` if successful or ``false`` otherwise (e.g. if the path does
not exist or has already been registered).
@ -3632,11 +3652,6 @@ considered stable.
Misc
----
* ``USE_GRAPHICS``
Contains the value of ``dfhack.screen.inGraphicsMode()``, which cannot be
changed without restarting the game and thus is constant during the session.
* ``CLEAR_PEN``
The black pen used to clear the screen.
@ -4144,6 +4159,8 @@ Base of all the widgets. Inherits from View and has the following attributes:
The pen to fill the outer frame with. Defaults to no fill.
.. _panel:
Panel class
-----------
@ -4306,7 +4323,6 @@ Attributes:
If it returns false, the character is ignored.
:on_change: Change notification callback; used as ``on_change(new_text,old_text)``.
:on_submit: Enter key callback; if set the field will handle the key and call ``on_submit(text)``.
:on_submit2: Shift-Enter key callback; if set the field will handle the key and call ``on_submit2(text)``.
:key: If specified, the field is disabled until this key is pressed. Must be given as a string.
:key_sep: If specified, will be used to customize how the activation key is
displayed. See ``token.key_sep`` in the ``Label`` documentation below.
@ -4336,21 +4352,36 @@ You can click where you want the cursor to move or you can use any of the
following keyboard hotkeys:
- Left/Right arrow: move the cursor one character to the left or right.
- Ctrl-Left/Right arrow: move the cursor one word to the left or right.
- Alt-Left/Right arrow: move the cursor to the beginning/end of the text.
- Ctrl-B/Ctrl-F: move the cursor one word back or forward.
- Ctrl-A/Ctrl-E: move the cursor to the beginning/end of the text.
The ``EditField`` class also provides the following functions:
* ``editfield:setCursor([cursor_pos])``
Sets the text insert cursor to the specified position. If ``cursor_pos`` is
not specified or is past the end of the current text string, the cursor will
be set to the end of the current input (that is, ``#editfield.text + 1``).
* ``editfield:setText(text[, cursor_pos])``
Sets the input text string and, optionally, the cursor position. If the
cursor position is not specified, it sets it to the end of the string.
* ``editfield:insert(text)``
Inserts the given text at the current cursor position.
Scrollbar class
---------------
This Widget subclass implements mouse-interactive scrollbars whose bar sizes
represent the amount of content currently visible in an associated display
widget (like a `Label class`_ or a `List class`_). By default they are styled
like scrollbars used in the vanilla DF help screens, but they are configurable.
widget (like a `Label class`_ or a `List class`_). They are styled like scrollbars
used in vanilla DF.
Scrollbars have the following attributes:
:fg: Specifies the pen for the scroll icons and the active part of the bar. Default is ``COLOR_LIGHTGREEN``.
:bg: Specifies the pen for the background part of the scrollbar. Default is ``COLOR_CYAN``.
:on_scroll: A callback called when the scrollbar is scrolled. If the scrollbar is clicked,
the callback will be called with one of the following string parameters: "up_large",
"down_large", "up_small", or "down_small". If the scrollbar is dragged, the callback will
@ -4377,6 +4408,10 @@ direction. The amount of scrolling done in each case in determined by the
associated widget, and after scrolling is complete, the associated widget must
call ``scrollbar:update()`` with updated new display info.
If the mouse wheel is scrolled while the mouse is over the Scrollbar widget's
parent view, then the parent is scrolled accordingly. Holding :kbd:`Shift`
while scrolling will result in faster movement.
You can click and drag the scrollbar to scroll to a specific spot, or you can
click and hold on the end arrows or in the unfilled portion of the scrollbar to
scroll multiple times, just like in a normal browser scrollbar. The speed of
@ -4621,8 +4656,8 @@ It has the following attributes:
with an empty list.
:on_submit: Enter key or mouse click callback; if specified, the list reacts to the
key/click and calls the callback as ``on_submit(index,choice)``.
:on_submit2: Shift-Enter key or shift-mouse click callback; if specified, the list
reacts to the key/click and calls it as ``on_submit2(index,choice)``.
:on_submit2: Shift-click callback; if specified, the list reacts to the click and
calls the callback as ``on_submit2(index,choice)``.
:row_height: Height of every row in text lines.
:icon_width: If not *nil*, the specified number of character columns
are reserved to the left of the list item for the icons.
@ -5455,11 +5490,11 @@ Scripts
:local:
Any files with the ``.lua`` extension placed into the :file:`hack/scripts` folder
are automatically made available as DFHack commands. The command corresponding to
a script is simply the script's filename, relative to the scripts folder, with
the extension omitted. For example:
(or any other folder in your `script-paths`) are automatically made available as
DFHack commands. The command corresponding to a script is simply the script's
filename, relative to the scripts folder, with the extension omitted. For example:
* :file:`hack/scripts/add-thought.lua` is invoked as ``add-thought``
* :file:`dfhack-config/scripts/startup.lua` is invoked as ``startup``
* :file:`hack/scripts/gui/teleport.lua` is invoked as ``gui/teleport``
.. note::
@ -5476,12 +5511,6 @@ the extension omitted. For example:
a mod developer would want to run a script from the console, it should
not be placed in this folder)
Scripts can also be placed in other folders - by default, these include
:file:`raw/scripts` and :file:`data/save/{region}/raw/scripts`, but additional
folders can be added (for example, a copy of the
:source-scripts:`scripts repository <>` for local development). See
`script-paths` for more information on how to configure this behavior.
Scripts are read from disk when run for the first time, or if they have changed
since the last time they were run.
@ -5509,7 +5538,7 @@ General script API
* ``dfhack.run_script(name[,args...])``
Run a Lua script in :file:`hack/scripts/`, as if it were started from the
Run a Lua script in your `script-paths`, as if it were started from the
DFHack command-line. The ``name`` argument should be the name of the script
without its extension, as it would be used on the command line.
@ -5551,8 +5580,8 @@ Importing scripts
Loads a Lua script and returns its environment (i.e. a table of all global
functions and variables). This is similar to the built-in ``require()``, but
searches all script paths for the first matching ``name.lua`` file instead
of searching the Lua library paths (like ``hack/lua``).
searches all `script-paths` for the first matching ``name.lua`` file instead
of searching the Lua library paths (like ``hack/lua/``).
Most scripts can be made to support ``reqscript()`` without significant
changes (in contrast, ``require()`` requires the use of ``mkmodule()`` and

@ -38,7 +38,7 @@ Overlay widget API
------------------
Overlay widgets are Lua classes that inherit from ``overlay.OverlayWidget``
(which itself inherits from `widgets.Widget <widget>`). The regular
(which itself inherits from `widgets.Panel <panel>`). The regular
``onInput(keys)``, ``onRenderFrame(dc, frame_rect)``, and ``onRenderBody(dc)``
functions work as normal, and they are called when the viewscreen that the
widget is associated with does its usual input and render processing. The widget
@ -125,6 +125,10 @@ The ``overlay.OverlayWidget`` superclass defines the following class attributes:
not annoy the player. Set to 0 to be called at the maximum rate. Be aware
that running more often than you really need to will impact game FPS,
especially if your widget can run while the game is unpaused.
- ``always_enabled`` (default: ``false``)
Set this to ``true`` if you don't want to let the user disable the widget.
This is useful for widgets that are controlled purely through their
triggers. See `gui/pathable` for an example.
Registering a widget with the overlay framework
***********************************************

@ -60,9 +60,10 @@ For scripts with the same name, the `order of precedence <script-paths>` will
be:
1. ``own-scripts/``
2. ``data/save/*/raw/scripts/``
3. ``raw/scripts/``
4. ``hack/scripts/``
2. ``dfhack-config/scripts/``
3. ``data/save/*/raw/scripts/``
4. ``raw/scripts/``
5. ``hack/scripts/``
The structure of the game
-------------------------

@ -12,7 +12,7 @@ watch list. Units will be ignored if they are:
* Untamed
* Nicknamed (for custom protection; you can use the `rename` ``unit`` tool
individually, or `zone` ``nick`` for groups)
* Caged, if and only if the cage is defined as a room (to protect zoos)
* Caged, if and only if the cage is in a zone (to protect zoos)
* Trained for war or hunting
Creatures who will not reproduce (because they're not interested in the

@ -7,4 +7,4 @@ pathable
:no-command:
This plugin provides a Lua API, but no direct commands. See `pathable-api` for
details.
details and `gui/pathable` for the user interface.

@ -96,6 +96,7 @@ endif()
set(MAIN_SOURCES_WINDOWS
${CONSOLE_SOURCES}
Hooks-windows.cpp
Hooks.cpp
PlugLoad-windows.cpp
Process-windows.cpp
)
@ -123,6 +124,7 @@ set(MODULE_HEADERS
include/modules/Buildings.h
include/modules/Burrows.h
include/modules/Constructions.h
include/modules/DFSDL.h
include/modules/Designations.h
include/modules/EventManager.h
include/modules/Filesystem.h
@ -140,6 +142,7 @@ set(MODULE_HEADERS
include/modules/Random.h
include/modules/Renderer.h
include/modules/Screen.h
include/modules/Textures.h
include/modules/Translation.h
include/modules/Units.h
include/modules/World.h
@ -149,6 +152,7 @@ set(MODULE_SOURCES
modules/Buildings.cpp
modules/Burrows.cpp
modules/Constructions.cpp
modules/DFSDL.cpp
modules/Designations.cpp
modules/EventManager.cpp
modules/Filesystem.cpp
@ -165,6 +169,7 @@ set(MODULE_SOURCES
modules/Random.cpp
modules/Renderer.cpp
modules/Screen.cpp
modules/Textures.cpp
modules/Translation.cpp
modules/Units.cpp
modules/World.cpp
@ -374,6 +379,8 @@ if(WIN32)
else()
set_target_properties(dfhack PROPERTIES COMPILE_FLAGS "-include Export.h" )
set_target_properties(dfhack-client PROPERTIES COMPILE_FLAGS "-include Export.h" )
add_library(dfhooks SHARED Hooks.cpp)
target_link_libraries(dfhooks dfhack)
endif()
# effectively disables debug builds...
@ -422,6 +429,9 @@ if(UNIX)
install(PROGRAMS ${dfhack_SOURCE_DIR}/package/linux/dfhack-run
DESTINATION .)
endif()
install(TARGETS dfhooks
LIBRARY DESTINATION .
RUNTIME DESTINATION .)
else()
# On windows, copy the renamed SDL so DF can still run.
install(PROGRAMS ${dfhack_SOURCE_DIR}/package/windows/win${DFHACK_BUILD_ARCH}/SDLreal.dll

@ -49,9 +49,11 @@ using namespace std;
#include "VersionInfo.h"
#include "PluginManager.h"
#include "ModuleFactory.h"
#include "modules/DFSDL.h"
#include "modules/EventManager.h"
#include "modules/Filesystem.h"
#include "modules/Gui.h"
#include "modules/Textures.h"
#include "modules/World.h"
#include "modules/Persistence.h"
#include "RemoteServer.h"
@ -63,8 +65,8 @@ using namespace std;
using namespace DFHack;
#include "df/ui.h"
#include "df/ui_sidebar_menus.h"
#include "df/plotinfost.h"
#include "df/gamest.h"
#include "df/world.h"
#include "df/world_data.h"
#include "df/interfacest.h"
@ -104,6 +106,9 @@ namespace DFHack {
DBG_DECLARE(core,keybinding,DebugCategory::LINFO);
DBG_DECLARE(core,script,DebugCategory::LINFO);
static const std::string CONFIG_PATH = "dfhack-config/";
static const std::string CONFIG_DEFAULTS_PATH = "hack/data/dfhack-config-defaults/";
class MainThread {
public:
//! MainThread::suspend keeps the main DF thread suspended from Core::Init to
@ -484,9 +489,10 @@ void Core::getScriptPaths(std::vector<std::string> *dest)
{
lock_guard<mutex> lock(script_path_mutex);
dest->clear();
string df_path = this->p->getPath();
string df_path = this->p->getPath() + "/";
for (auto it = script_paths[0].begin(); it != script_paths[0].end(); ++it)
dest->push_back(*it);
dest->push_back(df_path + CONFIG_PATH + "scripts");
if (df::global::world && isWorldLoaded()) {
string save = World::ReadWorldFolder();
if (save.size())
@ -515,7 +521,7 @@ string Core::findScript(string name)
bool loadScriptPaths(color_ostream &out, bool silent = false)
{
using namespace std;
string filename("dfhack-config/script-paths.txt");
string filename(CONFIG_PATH + "script-paths.txt");
ifstream file(filename);
if (!file)
{
@ -1014,10 +1020,12 @@ command_result Core::runCommand(color_ostream &con, const std::string &first_, v
else if (first == "fpause")
{
World::SetPauseState(true);
/* TODO: understand how this changes for v50
if (auto scr = Gui::getViewscreenByType<df::viewscreen_new_regionst>())
{
scr->worldgen_paused = true;
}
*/
con.print("The game was forced to pause!\n");
}
else if (first == "cls" || first == "clear")
@ -1299,18 +1307,18 @@ bool Core::loadScriptFile(color_ostream &out, string fname, bool silent)
static void run_dfhack_init(color_ostream &out, Core *core)
{
CoreSuspender lock;
if (!df::global::world || !df::global::ui || !df::global::gview)
if (!df::global::world || !df::global::plotinfo || !df::global::gview)
{
out.printerr("Key globals are missing, skipping loading dfhack.init.\n");
return;
}
// load baseline defaults
core->loadScriptFile(out, "dfhack-config/init/default.dfhack.init", false);
core->loadScriptFile(out, CONFIG_PATH + "init/default.dfhack.init", false);
// load user overrides
std::vector<std::string> prefixes(1, "dfhack");
loadScriptFiles(core, out, prefixes, "dfhack-config/init");
loadScriptFiles(core, out, prefixes, CONFIG_PATH + "init");
}
// Load dfhack.init in a dedicated thread (non-interactive console mode)
@ -1326,14 +1334,14 @@ void fInitthread(void * iodata)
// A thread function... for the interactive console.
void fIOthread(void * iodata)
{
static const char * HISTORY_FILE = "dfhack-config/dfhack.history";
static const std::string HISTORY_FILE = CONFIG_PATH + "dfhack.history";
IODATA * iod = ((IODATA*) iodata);
Core * core = iod->core;
PluginManager * plug_mgr = ((IODATA*) iodata)->plug_mgr;
CommandHistory main_history;
main_history.load(HISTORY_FILE);
main_history.load(HISTORY_FILE.c_str());
Console & con = core->getConsole();
if (plug_mgr == 0)
@ -1374,7 +1382,7 @@ void fIOthread(void * iodata)
{
// a proper, non-empty command was entered
main_history.add(command);
main_history.save(HISTORY_FILE);
main_history.save(HISTORY_FILE.c_str());
}
auto rv = core->runCommand(con, command);
@ -1479,11 +1487,14 @@ bool Core::Init()
// make it obvious what's going on if someone checks the *.txt files.
#ifndef LINUX_BUILD
// Don't do this on Linux because it will break PRINT_MODE:TEXT
// this is handled as appropriate in Console-posix.cpp
fprintf(stdout, "dfhack: redirecting stdout to stdout.log (again)\n");
fprintf(stderr, "dfhack: redirecting stderr to stderr.log (again)\n");
freopen("stdout.log", "w", stdout);
freopen("stderr.log", "w", stderr);
if (!freopen("stdout.log", "w", stdout))
cerr << "Could not redirect stdout to stdout.log" << endl;
#endif
fprintf(stderr, "dfhack: redirecting stderr to stderr.log\n");
if (!freopen("stderr.log", "w", stderr))
cerr << "Could not redirect stderr to stderr.log" << endl;
Filesystem::init();
@ -1606,46 +1617,44 @@ bool Core::Init()
// initialize data defs
virtual_identity::Init(this);
// create config directory if it doesn't already exist
if (!Filesystem::mkdir_recursive(CONFIG_PATH))
con.printerr("Failed to create config directory: '%s'\n", CONFIG_PATH.c_str());
// copy over default config files if necessary
std::map<std::string, bool> config_files;
std::map<std::string, bool> default_config_files;
if (Filesystem::listdir_recursive("dfhack-config", config_files, 10, false) != 0)
con.printerr("Failed to list directory: dfhack-config");
else if (Filesystem::listdir_recursive("dfhack-config/default", default_config_files, 10, false) != 0)
con.printerr("Failed to list directory: dfhack-config/default");
if (Filesystem::listdir_recursive(CONFIG_PATH, config_files, 10, false) != 0)
con.printerr("Failed to list directory: '%s'\n", CONFIG_PATH.c_str());
else if (Filesystem::listdir_recursive(CONFIG_DEFAULTS_PATH, default_config_files, 10, false) != 0)
con.printerr("Failed to list directory: '%s'\n", CONFIG_DEFAULTS_PATH.c_str());
else
{
// ensure all config file directories exist before we start copying files
for (auto it = default_config_files.begin(); it != default_config_files.end(); ++it)
{
for (auto &entry : default_config_files) {
// skip over files
if (!it->second)
if (!entry.second)
continue;
std::string dirname = "dfhack-config/" + it->first;
std::string dirname = CONFIG_PATH + entry.first;
if (!Filesystem::mkdir_recursive(dirname))
{
con.printerr("Failed to create config directory: '%s'\n", dirname.c_str());
}
}
// copy files from the default tree that don't already exist in the config tree
for (auto it = default_config_files.begin(); it != default_config_files.end(); ++it)
{
for (auto &entry : default_config_files) {
// skip over directories
if (it->second)
if (entry.second)
continue;
std::string filename = it->first;
if (config_files.find(filename) == config_files.end())
{
std::string src_file = std::string("dfhack-config/default/") + filename;
std::string filename = entry.first;
if (!config_files.count(filename)) {
std::string src_file = CONFIG_DEFAULTS_PATH + filename;
if (!Filesystem::isfile(src_file))
continue;
std::string dest_file = std::string("dfhack-config/") + filename;
std::string dest_file = CONFIG_PATH + filename;
std::ifstream src(src_file, std::ios::binary);
std::ofstream dest(dest_file, std::ios::binary);
if (!src.good() || !dest.good())
{
con.printerr("Copy failed: %s\n", filename.c_str());
if (!src.good() || !dest.good()) {
con.printerr("Copy failed: '%s'\n", filename.c_str());
continue;
}
dest << src.rdbuf();
@ -1664,8 +1673,15 @@ bool Core::Init()
return false;
}
cerr << "Binding to SDL.\n";
if (!DFSDL::init(con)) {
fatal("cannot bind SDL libraries");
return false;
}
cerr << "Initializing textures.\n";
Textures::init(con);
// create mutex for syncing with interactive tasks
cerr << "Initializing Plugins.\n";
cerr << "Initializing plugins.\n";
// create plugin manager
plug_mgr = new PluginManager(this);
plug_mgr->init();
@ -1696,10 +1712,10 @@ bool Core::Init()
if (!listen.get())
cerr << "TCP listen failed.\n";
if (df::global::ui_sidebar_menus)
if (df::global::game)
{
vector<string> args;
const string & raw = df::global::ui_sidebar_menus->command_line.original;
const string & raw = df::global::game->command_line.original;
size_t offset = 0;
while (offset < raw.size())
{
@ -1758,6 +1774,9 @@ bool Core::Init()
}
cerr << "DFHack is running.\n";
onStateChange(con, SC_CORE_INITIALIZED);
return true;
}
/// sets the current hotkey command
@ -1833,17 +1852,10 @@ bool Core::isSuspended(void)
return ownerThread.load() == std::this_thread::get_id();
}
void Core::doUpdate(color_ostream &out, bool first_update)
void Core::doUpdate(color_ostream &out)
{
Lua::Core::Reset(out, "DF code execution");
if (first_update) {
auto L = Lua::Core::State;
Lua::StackUnwinder top(L);
Lua::CallLuaModuleFunction(out, L, "script-manager", "reload");
onStateChange(out, SC_CORE_INITIALIZED);
}
// find the current viewscreen
df::viewscreen *screen = NULL;
if (df::global::gview)
@ -1867,7 +1879,7 @@ void Core::doUpdate(color_ostream &out, bool first_update)
strict_virtual_cast<df::viewscreen_savegamest>(screen);
// save data (do this before updating last_world_data_ptr and triggering unload events)
if ((df::global::ui->main.autosave_request && !d->last_autosave_request) ||
if ((df::global::plotinfo->main.autosave_request && !d->last_autosave_request) ||
(is_load_save && !d->was_load_save && strict_virtual_cast<df::viewscreen_savegamest>(screen)))
{
doSaveData(out);
@ -1929,7 +1941,7 @@ void Core::doUpdate(color_ostream &out, bool first_update)
// Execute per-frame handlers
onUpdate(out);
d->last_autosave_request = df::global::ui->main.autosave_request;
d->last_autosave_request = df::global::plotinfo->main.autosave_request;
d->was_load_save = is_load_save;
out << std::flush;
@ -1946,19 +1958,15 @@ int Core::Update()
// Pretend this thread has suspended the core in the usual way,
// and run various processing hooks.
{
// Initialize the core
bool first_update = false;
if(!started)
{
first_update = true;
// Initialize the core
Init();
if(errorstate)
return -1;
Lua::Core::Reset(con, "core init");
}
doUpdate(out, first_update);
doUpdate(out);
}
// Let all commands run that require CoreSuspender
@ -2083,9 +2091,9 @@ void Core::handleLoadAndUnloadScripts(color_ostream& out, state_change_event eve
const std::vector<std::string>& set = i->second;
// load baseline defaults
this->loadScriptFile(out, "dfhack-config/init/default." + set[0] + ".init", false);
this->loadScriptFile(out, CONFIG_PATH + "init/default." + set[0] + ".init", false);
loadScriptFiles(this, out, set, "dfhack-config/init");
loadScriptFiles(this, out, set, CONFIG_PATH + "init");
loadScriptFiles(this, out, set, rawFolder);
loadScriptFiles(this, out, set, rawFolder + "objects/");
}
@ -2135,6 +2143,13 @@ void Core::onStateChange(color_ostream &out, state_change_event event)
switch (event)
{
case SC_CORE_INITIALIZED:
{
auto L = Lua::Core::State;
Lua::StackUnwinder top(L);
Lua::CallLuaModuleFunction(con, L, "script-manager", "reload");
}
break;
case SC_WORLD_LOADED:
case SC_WORLD_UNLOADED:
case SC_MAP_LOADED:
@ -2168,6 +2183,10 @@ void Core::onStateChange(color_ostream &out, state_change_event event)
evtlog << std::endl;
}
}
break;
case SC_VIEWSCREEN_CHANGED:
Textures::init(out);
break;
default:
break;
}
@ -2245,6 +2264,8 @@ int Core::Shutdown ( void )
}
// invalidate all modules
allModules.clear();
Textures::cleanup();
DFSDL::cleanup();
memset(&(s_mods), 0, sizeof(s_mods));
d.reset();
return -1;
@ -2264,16 +2285,17 @@ bool Core::ncurses_wgetch(int in, int & out)
}
if(in >= KEY_F(1) && in <= KEY_F(8))
{
/* TODO: understand how this changes for v50
int idx = in - KEY_F(1);
// FIXME: copypasta, push into a method!
if(df::global::ui && df::global::gview)
if(df::global::plotinfo && df::global::gview)
{
df::viewscreen * ws = Gui::getCurViewscreen();
if (strict_virtual_cast<df::viewscreen_dwarfmodest>(ws) &&
df::global::ui->main.mode != ui_sidebar_mode::Hotkeys &&
df::global::ui->main.hotkeys[idx].cmd == df::ui_hotkey::T_cmd::None)
df::global::plotinfo->main.mode != ui_sidebar_mode::Hotkeys &&
df::global::plotinfo->main.hotkeys[idx].cmd == df::ui_hotkey::T_cmd::None)
{
setHotkeyCmd(df::global::ui->main.hotkeys[idx].name);
setHotkeyCmd(df::global::plotinfo->main.hotkeys[idx].name);
return false;
}
else
@ -2282,11 +2304,20 @@ bool Core::ncurses_wgetch(int in, int & out)
return true;
}
}
*/
}
out = in;
return true;
}
bool Core::DFH_ncurses_key(int key)
{
if (getenv("DFHACK_HEADLESS"))
return true;
int dummy;
return !ncurses_wgetch(key, dummy);
}
int UnicodeAwareSym(const SDL::KeyboardEvent& ke)
{
// Assume keyboard layouts don't change the order of numbers:
@ -2391,7 +2422,7 @@ int Core::DFH_SDL_Event(SDL::Event* ev)
bool Core::SelectHotkey(int sym, int modifiers)
{
// Find the topmost viewscreen
if (!df::global::gview || !df::global::ui)
if (!df::global::gview || !df::global::plotinfo)
return false;
df::viewscreen *screen = &df::global::gview->view;
@ -2441,15 +2472,17 @@ bool Core::SelectHotkey(int sym, int modifiers)
int idx = sym - SDL::K_F1;
if(idx >= 0 && idx < 8)
{
/* TODO: understand how this changes for v50
if (modifiers & 1)
idx += 8;
if (strict_virtual_cast<df::viewscreen_dwarfmodest>(screen) &&
df::global::ui->main.mode != ui_sidebar_mode::Hotkeys &&
df::global::ui->main.hotkeys[idx].cmd == df::ui_hotkey::T_cmd::None)
df::global::plotinfo->main.mode != ui_sidebar_mode::Hotkeys &&
df::global::plotinfo->main.hotkeys[idx].cmd == df::ui_hotkey::T_cmd::None)
{
cmd = df::global::ui->main.hotkeys[idx].name;
cmd = df::global::plotinfo->main.hotkeys[idx].name;
}
*/
}
}
}

@ -6,7 +6,7 @@
#include "df/world.h"
#include "df/world_data.h"
#include "df/ui.h"
#include "df/plotinfost.h"
#include "DataIdentity.h"

@ -279,9 +279,8 @@ DFhackCExport int DFH_SDL_Init(uint32_t flags)
{
// reroute stderr
fprintf(stderr,"dfhack: attempting to hook in\n");
freopen("stderr.log", "w", stderr);
// we don't reroute stdout until we figure out if this should be done at all
// See: Console-linux.cpp
// See: Console-posix.cpp
// find real functions
fprintf(stderr,"dfhack: saving real SDL functions\n");

@ -117,12 +117,6 @@ DFhackCExport int wgetch(WINDOW *win)
static int (*_SDL_Init)(uint32_t flags) = 0;
DFhackCExport int SDL_Init(uint32_t flags)
{
// reroute stderr
if (!freopen("stderr.log", "w", stderr))
fprintf(stderr, "dfhack: failed to reroute stderr\n");
// we don't reroute stdout until we figure out if this should be done at all
// See: Console-linux.cpp
// find real functions
_SDL_Init = (int (*)( uint32_t )) dlsym(RTLD_NEXT, "SDL_Init");
_SDL_Quit = (void (*)( void )) dlsym(RTLD_NEXT, "SDL_Quit");

@ -0,0 +1,33 @@
#include "Core.h"
#include "Export.h"
// called before main event loop starts
DFhackCExport void dfhooks_init() {
DFHack::Core::getInstance().Init();
}
// called after main event loops exits
DFhackCExport void dfhooks_shutdown() {
DFHack::Core::getInstance().Shutdown();
}
// called in the main event loop
DFhackCExport void dfhooks_update() {
DFHack::Core::getInstance().Update();
}
// called just before adding the macro recording/playback overlay
DFhackCExport void dfhooks_prerender() {
// TODO: render overlay widgets that are not attached to a viewscreen
}
// called for each SDL event, if true is returned, then the event has been
// consumed and further processing shouldn't happen
DFhackCExport bool dfhooks_sdl_event(SDL::Event* event) {
return DFHack::Core::getInstance().DFH_SDL_Event(event);
}
// called for each utf-8 char read from the ncurses input
// key is positive for ncurses keys and negative for everything else
DFhackCExport bool dfhooks_ncurses_key(int key) {
return DFHack::Core::getInstance().DFH_ncurses_key(key);
}

@ -57,6 +57,7 @@ distribution.
#include "modules/Materials.h"
#include "modules/Random.h"
#include "modules/Screen.h"
#include "modules/Textures.h"
#include "modules/Translation.h"
#include "modules/Units.h"
#include "modules/World.h"
@ -1436,17 +1437,8 @@ static int gui_getDwarfmodeViewDims(lua_State *state)
lua_newtable(state);
Lua::TableInsert(state, "map_x1", dims.map_x1);
Lua::TableInsert(state, "map_x2", dims.map_x2);
Lua::TableInsert(state, "menu_x1", dims.menu_x1);
Lua::TableInsert(state, "menu_x2", dims.menu_x2);
Lua::TableInsert(state, "area_x1", dims.area_x1);
Lua::TableInsert(state, "area_x2", dims.area_x2);
Lua::TableInsert(state, "y1", dims.y1);
Lua::TableInsert(state, "y2", dims.y2);
Lua::TableInsert(state, "map_y1", dims.map_y1);
Lua::TableInsert(state, "map_y2", dims.map_y2);
Lua::TableInsert(state, "menu_on", dims.menu_on);
Lua::TableInsert(state, "area_on", dims.area_on);
Lua::TableInsert(state, "menu_forced", dims.menu_forced);
return 1;
}
@ -1462,6 +1454,7 @@ static int gui_getMousePos(lua_State *L)
static const LuaWrapper::FunctionReg dfhack_gui_module[] = {
WRAPM(Gui, getCurViewscreen),
WRAPM(Gui, getDFViewscreen),
WRAPM(Gui, getFocusString),
WRAPM(Gui, getCurFocus),
WRAPM(Gui, getSelectedWorkshopJob),
@ -1679,6 +1672,13 @@ static const luaL_Reg dfhack_job_funcs[] = {
{ NULL, NULL }
};
/***** Textures module *****/
static const LuaWrapper::FunctionReg dfhack_textures_module[] = {
WRAPM(Textures, getDfhackLogoTexposStart),
{ NULL, NULL }
};
/***** Units module *****/
static const LuaWrapper::FunctionReg dfhack_units_module[] = {
@ -2373,6 +2373,11 @@ static int screen_getMousePos(lua_State *L)
return Lua::PushPosXY(L, Screen::getMousePos());
}
static int screen_getMousePixels(lua_State *L)
{
return Lua::PushPosXY(L, Screen::getMousePixels());
}
static int screen_getWindowSize(lua_State *L)
{
return Lua::PushPosXY(L, Screen::getWindowSize());
@ -2452,6 +2457,17 @@ static int screen_findGraphicsTile(lua_State *L)
}
}
static int screen_raise(lua_State *L) {
df::viewscreen *screen = dfhack_lua_viewscreen::get_pointer(L, 1, false);
// remove screen from the stack so it doesn't get returned as an output
lua_remove(L, 1);
Screen::raise(screen);
return 0;
}
static int screen_hideGuard(lua_State *L) {
df::viewscreen *screen = dfhack_lua_viewscreen::get_pointer(L, 1, false);
luaL_checktype(L, 2, LUA_TFUNCTION);
@ -2563,12 +2579,14 @@ static int screen_zoom(lua_State *L)
static const luaL_Reg dfhack_screen_funcs[] = {
{ "getMousePos", screen_getMousePos },
{ "getMousePixels", screen_getMousePixels },
{ "getWindowSize", screen_getWindowSize },
{ "paintTile", screen_paintTile },
{ "readTile", screen_readTile },
{ "paintString", screen_paintString },
{ "fillRect", screen_fillRect },
{ "findGraphicsTile", screen_findGraphicsTile },
CWRAP(raise, screen_raise),
CWRAP(hideGuard, screen_hideGuard),
CWRAP(show, screen_show),
CWRAP(dismiss, screen_dismiss),
@ -3360,6 +3378,7 @@ void OpenDFHackApi(lua_State *state)
luaL_setfuncs(state, dfhack_funcs, 0);
OpenModule(state, "gui", dfhack_gui_module, dfhack_gui_funcs);
OpenModule(state, "job", dfhack_job_module, dfhack_job_funcs);
OpenModule(state, "textures", dfhack_textures_module);
OpenModule(state, "units", dfhack_units_module, dfhack_units_funcs);
OpenModule(state, "items", dfhack_items_module, dfhack_items_funcs);
OpenModule(state, "maps", dfhack_maps_module, dfhack_maps_funcs);

@ -131,9 +131,16 @@ void DFHack::Lua::GetVector(lua_State *state, std::vector<std::string> &pvec)
}
}
static bool trigger_inhibit_l_down = false;
static bool trigger_inhibit_r_down = false;
static bool trigger_inhibit_m_down = false;
static bool inhibit_l_down = false;
static bool inhibit_r_down = false;
static bool inhibit_m_down = false;
void DFHack::Lua::PushInterfaceKeys(lua_State *L,
const std::set<df::interface_key> &keys) {
lua_createtable(L, 0, keys.size() + 5);
lua_createtable(L, 0, keys.size() + 7);
for (auto &key : keys)
{
@ -154,23 +161,32 @@ void DFHack::Lua::PushInterfaceKeys(lua_State *L,
}
if (df::global::enabler) {
if (df::global::enabler->mouse_lbut_down) {
if (!inhibit_l_down && df::global::enabler->mouse_lbut_down) {
lua_pushboolean(L, true);
lua_setfield(L, -2, "_MOUSE_L_DOWN");
trigger_inhibit_l_down = true;
}
if (df::global::enabler->mouse_rbut_down) {
if (!inhibit_r_down && df::global::enabler->mouse_rbut_down) {
lua_pushboolean(L, true);
lua_setfield(L, -2, "_MOUSE_R_DOWN");
trigger_inhibit_r_down = true;
}
if (!inhibit_m_down && df::global::enabler->mouse_mbut_down) {
lua_pushboolean(L, true);
lua_setfield(L, -2, "_MOUSE_M_DOWN");
trigger_inhibit_m_down = true;
}
if (df::global::enabler->mouse_lbut) {
lua_pushboolean(L, true);
lua_setfield(L, -2, "_MOUSE_L");
df::global::enabler->mouse_lbut_down = 0;
}
if (df::global::enabler->mouse_rbut) {
lua_pushboolean(L, true);
lua_setfield(L, -2, "_MOUSE_R");
df::global::enabler->mouse_rbut_down = 0;
}
if (df::global::enabler->mouse_mbut) {
lua_pushboolean(L, true);
lua_setfield(L, -2, "_MOUSE_M");
}
}
}
@ -2134,4 +2150,24 @@ void DFHack::Lua::Core::Reset(color_ostream &out, const char *where)
out.printerr("Common lua context stack top left at %d after %s.\n", top, where);
lua_settop(State, 0);
}
if (trigger_inhibit_l_down) {
trigger_inhibit_l_down = false;
inhibit_l_down = true;
}
if (trigger_inhibit_r_down) {
trigger_inhibit_r_down = false;
inhibit_r_down = true;
}
if (trigger_inhibit_m_down) {
trigger_inhibit_m_down = false;
inhibit_m_down = true;
}
if (!df::global::enabler->mouse_lbut)
inhibit_l_down = false;
if (!df::global::enabler->mouse_rbut)
inhibit_r_down = false;
if (!df::global::enabler->mouse_mbut)
inhibit_m_down = false;
}

@ -35,7 +35,6 @@ distribution.
#include <stdio.h>
#include "tinythread.h"
#include "../plugins/uicommon.h"
/*
* Plugin loading functions

@ -59,8 +59,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include "LuaTools.h"
#include "DataDefs.h"
#include "df/ui.h"
#include "df/ui_advmode.h"
#include "df/plotinfost.h"
#include "df/adventurest.h"
#include "df/world.h"
#include "df/world_data.h"
#include "df/unit.h"
@ -375,11 +375,11 @@ static command_result GetDFVersion(color_ostream &stream,
static command_result GetWorldInfo(color_ostream &stream,
const EmptyMessage *, GetWorldInfoOut *out)
{
using df::global::ui;
using df::global::ui_advmode;
using df::global::plotinfo;
using df::global::adventure;
using df::global::world;
if (!ui || !world || !Core::getInstance().isWorldLoaded())
if (!plotinfo || !world || !Core::getInstance().isWorldLoaded())
return CR_NOT_FOUND;
df::game_type gt = game_type::DWARF_MAIN;
@ -397,10 +397,10 @@ static command_result GetWorldInfo(color_ostream &stream,
case game_type::DWARF_RECLAIM:
case game_type::DWARF_UNRETIRE:
out->set_mode(GetWorldInfoOut::MODE_DWARF);
out->set_civ_id(ui->civ_id);
out->set_site_id(ui->site_id);
out->set_group_id(ui->group_id);
out->set_race_id(ui->race_id);
out->set_civ_id(plotinfo->civ_id);
out->set_site_id(plotinfo->site_id);
out->set_group_id(plotinfo->group_id);
out->set_race_id(plotinfo->race_id);
break;
case game_type::ADVENTURE_MAIN:
@ -410,10 +410,10 @@ static command_result GetWorldInfo(color_ostream &stream,
if (auto unit = vector_get(world->units.active, 0))
out->set_player_unit_id(unit->id);
if (!ui_advmode)
if (!adventure)
break;
if (auto nemesis = vector_get(world->nemesis.all, ui_advmode->player_id))
if (auto nemesis = vector_get(world->nemesis.all, adventure->player_id))
{
if (nemesis->figure)
out->set_player_histfig_id(nemesis->figure->id);
@ -613,7 +613,7 @@ static command_result ListUnits(color_ostream &stream,
static command_result ListSquads(color_ostream &stream,
const ListSquadsIn *in, ListSquadsOut *out)
{
auto entity = df::historical_entity::find(df::global::ui->group_id);
auto entity = df::historical_entity::find(df::global::plotinfo->group_id);
if (!entity)
return CR_NOT_FOUND;

@ -121,6 +121,12 @@ namespace DFHack
friend int ::SDL_Init(uint32_t flags);
friend int ::wgetch(WINDOW * w);
#endif
friend void ::dfhooks_init();
friend void ::dfhooks_shutdown();
friend void ::dfhooks_update();
friend void ::dfhooks_prerender();
friend bool ::dfhooks_sdl_event(SDL::Event* event);
friend bool ::dfhooks_ncurses_key(int key);
public:
/// Get the single Core instance or make one.
static Core& getInstance()
@ -202,8 +208,9 @@ namespace DFHack
int Shutdown (void);
int DFH_SDL_Event(SDL::Event* event);
bool ncurses_wgetch(int in, int & out);
bool DFH_ncurses_key(int key);
void doUpdate(color_ostream &out, bool first_update);
void doUpdate(color_ostream &out);
void onUpdate(color_ostream &out);
void onStateChange(color_ostream &out, state_change_event event);
void handleLoadAndUnloadScripts(color_ostream &out, state_change_event event);

@ -394,6 +394,7 @@ namespace df
template<class T>
class ro_stl_container_identity : public container_identity {
protected:
const char *name;
public:
@ -419,6 +420,30 @@ namespace df
}
};
template<class T>
class ro_stl_assoc_container_identity : public ro_stl_container_identity<T> {
type_identity *key_identity;
type_identity *item_identity;
public:
ro_stl_assoc_container_identity(const char *name, type_identity *key, type_identity *item)
: ro_stl_container_identity<T>(name, item),
key_identity(key),
item_identity(item)
{}
virtual std::string getFullName(type_identity*) override {
return std::string(ro_stl_assoc_container_identity<T>::name) + "<" + key_identity->getFullName() + ", " + item_identity->getFullName() + ">";
}
protected:
virtual void *item_pointer(type_identity *item, void *ptr, int idx) override {
auto iter = (*(T*)ptr).begin();
for (; idx > 0; idx--) ++iter;
return (void*)&iter->second;
}
};
class bit_array_identity : public bit_container_identity {
public:
/*
@ -609,6 +634,10 @@ namespace df
static container_identity *get();
};
template<class KT, class T> struct identity_traits<std::map<KT, T>> {
static container_identity *get();
};
template<> struct identity_traits<BitArray<int> > {
static bit_array_identity identity;
static bit_container_identity *get() { return &identity; }
@ -679,6 +708,13 @@ namespace df
return &identity;
}
template<class KT, class T>
inline container_identity *identity_traits<std::map<KT, T>>::get() {
typedef std::map<KT, T> container;
static ro_stl_assoc_container_identity<container> identity("map", identity_traits<KT>::get(), identity_traits<T>::get());
return &identity;
}
template<class T>
inline bit_container_identity *identity_traits<BitArray<T> >::get() {
static bit_array_identity identity(identity_traits<T>::get());

@ -42,13 +42,13 @@ class DebugCategory;
/*!
* \brief Container holding all registered runtime debug categories
* Singleton DebugManager is a minor extension to std::vector that allows signal
* callbacks to be attached from ui code that manages.
* callbacks to be attached from plotinfo code that manages.
*
* To avoid parallel plugin unload causing issues access to DebugManager must be
* protected by mutex. The access mutex will be taken when
* DFHack::DebugCategory::~DebugCategory performs unregister calls to
* DFHack::DebugManager. The mutex will protect from memory disappearing while
* ui code is accessing or changing the runtime state.
* plotinfo code is accessing or changing the runtime state.
*
* Signal emitting happens from a locked contexts. Taking the
* DFHack::DebugManager::access_mutex_ in a signal callback will results to a

@ -74,3 +74,11 @@ DFhackCExport void * SDL_GetVideoSurface(void);
DFhackCExport int SDL_SemWait(vPtr sem);
DFhackCExport int SDL_SemPost(vPtr sem);
// new Hooks API
DFhackCExport void dfhooks_init();
DFhackCExport void dfhooks_shutdown();
DFhackCExport void dfhooks_update();
DFhackCExport void dfhooks_prerender();
DFhackCExport bool dfhooks_sdl_event(SDL::Event* event);
DFhackCExport bool dfhooks_ncurses_key(int key);

@ -0,0 +1,92 @@
#pragma once
#include "Export.h"
#include "ColorText.h"
namespace DFHack
{
// SDL stand-in type definitions
typedef signed short SINT16;
typedef void DFSDL_sem;
typedef struct
{
int16_t x, y;
uint16_t w, h;
} DFSDL_Rect;
typedef struct
{
void *palette; // SDL_Palette*
uint8_t BitsPerPixel;
uint8_t BytesPerPixel;
uint8_t Rloss;
uint8_t Gloss;
uint8_t Bloss;
uint8_t Aloss;
uint8_t Rshift;
uint8_t Gshift;
uint8_t Bshift;
uint8_t Ashift;
uint32_t Rmask;
uint32_t Gmask;
uint32_t Bmask;
uint32_t Amask;
uint32_t colorkey;
uint8_t alpha;
} DFSDL_PixelFormat;
typedef struct
{
uint32_t flags;
DFSDL_PixelFormat* format;
int w, h;
int pitch;
void* pixels;
void* userdata; // as far as i could see DF doesnt use this
int locked;
void* lock_data;
DFSDL_Rect clip_rect;
void* map;
int refcount;
} DFSDL_Surface;
// =========
struct DFTileSurface
{
bool paintOver; // draw over original tile?
DFSDL_Surface* surface; // from where it should be drawn
DFSDL_Rect* rect; // from which coords (NULL to draw whole surface)
DFSDL_Rect* dstResize; // if not NULL dst rect will be resized (x/y/w/h will be added to original dst)
};
/**
* The DFSDL module - provides access to SDL functions without actually
* requiring build-time linkage to SDL
* \ingroup grp_modules
* \ingroup grp_dfsdl
*/
namespace DFSDL
{
/**
* Call this on DFHack init so we can load the SDL functions. Returns false on
* failure.
*/
bool init(DFHack::color_ostream &out);
/**
* Call this when DFHack is being unloaded.
*/
void cleanup();
DFHACK_EXPORT DFSDL_Surface * DFIMG_Load(const char *file);
DFHACK_EXPORT int DFSDL_SetAlpha(DFSDL_Surface *surface, uint32_t flag, uint8_t alpha);
DFHACK_EXPORT DFSDL_Surface * DFSDL_CreateRGBSurface(uint32_t flags, int width, int height, int depth, uint32_t Rmask, uint32_t Gmask, uint32_t Bmask, uint32_t Amask);
DFHACK_EXPORT int DFSDL_UpperBlit(DFSDL_Surface *src, const DFSDL_Rect *srcrect, DFSDL_Surface *dst, DFSDL_Rect *dstrect);
DFHACK_EXPORT DFSDL_Surface * DFSDL_ConvertSurface(DFSDL_Surface *src, const DFSDL_PixelFormat *fmt, uint32_t flags);
DFHACK_EXPORT void DFSDL_FreeSurface(DFSDL_Surface *surface);
DFHACK_EXPORT int DFSDL_SemWait(DFSDL_sem *sem);
DFHACK_EXPORT int DFSDL_SemPost(DFSDL_sem *sem);
}
}

@ -33,42 +33,11 @@ distribution.
#include <stdint.h>
#include "Export.h"
#include "Module.h"
#include "DFSDL.h"
#include <vector>
namespace DFHack
{
// SDL stuff
typedef signed short SINT16;
typedef struct
{
int16_t x, y;
uint16_t w, h;
} DFSDL_Rect;
typedef struct
{
uint32_t flags;
void* format; // PixelFormat*
int w, h;
int pitch;
void* pixels;
void* userdata; // as far as i could see DF doesnt use this
int locked;
void* lock_data;
DFSDL_Rect clip_rect;
void* map;
int refcount;
} DFSDL_Surface;
// =========
struct DFTileSurface
{
bool paintOver; // draw over original tile?
DFSDL_Surface* surface; // from where it should be drawn
DFSDL_Rect* rect; // from which coords (NULL to draw whole surface)
DFSDL_Rect* dstResize; // if not NULL dst rect will be resized (x/y/w/h will be added to original dst)
};
class DFHACK_EXPORT Graphic : public Module
{
public:
@ -83,7 +52,6 @@ namespace DFHack
private:
std::vector<DFTileSurface* (*)(int, int)> funcs;
};
}
#endif

@ -33,7 +33,7 @@ distribution.
#include "DataDefs.h"
#include "df/init.h"
#include "df/ui.h"
#include "df/plotinfost.h"
#include "df/announcement_type.h"
#include "df/announcement_flags.h"
#include "df/report_init.h"
@ -143,13 +143,10 @@ namespace DFHack
static const int MENU_WIDTH = 30;
struct DwarfmodeDims {
int map_x1, map_x2, menu_x1, menu_x2, area_x1, area_x2;
int y1, y2;
int map_x1, map_x2;
int map_y1, map_y2;
bool menu_on, area_on, menu_forced;
rect2d map() { return mkrect_xy(map_x1, map_y1, map_x2, map_y2); }
rect2d menu() { return mkrect_xy(menu_x1, y1, menu_x2, y2); }
};
DFHACK_EXPORT DwarfmodeDims getDwarfmodeViewDims();
@ -184,6 +181,9 @@ namespace DFHack
DFHACK_EXPORT df::viewscreen *getViewscreenByIdentity(virtual_identity &id, int n = 1);
/// Get the top-most underlying DF viewscreen (not owned by DFHack)
DFHACK_EXPORT df::viewscreen *getDFViewscreen(bool skip_dismissed = false);
/// Get the top-most viewscreen of the given type from the top `n` viewscreens (or all viewscreens if n < 1)
/// returns NULL if none match
template <typename T>
@ -198,18 +198,6 @@ namespace DFHack
/// get the size of the window buffer
DFHACK_EXPORT bool getWindowSize(int32_t & width, int32_t & height);
/**
*Menu width:
*3:3 - menu and area map closed
*2:3 - menu open single width
*1:3 - menu open double width
*1:2 - menu and area map open
*2:2 - area map open
*/
DFHACK_EXPORT bool getMenuWidth(uint8_t & menu_width, uint8_t & area_map_width);
DFHACK_EXPORT bool setMenuWidth(const uint8_t menu_width, const uint8_t area_map_width);
namespace Hooks {
GUI_HOOK_DECLARE(depth_at, int, (int32_t x, int32_t y));
GUI_HOOK_DECLARE(dwarfmode_view_dims, DwarfmodeDims, ());

@ -75,7 +75,7 @@ DFHACK_EXPORT void clearLimits();
DFHACK_EXPORT std::size_t size();
// Finds the index of a kitchen exclusion in ui.kitchen.exc_types. Returns -1 if not found.
// Finds the index of a kitchen exclusion in plotinfo.kitchen.exc_types. Returns -1 if not found.
DFHACK_EXPORT int findExclusion(df::kitchen_exc_type type,
df::item_type item_type, int16_t item_subtype,
int16_t mat_type, int32_t mat_index);

@ -5,13 +5,6 @@
#pragma once
namespace DFHack { namespace Renderer {
// If the the 'x' parameter points to this value, then the 'y' parameter will
// be interpreted as a boolean flag for whether to return map coordinates (false)
// or text tile coordinates (true). Only TWBT implements this logic, and this
// sentinel value can be removed once DF provides an API for retrieving the
// two sets of coordinates.
DFHACK_EXPORT extern const int32_t GET_MOUSE_COORDS_SENTINEL;
struct DFHACK_EXPORT renderer_wrap : public df::renderer {
void set_to_null();
void copy_from_parent();
@ -19,19 +12,12 @@ namespace DFHack { namespace Renderer {
renderer_wrap *parent;
renderer_wrap *child;
virtual void update_tile(int32_t x, int32_t y);
virtual void update_all();
virtual void render();
virtual void set_fullscreen();
virtual void zoom(df::zoom_commands z);
virtual void resize(int32_t w, int32_t h);
virtual void grid_resize(int32_t w, int32_t h);
virtual ~renderer_wrap() {
// All necessary cleanup should be handled by RemoveRenderer()
};
virtual bool get_mouse_coords(int32_t *x, int32_t *y);
virtual bool uses_opengl();
};
/* TODO: we can't cat enabler->renderer to renderer_wrap and expect it to work
// Returns the renderer instance given on success, or deletes it and returns NULL on failure
// Usage: renderer_foo *r = AddRenderer(new renderer_foo)
DFHACK_EXPORT renderer_wrap *AddRenderer(renderer_wrap*, bool refresh_screen = false);
@ -42,4 +28,5 @@ namespace DFHack { namespace Renderer {
{
return (renderer_wrap*)(df::global::enabler ? df::global::enabler->renderer : NULL);
}
*/
}}

@ -222,6 +222,7 @@ namespace DFHack
DFHACK_EXPORT void dismiss(df::viewscreen *screen, bool to_first = false);
DFHACK_EXPORT bool isDismissed(df::viewscreen *screen);
DFHACK_EXPORT bool hasActiveScreens(Plugin *p);
DFHACK_EXPORT void raise(df::viewscreen *screen);
/// Retrieve the string representation of the bound key.
DFHACK_EXPORT std::string getKeyDisplay(df::interface_key key);

@ -0,0 +1,34 @@
#pragma once
#include "Export.h"
#include "ColorText.h"
namespace DFHack {
/**
* The Textures module - loads and provides access to DFHack textures
* \ingroup grp_modules
* \ingroup grp_textures
*/
namespace Textures {
/**
* Call this on DFHack init and on every viewscreen change so we can reload
* and reindex textures as needed.
*/
void init(DFHack::color_ostream &out);
/**
* Call this when DFHack is being unloaded.
*
*/
void cleanup();
/**
* Get first texpos for the DFHack logo. This texpos and the next 11 make up the
* 4x3 grid of logo textures that can be displayed on the UI layer.
*/
DFHACK_EXPORT long getDfhackLogoTexposStart();
}
}

@ -7,17 +7,17 @@ local utils = require('utils')
local dscreen = dfhack.screen
local getval = utils.getval
USE_GRAPHICS = dscreen.inGraphicsMode()
local to_pen = dfhack.pen.parse
CLEAR_PEN = to_pen{ch=32,fg=0,bg=0}
CLEAR_PEN = to_pen{tile=909, ch=32, fg=0, bg=0}
local FAKE_INPUT_KEYS = {
_MOUSE_L = true,
_MOUSE_R = true,
_MOUSE_M = true,
_MOUSE_L_DOWN = true,
_MOUSE_R_DOWN = true,
_MOUSE_M_DOWN = true,
_STRING = true,
}
@ -484,6 +484,10 @@ function View:getMousePos(view_rect)
end
end
function View:getMouseFramePos()
return self:getMousePos(ViewRect{rect=self.frame_rect})
end
function View:computeFrame(parent_rect)
return mkdims_wh(0,0,parent_rect.width,parent_rect.height)
end
@ -599,6 +603,7 @@ end
Screen = defclass(Screen, View)
Screen.text_input_mode = false
Screen.request_full_screen_refresh = false
function Screen:postinit()
self:onResize(dscreen.getWindowSize())
@ -624,6 +629,10 @@ function Screen:renderParent()
else
dscreen.clear()
end
if Screen.request_full_screen_refresh then
df.global.gps.force_full_display_count = 1
Screen.request_full_screen_refresh = false
end
end
function Screen:sendInputToParent(...)
@ -658,6 +667,8 @@ function Screen:dismiss()
if self._native then
dscreen.dismiss(self)
end
-- don't leave artifacts behind on the parent screen when we disappear
Screen.request_full_screen_refresh = true
end
function Screen:onDismiss()
@ -674,9 +685,67 @@ function Screen:onRender()
self:render(Painter.new())
end
------------------------
-----------------------------
-- Z-order swapping screen --
-----------------------------
ZScreen = defclass(ZScreen, Screen)
function ZScreen:onIdle()
if self._native and self._native.parent then
self._native.parent:logic()
end
end
function ZScreen:render(dc)
self:renderParent()
ZScreen.super.render(self, dc)
end
local function zscreen_is_top(self)
return dfhack.gui.getCurViewscreen(true) == self._native
end
function ZScreen:onInput(keys)
if not zscreen_is_top(self) then
if keys._MOUSE_L_DOWN and self:isMouseOver() then
self:raise()
else
self:sendInputToParent(keys)
return
end
end
if ZScreen.super.onInput(self, keys) then
return
end
if keys.LEAVESCREEN or keys._MOUSE_R_DOWN then
self:dismiss()
return
end
if not keys._MOUSE_L or not self:isMouseOver() then
self:sendInputToParent(keys)
end
end
-- move this viewscreen to the top of the stack (if it's not there already)
function ZScreen:raise()
if self:isDismissed() or zscreen_is_top(self) then
return
end
dscreen.raise(self)
end
-- subclasses should override this and return whether the mouse is over an
-- owned screen element
function ZScreen:isMouseOver()
return false
end
--------------------------
-- Framed screen object --
------------------------
--------------------------
-- Plain grey-colored frame.
GREY_FRAME = {
@ -687,21 +756,23 @@ GREY_FRAME = {
-- The usual boundary used by the DF screens. Often has fancy pattern in tilesets.
BOUNDARY_FRAME = {
frame_pen = to_pen{ ch = 0xDB, fg = COLOR_DARKGREY, bg = COLOR_BLACK },
frame_pen = to_pen{ ch = 0xDB, fg = COLOR_GREY, bg = COLOR_BLACK },
title_pen = to_pen{ fg = COLOR_BLACK, bg = COLOR_GREY },
signature_pen = to_pen{ fg = COLOR_BLACK, bg = COLOR_DARKGREY },
signature_pen = to_pen{ fg = COLOR_BLACK, bg = COLOR_GREY },
}
GREY_LINE_FRAME = {
frame_pen = to_pen{ ch = 206, fg = COLOR_GREY, bg = COLOR_BLACK },
h_frame_pen = to_pen{ ch = 205, fg = COLOR_GREY, bg = COLOR_BLACK },
v_frame_pen = to_pen{ ch = 186, fg = COLOR_GREY, bg = COLOR_BLACK },
lt_frame_pen = to_pen{ ch = 201, fg = COLOR_GREY, bg = COLOR_BLACK },
lb_frame_pen = to_pen{ ch = 200, fg = COLOR_GREY, bg = COLOR_BLACK },
rt_frame_pen = to_pen{ ch = 187, fg = COLOR_GREY, bg = COLOR_BLACK },
rb_frame_pen = to_pen{ ch = 188, fg = COLOR_GREY, bg = COLOR_BLACK },
title_pen = to_pen{ fg = COLOR_BLACK, bg = COLOR_GREY },
signature_pen = to_pen{ fg = COLOR_DARKGREY, bg = COLOR_BLACK },
frame_pen = to_pen{ ch=206, fg=COLOR_GREY, bg=COLOR_BLACK },
t_frame_pen = to_pen{ tile=902, ch=205, fg=COLOR_GREY, bg=COLOR_BLACK },
l_frame_pen = to_pen{ tile=908, ch=186, fg=COLOR_GREY, bg=COLOR_BLACK },
b_frame_pen = to_pen{ tile=916, ch=205, fg=COLOR_GREY, bg=COLOR_BLACK },
r_frame_pen = to_pen{ tile=910, ch=186, fg=COLOR_GREY, bg=COLOR_BLACK },
lt_frame_pen = to_pen{ tile=901, ch=201, fg=COLOR_GREY, bg=COLOR_BLACK },
lb_frame_pen = to_pen{ tile=915, ch=200, fg=COLOR_GREY, bg=COLOR_BLACK },
rt_frame_pen = to_pen{ tile=903, ch=187, fg=COLOR_GREY, bg=COLOR_BLACK },
rb_frame_pen = to_pen{ tile=917, ch=188, fg=COLOR_GREY, bg=COLOR_BLACK },
title_pen = to_pen{ fg=COLOR_BLACK, bg=COLOR_GREY },
signature_pen = to_pen{ fg=COLOR_GREY, bg=COLOR_BLACK },
}
function paint_frame(dc,rect,style,title)

@ -258,8 +258,8 @@ function BuildingDialog:onSubmitItem(idx, item)
end
function BuildingDialog:onInput(keys)
if keys.LEAVESCREEN or keys.LEAVESCREEN_ALL then
if self.subviews.back.visible and not keys.LEAVESCREEN_ALL then
if keys.LEAVESCREEN then
if self.subviews.back.visible then
self:onGoBack()
else
self:dismiss()
@ -267,9 +267,9 @@ function BuildingDialog:onInput(keys)
self.on_cancel()
end
end
else
self:inputToSubviews(keys)
return true
end
self:inputToSubviews(keys)
end
function showBuildingPrompt(title, prompt, on_select, on_cancel, build_filter)

@ -48,7 +48,7 @@ end
function MessageBox:onRenderFrame(dc,rect)
MessageBox.super.onRenderFrame(self,dc,rect)
if self.on_accept then
dc:seek(rect.x1+2,rect.y2):key('LEAVESCREEN'):string('/'):key('MENU_CONFIRM')
dc:seek(rect.x1+2,rect.y2):key('LEAVESCREEN'):string('/'):key('SELECT')
end
end
@ -59,19 +59,16 @@ function MessageBox:onDestroy()
end
function MessageBox:onInput(keys)
if keys.MENU_CONFIRM then
if keys.SELECT or keys.LEAVESCREEN then
self:dismiss()
if self.on_accept then
if keys.SELECT and self.on_accept then
self.on_accept()
end
elseif keys.LEAVESCREEN or (keys.SELECT and not self.on_accept) then
self:dismiss()
if self.on_cancel then
elseif keys.LEAVESCREEN and self.on_cancel then
self.on_cancel()
end
else
self:inputToSubviews(keys)
return true
end
return self:inputToSubviews(keys)
end
function showMessage(title, text, tcolor, on_close)
@ -132,14 +129,15 @@ function InputBox:onInput(keys)
if self.on_input then
self.on_input(self.subviews.edit.text)
end
return true
elseif keys.LEAVESCREEN then
self:dismiss()
if self.on_cancel then
self.on_cancel()
end
else
self:inputToSubviews(keys)
return true
end
return self:inputToSubviews(keys)
end
function showInputPrompt(title, text, tcolor, input, on_input, on_cancel, min_width)
@ -238,9 +236,9 @@ function ListBox:onInput(keys)
if self.on_cancel then
self.on_cancel()
end
else
self:inputToSubviews(keys)
return true
end
return self:inputToSubviews(keys)
end
function showListPrompt(title, text, tcolor, choices, on_select, on_cancel, min_width, filter)

@ -49,7 +49,7 @@ function enterSidebarMode(sidebar_mode, max_esc)
while remaining_esc > 0 do
local screen = dfhack.gui.getCurViewscreen(true)
focus_string = dfhack.gui.getFocusString(screen)
if df.global.ui.main.mode == df.ui_sidebar_mode.Default and
if df.global.plotinfo.main.mode == df.ui_sidebar_mode.Default and
focus_string == 'dwarfmode/Default' then
if #navkey > 0 then gui.simulateInput(screen, navkey) end
if navkey == 'D_DESIGNATE' then
@ -71,30 +71,9 @@ end
function getPanelLayout()
local dims = dfhack.gui.getDwarfmodeViewDims()
local area_pos = df.global.ui_menu_width[1]
local menu_pos = df.global.ui_menu_width[0]
if dims.menu_forced then
menu_pos = area_pos - 1
end
local rv = {
menu_pos = menu_pos,
area_pos = area_pos,
map = gui.mkdims_xy(dims.map_x1, dims.map_y1, dims.map_x2, dims.map_y2),
return {
map=gui.mkdims_xy(dims.map_x1, dims.map_y1, dims.map_x2, dims.map_y2),
}
if dims.menu_forced then
rv.menu_forced = true
end
if dims.menu_on then
rv.menu = gui.mkdims_xy(dims.menu_x1, dims.y1, dims.menu_x2, dims.y2)
end
if dims.area_on then
rv.area_map = gui.mkdims_xy(dims.area_x1, dims.y1, dims.area_x2, dims.y2)
end
return rv
end
function getCursorPos()
@ -267,6 +246,10 @@ function Viewport:reveal(target,gap,max_scroll,scroll_gap,scroll_z)
end
MOVEMENT_KEYS = {
KEYBOARD_CURSOR_UP = { 0, -1, 0 }, KEYBOARD_CURSOR_DOWN = { 0, 1, 0 },
KEYBOARD_CURSOR_LEFT = { -1, 0, 0 }, KEYBOARD_CURSOR_RIGHT = { 1, 0, 0 },
KEYBOARD_CURSOR_UP_FAST = { 0, -1, 0, true }, KEYBOARD_CURSOR_DOWN_FAST = { 0, 1, 0, true },
KEYBOARD_CURSOR_LEFT_FAST = { -1, 0, 0, true }, KEYBOARD_CURSOR_RIGHT_FAST = { 1, 0, 0, true },
CURSOR_UP = { 0, -1, 0 }, CURSOR_DOWN = { 0, 1, 0 },
CURSOR_LEFT = { -1, 0, 0 }, CURSOR_RIGHT = { 1, 0, 0 },
CURSOR_UPLEFT = { -1, -1, 0 }, CURSOR_UPRIGHT = { 1, -1, 0 },
@ -292,7 +275,7 @@ end
HOTKEY_KEYS = {}
for i,v in ipairs(df.global.ui.main.hotkeys) do
for i,v in ipairs(df.global.plotinfo.main.hotkeys) do
HOTKEY_KEYS['D_HOTKEY'..(i+1)] = v
end
@ -450,7 +433,7 @@ function MenuOverlay:init()
end
if self.sidebar_mode then
self.saved_sidebar_mode = df.global.ui.main.mode
self.saved_sidebar_mode = df.global.plotinfo.main.mode
-- what mode should we restore when this window is dismissed? ideally, we'd
-- restore the mode that the user has set, but we should fall back to
-- restoring the default mode if either of the following conditions are
@ -553,66 +536,4 @@ function MenuOverlay:renderMapOverlay(get_overlay_char_fn, bounds_rect)
end
end
--fakes a "real" workshop sidebar menu, but on exactly selected workshop
WorkshopOverlay = defclass(WorkshopOverlay, MenuOverlay)
WorkshopOverlay.focus_path="WorkshopOverlay"
WorkshopOverlay.ATTRS={
workshop=DEFAULT_NIL,
}
function WorkshopOverlay:onAboutToShow(below)
WorkshopOverlay.super.onAboutToShow(self,below)
if df.global.world.selected_building ~= self.workshop then
error("The workshop overlay tried to show up for incorrect workshop")
end
end
function WorkshopOverlay:onInput(keys)
local allowedKeys={ --TODO add options: job management, profile, etc...
"CURSOR_RIGHT","CURSOR_RIGHT_FAST","CURSOR_LEFT","CURSOR_LEFT_FAST","CURSOR_UP","CURSOR_UP_FAST","CURSOR_DOWN","CURSOR_DOWN_FAST",
"CURSOR_UPRIGHT","CURSOR_UPRIGHT_FAST","CURSOR_UPLEFT","CURSOR_UPLEFT_FAST","CURSOR_DOWNRIGHT","CURSOR_DOWNRIGHT_FAST","CURSOR_DOWNLEFT","CURSOR_DOWNLEFT_FAST",
"CURSOR_UP_Z","CURSOR_DOWN_Z","DESTROYBUILDING","CHANGETAB","SUSPENDBUILDING"}
if keys.LEAVESCREEN then
self:dismiss()
self:sendInputToParent('LEAVESCREEN')
elseif keys.CHANGETAB then
self:sendInputToParent("CHANGETAB")
self:inputToSubviews(keys)
self:updateLayout()
else
for _,name in ipairs(allowedKeys) do
if keys[name] then
self:sendInputToParent(name)
break
end
end
self:inputToSubviews(keys)
end
if df.global.world.selected_building ~= self.workshop then
self:dismiss()
return
end
end
function WorkshopOverlay:onGetSelectedBuilding()
return self.workshop
end
local function is_slated_for_remove( bld )
for i,v in ipairs(bld.jobs) do
if v.job_type==df.job_type.DestroyBuilding then
return true
end
end
return false
end
function WorkshopOverlay:render(dc)
self:renderParent()
if df.global.world.selected_building ~= self.workshop then
return
end
if is_slated_for_remove(self.workshop) then
return
end
WorkshopOverlay.super.render(self, dc)
end
return _ENV

@ -255,8 +255,8 @@ function MaterialDialog:onSubmitItem(idx, item)
end
function MaterialDialog:onInput(keys)
if keys.LEAVESCREEN or keys.LEAVESCREEN_ALL then
if self.subviews.back.visible and not keys.LEAVESCREEN_ALL then
if keys.LEAVESCREEN then
if self.subviews.back.visible then
self:onGoBack()
else
self:dismiss()
@ -264,9 +264,9 @@ function MaterialDialog:onInput(keys)
self.on_cancel()
end
end
else
self:inputToSubviews(keys)
return true
end
return self:inputToSubviews(keys)
end
function showMaterialPrompt(title, prompt, on_select, on_cancel, mat_filter)

@ -8,6 +8,7 @@ local utils = require('utils')
local dscreen = dfhack.screen
local getval = utils.getval
local to_pen = dfhack.pen.parse
local function show_view(view,vis)
if view then
@ -25,16 +26,13 @@ end
STANDARDSCROLL = {
STANDARDSCROLL_UP = -1,
KEYBOARD_CURSOR_UP = -1,
STANDARDSCROLL_DOWN = 1,
KEYBOARD_CURSOR_DOWN = 1,
STANDARDSCROLL_PAGEUP = '-page',
KEYBOARD_CURSOR_UP_FAST = '-page',
STANDARDSCROLL_PAGEDOWN = '+page',
}
SECONDSCROLL = {
SECONDSCROLL_UP = -1,
SECONDSCROLL_DOWN = 1,
SECONDSCROLL_PAGEUP = '-page',
SECONDSCROLL_PAGEDOWN = '+page',
KEYBOARD_CURSOR_DOWN_FAST = '+page',
}
------------
@ -89,7 +87,7 @@ Panel.ATTRS {
function Panel:init(args)
if not self.drag_anchors then
self.drag_anchors = {title=true, frame=false, body=false}
self.drag_anchors = {title=true, frame=false, body=true}
end
if not self.resize_anchors then
self.resize_anchors = {t=false, l=true, r=true, b=true}
@ -305,8 +303,7 @@ function Panel:onInput(keys)
return true
end
if not keys._MOUSE_L_DOWN then return end
local rect = self.frame_rect
local x,y = self:getMousePos(gui.ViewRect{rect=rect})
local x,y = self:getMouseFramePos()
if not x then return end
if self.resizable and y == 0 then
@ -365,8 +362,10 @@ function Panel:setKeyboardDragEnabled(enabled)
return
end
if enabled then
local kbd_get_pos = function() return {x=0, y=0} end
Panel_begin_drag(self, kbd_get_pos())
local kbd_get_pos = function()
return {x=self.frame_rect.x1, y=self.frame_rect.y1}
end
Panel_begin_drag(self)
self.kbd_get_pos = kbd_get_pos
else
Panel_end_drag(self)
@ -441,6 +440,9 @@ end
-- if self.autoarrange_subviews is true, lay out visible subviews vertically,
-- adding gaps between widgets according to self.autoarrange_gap.
function Panel:postUpdateLayout()
-- don't leave artifacts behind on the parent screen when we move
gui.Screen.request_full_screen_refresh = true
if not self.autoarrange_subviews then return end
local gap = self.autoarrange_gap
@ -465,7 +467,7 @@ function Panel:onRenderFrame(dc, rect)
gui.paint_frame(dc, rect, self.frame_style, self.frame_title)
if self.kbd_get_pos then
local pos = self.kbd_get_pos()
local pen = dfhack.pen.parse{fg=COLOR_GREEN, bg=COLOR_BLACK}
local pen = to_pen{fg=COLOR_GREEN, bg=COLOR_BLACK}
dc:seek(pos.x, pos.y):pen(pen):char(string.char(0xDB))
end
if self.drag_offset and not self.kbd_get_pos
@ -654,6 +656,12 @@ function EditField:onRenderBody(dc)
dc:string((' '):rep(dc.clip_x2 - dc.x))
end
function EditField:insert(text)
local old = self.text
self:setText(old:sub(1,self.cursor-1)..text..old:sub(self.cursor),
self.cursor + #text)
end
function EditField:onInput(keys)
if not self.focus then
-- only react to our hotkey
@ -676,22 +684,20 @@ function EditField:onInput(keys)
return true
end
if keys.SELECT then
if keys.SELECT or keys.CUSTOM_SHIFT_ENTER then
if self.key then
self:setFocus(false)
end
if self.on_submit then
self.on_submit(self.text)
return true
end
return not not self.key
elseif keys.SEC_SELECT then
if self.key then
self:setFocus(false)
end
if self.on_submit2 then
self.on_submit2(self.text)
return true
if keys.CUSTOM_SHIFT_ENTER then
if self.on_submit2 then
self.on_submit2(self.text)
return true
end
else
if self.on_submit then
self.on_submit(self.text)
return true
end
end
return not not self.key
elseif keys._MOUSE_L then
@ -712,8 +718,7 @@ function EditField:onInput(keys)
else
local cv = string.char(keys._STRING)
if not self.on_char or self.on_char(cv, old) then
self:setText(old:sub(1,self.cursor-1)..cv..old:sub(self.cursor),
self.cursor + 1)
self:insert(cv)
elseif self.on_char then
return self.modal
end
@ -722,25 +727,25 @@ function EditField:onInput(keys)
self.on_change(self.text, old)
end
return true
elseif keys.CURSOR_LEFT then
elseif keys.KEYBOARD_CURSOR_LEFT then
self:setCursor(self.cursor - 1)
return true
elseif keys.A_MOVE_W_DOWN then -- Ctrl-Left (end of prev word)
elseif keys.CUSTOM_CTRL_B then -- back one word
local _, prev_word_end = self.text:sub(1, self.cursor-1):
find('.*[%w_%-][^%w_%-]')
find('.*[%w_%-][^%w_%-]')
self:setCursor(prev_word_end or 1)
return true
elseif keys.A_CARE_MOVE_W then -- Alt-Left (home)
elseif keys.CUSTOM_CTRL_A then -- home
self:setCursor(1)
return true
elseif keys.CURSOR_RIGHT then
elseif keys.KEYBOARD_CURSOR_RIGHT then
self:setCursor(self.cursor + 1)
return true
elseif keys.A_MOVE_E_DOWN then -- Ctrl-Right (beginning of next word)
elseif keys.CUSTOM_CTRL_F then -- forward one word
local _,next_word_start = self.text:find('[^%w_%-][%w_%-]', self.cursor)
self:setCursor(next_word_start)
return true
elseif keys.A_CARE_MOVE_E then -- Alt-Right (end)
elseif keys.CUSTOM_CTRL_E then -- end
self:setCursor()
return true
end
@ -759,14 +764,12 @@ SCROLL_DELAY_MS = 20
Scrollbar = defclass(Scrollbar, Widget)
Scrollbar.ATTRS{
fg = COLOR_LIGHTGREEN,
bg = COLOR_CYAN,
on_scroll = DEFAULT_NIL,
}
function Scrollbar:preinit(init_table)
init_table.frame = init_table.frame or {}
init_table.frame.w = init_table.frame.w or 1
init_table.frame.w = init_table.frame.w or 2
end
function Scrollbar:init()
@ -824,36 +827,95 @@ local function scrollbar_is_visible(scrollbar)
return scrollbar.elems_per_page < scrollbar.num_elems
end
local UP_ARROW_CHAR = string.char(24)
local DOWN_ARROW_CHAR = string.char(25)
local NO_ARROW_CHAR = string.char(32)
local BAR_CHAR = string.char(7)
local BAR_BG_CHAR = string.char(179)
local SCROLLBAR_UP_LEFT_PEN = to_pen{tile=922, ch=47, fg=COLOR_CYAN, bg=COLOR_BLACK}
local SCROLLBAR_UP_RIGHT_PEN = to_pen{tile=923, ch=92, fg=COLOR_CYAN, bg=COLOR_BLACK}
local SCROLLBAR_DOWN_LEFT_PEN = to_pen{tile=946, ch=92, fg=COLOR_CYAN, bg=COLOR_BLACK}
local SCROLLBAR_DOWN_RIGHT_PEN = to_pen{tile=947, ch=47, fg=COLOR_CYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_UP_LEFT_PEN = to_pen{tile=930, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_UP_RIGHT_PEN = to_pen{tile=931, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_LEFT_PEN = to_pen{tile=954, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_RIGHT_PEN = to_pen{tile=955, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_CENTER_UP_LEFT_PEN = to_pen{tile=932, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_CENTER_UP_RIGHT_PEN = to_pen{tile=933, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_CENTER_DOWN_LEFT_PEN = to_pen{tile=960, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_CENTER_DOWN_RIGHT_PEN = to_pen{tile=961, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_CENTER_LEFT_PEN = to_pen{tile=940, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_CENTER_RIGHT_PEN = to_pen{tile=941, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_DOWN_LEFT_PEN = to_pen{tile=966, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_DOWN_RIGHT_PEN = to_pen{tile=967, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK}
local SCROLLBAR_UP_LEFT_HOVER_PEN = to_pen{tile=924, ch=47, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK}
local SCROLLBAR_UP_RIGHT_HOVER_PEN = to_pen{tile=925, ch=92, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK}
local SCROLLBAR_DOWN_LEFT_HOVER_PEN = to_pen{tile=936, ch=92, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK}
local SCROLLBAR_DOWN_RIGHT_HOVER_PEN = to_pen{tile=937, ch=47, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_UP_LEFT_HOVER_PEN = to_pen{tile=930, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_UP_RIGHT_HOVER_PEN = to_pen{tile=931, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_LEFT_HOVER_PEN = to_pen{tile=954, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_RIGHT_HOVER_PEN = to_pen{tile=955, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_CENTER_UP_LEFT_HOVER_PEN = to_pen{tile=956, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_CENTER_UP_RIGHT_HOVER_PEN = to_pen{tile=957, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_CENTER_DOWN_LEFT_HOVER_PEN = to_pen{tile=968, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_CENTER_DOWN_RIGHT_HOVER_PEN = to_pen{tile=969, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_CENTER_LEFT_HOVER_PEN = to_pen{tile=942, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_CENTER_RIGHT_HOVER_PEN = to_pen{tile=943, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_DOWN_LEFT_HOVER_PEN = to_pen{tile=966, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_DOWN_RIGHT_HOVER_PEN = to_pen{tile=967, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK}
local SCROLLBAR_BAR_BG_LEFT_PEN = to_pen{tile=934, ch=176, fg=COLOR_DARKGREY, bg=COLOR_BLACK}
local SCROLLBAR_BAR_BG_RIGHT_PEN = to_pen{tile=935, ch=176, fg=COLOR_DARKGREY, bg=COLOR_BLACK}
function Scrollbar:onRenderBody(dc)
-- don't draw if all elements are visible
if not scrollbar_is_visible(self) then
return
end
-- render up arrow if we're not at the top
dc:seek(0, 0):char(
self.top_elem == 1 and NO_ARROW_CHAR or UP_ARROW_CHAR, self.fg, self.bg)
-- determine which elements should be highlighted
local _,hover_y = self:getMousePos()
local hover_up, hover_down, hover_bar = false, false, false
if hover_y == 0 then
hover_up = true
elseif hover_y == dc.height-1 then
hover_down = true
elseif hover_y then
hover_bar = true
end
-- render up arrow
dc:seek(0, 0)
dc:char(nil, hover_up and SCROLLBAR_UP_LEFT_HOVER_PEN or SCROLLBAR_UP_LEFT_PEN)
dc:char(nil, hover_up and SCROLLBAR_UP_RIGHT_HOVER_PEN or SCROLLBAR_UP_RIGHT_PEN)
-- render scrollbar body
local starty = self.bar_offset + 1
local endy = self.bar_offset + self.bar_height
local midy = (starty + endy)/2
for y=1,dc.height-2 do
dc:seek(0, y)
if y >= starty and y <= endy then
dc:char(BAR_CHAR, self.fg)
if y == starty and y <= midy - 1 then
dc:char(nil, hover_bar and SCROLLBAR_BAR_UP_LEFT_HOVER_PEN or SCROLLBAR_BAR_UP_LEFT_PEN)
dc:char(nil, hover_bar and SCROLLBAR_BAR_UP_RIGHT_HOVER_PEN or SCROLLBAR_BAR_UP_RIGHT_PEN)
elseif y == midy - 0.5 then
dc:char(nil, hover_bar and SCROLLBAR_BAR_CENTER_UP_LEFT_HOVER_PEN or SCROLLBAR_BAR_CENTER_UP_LEFT_PEN)
dc:char(nil, hover_bar and SCROLLBAR_BAR_CENTER_UP_RIGHT_HOVER_PEN or SCROLLBAR_BAR_CENTER_UP_RIGHT_PEN)
elseif y == midy + 0.5 then
dc:char(nil, hover_bar and SCROLLBAR_BAR_CENTER_DOWN_LEFT_HOVER_PEN or SCROLLBAR_BAR_CENTER_DOWN_LEFT_PEN)
dc:char(nil, hover_bar and SCROLLBAR_BAR_CENTER_DOWN_RIGHT_HOVER_PEN or SCROLLBAR_BAR_CENTER_DOWN_RIGHT_PEN)
elseif y == midy then
dc:char(nil, hover_bar and SCROLLBAR_BAR_CENTER_LEFT_HOVER_PEN or SCROLLBAR_BAR_CENTER_LEFT_PEN)
dc:char(nil, hover_bar and SCROLLBAR_BAR_CENTER_RIGHT_HOVER_PEN or SCROLLBAR_BAR_CENTER_RIGHT_PEN)
elseif y == endy and y >= midy + 1 then
dc:char(nil, hover_bar and SCROLLBAR_BAR_DOWN_LEFT_HOVER_PEN or SCROLLBAR_BAR_DOWN_LEFT_PEN)
dc:char(nil, hover_bar and SCROLLBAR_BAR_DOWN_RIGHT_HOVER_PEN or SCROLLBAR_BAR_DOWN_RIGHT_PEN)
else
dc:char(nil, hover_bar and SCROLLBAR_BAR_LEFT_HOVER_PEN or SCROLLBAR_BAR_LEFT_PEN)
dc:char(nil, hover_bar and SCROLLBAR_BAR_RIGHT_HOVER_PEN or SCROLLBAR_BAR_RIGHT_PEN)
end
else
dc:char(BAR_BG_CHAR, self.bg)
dc:char(nil, SCROLLBAR_BAR_BG_LEFT_PEN)
dc:char(nil, SCROLLBAR_BAR_BG_RIGHT_PEN)
end
end
-- render down arrow if we're not at the bottom
local last_visible_el = self.top_elem + self.elems_per_page - 1
dc:seek(0, dc.height-1):char(
last_visible_el >= self.num_elems and NO_ARROW_CHAR or DOWN_ARROW_CHAR,
self.fg, self.bg)
-- render down arrow
dc:seek(0, dc.height-1)
dc:char(nil, hover_down and SCROLLBAR_DOWN_LEFT_HOVER_PEN or SCROLLBAR_DOWN_LEFT_PEN)
dc:char(nil, hover_down and SCROLLBAR_DOWN_RIGHT_HOVER_PEN or SCROLLBAR_DOWN_RIGHT_PEN)
if not self.on_scroll then return end
-- manage state for dragging and continuous scrolling
if self.is_dragging then
@ -877,10 +939,26 @@ function Scrollbar:onRenderBody(dc)
end
function Scrollbar:onInput(keys)
if not keys._MOUSE_L_DOWN or not self.on_scroll
or not scrollbar_is_visible(self) then
if not self.on_scroll or not scrollbar_is_visible(self) then
return false
end
if self.parent_view:getMousePos() then
if keys.CONTEXT_SCROLL_UP then
self.on_scroll('up_small')
return true
elseif keys.CONTEXT_SCROLL_DOWN then
self.on_scroll('down_small')
return true
elseif keys.CONTEXT_SCROLL_PAGEUP then
self.on_scroll('up_large')
return true
elseif keys.CONTEXT_SCROLL_PAGEDOWN then
self.on_scroll('down_large')
return true
end
end
if not keys._MOUSE_L_DOWN then return false end
local _,y = self:getMousePos()
if not y then return false end
local scroll_spec = nil
@ -988,13 +1066,13 @@ function render_text(obj,dc,x0,y0,pen,dpen,disabled)
if token.tile then
x = x + 1
if dc then
dc:char(nil, token.tile)
dc:tile(nil, token.tile)
end
end
if token.text or token.key then
local text = ''..(getval(token.text) or '')
local keypen = dfhack.pen.parse(token.key_pen or COLOR_LIGHTGREEN)
local keypen = to_pen(token.key_pen or COLOR_LIGHTGREEN)
if dc then
local tpen = getval(token.pen)
@ -1027,6 +1105,9 @@ function render_text(obj,dc,x0,y0,pen,dpen,disabled)
end
if token.key then
if type(token.key) == 'string' and not df.interface_key[token.key] then
error('Invalid interface_key: ' .. token.key)
end
local keystr = gui.getKeyDisplay(token.key)
local sep = token.key_sep or ''
@ -1244,7 +1325,7 @@ end
-- we can't set the text in init() since we may not yet have a frame that we
-- can get wrapping bounds from.
function WrappedLabel:postComputeFrame()
local wrapped_text = self:getWrappedText(self.frame_body.width-1)
local wrapped_text = self:getWrappedText(self.frame_body.width-3)
if not wrapped_text then return end
local text = {}
for _,line in ipairs(wrapped_text:split(NEWLINE)) do
@ -1619,12 +1700,14 @@ end
function List:submit()
if self.on_submit and #self.choices > 0 then
self.on_submit(self:getSelected())
return true
end
end
function List:submit2()
if self.on_submit2 and #self.choices > 0 then
self.on_submit2(self:getSelected())
return true
end
end
@ -1632,12 +1715,10 @@ function List:onInput(keys)
if self:inputToSubviews(keys) then
return true
end
if self.on_submit and keys.SELECT then
self:submit()
return true
elseif self.on_submit2 and keys.SEC_SELECT then
self:submit2()
return true
if keys.SELECT then
return self:submit()
elseif keys.CUSTOM_SHIFT_ENTER then
return self:submit2()
elseif keys._MOUSE_L_DOWN then
local idx = self:getIdxUnderMouse()
if idx then

@ -288,11 +288,11 @@ end
function make_own(unit)
--tweak makeown
unit.flags2.resident = false; unit.flags1.merchant = false; unit.flags1.forest = false;
unit.civ_id = df.global.ui.civ_id
unit.civ_id = df.global.plotinfo.civ_id
if unit.profession == df.profession.MERCHANT then unit.profession = df.profession.TRADER end
if unit.profession2 == df.profession.MERCHANT then unit.profession2 = df.profession.TRADER end
fix_clothing_ownership(unit)
if unit.race == df.global.ui.race_id then
if unit.race == df.global.plotinfo.race_id then
make_citizen(unit)
end
end

@ -81,14 +81,14 @@ using namespace DFHack;
#include "df/job_item.h"
#include "df/map_block.h"
#include "df/tile_occupancy.h"
#include "df/ui.h"
#include "df/plotinfost.h"
#include "df/ui_look_list.h"
#include "df/unit.h"
#include "df/unit_relationship_type.h"
#include "df/world.h"
using namespace df::enums;
using df::global::ui;
using df::global::plotinfo;
using df::global::world;
using df::global::d_init;
using df::global::building_next_id;
@ -425,7 +425,7 @@ df::building *Buildings::allocInstance(df::coord pos, df::building_type type, in
bld->y1 = bld->y2 = bld->centery = pos.y;
bld->z = pos.z;
bld->race = ui->race_id;
bld->race = plotinfo->race_id;
if (subtype != -1)
bld->setSubtype(subtype);
@ -989,7 +989,7 @@ static void linkRooms(df::building *bld)
}
if (changed)
df::global::ui->equipment.update.bits.buildings = true;
df::global::plotinfo->equipment.update.bits.buildings = true;
*/
}
@ -1238,7 +1238,7 @@ bool Buildings::constructWithFilters(df::building *bld, std::vector<df::job_item
bool Buildings::deconstruct(df::building *bld)
{
using df::global::ui;
using df::global::plotinfo;
using df::global::world;
using df::global::ui_look_list;
@ -1263,7 +1263,7 @@ bool Buildings::deconstruct(df::building *bld)
// Assume: no parties.
unlinkRooms(bld);
// Assume: not unit destroy target
vector_erase_at(ui->tax_collection.rooms, linear_index(ui->tax_collection.rooms, bld->id));
vector_erase_at(plotinfo->tax_collection.rooms, linear_index(plotinfo->tax_collection.rooms, bld->id));
// Assume: not used in punishment
// Assume: not used in non-own jobs
// Assume: does not affect pathfinding

@ -42,14 +42,14 @@ using namespace std;
#include "df/block_burrow_link.h"
#include "df/burrow.h"
#include "df/map_block.h"
#include "df/ui.h"
#include "df/plotinfost.h"
#include "df/world.h"
using namespace DFHack;
using namespace df::enums;
using df::global::world;
using df::global::ui;
using df::global::plotinfo;
df::burrow *Burrows::findByName(std::string name)
{
@ -76,15 +76,17 @@ void Burrows::clearUnits(df::burrow *burrow)
burrow->units.clear();
// Sync ui if active
if (ui && ui->main.mode == ui_sidebar_mode::Burrows &&
ui->burrows.in_add_units_mode && ui->burrows.sel_id == burrow->id)
/* TODO: understand how this changes for v50
// Sync plotinfo if active
if (plotinfo && plotinfo->main.mode == ui_sidebar_mode::Burrows &&
plotinfo->burrows.in_add_units_mode && plotinfo->burrows.sel_id == burrow->id)
{
auto &sel = ui->burrows.sel_units;
auto &sel = plotinfo->burrows.sel_units;
for (size_t i = 0; i < sel.size(); i++)
sel[i] = false;
}
*/
}
bool Burrows::isAssignedUnit(df::burrow *burrow, df::unit *unit)
@ -97,7 +99,7 @@ bool Burrows::isAssignedUnit(df::burrow *burrow, df::unit *unit)
void Burrows::setAssignedUnit(df::burrow *burrow, df::unit *unit, bool enable)
{
using df::global::ui;
using df::global::plotinfo;
CHECK_NULL_POINTER(unit);
CHECK_NULL_POINTER(burrow);
@ -113,14 +115,16 @@ void Burrows::setAssignedUnit(df::burrow *burrow, df::unit *unit, bool enable)
erase_from_vector(burrow->units, unit->id);
}
// Sync ui if active
if (ui && ui->main.mode == ui_sidebar_mode::Burrows &&
ui->burrows.in_add_units_mode && ui->burrows.sel_id == burrow->id)
/* TODO: understand how this changes for v50
// Sync plotinfo if active
if (plotinfo && plotinfo->main.mode == ui_sidebar_mode::Burrows &&
plotinfo->burrows.in_add_units_mode && plotinfo->burrows.sel_id == burrow->id)
{
int idx = linear_index(ui->burrows.list_units, unit);
int idx = linear_index(plotinfo->burrows.list_units, unit);
if (idx >= 0)
ui->burrows.sel_units[idx] = enable;
plotinfo->burrows.sel_units[idx] = enable;
}
*/
}
void Burrows::listBlocks(std::vector<df::map_block*> *pvec, df::burrow *burrow)

@ -0,0 +1,120 @@
#include "Internal.h"
#include "modules/DFSDL.h"
#include "Debug.h"
#include "PluginManager.h"
namespace DFHack {
DBG_DECLARE(core, dfsdl, DebugCategory::LINFO);
}
using namespace DFHack;
static DFLibrary *g_sdl_handle = nullptr;
static DFLibrary *g_sdl_image_handle = nullptr;
static const std::vector<std::string> SDL_LIBS {
"SDLreal.dll", // TODO: change to SDL.dll once we move to dfhooks
"SDL.framework/Versions/A/SDL",
"SDL.framework/SDL",
"libSDL-1.2.so.0"
};
static const std::vector<std::string> SDL_IMAGE_LIBS {
"SDL_image.dll",
"SDL_image.framework/Versions/A/SDL_image",
"SDL_image.framework/SDL_image",
"libSDL_image-1.2.so.0"
};
DFSDL_Surface * (*g_IMG_Load)(const char *) = nullptr;
int (*g_SDL_SetAlpha)(DFSDL_Surface *, uint32_t, uint8_t) = nullptr;
DFSDL_Surface * (*g_SDL_CreateRGBSurface)(uint32_t, int, int, int, uint32_t, uint32_t, uint32_t, uint32_t);
int (*g_SDL_UpperBlit)(DFSDL_Surface *, const DFSDL_Rect *, DFSDL_Surface *, DFSDL_Rect *);
DFSDL_Surface * (*g_SDL_ConvertSurface)(DFSDL_Surface *, const DFSDL_PixelFormat *, uint32_t);
void (*g_SDL_FreeSurface)(DFSDL_Surface *);
int (*g_SDL_SemWait)(DFSDL_sem *);
int (*g_SDL_SemPost)(DFSDL_sem *);
bool DFSDL::init(color_ostream &out) {
for (auto &lib_str : SDL_LIBS) {
if ((g_sdl_handle = OpenPlugin(lib_str.c_str())))
break;
}
if (!g_sdl_handle) {
out.printerr("DFHack could not find SDL\n");
return false;
}
for (auto &lib_str : SDL_IMAGE_LIBS) {
if ((g_sdl_image_handle = OpenPlugin(lib_str.c_str())))
break;
}
if (!g_sdl_image_handle) {
out.printerr("DFHack could not find SDL_image\n");
return false;
}
#define bind(handle, name) \
g_##name = (decltype(g_##name))LookupPlugin(handle, #name); \
if (!g_##name) { \
out.printerr("DFHack could not find: " #name "\n"); \
return false; \
}
bind(g_sdl_image_handle, IMG_Load);
bind(g_sdl_handle, SDL_SetAlpha);
bind(g_sdl_handle, SDL_CreateRGBSurface);
bind(g_sdl_handle, SDL_UpperBlit);
bind(g_sdl_handle, SDL_ConvertSurface);
bind(g_sdl_handle, SDL_FreeSurface);
bind(g_sdl_handle, SDL_SemWait);
bind(g_sdl_handle, SDL_SemPost);
#undef bind
DEBUG(dfsdl,out).print("sdl successfully loaded\n");
return true;
}
// It's ok to leave NULLs in the raws list (according to usage in g_src)
void DFSDL::cleanup() {
if (g_sdl_handle) {
ClosePlugin(g_sdl_handle);
g_sdl_handle = nullptr;
}
if (g_sdl_image_handle) {
ClosePlugin(g_sdl_image_handle);
g_sdl_image_handle = nullptr;
}
}
DFSDL_Surface * DFSDL::DFIMG_Load(const char *file) {
return g_IMG_Load(file);
}
int DFSDL::DFSDL_SetAlpha(DFSDL_Surface *surface, uint32_t flag, uint8_t alpha) {
return g_SDL_SetAlpha(surface, flag, alpha);
}
DFSDL_Surface * DFSDL::DFSDL_CreateRGBSurface(uint32_t flags, int width, int height, int depth, uint32_t Rmask, uint32_t Gmask, uint32_t Bmask, uint32_t Amask) {
return g_SDL_CreateRGBSurface(flags, width, height, depth, Rmask, Gmask, Bmask, Amask);
}
int DFSDL::DFSDL_UpperBlit(DFSDL_Surface *src, const DFSDL_Rect *srcrect, DFSDL_Surface *dst, DFSDL_Rect *dstrect) {
return g_SDL_UpperBlit(src, srcrect, dst, dstrect);
}
DFSDL_Surface * DFSDL::DFSDL_ConvertSurface(DFSDL_Surface *src, const DFSDL_PixelFormat *fmt, uint32_t flags) {
return g_SDL_ConvertSurface(src, fmt, flags);
}
void DFSDL::DFSDL_FreeSurface(DFSDL_Surface *surface) {
g_SDL_FreeSurface(surface);
}
int DFSDL::DFSDL_SemWait(DFSDL_sem *sem) {
return g_SDL_SemWait(sem);
}
int DFSDL::DFSDL_SemPost(DFSDL_sem *sem) {
return g_SDL_SemPost(sem);
}

@ -1,5 +1,6 @@
#include "Core.h"
#include "Console.h"
#include "Debug.h"
#include "VTableInterpose.h"
#include "modules/Buildings.h"
#include "modules/Constructions.h"
@ -26,7 +27,7 @@
#include "df/job.h"
#include "df/job_list_link.h"
#include "df/report.h"
#include "df/ui.h"
#include "df/plotinfost.h"
#include "df/unit.h"
#include "df/unit_flags1.h"
#include "df/unit_inventory_item.h"
@ -43,6 +44,10 @@
#include <unordered_set>
#include <array>
namespace DFHack {
DBG_DECLARE(eventmanager, log, DebugCategory::LINFO);
}
using namespace std;
using namespace DFHack;
using namespace EventManager;
@ -63,6 +68,7 @@ static int32_t eventLastTick[EventType::EVENT_MAX];
static const int32_t ticksPerYear = 403200;
void DFHack::EventManager::registerListener(EventType::EventType e, EventHandler handler, Plugin* plugin) {
DEBUG(log).print("registering handler %p from plugin %s for event %d\n", handler.eventHandler, plugin->getName().c_str(), e);
handlers[e].insert(pair<Plugin*, EventHandler>(plugin, handler));
}
@ -78,6 +84,7 @@ int32_t DFHack::EventManager::registerTick(EventHandler handler, int32_t when, P
}
handler.freq = when;
tickQueue.insert(pair<int32_t, EventHandler>(handler.freq, handler));
DEBUG(log).print("registering handler %p from plugin %s for event TICK\n", handler.eventHandler, plugin->getName().c_str());
handlers[EventType::TICK].insert(pair<Plugin*,EventHandler>(plugin,handler));
return when;
}
@ -103,6 +110,7 @@ void DFHack::EventManager::unregister(EventType::EventType e, EventHandler handl
i++;
continue;
}
DEBUG(log).print("unregistering handler %p from plugin %s for event %d\n", handler.eventHandler, plugin->getName().c_str(), e);
i = handlers[e].erase(i);
if ( e == EventType::TICK )
removeFromTickQueue(handler);
@ -110,6 +118,7 @@ void DFHack::EventManager::unregister(EventType::EventType e, EventHandler handl
}
void DFHack::EventManager::unregisterAll(Plugin* plugin) {
DEBUG(log).print("unregistering all handlers for plugin %s\n", plugin->getName().c_str());
for ( auto i = handlers[EventType::TICK].find(plugin); i != handlers[EventType::TICK].end(); i++ ) {
if ( (*i).first != plugin )
break;
@ -268,6 +277,7 @@ void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event
multimap<Plugin*,EventHandler> copy(handlers[EventType::UNLOAD].begin(), handlers[EventType::UNLOAD].end());
for (auto &key_value : copy) {
DEBUG(log,out).print("calling handler for map unloaded state change event\n");
key_value.second.eventHandler(out, nullptr);
}
} else if ( event == DFHack::SC_MAP_LOADED ) {
@ -287,14 +297,14 @@ void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event
return;
if (!df::global::job_next_id)
return;
if (!df::global::ui)
if (!df::global::plotinfo)
return;
if (!df::global::world)
return;
nextItem = *df::global::item_next_id;
nextBuilding = *df::global::building_next_id;
nextInvasion = df::global::ui->invasions.next_id;
nextInvasion = df::global::plotinfo->invasions.next_id;
lastJobId = -1 + *df::global::job_next_id;
constructions.clear();
@ -358,6 +368,7 @@ void DFHack::EventManager::manageEvents(color_ostream& out) {
CoreSuspender suspender;
int32_t tick = df::global::world->frame_counter;
TRACE(log,out).print("processing events at tick %d\n", tick);
for ( size_t a = 0; a < EventType::EVENT_MAX; a++ ) {
if ( handlers[a].empty() )
@ -389,6 +400,7 @@ static void manageTickEvent(color_ostream& out) {
break;
EventHandler &handle = (*tickQueue.begin()).second;
tickQueue.erase(tickQueue.begin());
DEBUG(log,out).print("calling handler for tick event\n");
handle.eventHandler(out, (void*)intptr_t(tick));
toRemove.insert(handle);
}
@ -429,6 +441,7 @@ static void manageJobInitiatedEvent(color_ostream& out) {
continue;
for (auto &key_value : copy) {
EventHandler &handle = key_value.second;
DEBUG(log,out).print("calling handler for job initiated event\n");
handle.eventHandler(out, (void*)link->item);
}
}
@ -451,6 +464,7 @@ static void manageJobStartedEvent(color_ostream& out) {
for (auto &key_value : copy) {
auto &handler = key_value.second;
// the jobs must have a worker to start
DEBUG(log,out).print("calling handler for job started event\n");
handler.eventHandler(out, job);
}
}
@ -561,6 +575,7 @@ static void manageJobCompletedEvent(color_ostream& out) {
//still false positive if cancelled at EXACTLY the right time, but experiments show this doesn't happen
for (auto &key_value : copy) {
EventHandler &handle = key_value.second;
DEBUG(log,out).print("calling handler for repeated job completed event\n");
handle.eventHandler(out, (void*)&job0);
}
continue;
@ -573,6 +588,7 @@ static void manageJobCompletedEvent(color_ostream& out) {
for (auto &key_value : copy) {
EventHandler &handle = key_value.second;
DEBUG(log,out).print("calling handler for job completed event\n");
handle.eventHandler(out, (void*)&job0);
}
}
@ -607,6 +623,7 @@ static void manageNewUnitActiveEvent(color_ostream& out) {
int32_t id = unit->id;
if (!activeUnits.count(id)) {
activeUnits.emplace(id);
DEBUG(log,out).print("calling handler for new unit event\n");
handler.eventHandler(out, (void*) intptr_t(id)); // intptr_t() avoids cast from smaller type warning
}
}
@ -630,6 +647,7 @@ static void manageUnitDeathEvent(color_ostream& out) {
for (auto &key_value : copy) {
EventHandler &handle = key_value.second;
DEBUG(log,out).print("calling handler for unit death event\n");
handle.eventHandler(out, (void*)intptr_t(unit->id));
}
livingUnits.erase(unit->id);
@ -667,6 +685,7 @@ static void manageItemCreationEvent(color_ostream& out) {
continue;
for (auto &key_value : copy) {
EventHandler &handle = key_value.second;
DEBUG(log,out).print("calling handler for item created event\n");
handle.eventHandler(out, (void*)intptr_t(item->id));
}
}
@ -694,6 +713,7 @@ static void manageBuildingEvent(color_ostream& out) {
buildings.insert(a);
for (auto &key_value : copy) {
EventHandler &handle = key_value.second;
DEBUG(log,out).print("calling handler for created building event\n");
handle.eventHandler(out, (void*)intptr_t(a));
}
}
@ -710,6 +730,7 @@ static void manageBuildingEvent(color_ostream& out) {
for (auto &key_value : copy) {
EventHandler &handle = key_value.second;
DEBUG(log,out).print("calling handler for destroyed building event\n");
handle.eventHandler(out, (void*)intptr_t(id));
}
a = buildings.erase(a);
@ -733,6 +754,7 @@ static void manageConstructionEvent(color_ostream& out) {
// send construction to handlers, because it was removed
for (const auto &key_value: copy) {
EventHandler handle = key_value.second;
DEBUG(log,out).print("calling handler for destroyed construction event\n");
handle.eventHandler(out, (void*) &construction);
}
// erase from existent constructions
@ -747,6 +769,7 @@ static void manageConstructionEvent(color_ostream& out) {
// send construction to handlers, because it is new
for (const auto &key_value: copy) {
EventHandler handle = key_value.second;
DEBUG(log,out).print("calling handler for created construction event\n");
handle.eventHandler(out, (void*) &construction);
}
}
@ -775,6 +798,7 @@ static void manageSyndromeEvent(color_ostream& out) {
SyndromeData data(unit->id, b);
for (auto &key_value : copy) {
EventHandler &handle = key_value.second;
DEBUG(log,out).print("calling handler for syndrome event\n");
handle.eventHandler(out, (void*)&data);
}
}
@ -783,16 +807,17 @@ static void manageSyndromeEvent(color_ostream& out) {
}
static void manageInvasionEvent(color_ostream& out) {
if (!df::global::ui)
if (!df::global::plotinfo)
return;
multimap<Plugin*,EventHandler> copy(handlers[EventType::INVASION].begin(), handlers[EventType::INVASION].end());
if ( df::global::ui->invasions.next_id <= nextInvasion )
if ( df::global::plotinfo->invasions.next_id <= nextInvasion )
return;
nextInvasion = df::global::ui->invasions.next_id;
nextInvasion = df::global::plotinfo->invasions.next_id;
for (auto &key_value : copy) {
EventHandler &handle = key_value.second;
DEBUG(log,out).print("calling handler for invasion event\n");
handle.eventHandler(out, (void*)intptr_t(nextInvasion-1));
}
}
@ -834,6 +859,7 @@ static void manageEquipmentEvent(color_ostream& out) {
InventoryChangeData data(unit->id, nullptr, &item_new);
for (auto &key_value : copy) {
EventHandler &handle = key_value.second;
DEBUG(log,out).print("calling handler for new item equipped inventory change event\n");
handle.eventHandler(out, (void*)&data);
}
continue;
@ -849,6 +875,7 @@ static void manageEquipmentEvent(color_ostream& out) {
InventoryChangeData data(unit->id, &item_old, &item_new);
for (auto &key_value : copy) {
EventHandler &handle = key_value.second;
DEBUG(log,out).print("calling handler for inventory change event\n");
handle.eventHandler(out, (void*)&data);
}
}
@ -860,6 +887,7 @@ static void manageEquipmentEvent(color_ostream& out) {
InventoryChangeData data(unit->id, &i, nullptr);
for (auto &key_value : copy) {
EventHandler &handle = key_value.second;
DEBUG(log,out).print("calling handler for dropped item inventory change event\n");
handle.eventHandler(out, (void*)&data);
}
}
@ -913,6 +941,7 @@ static void manageReportEvent(color_ostream& out) {
df::report* report = reports[idx];
for (auto &key_value : copy) {
EventHandler &handle = key_value.second;
DEBUG(log,out).print("calling handler for report event\n");
handle.eventHandler(out, (void*)intptr_t(report->id));
}
lastReport = report->id;
@ -990,6 +1019,7 @@ static void manageUnitAttackEvent(color_ostream& out) {
alreadyDone[data.attacker][data.defender] = 1;
for (auto &key_value : copy) {
EventHandler &handle = key_value.second;
DEBUG(log,out).print("calling handler for unit1 attack unit attack event\n");
handle.eventHandler(out, (void*)&data);
}
}
@ -1002,6 +1032,7 @@ static void manageUnitAttackEvent(color_ostream& out) {
alreadyDone[data.attacker][data.defender] = 1;
for (auto &key_value : copy) {
EventHandler &handle = key_value.second;
DEBUG(log,out).print("calling handler for unit2 attack unit attack event\n");
handle.eventHandler(out, (void*)&data);
}
}
@ -1013,6 +1044,7 @@ static void manageUnitAttackEvent(color_ostream& out) {
alreadyDone[data.attacker][data.defender] = 1;
for (auto &key_value : copy) {
EventHandler &handle = key_value.second;
DEBUG(log,out).print("calling handler for unit1 killed unit attack event\n");
handle.eventHandler(out, (void*)&data);
}
}
@ -1024,6 +1056,7 @@ static void manageUnitAttackEvent(color_ostream& out) {
alreadyDone[data.attacker][data.defender] = 1;
for (auto &key_value : copy) {
EventHandler &handle = key_value.second;
DEBUG(log,out).print("calling handler for unit2 killed unit attack event\n");
handle.eventHandler(out, (void*)&data);
}
}
@ -1282,6 +1315,7 @@ static void manageInteractionEvent(color_ostream& out) {
//fire event
for (auto &key_value : copy) {
EventHandler &handle = key_value.second;
DEBUG(log,out).print("calling handler for interaction event\n");
handle.eventHandler(out, (void*)&data);
}
//TODO: deduce attacker from latest defend event first

@ -61,12 +61,12 @@ using namespace DFHack;
#include "df/general_ref.h"
#include "df/global_objects.h"
#include "df/graphic.h"
#include "df/graphic_viewportst.h"
#include "df/historical_figure.h"
#include "df/interfacest.h"
#include "df/item_corpsepiecest.h"
#include "df/item_corpsest.h"
#include "df/job.h"
#include "df/layer_object_listst.h"
#include "df/occupation.h"
#include "df/plant.h"
#include "df/popup_message.h"
@ -74,10 +74,10 @@ using namespace DFHack;
#include "df/report_zoom_type.h"
#include "df/route_stockpile_link.h"
#include "df/stop_depart_condition.h"
#include "df/ui_advmode.h"
#include "df/ui_build_selector.h"
#include "df/adventurest.h"
#include "df/buildreq.h"
#include "df/ui_look_list.h"
#include "df/ui_sidebar_menus.h"
#include "df/gamest.h"
#include "df/ui_unit_view_mode.h"
#include "df/unit.h"
#include "df/unit_inventory_item.h"
@ -101,9 +101,9 @@ using df::global::gps;
using df::global::gview;
using df::global::init;
using df::global::selection_rect;
using df::global::ui;
using df::global::plotinfo;
using df::global::ui_menu_width;
using df::global::ui_sidebar_menus;
using df::global::game;
using df::global::world;
/* TODO: understand how this changes for v50
@ -143,6 +143,7 @@ static std::map<virtual_identity*, getFocusStringHandler> getFocusStringHandlers
DEFINE_GET_FOCUS_STRING_HANDLER(dwarfmode)
{
/* TODO: understand how this changes for v50
using namespace df::enums::ui_sidebar_mode;
using df::global::ui_workshop_in_add;
@ -157,9 +158,9 @@ DEFINE_GET_FOCUS_STRING_HANDLER(dwarfmode)
using df::global::ui_building_assign_items;
using df::global::ui_building_in_assign;
focus += "/" + enum_item_key(ui->main.mode);
focus += "/" + enum_item_key(plotinfo->main.mode);
switch (ui->main.mode)
switch (plotinfo->main.mode)
{
case QueryBuilding:
if (df::building *selected = world->selected_building)
@ -303,39 +304,38 @@ DEFINE_GET_FOCUS_STRING_HANDLER(dwarfmode)
break;
case Burrows:
if (ui->burrows.in_confirm_delete)
if (plotinfo->burrows.in_confirm_delete)
focus += "/ConfirmDelete";
else if (ui->burrows.in_add_units_mode)
else if (plotinfo->burrows.in_add_units_mode)
focus += "/AddUnits";
else if (ui->burrows.in_edit_name_mode)
else if (plotinfo->burrows.in_edit_name_mode)
focus += "/EditName";
else if (ui->burrows.in_define_mode)
else if (plotinfo->burrows.in_define_mode)
focus += "/Define";
else
focus += "/List";
break;
/* TODO: understand how this changes for v50
case Hauling:
if (ui->hauling.in_assign_vehicle)
if (plotinfo->hauling.in_assign_vehicle)
{
auto vehicle = vector_get(ui->hauling.vehicles, ui->hauling.cursor_vehicle);
auto vehicle = vector_get(plotinfo->hauling.vehicles, plotinfo->hauling.cursor_vehicle);
focus += "/AssignVehicle/" + std::string(vehicle ? "Some" : "None");
}
else
{
int idx = ui->hauling.cursor_top;
auto route = vector_get(ui->hauling.view_routes, idx);
auto stop = vector_get(ui->hauling.view_stops, idx);
int idx = plotinfo->hauling.cursor_top;
auto route = vector_get(plotinfo->hauling.view_routes, idx);
auto stop = vector_get(plotinfo->hauling.view_stops, idx);
std::string tag = stop ? "Stop" : (route ? "Route" : "None");
if (ui->hauling.in_name)
if (plotinfo->hauling.in_name)
focus += "/Rename/" + tag;
else if (ui->hauling.in_stop)
else if (plotinfo->hauling.in_stop)
{
int sidx = ui->hauling.cursor_stop;
auto cond = vector_get(ui->hauling.stop_conditions, sidx);
auto link = vector_get(ui->hauling.stop_links, sidx);
int sidx = plotinfo->hauling.cursor_stop;
auto cond = vector_get(plotinfo->hauling.stop_conditions, sidx);
auto link = vector_get(plotinfo->hauling.stop_links, sidx);
focus += "/DefineStop";
@ -354,22 +354,22 @@ DEFINE_GET_FOCUS_STRING_HANDLER(dwarfmode)
focus += "/Select/" + tag;
}
break;
*/
default:
break;
}
*/
}
/* TODO: understand how this changes for v50
DEFINE_GET_FOCUS_STRING_HANDLER(dungeonmode)
{
using df::global::ui_advmode;
using df::global::adventure;
if (!ui_advmode)
if (!adventure)
return;
focus += "/" + enum_item_key(ui_advmode->menu);
focus += "/" + enum_item_key(adventure->menu);
}
DEFINE_GET_FOCUS_STRING_HANDLER(unitlist)
@ -667,14 +667,15 @@ bool Gui::cursor_hotkey(df::viewscreen *top)
bool Gui::workshop_job_hotkey(df::viewscreen *top)
{
if (!dwarfmode_hotkey(top))
return false;
/* TODO: understand how this changes for v50
using namespace ui_sidebar_mode;
using df::global::ui_workshop_in_add;
using df::global::ui_workshop_job_cursor;
if (!dwarfmode_hotkey(top))
return false;
switch (ui->main.mode) {
switch (plotinfo->main.mode) {
case QueryBuilding:
{
if (!ui_workshop_job_cursor) // allow missing
@ -699,17 +700,19 @@ bool Gui::workshop_job_hotkey(df::viewscreen *top)
default:
return false;
}
*/ return false;
}
bool Gui::build_selector_hotkey(df::viewscreen *top)
{
using namespace ui_sidebar_mode;
using df::global::ui_build_selector;
if (!dwarfmode_hotkey(top))
return false;
switch (ui->main.mode) {
/* TODO: understand how this changes for v50
using namespace ui_sidebar_mode;
using df::global::ui_build_selector;
switch (plotinfo->main.mode) {
case Build:
{
if (!ui_build_selector) // allow missing
@ -726,20 +729,23 @@ bool Gui::build_selector_hotkey(df::viewscreen *top)
default:
return false;
}
*/ return false;
}
bool Gui::view_unit_hotkey(df::viewscreen *top)
{
using df::global::ui_selected_unit;
if (!dwarfmode_hotkey(top))
return false;
if (ui->main.mode != ui_sidebar_mode::ViewUnits)
/* TODO: understand how this changes for v50
using df::global::ui_selected_unit;
if (plotinfo->main.mode != ui_sidebar_mode::ViewUnits)
return false;
if (!ui_selected_unit) // allow missing
return false;
return vector_get(world->units.active, *ui_selected_unit) != NULL;
*/ return false;
}
bool Gui::unit_inventory_hotkey(df::viewscreen *top)
@ -826,6 +832,7 @@ df::job *Gui::getSelectedJob(color_ostream &out, bool quiet)
df::unit *Gui::getAnyUnit(df::viewscreen *top)
{
/* TODO: understand how this changes for v50
using namespace ui_sidebar_mode;
using df::global::ui_look_cursor;
using df::global::ui_look_list;
@ -834,7 +841,6 @@ df::unit *Gui::getAnyUnit(df::viewscreen *top)
using df::global::ui_building_assign_units;
using df::global::ui_building_item_cursor;
/* TODO: understand how this changes for v50
if (VIRTUAL_CAST_VAR(screen, df::viewscreen_unitst, top))
{
return screen->unit;
@ -1011,19 +1017,19 @@ df::unit *Gui::getAnyUnit(df::viewscreen *top)
if (!Gui::dwarfmode_hotkey(top))
return NULL;
if (!ui)
if (!plotinfo)
return NULL;
// general assigning units in building, i.e. (q)uery cage -> (a)ssign
if (ui_building_in_assign && *ui_building_in_assign
&& ui_building_assign_units && ui_building_item_cursor
&& ui->main.mode != Zones) // dont show for (i) zone
&& plotinfo->main.mode != Zones) // dont show for (i) zone
return vector_get(*ui_building_assign_units, *ui_building_item_cursor);
if (ui->follow_unit != -1)
return df::unit::find(ui->follow_unit);
if (plotinfo->follow_unit != -1)
return df::unit::find(plotinfo->follow_unit);
switch (ui->main.mode) {
switch (plotinfo->main.mode) {
case ViewUnits:
{
if (!ui_selected_unit || !world)
@ -1041,8 +1047,8 @@ df::unit *Gui::getAnyUnit(df::viewscreen *top)
}
case Burrows:
{
if (ui->burrows.in_add_units_mode)
return vector_get(ui->burrows.list_units, ui->burrows.unit_cursor_pos);
if (plotinfo->burrows.in_add_units_mode)
return vector_get(plotinfo->burrows.list_units, plotinfo->burrows.unit_cursor_pos);
return NULL;
}
@ -1108,13 +1114,13 @@ df::unit *Gui::getSelectedUnit(color_ostream &out, bool quiet)
df::item *Gui::getAnyItem(df::viewscreen *top)
{
/* TODO: understand how this changes for v50
using namespace ui_sidebar_mode;
using df::global::ui_look_cursor;
using df::global::ui_look_list;
using df::global::ui_unit_view_mode;
using df::global::ui_building_item_cursor;
/* TODO: understand how this changes for v50
if (VIRTUAL_CAST_VAR(screen, df::viewscreen_textviewerst, top))
{
// return the main item if the parent screen is a viewscreen_itemst
@ -1190,16 +1196,16 @@ df::item *Gui::getAnyItem(df::viewscreen *top)
if (!Gui::dwarfmode_hotkey(top))
return NULL;
switch (ui->main.mode) {
switch (plotinfo->main.mode) {
case ViewUnits:
{
if (!ui_unit_view_mode || !ui_look_cursor || !ui_sidebar_menus)
if (!ui_unit_view_mode || !ui_look_cursor || !game)
return NULL;
if (ui_unit_view_mode->value != df::ui_unit_view_mode::Inventory)
return NULL;
auto inv_item = vector_get(ui_sidebar_menus->unit.inv_items, *ui_look_cursor);
auto inv_item = vector_get(game->unit.inv_items, *ui_look_cursor);
return inv_item ? inv_item->item : NULL;
}
case LookAround:
@ -1248,11 +1254,11 @@ df::item *Gui::getSelectedItem(color_ostream &out, bool quiet)
df::building *Gui::getAnyBuilding(df::viewscreen *top)
{
/* TODO: understand how this changes for v50
using namespace ui_sidebar_mode;
using df::global::ui_look_list;
using df::global::ui_look_cursor;
/* TODO: understand how this changes for v50
if (VIRTUAL_CAST_VAR(screen, df::viewscreen_buildinglistst, top))
return vector_get(screen->buildings, screen->cursor);
@ -1265,7 +1271,7 @@ df::building *Gui::getAnyBuilding(df::viewscreen *top)
if (!Gui::dwarfmode_hotkey(top))
return NULL;
switch (ui->main.mode) {
switch (plotinfo->main.mode) {
case LookAround:
{
if (!ui_look_list || !ui_look_cursor)
@ -1287,8 +1293,8 @@ df::building *Gui::getAnyBuilding(df::viewscreen *top)
case ZonesPitInfo:
case ZonesHospitalInfo:
{
if (ui_sidebar_menus)
return ui_sidebar_menus->zone.selected;
if (game)
return game->zone.selected;
return NULL;
}
default:
@ -1321,13 +1327,15 @@ df::plant *Gui::getAnyPlant(df::viewscreen *top)
if (Gui::dwarfmode_hotkey(top))
{
if (!cursor || !ui || !world)
if (!cursor || !plotinfo || !world)
return nullptr;
if (ui->main.mode == ui_sidebar_mode::LookAround)
/* TODO: understand how this changes for v50
if (plotinfo->main.mode == ui_sidebar_mode::LookAround)
{
return Maps::getPlantAtTile(cursor->x, cursor->y, cursor->z);
}
*/
}
return nullptr;
@ -1865,6 +1873,12 @@ bool Gui::autoDFAnnouncement(df::announcement_type type, df::coord pos, std::str
return autoDFAnnouncement(r, message);
}
static df::viewscreen * do_skip_dismissed(df::viewscreen * ws) {
while (ws && Screen::isDismissed(ws) && ws->parent)
ws = ws->parent;
return ws;
}
df::viewscreen *Gui::getCurViewscreen(bool skip_dismissed)
{
if (!gview)
@ -1875,10 +1889,7 @@ df::viewscreen *Gui::getCurViewscreen(bool skip_dismissed)
ws = ws->child;
if (skip_dismissed)
{
while (ws && Screen::isDismissed(ws) && ws->parent)
ws = ws->parent;
}
ws = do_skip_dismissed(ws);
return ws;
}
@ -1898,6 +1909,16 @@ df::viewscreen *Gui::getViewscreenByIdentity (virtual_identity &id, int n)
return NULL;
}
df::viewscreen *Gui::getDFViewscreen(bool skip_dismissed) {
df::viewscreen *screen = Gui::getCurViewscreen(skip_dismissed);
while (screen && dfhack_viewscreen::is_instance(screen)) {
screen = screen->parent;
if (skip_dismissed)
screen = do_skip_dismissed(screen);
}
return screen;
}
df::coord Gui::getViewportPos()
{
if (!df::global::window_x || !df::global::window_y || !df::global::window_z)
@ -1919,47 +1940,14 @@ Gui::DwarfmodeDims getDwarfmodeViewDims_default()
{
Gui::DwarfmodeDims dims;
auto ws = Screen::getWindowSize();
dims.y1 = 1;
dims.y2 = ws.y-2;
dims.map_x1 = 1;
dims.map_x2 = ws.x-2;
dims.map_y1 = dims.y1;
dims.map_y2 = dims.y2;
dims.area_x1 = dims.area_x2 = dims.menu_x1 = dims.menu_x2 = -1;
dims.menu_forced = false;
bool use_graphics = Screen::inGraphicsMode();
auto dimx = use_graphics ? gps->main_viewport->dim_x : gps->dimx;
auto dimy = use_graphics ? gps->main_viewport->dim_y : gps->dimy;
int menu_pos = (ui_menu_width ? (*ui_menu_width)[0] : 2);
int area_pos = (ui_menu_width ? (*ui_menu_width)[1] : 3);
if (ui && ui->main.mode != ui_sidebar_mode::Default && ui->main.mode != ui_sidebar_mode::ArenaWeather && menu_pos >= area_pos)
{
dims.menu_forced = true;
menu_pos = area_pos-1;
}
dims.area_on = (area_pos < 3);
dims.menu_on = (menu_pos < area_pos);
if (dims.menu_on)
{
dims.menu_x2 = ws.x - 2;
dims.menu_x1 = dims.menu_x2 - Gui::MENU_WIDTH + 1;
if (menu_pos == 1)
dims.menu_x1 -= Gui::AREA_MAP_WIDTH + 1;
dims.map_x2 = dims.menu_x1 - 2;
}
if (dims.area_on)
{
dims.area_x2 = ws.x-2;
dims.area_x1 = dims.area_x2 - Gui::AREA_MAP_WIDTH + 1;
if (dims.menu_on)
dims.menu_x2 = dims.area_x1 - 2;
else
dims.map_x2 = dims.area_x1 - 2;
}
dims.map_x1 = 0;
dims.map_x2 = dimx - 1;
dims.map_y1 = 0;
dims.map_y2 = dimy - 1;
return dims;
}
@ -1974,11 +1962,13 @@ void Gui::resetDwarfmodeView(bool pause)
{
using df::global::cursor;
if (ui)
if (plotinfo)
{
ui->follow_unit = -1;
ui->follow_item = -1;
ui->main.mode = ui_sidebar_mode::Default;
plotinfo->follow_unit = -1;
plotinfo->follow_item = -1;
/* TODO: understand how this changes for v50
plotinfo->main.mode = ui_sidebar_mode::Default;
*/
}
if (selection_rect)
@ -2034,8 +2024,8 @@ bool Gui::revealInDwarfmodeMap(int32_t x, int32_t y, int32_t z, bool center)
*window_x = clip_range(new_win_x, 0, (world->map.x_count - w));
*window_y = clip_range(new_win_y, 0, (world->map.y_count - h));
*window_z = clip_range(new_win_z, 0, (world->map.z_count - 1));
ui_sidebar_menus->minimap.need_render = true;
ui_sidebar_menus->minimap.need_scan = true;
game->minimap.need_render = true;
game->minimap.need_scan = true;
return true;
}
@ -2081,10 +2071,10 @@ bool Gui::refreshSidebar()
bool Gui::inRenameBuilding()
{
if (!ui_sidebar_menus)
if (!game)
return false;
/* TODO: understand how this changes for v50
return ui_sidebar_menus->barracks.in_rename;
return game->barracks.in_rename;
*/
return false;
}
@ -2150,24 +2140,33 @@ bool Gui::setDesignationCoords (const int32_t x, const int32_t y, const int32_t
df::coord Gui::getMousePos()
{
df::coord pos;
/* TODO: understand how this changes for v50
if (gps && gps->mouse_x > -1) {
// return invalid coords if the cursor is not over the map
DwarfmodeDims dims = getDwarfmodeViewDims();
if (gps->mouse_x < dims.map_x1 || gps->mouse_x > dims.map_x2 ||
gps->mouse_y < dims.map_y1 || gps->mouse_y > dims.map_y2) {
return pos;
}
if (gps && gps->precise_mouse_x > -1) {
pos = getViewportPos();
pos.x += gps->mouse_x - 1;
pos.y += gps->mouse_y - 1;
if (Screen::inGraphicsMode()) {
int32_t map_tile_pixels = gps->viewport_zoom_factor / 4;
pos.x += gps->precise_mouse_x / map_tile_pixels;
pos.y += gps->precise_mouse_y / map_tile_pixels;
} else {
pos.x += gps->mouse_x;
pos.y += gps->mouse_y;
}
}
*/
if (!Maps::isValidTilePos(pos.x, pos.y, pos.z))
return df::coord();
return pos;
}
int getDepthAt_default (int32_t x, int32_t y)
{
auto &main_vp = gps->main_viewport;
if (x < 0 || x >= main_vp->dim_x || y < 0 || y >= main_vp->dim_y)
return 0;
const size_t num_viewports = gps->viewport.size();
const size_t index = (x * main_vp->dim_y) + y;
for (size_t depth = 0; depth < num_viewports; ++depth) {
if (gps->viewport[depth]->screentexpos_background[index])
return depth;
}
return 0;
}
@ -2190,17 +2189,3 @@ bool Gui::getWindowSize (int32_t &width, int32_t &height)
return false;
}
}
bool Gui::getMenuWidth(uint8_t &menu_width, uint8_t &area_map_width)
{
menu_width = (*ui_menu_width)[0];
area_map_width = (*ui_menu_width)[1];
return true;
}
bool Gui::setMenuWidth(const uint8_t menu_width, const uint8_t area_map_width)
{
(*ui_menu_width)[0] = menu_width;
(*ui_menu_width)[1] = area_map_width;
return true;
}

@ -87,7 +87,7 @@ using namespace std;
#include "df/reaction_product_itemst.h"
#include "df/tool_uses.h"
#include "df/trapcomp_flags.h"
#include "df/ui.h"
#include "df/plotinfost.h"
#include "df/unit.h"
#include "df/unit_inventory_item.h"
#include "df/vehicle.h"
@ -100,7 +100,7 @@ using namespace std;
using namespace DFHack;
using namespace df::enums;
using df::global::world;
using df::global::ui;
using df::global::plotinfo;
using df::global::ui_selected_unit;
using df::global::proj_next_id;
@ -922,11 +922,13 @@ static bool detachItem(MapExtras::MapCache &mc, df::item *item)
case general_ref_type::UNIT_HOLDER:
if (auto unit = ref->getUnit())
{
/* TODO: understand how this changes for v50
// Unit view sidebar holds inventory item pointers
if (ui->main.mode == ui_sidebar_mode::ViewUnits &&
if (plotinfo->main.mode == ui_sidebar_mode::ViewUnits &&
(!ui_selected_unit ||
vector_get(world->units.active, *ui_selected_unit) == unit))
return false;
*/
for (int i = unit->inventory.size()-1; i >= 0; i--)
{
@ -1532,7 +1534,7 @@ int32_t Items::createItem(df::item_type item_type, int16_t item_subtype, int16_t
df::enums::game_type::game_type type = *df::global::gametype;
prod->produce(unit, &out_products, &out_items, &in_reag, &in_items, 1, job_skill::NONE,
0, df::historical_entity::find(unit->civ_id),
((type == df::enums::game_type::DWARF_MAIN) || (type == df::enums::game_type::DWARF_RECLAIM)) ? df::world_site::find(df::global::ui->site_id) : NULL,
((type == df::enums::game_type::DWARF_MAIN) || (type == df::enums::game_type::DWARF_RECLAIM)) ? df::world_site::find(df::global::plotinfo->site_id) : NULL,
NULL);
if ( out_items.size() != 1 )
return -1;
@ -1641,9 +1643,9 @@ bool Items::isRouteVehicle(df::item *item)
bool Items::isSquadEquipment(df::item *item)
{
CHECK_NULL_POINTER(item);
if (!ui)
if (!plotinfo)
return false;
auto &vec = ui->equipment.items_assigned[item->getType()];
auto &vec = plotinfo->equipment.items_assigned[item->getType()];
return binsearch_index(vec, &df::item::id, item->id) >= 0;
}

@ -43,7 +43,7 @@ using namespace std;
#include "DataDefs.h"
#include "df/world.h"
#include "df/ui.h"
#include "df/plotinfost.h"
#include "df/unit.h"
#include "df/building.h"
#include "df/job.h"

@ -20,13 +20,13 @@ using namespace DFHack;
#include "DataDefs.h"
#include "df/world.h"
#include "df/ui.h"
#include "df/plotinfost.h"
#include "df/item_type.h"
#include "df/plant_raw.h"
using namespace df::enums;
using df::global::world;
using df::global::ui;
using df::global::plotinfo;
// Special values used by "seedwatch" plugin to store seed limits
const df::enums::item_type::item_type SEEDLIMIT_ITEMTYPE = df::enums::item_type::BAR;
@ -41,12 +41,12 @@ void Kitchen::debug_print(color_ostream &out)
{
out.print("%2zu: IT:%2i IS:%i MT:%3i MI:%2i ET:%i %s\n",
i,
ui->kitchen.item_types[i],
ui->kitchen.item_subtypes[i],
ui->kitchen.mat_types[i],
ui->kitchen.mat_indices[i],
ui->kitchen.exc_types[i],
(ui->kitchen.mat_types[i] >= 419 && ui->kitchen.mat_types[i] <= 618) ? world->raws.plants.all[ui->kitchen.mat_indices[i]]->id.c_str() : "n/a"
plotinfo->kitchen.item_types[i],
plotinfo->kitchen.item_subtypes[i],
plotinfo->kitchen.mat_types[i],
plotinfo->kitchen.mat_indices[i],
plotinfo->kitchen.exc_types[i],
(plotinfo->kitchen.mat_types[i] >= 419 && plotinfo->kitchen.mat_types[i] <= 618) ? world->raws.plants.all[plotinfo->kitchen.mat_indices[i]]->id.c_str() : "n/a"
);
}
out.print("\n");
@ -83,11 +83,11 @@ void Kitchen::fillWatchMap(std::map<int32_t, int16_t>& watchMap)
watchMap.clear();
for (std::size_t i = 0; i < size(); ++i)
{
if (ui->kitchen.item_subtypes[i] == SEEDLIMIT_ITEMTYPE &&
ui->kitchen.item_subtypes[i] == SEEDLIMIT_ITEMSUBTYPE &&
ui->kitchen.exc_types[i] == SEEDLIMIT_EXCTYPE)
if (plotinfo->kitchen.item_subtypes[i] == SEEDLIMIT_ITEMTYPE &&
plotinfo->kitchen.item_subtypes[i] == SEEDLIMIT_ITEMSUBTYPE &&
plotinfo->kitchen.exc_types[i] == SEEDLIMIT_EXCTYPE)
{
watchMap[ui->kitchen.mat_indices[i]] = ui->kitchen.mat_types[i];
watchMap[plotinfo->kitchen.mat_indices[i]] = plotinfo->kitchen.mat_types[i];
}
}
}
@ -96,10 +96,10 @@ int Kitchen::findLimit(int32_t plant_id)
{
for (size_t i = 0; i < size(); ++i)
{
if (ui->kitchen.item_types[i] == SEEDLIMIT_ITEMTYPE &&
ui->kitchen.item_subtypes[i] == SEEDLIMIT_ITEMSUBTYPE &&
ui->kitchen.mat_indices[i] == plant_id &&
ui->kitchen.exc_types[i] == SEEDLIMIT_EXCTYPE)
if (plotinfo->kitchen.item_types[i] == SEEDLIMIT_ITEMTYPE &&
plotinfo->kitchen.item_subtypes[i] == SEEDLIMIT_ITEMSUBTYPE &&
plotinfo->kitchen.mat_indices[i] == plant_id &&
plotinfo->kitchen.exc_types[i] == SEEDLIMIT_EXCTYPE)
{
return int(i);
}
@ -113,11 +113,11 @@ bool Kitchen::removeLimit(int32_t plant_id)
if (i < 0)
return false;
ui->kitchen.item_types.erase(ui->kitchen.item_types.begin() + i);
ui->kitchen.item_subtypes.erase(ui->kitchen.item_subtypes.begin() + i);
ui->kitchen.mat_types.erase(ui->kitchen.mat_types.begin() + i);
ui->kitchen.mat_indices.erase(ui->kitchen.mat_indices.begin() + i);
ui->kitchen.exc_types.erase(ui->kitchen.exc_types.begin() + i);
plotinfo->kitchen.item_types.erase(plotinfo->kitchen.item_types.begin() + i);
plotinfo->kitchen.item_subtypes.erase(plotinfo->kitchen.item_subtypes.begin() + i);
plotinfo->kitchen.mat_types.erase(plotinfo->kitchen.mat_types.begin() + i);
plotinfo->kitchen.mat_indices.erase(plotinfo->kitchen.mat_indices.begin() + i);
plotinfo->kitchen.exc_types.erase(plotinfo->kitchen.exc_types.begin() + i);
return true;
}
@ -129,15 +129,15 @@ bool Kitchen::setLimit(int32_t plant_id, int16_t limit)
int i = findLimit(plant_id);
if (i < 0)
{
ui->kitchen.item_types.push_back(SEEDLIMIT_ITEMTYPE);
ui->kitchen.item_subtypes.push_back(SEEDLIMIT_ITEMSUBTYPE);
ui->kitchen.mat_types.push_back(limit);
ui->kitchen.mat_indices.push_back(plant_id);
ui->kitchen.exc_types.push_back(SEEDLIMIT_EXCTYPE);
plotinfo->kitchen.item_types.push_back(SEEDLIMIT_ITEMTYPE);
plotinfo->kitchen.item_subtypes.push_back(SEEDLIMIT_ITEMSUBTYPE);
plotinfo->kitchen.mat_types.push_back(limit);
plotinfo->kitchen.mat_indices.push_back(plant_id);
plotinfo->kitchen.exc_types.push_back(SEEDLIMIT_EXCTYPE);
}
else
{
ui->kitchen.mat_types[i] = limit;
plotinfo->kitchen.mat_types[i] = limit;
}
return true;
}
@ -146,11 +146,11 @@ void Kitchen::clearLimits()
{
for (size_t i = 0; i < size(); ++i)
{
if (ui->kitchen.item_types[i] == SEEDLIMIT_ITEMTYPE &&
ui->kitchen.item_subtypes[i] == SEEDLIMIT_ITEMSUBTYPE &&
ui->kitchen.exc_types[i] == SEEDLIMIT_EXCTYPE)
if (plotinfo->kitchen.item_types[i] == SEEDLIMIT_ITEMTYPE &&
plotinfo->kitchen.item_subtypes[i] == SEEDLIMIT_ITEMSUBTYPE &&
plotinfo->kitchen.exc_types[i] == SEEDLIMIT_EXCTYPE)
{
removeLimit(ui->kitchen.mat_indices[i]);
removeLimit(plotinfo->kitchen.mat_indices[i]);
--i;
}
}
@ -158,7 +158,7 @@ void Kitchen::clearLimits()
size_t Kitchen::size()
{
return ui->kitchen.item_types.size();
return plotinfo->kitchen.item_types.size();
}
int Kitchen::findExclusion(df::kitchen_exc_type type,
@ -167,11 +167,11 @@ int Kitchen::findExclusion(df::kitchen_exc_type type,
{
for (size_t i = 0; i < size(); i++)
{
if (ui->kitchen.item_types[i] == item_type &&
ui->kitchen.item_subtypes[i] == item_subtype &&
ui->kitchen.mat_types[i] == mat_type &&
ui->kitchen.mat_indices[i] == mat_index &&
ui->kitchen.exc_types[i] == type)
if (plotinfo->kitchen.item_types[i] == item_type &&
plotinfo->kitchen.item_subtypes[i] == item_subtype &&
plotinfo->kitchen.mat_types[i] == mat_type &&
plotinfo->kitchen.mat_indices[i] == mat_index &&
plotinfo->kitchen.exc_types[i] == type)
{
return int(i);
}
@ -186,11 +186,11 @@ bool Kitchen::addExclusion(df::kitchen_exc_type type,
if (findExclusion(type, item_type, item_subtype, mat_type, mat_index) >= 0)
return false;
ui->kitchen.item_types.push_back(item_type);
ui->kitchen.item_subtypes.push_back(item_subtype);
ui->kitchen.mat_types.push_back(mat_type);
ui->kitchen.mat_indices.push_back(mat_index);
ui->kitchen.exc_types.push_back(type);
plotinfo->kitchen.item_types.push_back(item_type);
plotinfo->kitchen.item_subtypes.push_back(item_subtype);
plotinfo->kitchen.mat_types.push_back(mat_type);
plotinfo->kitchen.mat_indices.push_back(mat_index);
plotinfo->kitchen.exc_types.push_back(type);
return true;
}
@ -202,10 +202,10 @@ bool Kitchen::removeExclusion(df::kitchen_exc_type type,
if (i < 0)
return false;
ui->kitchen.item_types.erase(ui->kitchen.item_types.begin() + i);
ui->kitchen.item_subtypes.erase(ui->kitchen.item_subtypes.begin() + i);
ui->kitchen.mat_types.erase(ui->kitchen.mat_types.begin() + i);
ui->kitchen.mat_indices.erase(ui->kitchen.mat_indices.begin() + i);
ui->kitchen.exc_types.erase(ui->kitchen.exc_types.begin() + i);
plotinfo->kitchen.item_types.erase(plotinfo->kitchen.item_types.begin() + i);
plotinfo->kitchen.item_subtypes.erase(plotinfo->kitchen.item_subtypes.begin() + i);
plotinfo->kitchen.mat_types.erase(plotinfo->kitchen.mat_types.begin() + i);
plotinfo->kitchen.mat_indices.erase(plotinfo->kitchen.mat_indices.begin() + i);
plotinfo->kitchen.exc_types.erase(plotinfo->kitchen.exc_types.begin() + i);
return true;
}

@ -42,7 +42,7 @@ using namespace std;
#include "MiscUtils.h"
#include "df/world.h"
#include "df/ui.h"
#include "df/plotinfost.h"
#include "df/item.h"
#include "df/creature_raw.h"
#include "df/caste_raw.h"
@ -68,7 +68,7 @@ using namespace DFHack;
using namespace df::enums;
using df::global::world;
using df::global::ui;
using df::global::plotinfo;
bool MaterialInfo::decode(df::item *item)
{
@ -516,7 +516,7 @@ void MaterialInfo::getMatchBits(df::job_item_flags2 &ok, df::job_item_flags2 &ma
TEST(fire_safe, material->heat.melting_point > 11000);
TEST(magma_safe, material->heat.melting_point > 12000);
TEST(deep_material, FLAG(inorganic, inorganic_flags::SPECIAL));
TEST(non_economic, !inorganic || !(ui && vector_get(ui->economic_stone, index)));
TEST(non_economic, !inorganic || !(plotinfo && vector_get(plotinfo->economic_stone, index)));
TEST(plant, plant);
TEST(silk, MAT_FLAG(SILK));

@ -7,10 +7,9 @@ using df::global::enabler;
using df::global::gps;
using DFHack::Renderer::renderer_wrap;
/*
static renderer_wrap *original_renderer = NULL;
const int32_t Renderer::GET_MOUSE_COORDS_SENTINEL = 0xcd1aa471;
bool init()
{
if (!original_renderer)
@ -156,3 +155,4 @@ bool Renderer::renderer_wrap::get_mouse_coords(int32_t* x, int32_t* y) {
bool Renderer::renderer_wrap::uses_opengl() {
return parent->uses_opengl();
};
*/

@ -34,6 +34,7 @@ using namespace std;
#include "modules/Renderer.h"
#include "modules/Screen.h"
#include "modules/GuiHooks.h"
#include "Debug.h"
#include "MemAccess.h"
#include "VersionInfo.h"
#include "Types.h"
@ -49,10 +50,11 @@ using namespace DFHack;
#include "DataDefs.h"
#include "df/init.h"
#include "df/texture_handler.h"
#include "df/tile_page.h"
#include "df/texture_handlerst.h"
#include "df/tile_pagest.h"
#include "df/interfacest.h"
#include "df/enabler.h"
#include "df/graphic_viewportst.h"
#include "df/unit.h"
#include "df/item.h"
#include "df/job.h"
@ -72,30 +74,29 @@ using Screen::PenArray;
using std::string;
namespace DFHack {
DBG_DECLARE(core, screen, DebugCategory::LINFO);
}
/*
* Screen painting API.
*/
// returns text grid coordinates, even if the game map is scaled differently
// returns ui grid coordinates, even if the game map is scaled differently
df::coord2d Screen::getMousePos()
{
int32_t pixelx = 0, pixely = 0, tilex = 0, tiley = 0;
if (!enabler || !enabler->renderer->get_mouse_coords(
&pixelx, &pixely, &tilex, &tiley)) {
if (!gps)
return df::coord2d(-1, -1);
}
return df::coord2d(tilex, tiley);
return df::coord2d(gps->mouse_x, gps->mouse_y);
}
// returns the screen pixel coordinates
df::coord2d Screen::getMousePixels()
{
int32_t pixelx = 0, pixely = 0, tilex = 0, tiley = 0;
if (!enabler || !enabler->renderer->get_mouse_coords(
&pixelx, &pixely, &tilex, &tiley)) {
if (!gps)
return df::coord2d(-1, -1);
}
return df::coord2d(pixelx, pixely);
return df::coord2d(gps->precise_mouse_x, gps->precise_mouse_y);
}
df::coord2d Screen::getWindowSize()
@ -114,25 +115,88 @@ bool Screen::inGraphicsMode()
return init && init->display.flag.is_set(init_display_flags::USE_GRAPHICS);
}
static bool doSetTile_map(const Pen &pen, int x, int y) {
size_t max_index = gps->main_viewport->dim_x * gps->main_viewport->dim_y - 1;
size_t index = (x * gps->main_viewport->dim_y) + y;
if (index < 0 || index > max_index)
return false;
long texpos = pen.tile;
if (texpos == 0) {
texpos = init->font.large_font_texpos[(uint8_t)pen.ch];
}
gps->main_viewport->screentexpos_interface[index] = texpos;
return true;
}
static bool doSetTile_default(const Pen &pen, int x, int y, bool map)
{
auto dim = Screen::getWindowSize();
if (x < 0 || x >= dim.x || y < 0 || y >= dim.y)
bool use_graphics = Screen::inGraphicsMode();
if (map && use_graphics)
return doSetTile_map(pen, x, y);
size_t index = (x * gps->dimy) + y;
uint8_t *screen = &gps->screen[index * 8];
if (screen > gps->screen_limit)
return false;
/* TODO: understand how this changes for v50
int index = ((x * gps->dimy) + y);
auto screen = gps->screen + index*4;
screen[0] = uint8_t(pen.ch);
screen[1] = uint8_t(pen.fg) & 15;
screen[2] = uint8_t(pen.bg) & 15;
screen[3] = uint8_t(pen.bold) & 1;
gps->screentexpos[index] = pen.tile;
gps->screentexpos_addcolor[index] = (pen.tile_mode == Screen::Pen::CharColor);
gps->screentexpos_grayscale[index] = (pen.tile_mode == Screen::Pen::TileColor);
gps->screentexpos_cf[index] = pen.tile_fg;
gps->screentexpos_cbr[index] = pen.tile_bg;
*/
long *texpos = &gps->screentexpos[index];
long *texpos_lower = &gps->screentexpos_lower[index];
uint32_t *flag = &gps->screentexpos_flag[index];
*screen = 0;
*texpos = 0;
*texpos_lower = 0;
gps->screentexpos_anchored[index] = 0;
// keep SCREENTEXPOS_FLAG_ANCHOR_SUBORDINATE so occluded anchored textures
// don't appear corrupted
*flag &= 4;
if (gps->top_in_use) {
screen = &gps->screen_top[index * 8];
texpos = &gps->screentexpos_top[index];
texpos_lower = &gps->screentexpos_top_lower[index];
flag = &gps->screentexpos_top_flag[index];
*screen = 0;
*texpos = 0;
*texpos_lower = 0;
gps->screentexpos_top_anchored[index] = 0;
*flag &= 4; // keep SCREENTEXPOS_FLAG_ANCHOR_SUBORDINATE
}
uint8_t fg = pen.fg | (pen.bold << 3);
uint8_t bg = pen.bg;
if (pen.tile_mode == Screen::Pen::CharColor)
*flag |= 2; // SCREENTEXPOS_FLAG_ADDCOLOR
else if (pen.tile_mode == Screen::Pen::TileColor) {
*flag |= 1; // SCREENTEXPOS_FLAG_GRAYSCALE
if (pen.tile_fg)
fg = pen.tile_fg;
if (pen.tile_bg)
bg = pen.tile_bg;
}
if (pen.tile && use_graphics) {
*texpos = pen.tile;
} else {
screen[0] = uint8_t(pen.ch);
*texpos_lower = 909;
}
auto rgb_fg = &gps->uccolor[fg][0];
auto rgb_bg = &gps->uccolor[bg][0];
screen[1] = rgb_fg[0];
screen[2] = rgb_fg[1];
screen[3] = rgb_fg[2];
screen[4] = rgb_bg[0];
screen[5] = rgb_bg[1];
screen[6] = rgb_bg[2];
return true;
}
@ -150,39 +214,83 @@ bool Screen::paintTile(const Pen &pen, int x, int y, bool map)
return true;
}
static Pen doGetTile_default(int x, int y, bool map)
{
auto dim = Screen::getWindowSize();
if (x < 0 || x >= dim.x || y < 0 || y >= dim.y)
return Pen(0,0,0,-1);
static Pen doGetTile_map(int x, int y) {
size_t max_index = gps->main_viewport->dim_x * gps->main_viewport->dim_y - 1;
size_t index = (x * gps->main_viewport->dim_y) + y;
/* TODO: understand how this changes for v50
int index = x*dim.y + y;
auto screen = gps->screen + index*4;
if (screen[3] & 0x80)
return Pen(0,0,0,-1);
if (index < 0 || index > max_index)
return Pen(0, 0, 0, -1);
Pen pen(
screen[0], screen[1], screen[2], screen[3]?true:false,
gps->screentexpos[index]
);
int tile = gps->main_viewport->screentexpos[index];
if (tile == 0)
tile = gps->main_viewport->screentexpos_item[index];
if (tile == 0)
tile = gps->main_viewport->screentexpos_building_one[index];
if (tile == 0)
tile = gps->main_viewport->screentexpos_background_two[index];
if (tile == 0)
tile = gps->main_viewport->screentexpos_background[index];
if (pen.tile)
{
if (gps->screentexpos_grayscale[index])
{
pen.tile_mode = Screen::Pen::TileColor;
pen.tile_fg = gps->screentexpos_cf[index];
pen.tile_bg = gps->screentexpos_cbr[index];
}
else if (gps->screentexpos_addcolor[index])
{
pen.tile_mode = Screen::Pen::CharColor;
char ch = 0;
uint8_t fg = 0;
uint8_t bg = 0;
return Pen(ch, fg, bg, tile, false);
}
static uint8_t to_16_bit_color(uint8_t *rgb) {
for (uint8_t c = 0; c < 16; ++c) {
if (rgb[0] == gps->uccolor[c][0] &&
rgb[1] == gps->uccolor[c][1] &&
rgb[2] == gps->uccolor[c][2]) {
return c;
}
}
return 0;
}
static Pen doGetTile_default(int x, int y, bool map) {
if (x < 0 || y < 0)
return Pen(0, 0, 0, -1);
bool use_graphics = Screen::inGraphicsMode();
return pen;
*/ return Pen(0,0,0,-1);
if (map && use_graphics)
return doGetTile_map(x, y);
size_t index = (x * gps->dimy) + y;
uint8_t *screen = &gps->screen[index * 8];
if (screen > gps->screen_limit)
return Pen(0, 0, 0, -1);
long *texpos = &gps->screentexpos[index];
uint32_t *flag = &gps->screentexpos_flag[index];
if (gps->top_in_use &&
(gps->screen_top[index * 8] ||
(use_graphics && gps->screentexpos_top[index]))) {
screen = &gps->screen_top[index * 8];
texpos = &gps->screentexpos_top[index];
flag = &gps->screentexpos_top_flag[index];
}
char ch = *screen;
uint8_t fg = to_16_bit_color(&screen[1]);
uint8_t bg = to_16_bit_color(&screen[4]);
int tile = 0;
if (use_graphics)
tile = *texpos;
if (*flag & 1) {
// TileColor
return Pen(ch, fg&7, bg, !!(fg&8), tile, fg, bg);
} else if (*flag & 2) {
// CharColor
return Pen(ch, fg, bg, tile, true);
}
// AsIs
return Pen(ch, fg, bg, tile, false);
}
GUI_HOOK_DEFINE(Screen::Hooks::get_tile, doGetTile_default);
@ -394,6 +502,10 @@ bool Screen::hasActiveScreens(Plugin *plugin)
return false;
}
void Screen::raise(df::viewscreen *screen) {
Hide swapper(screen, Screen::Hide::RESTORE_AT_TOP);
}
namespace DFHack { namespace Screen {
Hide::Hide(df::viewscreen* screen, int flags) :
@ -592,11 +704,13 @@ bool dfhack_viewscreen::key_conflict(df::interface_key key)
if (key == interface_key::OPTIONS)
return true;
/* TODO: understand how this changes for v50
if (text_input_mode)
{
if (key == interface_key::HELP || key == interface_key::MOVIES)
return true;
}
*/
return false;
}

@ -0,0 +1,148 @@
#include "Internal.h"
#include "modules/DFSDL.h"
#include "modules/Textures.h"
#include "Debug.h"
#include "PluginManager.h"
#include "df/enabler.h"
using df::global::enabler;
using namespace DFHack;
using namespace DFHack::DFSDL;
namespace DFHack {
DBG_DECLARE(core, textures, DebugCategory::LINFO);
}
static bool g_loaded = false;
static long g_num_dfhack_textures = 0;
static long g_dfhack_logo_texpos_start = -1;
// Converts an arbitrary Surface to something like the display format
// (32-bit RGBA), and converts magenta to transparency if convert_magenta is set
// and the source surface didn't already have an alpha channel.
// It also deletes the source surface.
//
// It uses the same pixel format (RGBA, R at lowest address) regardless of
// hardware.
DFSDL_Surface * canonicalize_format(DFSDL_Surface *src) {
DFSDL_PixelFormat fmt;
fmt.palette = NULL;
fmt.BitsPerPixel = 32;
fmt.BytesPerPixel = 4;
fmt.Rloss = fmt.Gloss = fmt.Bloss = fmt.Aloss = 0;
//#if SDL_BYTEORDER == SDL_BIG_ENDIAN
// fmt.Rshift = 24; fmt.Gshift = 16; fmt.Bshift = 8; fmt.Ashift = 0;
//#else
fmt.Rshift = 0; fmt.Gshift = 8; fmt.Bshift = 16; fmt.Ashift = 24;
//#endif
fmt.Rmask = 255 << fmt.Rshift;
fmt.Gmask = 255 << fmt.Gshift;
fmt.Bmask = 255 << fmt.Bshift;
fmt.Amask = 255 << fmt.Ashift;
fmt.colorkey = 0;
fmt.alpha = 255;
DFSDL_Surface *tgt = DFSDL_ConvertSurface(src, &fmt, 0); // SDL_SWSURFACE
DFSDL_FreeSurface(src);
return tgt;
}
const uint32_t TILE_WIDTH_PX = 8;
const uint32_t TILE_HEIGHT_PX = 12;
static size_t load_textures(color_ostream & out, const char * fname,
long *texpos_start) {
DFSDL_Surface *s = DFIMG_Load(fname);
if (!s) {
out.printerr("unable to load textures from '%s'\n", fname);
return 0;
}
s = canonicalize_format(s);
DFSDL_SetAlpha(s, 0, 255);
int dimx = s->w / TILE_WIDTH_PX;
int dimy = s->h / TILE_HEIGHT_PX;
long count = 0;
for (int y = 0; y < dimy; y++) {
for (int x = 0; x < dimx; x++) {
DFSDL_Surface *tile = DFSDL_CreateRGBSurface(0, // SDL_SWSURFACE
TILE_WIDTH_PX, TILE_HEIGHT_PX, 32,
s->format->Rmask, s->format->Gmask, s->format->Bmask,
s->format->Amask);
DFSDL_SetAlpha(tile, 0,255);
DFSDL_Rect vp;
vp.x = TILE_WIDTH_PX * x;
vp.y = TILE_HEIGHT_PX * y;
vp.w = TILE_WIDTH_PX;
vp.h = TILE_HEIGHT_PX;
DFSDL_UpperBlit(s, &vp, tile, NULL);
if (!count++)
*texpos_start = enabler->textures.raws.size();
enabler->textures.raws.push_back(tile);
}
}
DFSDL_FreeSurface(s);
DEBUG(textures,out).print("loaded %ld textures from '%s'\n", count, fname);
return count;
}
// DFHack could conceivably be loaded at any time, so we need to be able to
// handle loading textures before or after a world is loaded.
// If a world is already loaded, then append our textures to the raws. they'll
// be freed when the world is unloaded and we'll reload when we get to the title
// screen. If it's pre-world, append our textures and then adjust the "init"
// texture count so our textures will no longer be freed when worlds are
// unloaded.
//
void Textures::init(color_ostream &out) {
auto & textures = enabler->textures;
long num_textures = textures.raws.size();
if (num_textures <= g_dfhack_logo_texpos_start)
g_loaded = false;
if (g_loaded)
return;
bool is_pre_world = num_textures == textures.init_texture_size;
g_num_dfhack_textures = load_textures(out, "hack/data/art/dfhack.png",
&g_dfhack_logo_texpos_start);
DEBUG(textures,out).print("loaded %ld textures\n", g_num_dfhack_textures);
if (is_pre_world)
textures.init_texture_size += g_num_dfhack_textures;
// NOTE: when GL modes are supported, we'll have to re-upload textures here
g_loaded = true;
}
// It's ok to leave NULLs in the raws list (according to usage in g_src)
void Textures::cleanup() {
if (!g_loaded)
return;
auto & textures = enabler->textures;
auto &raws = textures.raws;
size_t texpos_end = g_dfhack_logo_texpos_start + g_num_dfhack_textures;
for (size_t idx = g_dfhack_logo_texpos_start; idx <= texpos_end; ++idx) {
DFSDL_FreeSurface((DFSDL_Surface *)raws[idx]);
raws[idx] = NULL;
}
if (g_dfhack_logo_texpos_start == textures.init_texture_size - g_num_dfhack_textures)
textures.init_texture_size -= g_num_dfhack_textures;
g_loaded = false;
g_num_dfhack_textures = 0;
g_dfhack_logo_texpos_start = -1;
}
long Textures::getDfhackLogoTexposStart() {
return g_dfhack_logo_texpos_start;
}

@ -73,7 +73,7 @@ using namespace std;
#include "df/nemesis_record.h"
#include "df/squad.h"
#include "df/tile_occupancy.h"
#include "df/ui.h"
#include "df/plotinfost.h"
#include "df/unit_inventory_item.h"
#include "df/unit_misc_trait.h"
#include "df/unit_relationship_type.h"
@ -87,7 +87,7 @@ using namespace std;
using namespace DFHack;
using namespace df::enums;
using df::global::world;
using df::global::ui;
using df::global::plotinfo;
using df::global::gamemode;
using df::global::gametype;
@ -178,7 +178,7 @@ bool Units::isFortControlled(df::unit *unit)
unit->flags2.bits.resident)
return false;
return unit->civ_id != -1 && unit->civ_id == ui->civ_id;
return unit->civ_id != -1 && unit->civ_id == plotinfo->civ_id;
}
// check if creature belongs to the player's civilization
@ -186,7 +186,7 @@ bool Units::isFortControlled(df::unit *unit)
bool Units::isOwnCiv(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
return unit->civ_id == ui->civ_id;
return unit->civ_id == plotinfo->civ_id;
}
// check if creature belongs to the player's group
@ -199,7 +199,7 @@ bool Units::isOwnGroup(df::unit* unit)
for (size_t i = 0; i < histfig->entity_links.size(); i++)
{
auto link = histfig->entity_links[i];
if (link->entity_id == ui->group_id && link->getType() == df::histfig_entity_link_type::MEMBER)
if (link->entity_id == plotinfo->group_id && link->getType() == df::histfig_entity_link_type::MEMBER)
return true;
}
return false;
@ -210,7 +210,7 @@ bool Units::isOwnGroup(df::unit* unit)
bool Units::isOwnRace(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
return unit->race == ui->race_id;
return unit->race == plotinfo->race_id;
}
@ -622,8 +622,8 @@ bool Units::isDwarf(df::unit *unit)
{
CHECK_NULL_POINTER(unit);
return unit->race == ui->race_id ||
unit->enemy.normal_race == ui->race_id;
return unit->race == plotinfo->race_id ||
unit->enemy.normal_race == plotinfo->race_id;
}
bool Units::isAnimal(df::unit* unit) {
@ -1301,7 +1301,7 @@ bool Units::setLaborValidity(df::unit_labor labor, bool isValid)
return false;
if (labor == df::unit_labor::NONE)
return false;
df::historical_entity *entity = df::historical_entity::find(ui->civ_id);
df::historical_entity *entity = df::historical_entity::find(plotinfo->civ_id);
if (!entity || !entity->entity_raw)
return false;
entity->entity_raw->jobs.permitted_labor[labor] = isValid;
@ -1704,7 +1704,7 @@ std::string Units::getCasteProfessionName(int race, int casteid, df::profession
if (pid < (df::profession)0 || !is_valid_enum_item(pid))
return "";
int16_t current_race = df::global::ui->race_id;
int16_t current_race = df::global::plotinfo->race_id;
if (df::global::gamemode && *df::global::gamemode == df::game_mode::ADVENTURE)
current_race = world->units.active[0]->race;
bool use_race_prefix = (race >= 0 && race != current_race);

@ -1 +1 @@
Subproject commit 617d6acc10d499f6b158d3f51776d84c689aac9e
Subproject commit d026f34ed1f7ab79aebb1c5bc8a36ee9b30bd13d

@ -0,0 +1 @@
!buildingplan/

@ -2,12 +2,12 @@ include(Plugins.cmake)
option(BUILD_STONESENSE "Build stonesense (needs a checkout first)." OFF)
if(BUILD_STONESENSE)
add_subdirectory(stonesense)
#add_subdirectory(stonesense)
endif()
option(BUILD_ISOWORLD "Build isoworld (needs a checkout first)." OFF)
if(BUILD_ISOWORLD)
add_subdirectory(isoworld)
#add_subdirectory(isoworld)
if(UNIX)
if(APPLE)
# TODO: add an OSX runner script
@ -21,12 +21,12 @@ endif()
option(BUILD_DEV_PLUGINS "Build developer plugins." OFF)
if(BUILD_DEV_PLUGINS)
add_subdirectory(devel)
#add_subdirectory(devel)
endif()
option(BUILD_RUBY "Build ruby binding." ON)
if(BUILD_RUBY)
add_subdirectory(ruby)
#add_subdirectory(ruby)
endif()
install(DIRECTORY lua/
@ -75,111 +75,108 @@ add_custom_target(generate_proto DEPENDS ${PROJECT_PROTO_TMP_FILES})
set_source_files_properties( Brushes.h PROPERTIES HEADER_FILE_ONLY TRUE )
# Plugins
option(BUILD_SUPPORTED "Build the supported plugins (reveal, probe, etc.)." ON)
if(BUILD_SUPPORTED)
# If you are adding a plugin that you do not intend to commit to the DFHack repo,
# see instructions for adding "external" plugins at the end of this file.
dfhack_plugin(3dveins 3dveins.cpp)
dfhack_plugin(add-spatter add-spatter.cpp)
dfhack_plugin(autobutcher autobutcher.cpp LINK_LIBRARIES lua)
dfhack_plugin(autochop autochop.cpp)
dfhack_plugin(autoclothing autoclothing.cpp)
dfhack_plugin(autodump autodump.cpp)
dfhack_plugin(autofarm autofarm.cpp)
dfhack_plugin(autogems autogems.cpp LINK_LIBRARIES jsoncpp_static)
add_subdirectory(autolabor)
dfhack_plugin(automaterial automaterial.cpp LINK_LIBRARIES lua)
dfhack_plugin(automelt automelt.cpp)
dfhack_plugin(autonestbox autonestbox.cpp LINK_LIBRARIES lua)
dfhack_plugin(autotrade autotrade.cpp)
dfhack_plugin(blueprint blueprint.cpp LINK_LIBRARIES lua)
dfhack_plugin(burrows burrows.cpp LINK_LIBRARIES lua)
dfhack_plugin(building-hacks building-hacks.cpp LINK_LIBRARIES lua)
add_subdirectory(buildingplan)
dfhack_plugin(changeitem changeitem.cpp)
dfhack_plugin(changelayer changelayer.cpp)
dfhack_plugin(changevein changevein.cpp)
add_subdirectory(channel-safely)
dfhack_plugin(cleanconst cleanconst.cpp)
dfhack_plugin(cleaners cleaners.cpp)
dfhack_plugin(cleanowned cleanowned.cpp)
dfhack_plugin(confirm confirm.cpp LINK_LIBRARIES lua)
dfhack_plugin(createitem createitem.cpp)
dfhack_plugin(cursecheck cursecheck.cpp)
dfhack_plugin(cxxrandom cxxrandom.cpp LINK_LIBRARIES lua)
dfhack_plugin(deramp deramp.cpp)
dfhack_plugin(debug debug.cpp LINK_LIBRARIES jsoncpp_static)
dfhack_plugin(dig dig.cpp)
dfhack_plugin(dig-now dig-now.cpp LINK_LIBRARIES lua)
dfhack_plugin(digFlood digFlood.cpp)
add_subdirectory(diggingInvaders)
dfhack_plugin(dwarfvet dwarfvet.cpp)
dfhack_plugin(dwarfmonitor dwarfmonitor.cpp LINK_LIBRARIES lua)
add_subdirectory(embark-assistant)
dfhack_plugin(embark-tools embark-tools.cpp)
dfhack_plugin(eventful eventful.cpp LINK_LIBRARIES lua)
dfhack_plugin(fastdwarf fastdwarf.cpp)
dfhack_plugin(filltraffic filltraffic.cpp)
dfhack_plugin(fix-unit-occupancy fix-unit-occupancy.cpp)
dfhack_plugin(fixveins fixveins.cpp)
dfhack_plugin(flows flows.cpp)
dfhack_plugin(follow follow.cpp)
dfhack_plugin(forceequip forceequip.cpp)
dfhack_plugin(generated-creature-renamer generated-creature-renamer.cpp)
dfhack_plugin(getplants getplants.cpp)
dfhack_plugin(hotkeys hotkeys.cpp LINK_LIBRARIES lua)
dfhack_plugin(infiniteSky infiniteSky.cpp)
dfhack_plugin(isoworldremote isoworldremote.cpp PROTOBUFS isoworldremote)
dfhack_plugin(jobutils jobutils.cpp)
dfhack_plugin(lair lair.cpp)
dfhack_plugin(liquids liquids.cpp Brushes.h LINK_LIBRARIES lua)
dfhack_plugin(luasocket luasocket.cpp LINK_LIBRARIES clsocket lua dfhack-tinythread)
dfhack_plugin(manipulator manipulator.cpp)
dfhack_plugin(map-render map-render.cpp LINK_LIBRARIES lua)
dfhack_plugin(misery misery.cpp)
dfhack_plugin(mode mode.cpp)
dfhack_plugin(mousequery mousequery.cpp)
dfhack_plugin(nestboxes nestboxes.cpp)
dfhack_plugin(orders orders.cpp LINK_LIBRARIES jsoncpp_static)
dfhack_plugin(overlay overlay.cpp LINK_LIBRARIES lua)
dfhack_plugin(pathable pathable.cpp LINK_LIBRARIES lua)
dfhack_plugin(petcapRemover petcapRemover.cpp)
dfhack_plugin(plants plants.cpp)
dfhack_plugin(probe probe.cpp)
dfhack_plugin(prospector prospector.cpp LINK_LIBRARIES lua)
dfhack_plugin(power-meter power-meter.cpp LINK_LIBRARIES lua)
dfhack_plugin(regrass regrass.cpp)
add_subdirectory(remotefortressreader)
dfhack_plugin(rename rename.cpp LINK_LIBRARIES lua PROTOBUFS rename)
add_subdirectory(rendermax)
dfhack_plugin(reveal reveal.cpp LINK_LIBRARIES lua)
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(sort sort.cpp LINK_LIBRARIES lua)
dfhack_plugin(steam-engine steam-engine.cpp)
add_subdirectory(spectate)
dfhack_plugin(stockflow stockflow.cpp LINK_LIBRARIES lua)
add_subdirectory(stockpiles)
dfhack_plugin(stocks stocks.cpp)
dfhack_plugin(strangemood strangemood.cpp)
dfhack_plugin(tailor tailor.cpp)
dfhack_plugin(tiletypes tiletypes.cpp Brushes.h LINK_LIBRARIES lua)
dfhack_plugin(title-folder title-folder.cpp)
dfhack_plugin(title-version title-version.cpp)
dfhack_plugin(trackstop trackstop.cpp)
dfhack_plugin(tubefill tubefill.cpp)
add_subdirectory(tweak)
dfhack_plugin(workflow workflow.cpp LINK_LIBRARIES lua)
dfhack_plugin(workNow workNow.cpp)
dfhack_plugin(xlsxreader xlsxreader.cpp LINK_LIBRARIES lua xlsxio_read_STATIC zip expat)
dfhack_plugin(zone zone.cpp)
# If you are adding a plugin that you do not intend to commit to the DFHack repo,
# see instructions for adding "external" plugins at the end of this file.
endif()
# If you are adding a plugin that you do not intend to commit to the DFHack repo,
# see instructions for adding "external" plugins at the end of this file.
#dfhack_plugin(3dveins 3dveins.cpp)
#dfhack_plugin(add-spatter add-spatter.cpp)
dfhack_plugin(autobutcher autobutcher.cpp LINK_LIBRARIES lua)
#dfhack_plugin(autochop autochop.cpp)
#dfhack_plugin(autoclothing autoclothing.cpp)
#dfhack_plugin(autodump autodump.cpp)
#dfhack_plugin(autofarm autofarm.cpp)
#dfhack_plugin(autogems autogems.cpp LINK_LIBRARIES jsoncpp_static)
#add_subdirectory(autolabor)
#dfhack_plugin(automaterial automaterial.cpp LINK_LIBRARIES lua)
#dfhack_plugin(automelt automelt.cpp)
#dfhack_plugin(autonestbox autonestbox.cpp LINK_LIBRARIES lua)
#dfhack_plugin(autotrade autotrade.cpp)
#dfhack_plugin(blueprint blueprint.cpp LINK_LIBRARIES lua)
#dfhack_plugin(burrows burrows.cpp LINK_LIBRARIES lua)
#dfhack_plugin(building-hacks building-hacks.cpp LINK_LIBRARIES lua)
#add_subdirectory(buildingplan)
#dfhack_plugin(changeitem changeitem.cpp)
#dfhack_plugin(changelayer changelayer.cpp)
#dfhack_plugin(changevein changevein.cpp)
#add_subdirectory(channel-safely)
#dfhack_plugin(cleanconst cleanconst.cpp)
#dfhack_plugin(cleaners cleaners.cpp)
#dfhack_plugin(cleanowned cleanowned.cpp)
#dfhack_plugin(confirm confirm.cpp LINK_LIBRARIES lua)
#dfhack_plugin(createitem createitem.cpp)
#dfhack_plugin(cursecheck cursecheck.cpp)
#dfhack_plugin(cxxrandom cxxrandom.cpp LINK_LIBRARIES lua)
#dfhack_plugin(deramp deramp.cpp)
dfhack_plugin(debug debug.cpp LINK_LIBRARIES jsoncpp_static)
#dfhack_plugin(dig dig.cpp)
#dfhack_plugin(dig-now dig-now.cpp LINK_LIBRARIES lua)
#dfhack_plugin(digFlood digFlood.cpp)
#add_subdirectory(diggingInvaders)
#dfhack_plugin(dwarfvet dwarfvet.cpp)
#dfhack_plugin(dwarfmonitor dwarfmonitor.cpp LINK_LIBRARIES lua)
#add_subdirectory(embark-assistant)
#dfhack_plugin(embark-tools embark-tools.cpp)
dfhack_plugin(eventful eventful.cpp LINK_LIBRARIES lua)
#dfhack_plugin(fastdwarf fastdwarf.cpp)
#dfhack_plugin(filltraffic filltraffic.cpp)
#dfhack_plugin(fix-unit-occupancy fix-unit-occupancy.cpp)
#dfhack_plugin(fixveins fixveins.cpp)
#dfhack_plugin(flows flows.cpp)
#dfhack_plugin(follow follow.cpp)
#dfhack_plugin(forceequip forceequip.cpp)
#dfhack_plugin(generated-creature-renamer generated-creature-renamer.cpp)
#dfhack_plugin(getplants getplants.cpp)
dfhack_plugin(hotkeys hotkeys.cpp LINK_LIBRARIES lua)
#dfhack_plugin(infiniteSky infiniteSky.cpp)
#dfhack_plugin(isoworldremote isoworldremote.cpp PROTOBUFS isoworldremote)
#dfhack_plugin(jobutils jobutils.cpp)
#dfhack_plugin(lair lair.cpp)
#dfhack_plugin(liquids liquids.cpp Brushes.h LINK_LIBRARIES lua)
#dfhack_plugin(luasocket luasocket.cpp LINK_LIBRARIES clsocket lua dfhack-tinythread)
#dfhack_plugin(manipulator manipulator.cpp)
#dfhack_plugin(map-render map-render.cpp LINK_LIBRARIES lua)
#dfhack_plugin(misery misery.cpp)
#dfhack_plugin(mode mode.cpp)
#dfhack_plugin(mousequery mousequery.cpp)
#dfhack_plugin(nestboxes nestboxes.cpp)
#dfhack_plugin(orders orders.cpp LINK_LIBRARIES jsoncpp_static)
dfhack_plugin(overlay overlay.cpp LINK_LIBRARIES lua)
dfhack_plugin(pathable pathable.cpp LINK_LIBRARIES lua)
#dfhack_plugin(petcapRemover petcapRemover.cpp)
#dfhack_plugin(plants plants.cpp)
#dfhack_plugin(probe probe.cpp)
#dfhack_plugin(prospector prospector.cpp LINK_LIBRARIES lua)
#dfhack_plugin(power-meter power-meter.cpp LINK_LIBRARIES lua)
#dfhack_plugin(regrass regrass.cpp)
#add_subdirectory(remotefortressreader)
#dfhack_plugin(rename rename.cpp LINK_LIBRARIES lua PROTOBUFS rename)
#add_subdirectory(rendermax)
dfhack_plugin(reveal reveal.cpp LINK_LIBRARIES lua)
#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(sort sort.cpp LINK_LIBRARIES lua)
#dfhack_plugin(steam-engine steam-engine.cpp)
#add_subdirectory(spectate)
#dfhack_plugin(stockflow stockflow.cpp LINK_LIBRARIES lua)
#add_subdirectory(stockpiles)
#dfhack_plugin(stocks stocks.cpp)
#dfhack_plugin(strangemood strangemood.cpp)
#dfhack_plugin(tailor tailor.cpp)
#dfhack_plugin(tiletypes tiletypes.cpp Brushes.h LINK_LIBRARIES lua)
#dfhack_plugin(title-folder title-folder.cpp)
#dfhack_plugin(title-version title-version.cpp)
#dfhack_plugin(trackstop trackstop.cpp)
#dfhack_plugin(tubefill tubefill.cpp)
#add_subdirectory(tweak)
#dfhack_plugin(workflow workflow.cpp LINK_LIBRARIES lua)
#dfhack_plugin(workNow workNow.cpp)
#dfhack_plugin(xlsxreader xlsxreader.cpp LINK_LIBRARIES lua xlsxio_read_STATIC zip expat)
#dfhack_plugin(zone zone.cpp)
# If you are adding a plugin that you do not intend to commit to the DFHack repo,
# see instructions for adding "external" plugins at the end of this file.
# this is the skeleton plugin. If you want to make your own, make a copy and then change it
option(BUILD_SKELETON "Build the skeleton plugin." OFF)

@ -24,7 +24,7 @@
#include "df/job.h"
#include "df/job_item.h"
#include "df/job_item_ref.h"
#include "df/ui.h"
#include "df/plotinfost.h"
#include "df/report.h"
#include "df/reaction.h"
#include "df/reaction_reagent_itemst.h"
@ -45,7 +45,7 @@ DFHACK_PLUGIN("add-spatter");
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
REQUIRE_GLOBAL(gps);
REQUIRE_GLOBAL(world);
REQUIRE_GLOBAL(ui);
REQUIRE_GLOBAL(plotinfo);
typedef df::reaction_product_item_improvementst improvement_product;

@ -712,13 +712,20 @@ static bool hasValidMapPos(df::unit *unit) {
&& unit->pos.z < world->map.z_count;
}
// built cage defined as room (supposed to detect zoo cages)
// built cage in a zone (supposed to detect zoo cages)
static bool isInBuiltCageRoom(df::unit *unit) {
for (auto building : world->buildings.all) {
// !!! building->isRoom() returns true if the building can be made a room but currently isn't
// !!! except for coffins/tombs which always return false
// !!! using the bool is_room however gives the correct state/value
if (!building->is_room || building->getType() != df::building_type::Cage)
if (building->getType() != df::building_type::Cage)
continue;
bool in_zone = false;
for (auto relation : building->relations) {
if (relation->getType() == df::building_type::Civzone) {
in_zone = true;
break;
}
}
if (!in_zone)
continue;
df::building_cagest* cage = (df::building_cagest*)building;

@ -22,7 +22,7 @@
#include "df/plant_tree_tile.h"
#include "df/plant_raw.h"
#include "df/tile_dig_designation.h"
#include "df/ui.h"
#include "df/plotinfost.h"
#include "df/viewscreen_dwarfmodest.h"
#include "df/world.h"
@ -45,7 +45,7 @@ using namespace df::enums;
#define PLUGIN_VERSION 0.3
DFHACK_PLUGIN("autochop");
REQUIRE_GLOBAL(world);
REQUIRE_GLOBAL(ui);
REQUIRE_GLOBAL(plotinfo);
static int get_log_count();
@ -499,7 +499,7 @@ public:
burrows_column.clear();
for (df::burrow *burrow : ui->burrows.list)
for (df::burrow *burrow : plotinfo->burrows.list)
{
string name = burrow->name;
if (name.empty())
@ -820,7 +820,7 @@ struct autochop_hook : public df::viewscreen_dwarfmodest
bool isInDesignationMenu()
{
using namespace df::enums::ui_sidebar_mode;
return (ui->main.mode == DesignateChopTrees);
return (plotinfo->main.mode == DesignateChopTrees);
}
void sendKey(const df::interface_key &key)

@ -5,7 +5,7 @@
#include "DataDefs.h"
#include "df/world.h"
#include "df/ui.h"
#include "df/plotinfost.h"
#include "df/building_type.h"
#include "df/building_farmplotst.h"
#include "df/buildings_other_id.h"
@ -30,7 +30,7 @@ using namespace DFHack;
using namespace df::enums;
using df::global::world;
using df::global::ui;
using df::global::plotinfo;
static command_result autofarm(color_ostream& out, std::vector<std::string>& parameters);
@ -348,7 +348,7 @@ static std::unique_ptr<AutoFarm> autofarmInstance;
DFhackCExport command_result plugin_init(color_ostream& out, std::vector <PluginCommand>& commands)
{
if (world && ui) {
if (world && plotinfo) {
commands.push_back(
PluginCommand("autofarm",
"Automatically manage farm crop selection.",

@ -33,7 +33,7 @@ using namespace DFHack;
DFHACK_PLUGIN("autogems");
DFHACK_PLUGIN_IS_ENABLED(enabled);
REQUIRE_GLOBAL(ui);
REQUIRE_GLOBAL(plotinfo);
REQUIRE_GLOBAL(world);
typedef int32_t item_id;
@ -242,7 +242,7 @@ struct autogem_hook : public df::viewscreen_dwarfmodest {
bool in_menu() {
// Determines whether we're looking at the Workshop Orders screen.
return ui->main.mode == ui_sidebar_mode::OrdersWorkshop;
return plotinfo->main.mode == ui_sidebar_mode::OrdersWorkshop;
}
bool handleInput(std::set<df::interface_key> *input) {

@ -12,7 +12,7 @@
// DF data structure definition headers
#include "DataDefs.h"
#include <df/ui.h>
#include <df/plotinfost.h>
#include <df/world.h>
#include <df/unit.h>
#include <df/unit_soul.h>
@ -32,7 +32,7 @@
#include <df/building_tradedepotst.h>
#include <df/building_stockpilest.h>
#include <df/items_other_id.h>
#include <df/ui.h>
#include <df/plotinfost.h>
#include <df/activity_info.h>
#include <MiscUtils.h>
@ -47,7 +47,7 @@ using namespace DFHack;
using namespace df::enums;
DFHACK_PLUGIN("autohauler");
REQUIRE_GLOBAL(ui);
REQUIRE_GLOBAL(plotinfo);
REQUIRE_GLOBAL(world);
#define ARRAY_COUNT(array) (sizeof(array)/sizeof((array)[0]))

@ -12,7 +12,7 @@
// DF data structure definition headers
#include "DataDefs.h"
#include <df/ui.h>
#include <df/plotinfost.h>
#include <df/world.h>
#include <df/unit.h>
#include <df/unit_soul.h>
@ -32,7 +32,7 @@
#include <df/building_tradedepotst.h>
#include <df/building_stockpilest.h>
#include <df/items_other_id.h>
#include <df/ui.h>
#include <df/plotinfost.h>
#include <df/activity_info.h>
#include <MiscUtils.h>
@ -47,7 +47,7 @@ using namespace DFHack;
using namespace df::enums;
DFHACK_PLUGIN("autolabor");
REQUIRE_GLOBAL(ui);
REQUIRE_GLOBAL(plotinfo);
REQUIRE_GLOBAL(world);
#define ARRAY_COUNT(array) (sizeof(array)/sizeof((array)[0]))
@ -813,7 +813,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
// identify dwarfs who are needed for meetings and mark them for exclusion
for (auto& act : ui->activities)
for (auto& act : plotinfo->activities)
{
if (!act) continue;
bool p1 = act->unit_actor == dwarfs[dwarf];

@ -56,7 +56,7 @@ using std::string;
using std::endl;
using namespace DFHack;
using namespace df::enums;
using df::global::ui;
using df::global::plotinfo;
using df::global::world;
#include "labormanager.h"

@ -25,7 +25,7 @@
#include "DataDefs.h"
#include <MiscUtils.h>
#include <df/ui.h>
#include <df/plotinfost.h>
#include <df/world.h>
#include <df/unit.h>
#include <df/unit_relationship_type.h>
@ -46,7 +46,7 @@
#include <df/building_tradedepotst.h>
#include <df/building_stockpilest.h>
#include <df/items_other_id.h>
#include <df/ui.h>
#include <df/plotinfost.h>
#include <df/activity_info.h>
#include <df/tile_dig_designation.h>
#include <df/item_weaponst.h>
@ -64,7 +64,7 @@
#include <df/building_design.h>
#include <df/vehicle.h>
#include <df/units_other_id.h>
#include <df/ui.h>
#include <df/plotinfost.h>
#include <df/training_assignment.h>
#include <df/general_ref_contains_itemst.h>
#include <df/personality_facet_type.h>
@ -82,7 +82,7 @@ using std::string;
using std::endl;
using namespace DFHack;
using namespace df::enums;
using df::global::ui;
using df::global::plotinfo;
using df::global::world;
#define ARRAY_COUNT(array) (sizeof(array)/sizeof((array)[0]))
@ -948,9 +948,9 @@ private:
// identify dwarfs who are needed for meetings and mark them for exclusion
for (size_t i = 0; i < ui->activities.size(); ++i)
for (size_t i = 0; i < plotinfo->activities.size(); ++i)
{
df::activity_info *act = ui->activities[i];
df::activity_info *act = plotinfo->activities[i];
if (!act) continue;
bool p1 = act->unit_actor == dwarf->dwarf;
@ -996,11 +996,11 @@ private:
for (size_t j = 0; j < dwarf->dwarf->inventory.size(); j++)
{
df::unit_inventory_item* ui = dwarf->dwarf->inventory[j];
if (ui->mode == df::unit_inventory_item::Weapon && ui->item->isWeapon())
df::unit_inventory_item* plotinfo = dwarf->dwarf->inventory[j];
if (plotinfo->mode == df::unit_inventory_item::Weapon && plotinfo->item->isWeapon())
{
dwarf->armed = true;
df::itemdef_weaponst* weapondef = ((df::item_weaponst*)(ui->item))->subtype;
df::itemdef_weaponst* weapondef = ((df::item_weaponst*)(plotinfo->item))->subtype;
df::job_skill weaponsk = (df::job_skill) weapondef->skill_melee;
df::job_skill rangesk = (df::job_skill) weapondef->skill_ranged;
if (weaponsk == df::job_skill::AXE)
@ -1408,8 +1408,8 @@ public:
(isOptionEnabled(CF_ALLOW_HUNTING) && has_butchers) ? 1 : 0;
/* add animal trainers */
for (auto a = df::global::ui->equipment.training_assignments.begin();
a != df::global::ui->equipment.training_assignments.end();
for (auto a = df::global::plotinfo->equipment.training_assignments.begin();
a != df::global::plotinfo->equipment.training_assignments.end();
a++)
{
labor_needed[df::unit_labor::ANIMALTRAIN]++;

@ -21,8 +21,8 @@
#include "df/build_req_choice_specst.h"
#include "df/construction_type.h"
#include "df/item.h"
#include "df/ui.h"
#include "df/ui_build_selector.h"
#include "df/plotinfost.h"
#include "df/buildreq.h"
#include "df/viewscreen_dwarfmodest.h"
#include "df/items_other_id.h"
#include "df/job.h"
@ -50,7 +50,7 @@ using namespace df::enums;
DFHACK_PLUGIN("automaterial");
REQUIRE_GLOBAL(gps);
REQUIRE_GLOBAL(ui);
REQUIRE_GLOBAL(plotinfo);
REQUIRE_GLOBAL(ui_build_selector);
namespace DFHack {
@ -115,14 +115,14 @@ static inline bool in_material_choice_stage()
{
return Gui::build_selector_hotkey(Core::getTopViewscreen()) &&
ui_build_selector->building_type == df::building_type::Construction &&
ui->main.mode == ui_sidebar_mode::Build &&
plotinfo->main.mode == ui_sidebar_mode::Build &&
ui_build_selector->stage == 2;
}
static inline bool in_placement_stage()
{
return Gui::dwarfmode_hotkey(Core::getTopViewscreen()) &&
ui->main.mode == ui_sidebar_mode::Build &&
plotinfo->main.mode == ui_sidebar_mode::Build &&
ui_build_selector &&
ui_build_selector->building_type == df::building_type::Construction &&
ui_build_selector->stage == 1;
@ -131,7 +131,7 @@ static inline bool in_placement_stage()
static inline bool in_type_choice_stage()
{
return Gui::dwarfmode_hotkey(Core::getTopViewscreen()) &&
ui->main.mode == ui_sidebar_mode::Build &&
plotinfo->main.mode == ui_sidebar_mode::Build &&
ui_build_selector &&
ui_build_selector->building_type < 0;
}
@ -713,7 +713,7 @@ struct jobutils_hook : public df::viewscreen_dwarfmodest
if (!box_select_enabled)
return;
if (ui->main.mode != df::ui_sidebar_mode::Build ||
if (plotinfo->main.mode != df::ui_sidebar_mode::Build ||
ui_build_selector->building_type != df::building_type::Construction)
return;

@ -9,7 +9,7 @@
#include "df/building_stockpilest.h"
#include "modules/Buildings.h"
#include "modules/Items.h"
#include "df/ui.h"
#include "df/plotinfost.h"
#include "modules/Maps.h"
#include "modules/World.h"
#include "df/item_quality.h"
@ -21,7 +21,7 @@ DFHACK_PLUGIN("automelt");
REQUIRE_GLOBAL(gps);
REQUIRE_GLOBAL(world);
REQUIRE_GLOBAL(cursor);
REQUIRE_GLOBAL(ui);
REQUIRE_GLOBAL(plotinfo);
static const string PERSISTENCE_KEY = "automelt/stockpiles";

@ -15,7 +15,7 @@
#include "df/job.h"
#include "df/job_item_ref.h"
#include "modules/Job.h"
#include "df/ui.h"
#include "df/plotinfost.h"
#include "df/mandate.h"
#include "modules/Maps.h"
@ -25,7 +25,7 @@ DFHACK_PLUGIN("autotrade");
REQUIRE_GLOBAL(gps);
REQUIRE_GLOBAL(world);
REQUIRE_GLOBAL(cursor);
REQUIRE_GLOBAL(ui);
REQUIRE_GLOBAL(plotinfo);
static const string PERSISTENCE_KEY = "autotrade/stockpiles";

@ -6,7 +6,7 @@
#include "df/building_type.h"
#include "df/general_ref_building_holderst.h"
#include "df/job_item.h"
#include "df/ui_build_selector.h"
#include "df/buildreq.h"
#include "modules/Buildings.h"
#include "modules/Gui.h"

@ -1,7 +1,7 @@
#include "df/construction_type.h"
#include "df/entity_position.h"
#include "df/interface_key.h"
#include "df/ui_build_selector.h"
#include "df/buildreq.h"
#include "df/viewscreen_dwarfmodest.h"
#include "modules/Gui.h"
@ -18,7 +18,7 @@
DFHACK_PLUGIN("buildingplan");
#define PLUGIN_VERSION "2.0"
REQUIRE_GLOBAL(ui);
REQUIRE_GLOBAL(plotinfo);
REQUIRE_GLOBAL(ui_build_selector);
REQUIRE_GLOBAL(world); // used in buildingplan library
@ -455,8 +455,8 @@ struct buildingplan_query_hook : public df::viewscreen_dwarfmodest
bool isInPlannedBuildingQueryMode()
{
return (ui->main.mode == df::ui_sidebar_mode::QueryBuilding ||
ui->main.mode == df::ui_sidebar_mode::BuildingItems) &&
return (plotinfo->main.mode == df::ui_sidebar_mode::QueryBuilding ||
plotinfo->main.mode == df::ui_sidebar_mode::BuildingItems) &&
planner.getPlannedBuilding(world->selected_building);
}
@ -595,7 +595,7 @@ struct buildingplan_place_hook : public df::viewscreen_dwarfmodest
bool isInPlannedBuildingPlacementMode()
{
return ui->main.mode == ui_sidebar_mode::Build &&
return plotinfo->main.mode == ui_sidebar_mode::Build &&
df::global::ui_build_selector &&
df::global::ui_build_selector->stage < 2 &&
planner.isPlannableBuilding(toBuildingTypeKey(ui_build_selector));
@ -861,7 +861,7 @@ struct buildingplan_room_hook : public df::viewscreen_dwarfmodest
std::vector<Units::NoblePosition> getNoblePositionOfSelectedBuildingOwner()
{
std::vector<Units::NoblePosition> np;
if (ui->main.mode != df::ui_sidebar_mode::QueryBuilding ||
if (plotinfo->main.mode != df::ui_sidebar_mode::QueryBuilding ||
!world->selected_building ||
!world->selected_building->owner)
{
@ -1084,7 +1084,7 @@ DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_chan
static bool is_paused()
{
return World::ReadPauseState() ||
ui->main.mode > df::ui_sidebar_mode::Squads ||
plotinfo->main.mode > df::ui_sidebar_mode::Squads ||
!strict_virtual_cast<df::viewscreen_dwarfmodest>(Gui::getCurViewscreen(true));
}

@ -17,7 +17,7 @@
#include "TileTypes.h"
#include "DataDefs.h"
#include "df/ui.h"
#include "df/plotinfost.h"
#include "df/world.h"
#include "df/unit.h"
#include "df/burrow.h"
@ -38,7 +38,7 @@ using namespace df::enums;
using namespace dfproto;
DFHACK_PLUGIN("burrows");
REQUIRE_GLOBAL(ui);
REQUIRE_GLOBAL(plotinfo);
REQUIRE_GLOBAL(world);
REQUIRE_GLOBAL(gamemode);
@ -102,11 +102,11 @@ DEFINE_LUA_EVENT_1(onBurrowRename, handle_burrow_rename, df::burrow*);
static void detect_burrow_renames(color_ostream &out)
{
if (ui->main.mode == ui_sidebar_mode::Burrows &&
ui->burrows.in_edit_name_mode &&
ui->burrows.sel_id >= 0)
if (plotinfo->main.mode == ui_sidebar_mode::Burrows &&
plotinfo->burrows.in_edit_name_mode &&
plotinfo->burrows.sel_id >= 0)
{
name_burrow_id = ui->burrows.sel_id;
name_burrow_id = plotinfo->burrows.sel_id;
}
else if (name_burrow_id >= 0)
{
@ -222,7 +222,7 @@ static std::map<std::string,int> name_lookup;
static void parse_names()
{
auto &list = ui->burrows.list;
auto &list = plotinfo->burrows.list;
grow_burrows.clear();
name_lookup.clear();

@ -36,7 +36,7 @@ using std::vector;
DFHACK_PLUGIN("confirm");
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
REQUIRE_GLOBAL(gps);
REQUIRE_GLOBAL(ui);
REQUIRE_GLOBAL(plotinfo);
typedef std::set<df::interface_key> ikey_set;
command_result df_confirm (color_ostream &out, vector <string> & parameters);

@ -16,7 +16,7 @@
#include "DataDefs.h"
#include "df/game_type.h"
#include "df/world.h"
#include "df/ui.h"
#include "df/plotinfost.h"
#include "df/unit.h"
#include "df/historical_entity.h"
#include "df/world_site.h"
@ -38,7 +38,7 @@ using namespace df::enums;
DFHACK_PLUGIN("createitem");
REQUIRE_GLOBAL(cursor);
REQUIRE_GLOBAL(world);
REQUIRE_GLOBAL(ui);
REQUIRE_GLOBAL(plotinfo);
REQUIRE_GLOBAL(gametype);
REQUIRE_GLOBAL(cur_year_tick);
@ -78,7 +78,7 @@ bool makeItem (df::reaction_product_itemst *prod, df::unit *unit, bool second_it
prod->produce(unit, &out_products, &out_items, &in_reag, &in_items, 1, job_skill::NONE,
0, df::historical_entity::find(unit->civ_id),
(World::isFortressMode()) ? df::world_site::find(ui->site_id) : NULL, NULL);
(World::isFortressMode()) ? df::world_site::find(plotinfo->site_id) : NULL, NULL);
if (!out_items.size())
return false;
// if we asked to make shoes and we got twice as many as we asked, then we're okay

@ -43,7 +43,7 @@ namespace DFHack {
DBG_DECLARE(debug,filter);
DBG_DECLARE(debug,init);
DBG_DECLARE(debug,command);
DBG_DECLARE(debug,ui);
DBG_DECLARE(debug,plotinfo);
DBG_DECLARE(debug,example,DebugCategory::LINFO);
}

@ -33,7 +33,7 @@ using namespace DFHack;
DFHACK_PLUGIN("kittens");
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
REQUIRE_GLOBAL(ui);
REQUIRE_GLOBAL(plotinfo);
REQUIRE_GLOBAL(world);
namespace DFHack {
@ -119,9 +119,9 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
}
if(trackmenu_flg)
{
if (last_menu != ui->main.mode)
if (last_menu != plotinfo->main.mode)
{
last_menu = ui->main.mode;
last_menu = plotinfo->main.mode;
out.print("Menu: %d\n",last_menu);
}
}
@ -157,7 +157,7 @@ command_result trackmenu (color_ostream &out, vector <string> & parameters)
else
{
is_enabled = true;
last_menu = ui->main.mode;
last_menu = plotinfo->main.mode;
out.print("Menu: %d\n",last_menu);
trackmenu_flg = true;
return CR_OK;

@ -5,7 +5,7 @@
#include "DataDefs.h"
#include "df/world.h"
#include "df/ui.h"
#include "df/plotinfost.h"
#include "df/building_stockpilest.h"
#include "df/global_objects.h"
#include "df/item.h"
@ -24,7 +24,7 @@ using namespace DFHack;
using namespace df::enums;
using df::global::world;
using df::global::ui;
using df::global::plotinfo;
using df::global::selection_rect;
using df::building_stockpilest;
@ -35,7 +35,7 @@ DFHACK_PLUGIN("stockcheck");
DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands)
{
if (world && ui) {
if (world && plotinfo) {
commands.push_back(
PluginCommand("stockcheck", "Check for unprotected rottable items.",
stockcheck, false,

@ -20,7 +20,7 @@ using namespace std;
#include "modules/World.h"
#include "MiscUtils.h"
#include <df/ui.h>
#include <df/plotinfost.h>
#include "df/world.h"
#include "df/world_raws.h"
#include "df/building_def.h"
@ -34,7 +34,7 @@ using namespace DFHack;
using namespace df::enums;
using df::global::world;
using df::global::cursor;
using df::global::ui;
using df::global::plotinfo;
using namespace DFHack::Gui;

@ -20,14 +20,14 @@
#include <df/reaction_product_itemst.h>
#include <df/tile_designation.h>
#include <df/tile_occupancy.h>
#include <df/ui.h>
#include <df/plotinfost.h>
#include <df/unit.h>
#include <df/vermin.h>
#include <df/world.h>
#include <df/world_site.h>
DFHACK_PLUGIN("dig-now");
REQUIRE_GLOBAL(ui);
REQUIRE_GLOBAL(plotinfo);
REQUIRE_GLOBAL(world);
using namespace DFHack;
@ -678,7 +678,7 @@ static void create_boulders(color_ostream &out,
df::unit *unit = world->units.active[0];
df::historical_entity *civ = df::historical_entity::find(unit->civ_id);
df::world_site *site = World::isFortressMode() ?
df::world_site::find(ui->site_id) : NULL;
df::world_site::find(plotinfo->site_id) : NULL;
std::vector<df::reaction_reagent *> in_reag;
std::vector<df::item *> in_items;

@ -16,7 +16,7 @@
#include "modules/Maps.h"
#include "modules/Materials.h"
#include "df/ui_sidebar_menus.h"
#include "df/gamest.h"
using std::vector;
using std::string;
@ -33,7 +33,7 @@ command_result digcircle (color_ostream &out, vector <string> & parameters);
command_result digtype (color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("dig");
REQUIRE_GLOBAL(ui_sidebar_menus);
REQUIRE_GLOBAL(game);
REQUIRE_GLOBAL(world);
REQUIRE_GLOBAL(window_z);
@ -213,7 +213,7 @@ bool lineY (MapExtras::MapCache & MCache,
int32_t parse_priority(color_ostream &out, vector<string> &parameters)
{
int32_t default_priority = ui_sidebar_menus->designation.priority;
int32_t default_priority = game->designation.priority;
for (auto it = parameters.begin(); it != parameters.end(); ++it)
{

Some files were not shown because too many files have changed in this diff Show More