diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 7a296dbc7..033c82053 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -113,36 +113,39 @@ SET(MODULE_HEADERS include/modules/Buildings.h include/modules/Burrows.h include/modules/Constructions.h -include/modules/Units.h +include/modules/Designations.h include/modules/Engravings.h include/modules/EventManager.h +include/modules/Filesystem.h +include/modules/Graphic.h include/modules/Gui.h include/modules/GuiHooks.h include/modules/Items.h include/modules/Job.h include/modules/kitchen.h -include/modules/Maps.h include/modules/MapCache.h +include/modules/Maps.h include/modules/Materials.h include/modules/Notes.h +include/modules/Once.h include/modules/Random.h include/modules/Renderer.h include/modules/Screen.h include/modules/Translation.h +include/modules/Units.h include/modules/Vermin.h include/modules/World.h -include/modules/Graphic.h -include/modules/Once.h -include/modules/Filesystem.h ) SET( MODULE_SOURCES modules/Buildings.cpp modules/Burrows.cpp modules/Constructions.cpp -modules/Units.cpp +modules/Designations.cpp modules/Engravings.cpp modules/EventManager.cpp +modules/Filesystem.cpp +modules/Graphic.cpp modules/Gui.cpp modules/Items.cpp modules/Job.cpp @@ -151,16 +154,15 @@ modules/MapCache.cpp modules/Maps.cpp modules/Materials.cpp modules/Notes.cpp +modules/Once.cpp modules/Random.cpp modules/Renderer.cpp modules/Screen.cpp modules/Translation.cpp +modules/Units.cpp modules/Vermin.cpp -modules/World.cpp -modules/Graphic.cpp modules/Windows.cpp -modules/Once.cpp -modules/Filesystem.cpp +modules/World.cpp ) SET(STATIC_FIELDS_FILES) diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 0c153f91e..fd4ce1c02 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -56,6 +56,7 @@ distribution. #include "modules/Constructions.h" #include "modules/Random.h" #include "modules/Filesystem.h" +#include "modules/Designations.h" #include "LuaWrapper.h" #include "LuaTools.h" @@ -92,6 +93,7 @@ distribution. #include "df/itemdef.h" #include "df/enabler.h" #include "df/feature_init.h" +#include "df/plant.h" #include #include @@ -2314,6 +2316,17 @@ static const luaL_Reg dfhack_filesystem_funcs[] = { {NULL, NULL} }; +/***** Designations module *****/ + +static const LuaWrapper::FunctionReg dfhack_designations_module[] = { + WRAPM(Designations, markPlant), + WRAPM(Designations, unmarkPlant), + WRAPM(Designations, canMarkPlant), + WRAPM(Designations, canUnmarkPlant), + WRAPM(Designations, isPlantMarked), + {NULL, NULL} +}; + /***** Internal module *****/ static void *checkaddr(lua_State *L, int idx, bool allow_null = false) @@ -2792,5 +2805,6 @@ void OpenDFHackApi(lua_State *state) OpenModule(state, "constructions", dfhack_constructions_module); OpenModule(state, "screen", dfhack_screen_module, dfhack_screen_funcs); OpenModule(state, "filesystem", dfhack_filesystem_module, dfhack_filesystem_funcs); + OpenModule(state, "designations", dfhack_designations_module); OpenModule(state, "internal", dfhack_internal_module, dfhack_internal_funcs); } diff --git a/library/include/modules/Designations.h b/library/include/modules/Designations.h new file mode 100644 index 000000000..6dcf85f59 --- /dev/null +++ b/library/include/modules/Designations.h @@ -0,0 +1,18 @@ +#pragma once + +namespace df { + struct plant; +} + +namespace DFHack { + namespace Designations { + // Mark or un-mark a plant (e.g. fell trees, gather plants) + // Return value indicates whether the plant's designation was changed or not + // (This can be false if markPlant() is called on an already-designated plant, for example) + DFHACK_EXPORT bool markPlant(const df::plant *plant); + DFHACK_EXPORT bool unmarkPlant(const df::plant *plant); + DFHACK_EXPORT bool canMarkPlant(const df::plant *plant); + DFHACK_EXPORT bool canUnmarkPlant(const df::plant *plant); + DFHACK_EXPORT bool isPlantMarked(const df::plant *plant); + } +} diff --git a/library/modules/Designations.cpp b/library/modules/Designations.cpp new file mode 100644 index 000000000..8cae35d78 --- /dev/null +++ b/library/modules/Designations.cpp @@ -0,0 +1,119 @@ +#include "DataDefs.h" +#include "Error.h" + +#include "modules/Designations.h" +#include "modules/Job.h" +#include "modules/Maps.h" + +#include "df/job.h" +#include "df/map_block.h" +#include "df/plant.h" +#include "df/tile_dig_designation.h" +#include "df/world.h" + +using namespace DFHack; +using namespace df::enums; + +using df::global::world; + +static df::map_block *getPlantBlock(const df::plant *plant) +{ + if (!world) + return nullptr; + return Maps::getTileBlock(plant->pos); +} + +bool Designations::isPlantMarked(const df::plant *plant) +{ + CHECK_NULL_POINTER(plant); + + df::map_block *block = getPlantBlock(plant); + if (!block) + return false; + + if (block->designation[plant->pos.x % 16][plant->pos.y % 16].bits.dig == tile_dig_designation::Default) + return true; + + for (auto *link = world->job_list.next; link; link = link->next) + { + df::job *job = link->item; + if (!job) + continue; + if (job->job_type != job_type::FellTree && job->job_type != job_type::GatherPlants) + continue; + if (job->pos == plant->pos) + return true; + } + return false; +} + +bool Designations::canMarkPlant(const df::plant *plant) +{ + CHECK_NULL_POINTER(plant); + + if (!getPlantBlock(plant)) + return false; + + return !isPlantMarked(plant); +} + +bool Designations::markPlant(const df::plant *plant) +{ + CHECK_NULL_POINTER(plant); + + if (canMarkPlant(plant)) + { + df::map_block *block = getPlantBlock(plant); + block->designation[plant->pos.x % 16][plant->pos.y % 16].bits.dig = tile_dig_designation::Default; + block->flags.bits.designated = true; + return true; + } + else + { + return false; + } +} + +bool Designations::canUnmarkPlant(const df::plant *plant) +{ + CHECK_NULL_POINTER(plant); + + if (!getPlantBlock(plant)) + return false; + + return isPlantMarked(plant); +} + +bool Designations::unmarkPlant(const df::plant *plant) +{ + CHECK_NULL_POINTER(plant); + + if (canUnmarkPlant(plant)) + { + df::map_block *block = getPlantBlock(plant); + block->designation[plant->pos.x % 16][plant->pos.y % 16].bits.dig = tile_dig_designation::No; + block->flags.bits.designated = true; + + auto *link = world->job_list.next; + while (link) + { + auto *next = link->next; + df::job *job = link->item; + + if (!job) + continue; + if (job->job_type != job_type::FellTree && job->job_type != job_type::GatherPlants) + continue; + if (job->pos == plant->pos) + Job::removeJob(job); + + link = next; + } + + return true; + } + else + { + return false; + } +}