Add Designations module, currently supporting plant/tree designations

This makes it easier for tools to properly handle designating and undesignating
trees for chopping and plants for gathering, which changed significantly in
0.40.20.

Ref #531 (?), #656, #1014, #1018, #1030, #1076
develop
lethosor 2017-05-04 21:47:12 -04:00
parent e3258defd7
commit 1e469453fc
4 changed files with 163 additions and 10 deletions

@ -113,36 +113,39 @@ SET(MODULE_HEADERS
include/modules/Buildings.h include/modules/Buildings.h
include/modules/Burrows.h include/modules/Burrows.h
include/modules/Constructions.h include/modules/Constructions.h
include/modules/Units.h include/modules/Designations.h
include/modules/Engravings.h include/modules/Engravings.h
include/modules/EventManager.h include/modules/EventManager.h
include/modules/Filesystem.h
include/modules/Graphic.h
include/modules/Gui.h include/modules/Gui.h
include/modules/GuiHooks.h include/modules/GuiHooks.h
include/modules/Items.h include/modules/Items.h
include/modules/Job.h include/modules/Job.h
include/modules/kitchen.h include/modules/kitchen.h
include/modules/Maps.h
include/modules/MapCache.h include/modules/MapCache.h
include/modules/Maps.h
include/modules/Materials.h include/modules/Materials.h
include/modules/Notes.h include/modules/Notes.h
include/modules/Once.h
include/modules/Random.h include/modules/Random.h
include/modules/Renderer.h include/modules/Renderer.h
include/modules/Screen.h include/modules/Screen.h
include/modules/Translation.h include/modules/Translation.h
include/modules/Units.h
include/modules/Vermin.h include/modules/Vermin.h
include/modules/World.h include/modules/World.h
include/modules/Graphic.h
include/modules/Once.h
include/modules/Filesystem.h
) )
SET( MODULE_SOURCES SET( MODULE_SOURCES
modules/Buildings.cpp modules/Buildings.cpp
modules/Burrows.cpp modules/Burrows.cpp
modules/Constructions.cpp modules/Constructions.cpp
modules/Units.cpp modules/Designations.cpp
modules/Engravings.cpp modules/Engravings.cpp
modules/EventManager.cpp modules/EventManager.cpp
modules/Filesystem.cpp
modules/Graphic.cpp
modules/Gui.cpp modules/Gui.cpp
modules/Items.cpp modules/Items.cpp
modules/Job.cpp modules/Job.cpp
@ -151,16 +154,15 @@ modules/MapCache.cpp
modules/Maps.cpp modules/Maps.cpp
modules/Materials.cpp modules/Materials.cpp
modules/Notes.cpp modules/Notes.cpp
modules/Once.cpp
modules/Random.cpp modules/Random.cpp
modules/Renderer.cpp modules/Renderer.cpp
modules/Screen.cpp modules/Screen.cpp
modules/Translation.cpp modules/Translation.cpp
modules/Units.cpp
modules/Vermin.cpp modules/Vermin.cpp
modules/World.cpp
modules/Graphic.cpp
modules/Windows.cpp modules/Windows.cpp
modules/Once.cpp modules/World.cpp
modules/Filesystem.cpp
) )
SET(STATIC_FIELDS_FILES) SET(STATIC_FIELDS_FILES)

@ -56,6 +56,7 @@ distribution.
#include "modules/Constructions.h" #include "modules/Constructions.h"
#include "modules/Random.h" #include "modules/Random.h"
#include "modules/Filesystem.h" #include "modules/Filesystem.h"
#include "modules/Designations.h"
#include "LuaWrapper.h" #include "LuaWrapper.h"
#include "LuaTools.h" #include "LuaTools.h"
@ -92,6 +93,7 @@ distribution.
#include "df/itemdef.h" #include "df/itemdef.h"
#include "df/enabler.h" #include "df/enabler.h"
#include "df/feature_init.h" #include "df/feature_init.h"
#include "df/plant.h"
#include <lua.h> #include <lua.h>
#include <lauxlib.h> #include <lauxlib.h>
@ -2314,6 +2316,17 @@ static const luaL_Reg dfhack_filesystem_funcs[] = {
{NULL, NULL} {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 *****/ /***** Internal module *****/
static void *checkaddr(lua_State *L, int idx, bool allow_null = false) 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, "constructions", dfhack_constructions_module);
OpenModule(state, "screen", dfhack_screen_module, dfhack_screen_funcs); OpenModule(state, "screen", dfhack_screen_module, dfhack_screen_funcs);
OpenModule(state, "filesystem", dfhack_filesystem_module, dfhack_filesystem_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); OpenModule(state, "internal", dfhack_internal_module, dfhack_internal_funcs);
} }

@ -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);
}
}

@ -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;
}
}