From e48e2e65341ee9daf2e5daa3fb35c4733dda6dec Mon Sep 17 00:00:00 2001 From: Warmist Date: Sat, 14 May 2016 19:41:51 +0300 Subject: [PATCH 001/109] A twbt utils plugin for misc stuff used in twbt by mifki. Currently only render map function. --- plugins/CMakeLists.txt | 1 + plugins/lua/twbt-utils.lua | 11 ++++ plugins/twbt-utils.cpp | 122 +++++++++++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 plugins/lua/twbt-utils.lua create mode 100644 plugins/twbt-utils.cpp diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index b6e05b749..5d2d40813 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -149,6 +149,7 @@ if (BUILD_SUPPORTED) add_subdirectory(rendermax) DFHACK_PLUGIN(resume resume.cpp) DFHACK_PLUGIN(reveal reveal.cpp) + DFHACK_PLUGIN(twbt-utils twbt-utils.cpp LINK_LIBRARIES lua) DFHACK_PLUGIN(search search.cpp) DFHACK_PLUGIN(seedwatch seedwatch.cpp) DFHACK_PLUGIN(showmood showmood.cpp) diff --git a/plugins/lua/twbt-utils.lua b/plugins/lua/twbt-utils.lua new file mode 100644 index 000000000..56bdb0b19 --- /dev/null +++ b/plugins/lua/twbt-utils.lua @@ -0,0 +1,11 @@ +local _ENV = mkmodule('plugins.twbt-utils') + +--[[ + + Native functions: + + * render_map_rect(x,y,z,w,h) + +--]] + +return _ENV \ No newline at end of file diff --git a/plugins/twbt-utils.cpp b/plugins/twbt-utils.cpp new file mode 100644 index 000000000..7524ac29e --- /dev/null +++ b/plugins/twbt-utils.cpp @@ -0,0 +1,122 @@ +#include "Core.h" +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" +#include "VersionInfo.h" +#include "VTableInterpose.h" +#include "LuaTools.h" + +#include "DataDefs.h" + +#include "df/viewscreen_dwarfmodest.h" +#include "df/init.h" +#include "df/renderer.h" +#include "df/graphic.h" + +using std::string; +using std::vector; +using namespace DFHack; +using namespace df::enums; + +DFHACK_PLUGIN("twbt-utils"); +REQUIRE_GLOBAL(window_x) +REQUIRE_GLOBAL(window_y) +REQUIRE_GLOBAL(window_z) +REQUIRE_GLOBAL_NO_USE(gps) + +#ifdef WIN32 + // On Windows there's no convert_magenta parameter. Arguments are pushed onto stack, + // except for tex_pos and filename, which go into ecx and edx. Simulating this with __fastcall. + typedef void(__fastcall *LOAD_MULTI_PDIM)(long *tex_pos, const string &filename, void *tex, long dimx, long dimy, long *disp_x, long *disp_y); + + // On Windows there's no parameter pointing to the map_renderer structure + typedef void(_stdcall *RENDER_MAP)(int); + typedef void(_stdcall *RENDER_UPDOWN)(); + + RENDER_MAP _render_map; + void render_map(){ _render_map(0); } +#else + typedef void(*LOAD_MULTI_PDIM)(void *tex, const string &filename, long *tex_pos, long dimx, long dimy, bool convert_magenta, long *disp_x, long *disp_y); + + typedef void(*RENDER_MAP)(void*, int); + typedef void(*RENDER_UPDOWN)(void*); + + RENDER_MAP _render_map; + void render_map(){ _render_map(); } +#endif +static int render_map_rect(lua_State* L) +{ + CoreSuspender suspender; + + int x = luaL_checkint(L, 1); + int y = luaL_checkint(L, 2); + int z = luaL_checkint(L, 3); + int w = luaL_checkint(L, 4); + int h = luaL_checkint(L, 5); + //backup state + uint8_t *s = df::global::gps->screen; + int32_t win_h = df::global::gps->dimy; + int32_t was_x = *window_x; + int32_t was_y = *window_y; + int32_t was_z = *window_z; + int32_t gx = df::global::init->display.grid_x; + int32_t gy = df::global::init->display.grid_y; + df::global::init->display.grid_x = w+1; + df::global::init->display.grid_y = h+1; + *window_x = x; + *window_y = y; + *window_z = z; + //force full redraw + df::global::gps->force_full_display_count = 1; + for (int ty = 0; ty < h; ty++) + for (int tx = 0; tx < w; tx++) + { + for (int i = 0; i < 4; i++) + { + int t = (tx + 1)*win_h + ty + 1; + s[t * 4 + i] = 0; + } + } + render_map(); + //restore state + *window_x = was_x; + *window_y = was_y; + *window_z = was_z; + df::global::init->display.grid_x = gx; + df::global::init->display.grid_y = gy; + + lua_createtable(L,w*h*4,0); + + int counter = 0; + for (int ty = 0; ty < h; ty++) + for (int tx = 0; tx < w; tx++) + { + for (int i = 0; i < 4;i++) + { + int t = (tx + 1)*win_h + ty + 1; + lua_pushnumber(L, s[t*4+i]); + lua_rawseti(L, -2, counter); + counter++; + } + } + return 1; +} + +DFHACK_PLUGIN_LUA_COMMANDS{ + DFHACK_LUA_COMMAND(render_map_rect), + DFHACK_LUA_END +}; + +DFhackCExport command_result plugin_init(color_ostream &out, std::vector &commands) +{ + auto addr =reinterpret_cast(Core::getInstance().vinfo->getAddress("twbt_render_map")); + if (addr == nullptr) + return CR_FAILURE; + _render_map = addr; + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown(color_ostream &out) +{ + return CR_OK; +} From 6a65ad2fcbb6d4cb3a6d4cc6ddc53837c3079db2 Mon Sep 17 00:00:00 2001 From: Warmist Date: Sat, 21 Oct 2017 14:07:07 +0300 Subject: [PATCH 002/109] add more functions (not used yet) and fix linux --- plugins/twbt-utils.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/plugins/twbt-utils.cpp b/plugins/twbt-utils.cpp index 7524ac29e..4532f3320 100644 --- a/plugins/twbt-utils.cpp +++ b/plugins/twbt-utils.cpp @@ -12,6 +12,8 @@ #include "df/init.h" #include "df/renderer.h" #include "df/graphic.h" +#include "df/enabler.h" +#include "df/map_renderer.h" using std::string; using std::vector; @@ -23,6 +25,7 @@ REQUIRE_GLOBAL(window_x) REQUIRE_GLOBAL(window_y) REQUIRE_GLOBAL(window_z) REQUIRE_GLOBAL_NO_USE(gps) +REQUIRE_GLOBAL_NO_USE(enabler) #ifdef WIN32 // On Windows there's no convert_magenta parameter. Arguments are pushed onto stack, @@ -34,15 +37,31 @@ REQUIRE_GLOBAL_NO_USE(gps) typedef void(_stdcall *RENDER_UPDOWN)(); RENDER_MAP _render_map; + RENDER_UPDOWN _render_updown; + LOAD_MULTI_PDIM _load_multi_pdim; + void render_map(){ _render_map(0); } + void render_updown() { _render_updown(); } + void load_tileset(const string &filename, long * tex_pos, long dimx, long dimy, long* disp_x,long* disp_y) { + _load_multi_pdim(tex_pos, filename, &df::global::enabler->textures, dimx, dimy, disp_x, disp_y); + } #else +REQUIRE_GLOBAL_NO_USE(map_renderer) + typedef void(*LOAD_MULTI_PDIM)(void *tex, const string &filename, long *tex_pos, long dimx, long dimy, bool convert_magenta, long *disp_x, long *disp_y); typedef void(*RENDER_MAP)(void*, int); typedef void(*RENDER_UPDOWN)(void*); - RENDER_MAP _render_map; - void render_map(){ _render_map(); } + RENDER_MAP _render_map; + RENDER_UPDOWN _render_updown; + LOAD_MULTI_PDIM _load_multi_pdim; + + void render_map(){ _render_map(df::global::map_renderer,0); } + void render_updown() { _render_updown(df::global::map_renderer); } + void load_tileset(const string &filename, long * tex_pos, long dimx, long dimy, long* disp_x, long* disp_y) { + _load_multi_pdim(&df::global::enabler->textures, filename,tex_pos, &df::global::enabler->textures, dimx, dimy,true, disp_x, disp_y); + } #endif static int render_map_rect(lua_State* L) { From 04465f59f5bb7a3f60e3d643b41b6f43ccdf97ab Mon Sep 17 00:00:00 2001 From: Warmist Date: Sat, 21 Oct 2017 14:27:08 +0300 Subject: [PATCH 003/109] Fix spaces and fix linux (again) --- plugins/twbt-utils.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/plugins/twbt-utils.cpp b/plugins/twbt-utils.cpp index 4532f3320..dd63418ca 100644 --- a/plugins/twbt-utils.cpp +++ b/plugins/twbt-utils.cpp @@ -37,14 +37,14 @@ REQUIRE_GLOBAL_NO_USE(enabler) typedef void(_stdcall *RENDER_UPDOWN)(); RENDER_MAP _render_map; - RENDER_UPDOWN _render_updown; - LOAD_MULTI_PDIM _load_multi_pdim; + RENDER_UPDOWN _render_updown; + LOAD_MULTI_PDIM _load_multi_pdim; void render_map(){ _render_map(0); } - void render_updown() { _render_updown(); } - void load_tileset(const string &filename, long * tex_pos, long dimx, long dimy, long* disp_x,long* disp_y) { - _load_multi_pdim(tex_pos, filename, &df::global::enabler->textures, dimx, dimy, disp_x, disp_y); - } + void render_updown() { _render_updown(); } + void load_tileset(const string &filename, long * tex_pos, long dimx, long dimy, long* disp_x,long* disp_y) { + _load_multi_pdim(tex_pos, filename, &df::global::enabler->textures, dimx, dimy, disp_x, disp_y); + } #else REQUIRE_GLOBAL_NO_USE(map_renderer) @@ -53,15 +53,15 @@ REQUIRE_GLOBAL_NO_USE(map_renderer) typedef void(*RENDER_MAP)(void*, int); typedef void(*RENDER_UPDOWN)(void*); - RENDER_MAP _render_map; - RENDER_UPDOWN _render_updown; - LOAD_MULTI_PDIM _load_multi_pdim; + RENDER_MAP _render_map; + RENDER_UPDOWN _render_updown; + LOAD_MULTI_PDIM _load_multi_pdim; void render_map(){ _render_map(df::global::map_renderer,0); } - void render_updown() { _render_updown(df::global::map_renderer); } - void load_tileset(const string &filename, long * tex_pos, long dimx, long dimy, long* disp_x, long* disp_y) { - _load_multi_pdim(&df::global::enabler->textures, filename,tex_pos, &df::global::enabler->textures, dimx, dimy,true, disp_x, disp_y); - } + void render_updown() { _render_updown(df::global::map_renderer); } + void load_tileset(const string &filename, long * tex_pos, long dimx, long dimy, long* disp_x, long* disp_y) { + _load_multi_pdim(&df::global::enabler->textures, filename,tex_pos, dimx, dimy,true, disp_x, disp_y); + } #endif static int render_map_rect(lua_State* L) { From d6df9cd257ddada6394cb1e08af7cbe0416adef0 Mon Sep 17 00:00:00 2001 From: Warmist Date: Sun, 31 Dec 2017 11:39:51 +0200 Subject: [PATCH 004/109] tidying up --- plugins/twbt-utils.cpp | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/plugins/twbt-utils.cpp b/plugins/twbt-utils.cpp index dd63418ca..4dbe3ca45 100644 --- a/plugins/twbt-utils.cpp +++ b/plugins/twbt-utils.cpp @@ -26,42 +26,23 @@ REQUIRE_GLOBAL(window_y) REQUIRE_GLOBAL(window_z) REQUIRE_GLOBAL_NO_USE(gps) REQUIRE_GLOBAL_NO_USE(enabler) +REQUIRE_GLOBAL_NO_USE(twbt_render_map) #ifdef WIN32 - // On Windows there's no convert_magenta parameter. Arguments are pushed onto stack, - // except for tex_pos and filename, which go into ecx and edx. Simulating this with __fastcall. - typedef void(__fastcall *LOAD_MULTI_PDIM)(long *tex_pos, const string &filename, void *tex, long dimx, long dimy, long *disp_x, long *disp_y); - // On Windows there's no parameter pointing to the map_renderer structure typedef void(_stdcall *RENDER_MAP)(int); - typedef void(_stdcall *RENDER_UPDOWN)(); RENDER_MAP _render_map; - RENDER_UPDOWN _render_updown; - LOAD_MULTI_PDIM _load_multi_pdim; void render_map(){ _render_map(0); } - void render_updown() { _render_updown(); } - void load_tileset(const string &filename, long * tex_pos, long dimx, long dimy, long* disp_x,long* disp_y) { - _load_multi_pdim(tex_pos, filename, &df::global::enabler->textures, dimx, dimy, disp_x, disp_y); - } #else REQUIRE_GLOBAL_NO_USE(map_renderer) - typedef void(*LOAD_MULTI_PDIM)(void *tex, const string &filename, long *tex_pos, long dimx, long dimy, bool convert_magenta, long *disp_x, long *disp_y); - typedef void(*RENDER_MAP)(void*, int); - typedef void(*RENDER_UPDOWN)(void*); RENDER_MAP _render_map; - RENDER_UPDOWN _render_updown; - LOAD_MULTI_PDIM _load_multi_pdim; void render_map(){ _render_map(df::global::map_renderer,0); } - void render_updown() { _render_updown(df::global::map_renderer); } - void load_tileset(const string &filename, long * tex_pos, long dimx, long dimy, long* disp_x, long* disp_y) { - _load_multi_pdim(&df::global::enabler->textures, filename,tex_pos, dimx, dimy,true, disp_x, disp_y); - } #endif static int render_map_rect(lua_State* L) { From 6ef85908ac2176149d198918dc56e1d49c009890 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Mon, 18 Jun 2018 21:28:56 +0530 Subject: [PATCH 005/109] Bump df version --- plugins/remotefortressreader/df_version_int.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/remotefortressreader/df_version_int.h b/plugins/remotefortressreader/df_version_int.h index 35c9ed851..5c89d88c4 100644 --- a/plugins/remotefortressreader/df_version_int.h +++ b/plugins/remotefortressreader/df_version_int.h @@ -1,2 +1,2 @@ #pragma once -#define DF_VERSION_INT 44002 +#define DF_VERSION_INT 44010 From dc367f212e7a569a80f514555c5feab6eaa634fb Mon Sep 17 00:00:00 2001 From: JapaMala Date: Mon, 18 Jun 2018 22:12:52 +0530 Subject: [PATCH 006/109] Move fortress mode control stuff into a different file. --- plugins/remotefortressreader/CMakeLists.txt | 2 + .../remotefortressreader/dwarf_control.cpp | 101 ++++++++++++++++++ plugins/remotefortressreader/dwarf_control.h | 12 +++ .../remotefortressreader.cpp | 88 +-------------- 4 files changed, 116 insertions(+), 87 deletions(-) create mode 100644 plugins/remotefortressreader/dwarf_control.cpp create mode 100644 plugins/remotefortressreader/dwarf_control.h diff --git a/plugins/remotefortressreader/CMakeLists.txt b/plugins/remotefortressreader/CMakeLists.txt index 1ff1cac7f..c7c9d74fe 100644 --- a/plugins/remotefortressreader/CMakeLists.txt +++ b/plugins/remotefortressreader/CMakeLists.txt @@ -4,12 +4,14 @@ SET(PROJECT_SRCS remotefortressreader.cpp adventure_control.cpp building_reader.cpp + dwarf_control.cpp item_reader.cpp ) # A list of headers SET(PROJECT_HDRS adventure_control.h building_reader.h + dwarf_control.h item_reader.h df_version_int.h ) diff --git a/plugins/remotefortressreader/dwarf_control.cpp b/plugins/remotefortressreader/dwarf_control.cpp new file mode 100644 index 000000000..461b2f89e --- /dev/null +++ b/plugins/remotefortressreader/dwarf_control.cpp @@ -0,0 +1,101 @@ +#include "dwarf_control.h" +#include "DataDefs.h" +#include "df_version_int.h" + +#include "df/job.h" +#include "df/job_list_link.h" +#include "df/world.h" + +#include "modules/Buildings.h" +#include "modules/Job.h" +#include "modules/MapCache.h" +#include "modules/Maps.h" +#include "modules/World.h" + +using namespace DFHack; +using namespace RemoteFortressReader; + +command_result SendDigCommand(color_ostream &stream, const DigCommand *in) +{ + MapExtras::MapCache mc; + + for (int i = 0; i < in->locations_size(); i++) + { + auto pos = in->locations(i); + auto des = mc.designationAt(DFCoord(pos.x(), pos.y(), pos.z())); + switch (in->designation()) + { + case NO_DIG: + des.bits.dig = tile_dig_designation::No; + break; + case DEFAULT_DIG: + des.bits.dig = tile_dig_designation::Default; + break; + case UP_DOWN_STAIR_DIG: + des.bits.dig = tile_dig_designation::UpDownStair; + break; + case CHANNEL_DIG: + des.bits.dig = tile_dig_designation::Channel; + break; + case RAMP_DIG: + des.bits.dig = tile_dig_designation::Ramp; + break; + case DOWN_STAIR_DIG: + des.bits.dig = tile_dig_designation::DownStair; + break; + case UP_STAIR_DIG: + des.bits.dig = tile_dig_designation::UpStair; + break; + default: + break; + } + mc.setDesignationAt(DFCoord(pos.x(), pos.y(), pos.z()), des); + +#if DF_VERSION_INT >= 43005 + //remove and job postings related. + for (df::job_list_link * listing = &(df::global::world->jobs.list); listing != NULL; listing = listing->next) + { + if (listing->item == NULL) + continue; + auto type = listing->item->job_type; + switch (type) + { + case df::enums::job_type::CarveFortification: + case df::enums::job_type::DetailWall: + case df::enums::job_type::DetailFloor: + case df::enums::job_type::Dig: + case df::enums::job_type::CarveUpwardStaircase: + case df::enums::job_type::CarveDownwardStaircase: + case df::enums::job_type::CarveUpDownStaircase: + case df::enums::job_type::CarveRamp: + case df::enums::job_type::DigChannel: + case df::enums::job_type::FellTree: + case df::enums::job_type::GatherPlants: + case df::enums::job_type::RemoveConstruction: + case df::enums::job_type::CarveTrack: + { + if (listing->item->pos == DFCoord(pos.x(), pos.y(), pos.z())) + { + Job::removeJob(listing->item); + goto JOB_FOUND; + } + break; + } + default: + continue; + } + } + JOB_FOUND: + continue; +#endif + } + + mc.WriteAll(); + return CR_OK; +} + +command_result SetPauseState(color_ostream &stream, const SingleBool *in) +{ + DFHack::World::SetPauseState(in->value()); + return CR_OK; +} diff --git a/plugins/remotefortressreader/dwarf_control.h b/plugins/remotefortressreader/dwarf_control.h new file mode 100644 index 000000000..bb08e8b7a --- /dev/null +++ b/plugins/remotefortressreader/dwarf_control.h @@ -0,0 +1,12 @@ +#ifndef DWARF_CONTROL_H +#define DWARF_CONTROL_H + +#include "RemoteClient.h" +#include "RemoteFortressReader.pb.h" + +DFHack::command_result SendDigCommand(DFHack::color_ostream &stream, const RemoteFortressReader::DigCommand *in); +DFHack::command_result SetPauseState(DFHack::color_ostream &stream, const RemoteFortressReader::SingleBool *in); + +#endif // !DWARF_CONTROL_H + + diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index 7dced3b9f..8f3ac5b04 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -117,6 +117,7 @@ #include "adventure_control.h" #include "building_reader.h" +#include "dwarf_control.h" #include "item_reader.h" using namespace DFHack; @@ -161,8 +162,6 @@ static command_result GetPlantRaws(color_ostream &stream, const EmptyMessage *in static command_result GetPartialPlantRaws(color_ostream &stream, const ListRequest *in, PlantRawList *out); static command_result CopyScreen(color_ostream &stream, const EmptyMessage *in, ScreenCapture *out); static command_result PassKeyboardEvent(color_ostream &stream, const KeyboardEvent *in); -static command_result SendDigCommand(color_ostream &stream, const DigCommand *in); -static command_result SetPauseState(color_ostream & stream, const SingleBool * in); static command_result GetPauseState(color_ostream & stream, const EmptyMessage * in, SingleBool * out); static command_result GetVersionInfo(color_ostream & stream, const EmptyMessage * in, RemoteFortressReader::VersionInfo * out); static command_result GetReports(color_ostream & stream, const EmptyMessage * in, RemoteFortressReader::Status * out); @@ -2893,91 +2892,6 @@ static command_result PassKeyboardEvent(color_ostream &stream, const KeyboardEve return CR_OK; } -static command_result SendDigCommand(color_ostream &stream, const DigCommand *in) -{ - MapExtras::MapCache mc; - - for (int i = 0; i < in->locations_size(); i++) - { - auto pos = in->locations(i); - auto des = mc.designationAt(DFCoord(pos.x(), pos.y(), pos.z())); - switch (in->designation()) - { - case NO_DIG: - des.bits.dig = tile_dig_designation::No; - break; - case DEFAULT_DIG: - des.bits.dig = tile_dig_designation::Default; - break; - case UP_DOWN_STAIR_DIG: - des.bits.dig = tile_dig_designation::UpDownStair; - break; - case CHANNEL_DIG: - des.bits.dig = tile_dig_designation::Channel; - break; - case RAMP_DIG: - des.bits.dig = tile_dig_designation::Ramp; - break; - case DOWN_STAIR_DIG: - des.bits.dig = tile_dig_designation::DownStair; - break; - case UP_STAIR_DIG: - des.bits.dig = tile_dig_designation::UpStair; - break; - default: - break; - } - mc.setDesignationAt(DFCoord(pos.x(), pos.y(), pos.z()), des); - -#if DF_VERSION_INT >= 43005 - //remove and job postings related. - for (df::job_list_link * listing = &(world->jobs.list); listing != NULL; listing = listing->next) - { - if (listing->item == NULL) - continue; - auto type = listing->item->job_type; - switch (type) - { - case df::enums::job_type::CarveFortification: - case df::enums::job_type::DetailWall: - case df::enums::job_type::DetailFloor: - case df::enums::job_type::Dig: - case df::enums::job_type::CarveUpwardStaircase: - case df::enums::job_type::CarveDownwardStaircase: - case df::enums::job_type::CarveUpDownStaircase: - case df::enums::job_type::CarveRamp: - case df::enums::job_type::DigChannel: - case df::enums::job_type::FellTree: - case df::enums::job_type::GatherPlants: - case df::enums::job_type::RemoveConstruction: - case df::enums::job_type::CarveTrack: - { - if (listing->item->pos == DFCoord(pos.x(), pos.y(), pos.z())) - { - Job::removeJob(listing->item); - goto JOB_FOUND; - } - break; - } - default: - continue; - } - } - JOB_FOUND: - continue; -#endif - } - - mc.WriteAll(); - return CR_OK; -} - -static command_result SetPauseState(color_ostream &stream, const SingleBool *in) -{ - DFHack::World::SetPauseState(in->value()); - return CR_OK; -} - static command_result GetPauseState(color_ostream &stream, const EmptyMessage *in, SingleBool *out) { out->set_value(World::ReadPauseState()); From 93c3418f974bac277c6136d80d97883c5d7a3b72 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Sun, 24 Jun 2018 14:45:57 +0530 Subject: [PATCH 007/109] Added a simple function to get the current sidebar mode in fort mode. --- plugins/proto/DwarfControl.proto | 12 ++++ plugins/proto/ui_sidebar_mode.proto | 63 +++++++++++++++++++ plugins/remotefortressreader/CMakeLists.txt | 2 + .../remotefortressreader/dwarf_control.cpp | 7 +++ plugins/remotefortressreader/dwarf_control.h | 2 + .../remotefortressreader.cpp | 1 + 6 files changed, 87 insertions(+) create mode 100644 plugins/proto/DwarfControl.proto create mode 100644 plugins/proto/ui_sidebar_mode.proto diff --git a/plugins/proto/DwarfControl.proto b/plugins/proto/DwarfControl.proto new file mode 100644 index 000000000..2918b5a82 --- /dev/null +++ b/plugins/proto/DwarfControl.proto @@ -0,0 +1,12 @@ +syntax = "proto2"; +package DwarfControl; + +//Attempts to provide a complete framework for reading everything from a fortress needed for vizualization +option optimize_for = LITE_RUNTIME; + +import "ui_sidebar_mode.proto"; + +message SidebarState +{ + optional proto.enums.ui_sidebar_mode.ui_sidebar_mode mode = 1; +} \ No newline at end of file diff --git a/plugins/proto/ui_sidebar_mode.proto b/plugins/proto/ui_sidebar_mode.proto new file mode 100644 index 000000000..26b570d21 --- /dev/null +++ b/plugins/proto/ui_sidebar_mode.proto @@ -0,0 +1,63 @@ +package proto.enums.ui_sidebar_mode; + +//Attempts to provide a complete framework for reading everything from a fortress needed for vizualization +option optimize_for = LITE_RUNTIME; + +enum ui_sidebar_mode +{ + Default = 1; + Squads = 2; + DesignateMine = 3; + DesignateRemoveRamps = 4; + DesignateUpStair = 5; + DesignateDownStair = 6; + DesignateUpDownStair = 7; + DesignateUpRamp = 8; + DesignateChannel = 9; + DesignateGatherPlants = 10; + DesignateRemoveDesignation = 11; + DesignateSmooth = 12; + DesignateCarveTrack = 13; + DesignateEngrave = 14; + DesignateCarveFortification = 15; + Stockpiles = 16; + Build = 17; + QueryBuilding = 18; + Orders = 19; + OrdersForbid = 20; + OrdersRefuse = 21; + OrdersWorkshop = 22; + OrdersZone = 23; + BuildingItems = 24; + ViewUnits = 25; + LookAround = 26; + DesignateItemsClaim = 27; + DesignateItemsForbid = 28; + DesignateItemsMelt = 29; + DesignateItemsUnmelt = 30; + DesignateItemsDump = 31; + DesignateItemsUndump = 32; + DesignateItemsHide = 33; + DesignateItemsUnhide = 34; + DesignateChopTrees = 35; + DesignateToggleEngravings = 36; + DesignateToggleMarker = 37; + Hotkeys = 38; + DesignateTrafficHigh = 39; + DesignateTrafficNormal = 40; + DesignateTrafficLow = 41; + DesignateTrafficRestricted = 42; + Zones = 43; + ZonesPenInfo = 44; + ZonesPitInfo = 45; + ZonesHospitalInfo = 46; + ZonesGatherInfo = 47; + DesignateRemoveConstruction = 48; + DepotAccess = 49; + NotesPoints = 50; + NotesRoutes = 51; + Burrows = 52; + Hauling = 53; + ArenaWeather = 54; + ArenaTrees = 55; +} \ No newline at end of file diff --git a/plugins/remotefortressreader/CMakeLists.txt b/plugins/remotefortressreader/CMakeLists.txt index c7c9d74fe..954dbcbbf 100644 --- a/plugins/remotefortressreader/CMakeLists.txt +++ b/plugins/remotefortressreader/CMakeLists.txt @@ -20,6 +20,8 @@ SET(PROJECT_PROTO ${CMAKE_CURRENT_SOURCE_DIR}/../proto/RemoteFortressReader.pb.cc ${CMAKE_CURRENT_SOURCE_DIR}/../proto/AdventureControl.pb.cc ${CMAKE_CURRENT_SOURCE_DIR}/../proto/ItemdefInstrument.pb.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../proto/DwarfControl.pb.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../proto/ui_sidebar_mode.pb.cc ) SET_SOURCE_FILES_PROPERTIES( ${PROJECT_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE) diff --git a/plugins/remotefortressreader/dwarf_control.cpp b/plugins/remotefortressreader/dwarf_control.cpp index 461b2f89e..3bb4d4af6 100644 --- a/plugins/remotefortressreader/dwarf_control.cpp +++ b/plugins/remotefortressreader/dwarf_control.cpp @@ -4,6 +4,7 @@ #include "df/job.h" #include "df/job_list_link.h" +#include "df/ui.h" #include "df/world.h" #include "modules/Buildings.h" @@ -15,6 +16,7 @@ using namespace DFHack; using namespace RemoteFortressReader; + command_result SendDigCommand(color_ostream &stream, const DigCommand *in) { MapExtras::MapCache mc; @@ -99,3 +101,8 @@ command_result SetPauseState(color_ostream &stream, const SingleBool *in) DFHack::World::SetPauseState(in->value()); return CR_OK; } + +command_result GetSideMenu(DFHack::color_ostream &stream, const dfproto::EmptyMessage *in, DwarfControl::SidebarState *out) +{ + out->set_mode((proto::enums::ui_sidebar_mode::ui_sidebar_mode)df::global::ui->main.mode); +} diff --git a/plugins/remotefortressreader/dwarf_control.h b/plugins/remotefortressreader/dwarf_control.h index bb08e8b7a..b66309d9e 100644 --- a/plugins/remotefortressreader/dwarf_control.h +++ b/plugins/remotefortressreader/dwarf_control.h @@ -3,9 +3,11 @@ #include "RemoteClient.h" #include "RemoteFortressReader.pb.h" +#include "DwarfControl.pb.h" DFHack::command_result SendDigCommand(DFHack::color_ostream &stream, const RemoteFortressReader::DigCommand *in); DFHack::command_result SetPauseState(DFHack::color_ostream &stream, const RemoteFortressReader::SingleBool *in); +DFHack::command_result GetSideMenu(DFHack::color_ostream &stream, const dfproto::EmptyMessage *in, DwarfControl::SidebarState *out); #endif // !DWARF_CONTROL_H diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index 8f3ac5b04..baae99c5b 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -328,6 +328,7 @@ DFhackCExport RPCService *plugin_rpcconnect(color_ostream &) svc->addFunction("MovementSelectCommand", MovementSelectCommand, SF_ALLOW_REMOTE); svc->addFunction("MiscMoveCommand", MiscMoveCommand, SF_ALLOW_REMOTE); svc->addFunction("GetLanguage", GetLanguage, SF_ALLOW_REMOTE); + svc->addFunction("GetSideMenu", GetSideMenu, SF_ALLOW_REMOTE); return svc; } From 4970935b9af9f709ebf01db331efef5c7b66ff23 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Sun, 24 Jun 2018 16:19:52 +0530 Subject: [PATCH 008/109] fixed sidebar mode numbering. --- plugins/proto/ui_sidebar_mode.proto | 110 +++++++++--------- .../remotefortressreader/dwarf_control.cpp | 4 +- 2 files changed, 58 insertions(+), 56 deletions(-) diff --git a/plugins/proto/ui_sidebar_mode.proto b/plugins/proto/ui_sidebar_mode.proto index 26b570d21..b07bb1baa 100644 --- a/plugins/proto/ui_sidebar_mode.proto +++ b/plugins/proto/ui_sidebar_mode.proto @@ -5,59 +5,59 @@ option optimize_for = LITE_RUNTIME; enum ui_sidebar_mode { - Default = 1; - Squads = 2; - DesignateMine = 3; - DesignateRemoveRamps = 4; - DesignateUpStair = 5; - DesignateDownStair = 6; - DesignateUpDownStair = 7; - DesignateUpRamp = 8; - DesignateChannel = 9; - DesignateGatherPlants = 10; - DesignateRemoveDesignation = 11; - DesignateSmooth = 12; - DesignateCarveTrack = 13; - DesignateEngrave = 14; - DesignateCarveFortification = 15; - Stockpiles = 16; - Build = 17; - QueryBuilding = 18; - Orders = 19; - OrdersForbid = 20; - OrdersRefuse = 21; - OrdersWorkshop = 22; - OrdersZone = 23; - BuildingItems = 24; - ViewUnits = 25; - LookAround = 26; - DesignateItemsClaim = 27; - DesignateItemsForbid = 28; - DesignateItemsMelt = 29; - DesignateItemsUnmelt = 30; - DesignateItemsDump = 31; - DesignateItemsUndump = 32; - DesignateItemsHide = 33; - DesignateItemsUnhide = 34; - DesignateChopTrees = 35; - DesignateToggleEngravings = 36; - DesignateToggleMarker = 37; - Hotkeys = 38; - DesignateTrafficHigh = 39; - DesignateTrafficNormal = 40; - DesignateTrafficLow = 41; - DesignateTrafficRestricted = 42; - Zones = 43; - ZonesPenInfo = 44; - ZonesPitInfo = 45; - ZonesHospitalInfo = 46; - ZonesGatherInfo = 47; - DesignateRemoveConstruction = 48; - DepotAccess = 49; - NotesPoints = 50; - NotesRoutes = 51; - Burrows = 52; - Hauling = 53; - ArenaWeather = 54; - ArenaTrees = 55; + Default = 0; + Squads = 1; + DesignateMine = 2; + DesignateRemoveRamps = 3; + DesignateUpStair = 4; + DesignateDownStair = 5; + DesignateUpDownStair = 6; + DesignateUpRamp = 7; + DesignateChannel = 8; + DesignateGatherPlants = 9; + DesignateRemoveDesignation = 10; + DesignateSmooth = 11; + DesignateCarveTrack = 12; + DesignateEngrave = 13; + DesignateCarveFortification = 14; + Stockpiles = 15; + Build = 16; + QueryBuilding = 17; + Orders = 18; + OrdersForbid = 19; + OrdersRefuse = 20; + OrdersWorkshop = 21; + OrdersZone = 22; + BuildingItems = 23; + ViewUnits = 24; + LookAround = 25; + DesignateItemsClaim = 26; + DesignateItemsForbid = 27; + DesignateItemsMelt = 28; + DesignateItemsUnmelt = 29; + DesignateItemsDump = 30; + DesignateItemsUndump = 31; + DesignateItemsHide = 32; + DesignateItemsUnhide = 33; + DesignateChopTrees = 34; + DesignateToggleEngravings = 35; + DesignateToggleMarker = 36; + Hotkeys = 37; + DesignateTrafficHigh = 38; + DesignateTrafficNormal = 39; + DesignateTrafficLow = 40; + DesignateTrafficRestricted = 41; + Zones = 42; + ZonesPenInfo = 43; + ZonesPitInfo = 44; + ZonesHospitalInfo = 45; + ZonesGatherInfo = 46; + DesignateRemoveConstruction = 47; + DepotAccess = 48; + NotesPoints = 49; + NotesRoutes = 50; + Burrows = 51; + Hauling = 52; + ArenaWeather = 53; + ArenaTrees = 54; } \ No newline at end of file diff --git a/plugins/remotefortressreader/dwarf_control.cpp b/plugins/remotefortressreader/dwarf_control.cpp index 3bb4d4af6..90997ebb9 100644 --- a/plugins/remotefortressreader/dwarf_control.cpp +++ b/plugins/remotefortressreader/dwarf_control.cpp @@ -104,5 +104,7 @@ command_result SetPauseState(color_ostream &stream, const SingleBool *in) command_result GetSideMenu(DFHack::color_ostream &stream, const dfproto::EmptyMessage *in, DwarfControl::SidebarState *out) { - out->set_mode((proto::enums::ui_sidebar_mode::ui_sidebar_mode)df::global::ui->main.mode); + auto ui = df::global::ui; + out->set_mode((proto::enums::ui_sidebar_mode::ui_sidebar_mode)ui->main.mode); + return CR_OK; } From 897b7b6a477408f8dd4679f7d2bd16d97c31d46f Mon Sep 17 00:00:00 2001 From: JapaMala Date: Thu, 28 Jun 2018 20:27:12 +0530 Subject: [PATCH 009/109] Send the building menu items over RFR --- plugins/proto/DwarfControl.proto | 23 ++- .../remotefortressreader/dwarf_control.cpp | 179 ++++++++++++++++-- plugins/remotefortressreader/dwarf_control.h | 1 + .../remotefortressreader.cpp | 1 + 4 files changed, 189 insertions(+), 15 deletions(-) diff --git a/plugins/proto/DwarfControl.proto b/plugins/proto/DwarfControl.proto index 2918b5a82..bc1f26512 100644 --- a/plugins/proto/DwarfControl.proto +++ b/plugins/proto/DwarfControl.proto @@ -5,8 +5,29 @@ package DwarfControl; option optimize_for = LITE_RUNTIME; import "ui_sidebar_mode.proto"; +import "RemoteFortressReader.proto"; + +enum BuildCategory +{ + NotCategory = 0; + SiegeEngines = 1; + Traps = 2; + Workshops = 3; + Furnaces = 4; + Constructions = 5; + MachineComponents = 6; + Track = 7; +} message SidebarState { optional proto.enums.ui_sidebar_mode.ui_sidebar_mode mode = 1; -} \ No newline at end of file + repeated MenuItem menu_items = 2; +} + +message MenuItem +{ + optional RemoteFortressReader.BuildingType building_type = 1; + optional int32 existing_count = 2; + optional BuildCategory build_category = 3; +} diff --git a/plugins/remotefortressreader/dwarf_control.cpp b/plugins/remotefortressreader/dwarf_control.cpp index 90997ebb9..071903cf0 100644 --- a/plugins/remotefortressreader/dwarf_control.cpp +++ b/plugins/remotefortressreader/dwarf_control.cpp @@ -4,7 +4,10 @@ #include "df/job.h" #include "df/job_list_link.h" +#include "df/interface_button_construction_building_selectorst.h" +#include "df/interface_button_construction_category_selectorst.h" #include "df/ui.h" +#include "df/ui_sidebar_menus.h" #include "df/world.h" #include "modules/Buildings.h" @@ -15,7 +18,7 @@ using namespace DFHack; using namespace RemoteFortressReader; - +using namespace df::enums; command_result SendDigCommand(color_ostream &stream, const DigCommand *in) { @@ -62,19 +65,19 @@ command_result SendDigCommand(color_ostream &stream, const DigCommand *in) auto type = listing->item->job_type; switch (type) { - case df::enums::job_type::CarveFortification: - case df::enums::job_type::DetailWall: - case df::enums::job_type::DetailFloor: - case df::enums::job_type::Dig: - case df::enums::job_type::CarveUpwardStaircase: - case df::enums::job_type::CarveDownwardStaircase: - case df::enums::job_type::CarveUpDownStaircase: - case df::enums::job_type::CarveRamp: - case df::enums::job_type::DigChannel: - case df::enums::job_type::FellTree: - case df::enums::job_type::GatherPlants: - case df::enums::job_type::RemoveConstruction: - case df::enums::job_type::CarveTrack: + case job_type::CarveFortification: + case job_type::DetailWall: + case job_type::DetailFloor: + case job_type::Dig: + case job_type::CarveUpwardStaircase: + case job_type::CarveDownwardStaircase: + case job_type::CarveUpDownStaircase: + case job_type::CarveRamp: + case job_type::DigChannel: + case job_type::FellTree: + case job_type::GatherPlants: + case job_type::RemoveConstruction: + case job_type::CarveTrack: { if (listing->item->pos == DFCoord(pos.x(), pos.y(), pos.z())) { @@ -106,5 +109,153 @@ command_result GetSideMenu(DFHack::color_ostream &stream, const dfproto::EmptyMe { auto ui = df::global::ui; out->set_mode((proto::enums::ui_sidebar_mode::ui_sidebar_mode)ui->main.mode); + auto mode = ui->main.mode; + switch (mode) + { + case ui_sidebar_mode::Default: + break; + case ui_sidebar_mode::Squads: + break; + case ui_sidebar_mode::DesignateMine: + break; + case ui_sidebar_mode::DesignateRemoveRamps: + break; + case ui_sidebar_mode::DesignateUpStair: + break; + case ui_sidebar_mode::DesignateDownStair: + break; + case ui_sidebar_mode::DesignateUpDownStair: + break; + case ui_sidebar_mode::DesignateUpRamp: + break; + case ui_sidebar_mode::DesignateChannel: + break; + case ui_sidebar_mode::DesignateGatherPlants: + break; + case ui_sidebar_mode::DesignateRemoveDesignation: + break; + case ui_sidebar_mode::DesignateSmooth: + break; + case ui_sidebar_mode::DesignateCarveTrack: + break; + case ui_sidebar_mode::DesignateEngrave: + break; + case ui_sidebar_mode::DesignateCarveFortification: + break; + case ui_sidebar_mode::Stockpiles: + break; + case ui_sidebar_mode::Build: + { + auto menus = df::global::ui_sidebar_menus; + for (int i = 0; i < menus->building.choices_visible.size(); i++) + { + auto menu_item = menus->building.choices_visible[i]; + auto send_item = out->add_menu_items(); + STRICT_VIRTUAL_CAST_VAR(building, df::interface_button_construction_building_selectorst, menu_item); + if (building) + { + auto send_bld = send_item->mutable_building_type(); + send_bld->set_building_type(building->building_type); + send_bld->set_building_subtype(building->building_subtype); + send_bld->set_building_custom(building->custom_type); + send_item->set_existing_count(building->existing_count); + } + STRICT_VIRTUAL_CAST_VAR(sub_category, df::interface_button_construction_category_selectorst, menu_item); + if (sub_category) + { + send_item->set_build_category((DwarfControl::BuildCategory)sub_category->category_id); + } + } + } + break; + case ui_sidebar_mode::QueryBuilding: + break; + case ui_sidebar_mode::Orders: + break; + case ui_sidebar_mode::OrdersForbid: + break; + case ui_sidebar_mode::OrdersRefuse: + break; + case ui_sidebar_mode::OrdersWorkshop: + break; + case ui_sidebar_mode::OrdersZone: + break; + case ui_sidebar_mode::BuildingItems: + break; + case ui_sidebar_mode::ViewUnits: + break; + case ui_sidebar_mode::LookAround: + break; + case ui_sidebar_mode::DesignateItemsClaim: + break; + case ui_sidebar_mode::DesignateItemsForbid: + break; + case ui_sidebar_mode::DesignateItemsMelt: + break; + case ui_sidebar_mode::DesignateItemsUnmelt: + break; + case ui_sidebar_mode::DesignateItemsDump: + break; + case ui_sidebar_mode::DesignateItemsUndump: + break; + case ui_sidebar_mode::DesignateItemsHide: + break; + case ui_sidebar_mode::DesignateItemsUnhide: + break; + case ui_sidebar_mode::DesignateChopTrees: + break; + case ui_sidebar_mode::DesignateToggleEngravings: + break; + case ui_sidebar_mode::DesignateToggleMarker: + break; + case ui_sidebar_mode::Hotkeys: + break; + case ui_sidebar_mode::DesignateTrafficHigh: + break; + case ui_sidebar_mode::DesignateTrafficNormal: + break; + case ui_sidebar_mode::DesignateTrafficLow: + break; + case ui_sidebar_mode::DesignateTrafficRestricted: + break; + case ui_sidebar_mode::Zones: + break; + case ui_sidebar_mode::ZonesPenInfo: + break; + case ui_sidebar_mode::ZonesPitInfo: + break; + case ui_sidebar_mode::ZonesHospitalInfo: + break; + case ui_sidebar_mode::ZonesGatherInfo: + break; + case ui_sidebar_mode::DesignateRemoveConstruction: + break; + case ui_sidebar_mode::DepotAccess: + break; + case ui_sidebar_mode::NotesPoints: + break; + case ui_sidebar_mode::NotesRoutes: + break; + case ui_sidebar_mode::Burrows: + break; + case ui_sidebar_mode::Hauling: + break; + case ui_sidebar_mode::ArenaWeather: + break; + case ui_sidebar_mode::ArenaTrees: + break; + default: + break; + } + return CR_OK; +} + +command_result SetSideMenu(DFHack::color_ostream &stream, const DwarfControl::SidebarState *in) +{ + auto ui = df::global::ui; + if (in->has_mode()) + { + ui->main.mode = (ui_sidebar_mode::ui_sidebar_mode)in->mode(); + } return CR_OK; } diff --git a/plugins/remotefortressreader/dwarf_control.h b/plugins/remotefortressreader/dwarf_control.h index b66309d9e..0a1e5a82e 100644 --- a/plugins/remotefortressreader/dwarf_control.h +++ b/plugins/remotefortressreader/dwarf_control.h @@ -8,6 +8,7 @@ DFHack::command_result SendDigCommand(DFHack::color_ostream &stream, const RemoteFortressReader::DigCommand *in); DFHack::command_result SetPauseState(DFHack::color_ostream &stream, const RemoteFortressReader::SingleBool *in); DFHack::command_result GetSideMenu(DFHack::color_ostream &stream, const dfproto::EmptyMessage *in, DwarfControl::SidebarState *out); +DFHack::command_result SetSideMenu(DFHack::color_ostream &stream, const DwarfControl::SidebarState *in); #endif // !DWARF_CONTROL_H diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index baae99c5b..7c009f4f5 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -329,6 +329,7 @@ DFhackCExport RPCService *plugin_rpcconnect(color_ostream &) svc->addFunction("MiscMoveCommand", MiscMoveCommand, SF_ALLOW_REMOTE); svc->addFunction("GetLanguage", GetLanguage, SF_ALLOW_REMOTE); svc->addFunction("GetSideMenu", GetSideMenu, SF_ALLOW_REMOTE); + svc->addFunction("SetSideMenu", SetSideMenu, SF_ALLOW_REMOTE); return svc; } From 61cf85766583398c036424618056cd3a34d05654 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Thu, 28 Jun 2018 20:31:32 +0530 Subject: [PATCH 010/109] Update changelog --- docs/changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog.txt b/docs/changelog.txt index ca7d50538..c377a8c1c 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -62,6 +62,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: - added depth display for TWBT (when multilevel is enabled) - made shift+click jump to lower levels visible with TWBT - `title-version`: added version to options screen too +- `remotefortressreader`: added build menu information ## API - New functions (also exposed to Lua): From 44f461711c037bf12c50d6a4f2ccc6af51ad2b6d Mon Sep 17 00:00:00 2001 From: JapaMala Date: Fri, 29 Jun 2018 21:59:48 +0530 Subject: [PATCH 011/109] Respond to building selection commands. --- plugins/proto/DwarfControl.proto | 20 ++++++++ .../remotefortressreader/dwarf_control.cpp | 49 ++++++++++++++++++- plugins/remotefortressreader/dwarf_control.h | 2 +- 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/plugins/proto/DwarfControl.proto b/plugins/proto/DwarfControl.proto index bc1f26512..3f1e8942d 100644 --- a/plugins/proto/DwarfControl.proto +++ b/plugins/proto/DwarfControl.proto @@ -19,10 +19,18 @@ enum BuildCategory Track = 7; } +enum MenuAction +{ + MenuNone = 0; + MenuSelect = 1; + MenuCancel = 2; +} + message SidebarState { optional proto.enums.ui_sidebar_mode.ui_sidebar_mode mode = 1; repeated MenuItem menu_items = 2; + optional BuildSelector buildSelector = 3; } message MenuItem @@ -31,3 +39,15 @@ message MenuItem optional int32 existing_count = 2; optional BuildCategory build_category = 3; } + +message SidebarCommand +{ + optional proto.enums.ui_sidebar_mode.ui_sidebar_mode mode = 1; + optional int32 menu_index = 2; + optional MenuAction action = 3; +} + +message BuildSelector +{ + optional RemoteFortressReader.BuildingType building_type = 1; +} diff --git a/plugins/remotefortressreader/dwarf_control.cpp b/plugins/remotefortressreader/dwarf_control.cpp index 071903cf0..3d240b0c3 100644 --- a/plugins/remotefortressreader/dwarf_control.cpp +++ b/plugins/remotefortressreader/dwarf_control.cpp @@ -8,17 +8,24 @@ #include "df/interface_button_construction_category_selectorst.h" #include "df/ui.h" #include "df/ui_sidebar_menus.h" +#include "df/viewscreen.h" #include "df/world.h" #include "modules/Buildings.h" +#include "modules/Gui.h" #include "modules/Job.h" #include "modules/MapCache.h" #include "modules/Maps.h" #include "modules/World.h" +#include + using namespace DFHack; using namespace RemoteFortressReader; using namespace df::enums; +using namespace Gui; + +extern std::queue keyQueue; command_result SendDigCommand(color_ostream &stream, const DigCommand *in) { @@ -250,12 +257,50 @@ command_result GetSideMenu(DFHack::color_ostream &stream, const dfproto::EmptyMe return CR_OK; } -command_result SetSideMenu(DFHack::color_ostream &stream, const DwarfControl::SidebarState *in) +command_result SetSideMenu(DFHack::color_ostream &stream, const DwarfControl::SidebarCommand *in) { auto ui = df::global::ui; if (in->has_mode()) { - ui->main.mode = (ui_sidebar_mode::ui_sidebar_mode)in->mode(); + ui_sidebar_mode::ui_sidebar_mode set_mode = (ui_sidebar_mode::ui_sidebar_mode)in->mode(); + if (ui->main.mode != set_mode) + { + ui->main.mode = ui_sidebar_mode::Default; + switch (set_mode) + { + case ui_sidebar_mode::Build: + keyQueue.push(interface_key::D_BUILDING); + default: + ui->main.mode = set_mode; + break; + } + } + } + switch (ui->main.mode) + { + case ui_sidebar_mode::Build: + if (in->has_menu_index()) + { + df::global::ui_sidebar_menus->building.cursor = in->menu_index(); + } + break; + default: + break; + } + auto viewScreen = getCurViewscreen(); + if (in->has_action()) + { + switch (in->action()) + { + case DwarfControl::MenuSelect: + keyQueue.push(interface_key::SELECT); + break; + case DwarfControl::MenuCancel: + keyQueue.push(interface_key::LEAVESCREEN); + break; + default: + break; + } } return CR_OK; } diff --git a/plugins/remotefortressreader/dwarf_control.h b/plugins/remotefortressreader/dwarf_control.h index 0a1e5a82e..b16a4365d 100644 --- a/plugins/remotefortressreader/dwarf_control.h +++ b/plugins/remotefortressreader/dwarf_control.h @@ -8,7 +8,7 @@ DFHack::command_result SendDigCommand(DFHack::color_ostream &stream, const RemoteFortressReader::DigCommand *in); DFHack::command_result SetPauseState(DFHack::color_ostream &stream, const RemoteFortressReader::SingleBool *in); DFHack::command_result GetSideMenu(DFHack::color_ostream &stream, const dfproto::EmptyMessage *in, DwarfControl::SidebarState *out); -DFHack::command_result SetSideMenu(DFHack::color_ostream &stream, const DwarfControl::SidebarState *in); +DFHack::command_result SetSideMenu(DFHack::color_ostream &stream, const DwarfControl::SidebarCommand *in); #endif // !DWARF_CONTROL_H From 9c2e052d4d0c9227724d411c6050921d2a8b0af6 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Sun, 1 Jul 2018 14:00:05 +0530 Subject: [PATCH 012/109] More detail in build menu --- plugins/proto/DwarfControl.proto | 32 ++++++- .../remotefortressreader/building_reader.cpp | 14 +-- .../remotefortressreader/dwarf_control.cpp | 88 +++++++++++++------ 3 files changed, 102 insertions(+), 32 deletions(-) diff --git a/plugins/proto/DwarfControl.proto b/plugins/proto/DwarfControl.proto index 3f1e8942d..5c0b9cebe 100644 --- a/plugins/proto/DwarfControl.proto +++ b/plugins/proto/DwarfControl.proto @@ -24,13 +24,21 @@ enum MenuAction MenuNone = 0; MenuSelect = 1; MenuCancel = 2; + MenuSelectAll = 3; +} + +enum BuildSelectorStage +{ + StageNoMat = 0; + StagePlace = 1; + StageItemSelect = 2; } message SidebarState { optional proto.enums.ui_sidebar_mode.ui_sidebar_mode mode = 1; repeated MenuItem menu_items = 2; - optional BuildSelector buildSelector = 3; + optional BuildSelector build_selector = 3; } message MenuItem @@ -47,7 +55,29 @@ message SidebarCommand optional MenuAction action = 3; } +message BuiildReqChoice +{ + optional int32 distance = 1; + optional string name = 2; + optional int32 num_candidates = 3; + optional int32 used_count = 4; +} + +message BuildItemReq +{ + //Put filter here = 1 + optional int32 count_required = 2; + optional int32 count_max = 3; + optional int32 count_provided = 4; +} + message BuildSelector { optional RemoteFortressReader.BuildingType building_type = 1; + optional BuildSelectorStage stage = 2; + repeated BuiildReqChoice choices = 3; + optional int32 sel_index = 4; + repeated BuildItemReq requirements = 5; + optional int32 req_index = 6; + repeated string errors = 7; } diff --git a/plugins/remotefortressreader/building_reader.cpp b/plugins/remotefortressreader/building_reader.cpp index 5a0dd5c96..2d396980a 100644 --- a/plugins/remotefortressreader/building_reader.cpp +++ b/plugins/remotefortressreader/building_reader.cpp @@ -78,7 +78,7 @@ DFHack::command_result GetBuildingDefList(DFHack::color_ostream &stream, const D bld->mutable_building_type()->set_building_subtype(-1); bld->mutable_building_type()->set_building_custom(-1); bld->set_id(ENUM_KEY_STR(building_type, bt)); - + bld->set_name(ENUM_ATTR_STR(building_type, name, bt)); switch (bt) { case df::enums::building_type::NONE: @@ -101,6 +101,7 @@ DFHack::command_result GetBuildingDefList(DFHack::color_ostream &stream, const D bld->mutable_building_type()->set_building_subtype(st); bld->mutable_building_type()->set_building_custom(-1); bld->set_id(ENUM_KEY_STR(building_type, bt) + "/" + ENUM_KEY_STR(furnace_type, st)); + bld->set_name(ENUM_ATTR_STR(furnace_type, name, st)); if (st == furnace_type::Custom) { @@ -128,7 +129,7 @@ DFHack::command_result GetBuildingDefList(DFHack::color_ostream &stream, const D bld->mutable_building_type()->set_building_subtype(st); bld->mutable_building_type()->set_building_custom(-1); bld->set_id(ENUM_KEY_STR(building_type, bt) + "/" + ENUM_KEY_STR(shop_type, st)); - + bld->set_name(ENUM_KEY_STR(shop_type, st)); } break; case df::enums::building_type::Door: @@ -149,6 +150,7 @@ DFHack::command_result GetBuildingDefList(DFHack::color_ostream &stream, const D bld->mutable_building_type()->set_building_subtype(st); bld->mutable_building_type()->set_building_custom(-1); bld->set_id(ENUM_KEY_STR(building_type, bt) + "/" + ENUM_KEY_STR(workshop_type, st)); + bld->set_name(ENUM_ATTR_STR(workshop_type, name, st)); if (st == workshop_type::Custom) { @@ -190,7 +192,7 @@ DFHack::command_result GetBuildingDefList(DFHack::color_ostream &stream, const D bld->mutable_building_type()->set_building_subtype(st); bld->mutable_building_type()->set_building_custom(-1); bld->set_id(ENUM_KEY_STR(building_type, bt) + "/" + ENUM_KEY_STR(siegeengine_type, st)); - + bld->set_name(ENUM_KEY_STR(siegeengine_type, st)); } break; case df::enums::building_type::Trap: @@ -201,7 +203,7 @@ DFHack::command_result GetBuildingDefList(DFHack::color_ostream &stream, const D bld->mutable_building_type()->set_building_subtype(st); bld->mutable_building_type()->set_building_custom(-1); bld->set_id(ENUM_KEY_STR(building_type, bt) + "/" + ENUM_KEY_STR(trap_type, st)); - + bld->set_name(ENUM_KEY_STR(trap_type, st)); } break; case df::enums::building_type::AnimalTrap: @@ -224,7 +226,7 @@ DFHack::command_result GetBuildingDefList(DFHack::color_ostream &stream, const D bld->mutable_building_type()->set_building_subtype(st); bld->mutable_building_type()->set_building_custom(-1); bld->set_id(ENUM_KEY_STR(building_type, bt) + "/" + ENUM_KEY_STR(civzone_type, st)); - + bld->set_name(ENUM_KEY_STR(civzone_type, st)); } break; case df::enums::building_type::Weapon: @@ -241,7 +243,7 @@ DFHack::command_result GetBuildingDefList(DFHack::color_ostream &stream, const D bld->mutable_building_type()->set_building_subtype(st); bld->mutable_building_type()->set_building_custom(-1); bld->set_id(ENUM_KEY_STR(building_type, bt) + "/" + ENUM_KEY_STR(construction_type, st)); - + bld->set_name(ENUM_KEY_STR(construction_type, st)); } break; case df::enums::building_type::Hatch: diff --git a/plugins/remotefortressreader/dwarf_control.cpp b/plugins/remotefortressreader/dwarf_control.cpp index 3d240b0c3..8cd95b133 100644 --- a/plugins/remotefortressreader/dwarf_control.cpp +++ b/plugins/remotefortressreader/dwarf_control.cpp @@ -2,11 +2,15 @@ #include "DataDefs.h" #include "df_version_int.h" +#include "df/build_req_choice_genst.h" +#include "df/build_req_choice_specst.h" +#include "df/build_req_choicest.h" #include "df/job.h" #include "df/job_list_link.h" #include "df/interface_button_construction_building_selectorst.h" #include "df/interface_button_construction_category_selectorst.h" #include "df/ui.h" +#include "df/ui_build_selector.h" #include "df/ui_sidebar_menus.h" #include "df/viewscreen.h" #include "df/world.h" @@ -112,6 +116,57 @@ command_result SetPauseState(color_ostream &stream, const SingleBool *in) return CR_OK; } +void CopyBuildMenu(DwarfControl::SidebarState * out) +{ + auto menus = df::global::ui_sidebar_menus; + auto build_selector = df::global::ui_build_selector; + if (build_selector->building_type == -1) + for (int i = 0; i < menus->building.choices_visible.size(); i++) + { + auto menu_item = menus->building.choices_visible[i]; + auto send_item = out->add_menu_items(); + STRICT_VIRTUAL_CAST_VAR(building, df::interface_button_construction_building_selectorst, menu_item); + if (building) + { + auto send_bld = send_item->mutable_building_type(); + send_bld->set_building_type(building->building_type); + send_bld->set_building_subtype(building->building_subtype); + send_bld->set_building_custom(building->custom_type); + send_item->set_existing_count(building->existing_count); + } + STRICT_VIRTUAL_CAST_VAR(sub_category, df::interface_button_construction_category_selectorst, menu_item); + if (sub_category) + { + send_item->set_build_category((DwarfControl::BuildCategory)sub_category->category_id); + } + } + else + { + auto send_selector = out->mutable_build_selector(); + auto send_bld = send_selector->mutable_building_type(); + send_bld->set_building_type(build_selector->building_type); + send_bld->set_building_subtype(build_selector->building_subtype); + send_bld->set_building_custom(build_selector->custom_type); + send_selector->set_stage((DwarfControl::BuildSelectorStage)build_selector->stage); + for (int i = 0; i < build_selector->errors.size(); i++) + { + if (build_selector->errors[i]) + send_selector->add_errors(*build_selector->errors[i]); + } + for (int i = 0; i < build_selector->choices.size(); i++) + { + auto choice = build_selector->choices[i]; + auto send_choice = send_selector->add_choices(); + send_choice->set_distance(choice->distance); + std::string name; + choice->getName(&name); + send_choice->set_name(name); + send_choice->set_num_candidates(choice->getNumCandidates()); + send_choice->set_used_count(choice->getUsedCount()); + } + } +} + command_result GetSideMenu(DFHack::color_ostream &stream, const dfproto::EmptyMessage *in, DwarfControl::SidebarState *out) { auto ui = df::global::ui; @@ -152,28 +207,7 @@ command_result GetSideMenu(DFHack::color_ostream &stream, const dfproto::EmptyMe case ui_sidebar_mode::Stockpiles: break; case ui_sidebar_mode::Build: - { - auto menus = df::global::ui_sidebar_menus; - for (int i = 0; i < menus->building.choices_visible.size(); i++) - { - auto menu_item = menus->building.choices_visible[i]; - auto send_item = out->add_menu_items(); - STRICT_VIRTUAL_CAST_VAR(building, df::interface_button_construction_building_selectorst, menu_item); - if (building) - { - auto send_bld = send_item->mutable_building_type(); - send_bld->set_building_type(building->building_type); - send_bld->set_building_subtype(building->building_subtype); - send_bld->set_building_custom(building->custom_type); - send_item->set_existing_count(building->existing_count); - } - STRICT_VIRTUAL_CAST_VAR(sub_category, df::interface_button_construction_category_selectorst, menu_item); - if (sub_category) - { - send_item->set_build_category((DwarfControl::BuildCategory)sub_category->category_id); - } - } - } + CopyBuildMenu(out); break; case ui_sidebar_mode::QueryBuilding: break; @@ -270,6 +304,7 @@ command_result SetSideMenu(DFHack::color_ostream &stream, const DwarfControl::Si { case ui_sidebar_mode::Build: keyQueue.push(interface_key::D_BUILDING); + break; default: ui->main.mode = set_mode; break; @@ -279,11 +314,14 @@ command_result SetSideMenu(DFHack::color_ostream &stream, const DwarfControl::Si switch (ui->main.mode) { case ui_sidebar_mode::Build: - if (in->has_menu_index()) + if (in->has_action()) { - df::global::ui_sidebar_menus->building.cursor = in->menu_index(); + if (in->has_menu_index()) + df::global::ui_sidebar_menus->building.cursor = in->menu_index(); + else + df::global::ui_sidebar_menus->building.cursor = 0; + break; } - break; default: break; } From d9b910f79cc4dfa5e24637948774ddb9a420b570 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Sun, 1 Jul 2018 20:36:36 +0530 Subject: [PATCH 013/109] Made a function to find building extents for un-built buildings. --- .../remotefortressreader/dwarf_control.cpp | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/plugins/remotefortressreader/dwarf_control.cpp b/plugins/remotefortressreader/dwarf_control.cpp index 8cd95b133..01c892887 100644 --- a/plugins/remotefortressreader/dwarf_control.cpp +++ b/plugins/remotefortressreader/dwarf_control.cpp @@ -5,6 +5,9 @@ #include "df/build_req_choice_genst.h" #include "df/build_req_choice_specst.h" #include "df/build_req_choicest.h" +#include "df/building_def.h" +#include "df/building_def_furnacest.h" +#include "df/building_def_workshopst.h" #include "df/job.h" #include "df/job_list_link.h" #include "df/interface_button_construction_building_selectorst.h" @@ -22,15 +25,124 @@ #include "modules/Maps.h" #include "modules/World.h" +#include "MiscUtils.h" + #include using namespace DFHack; using namespace RemoteFortressReader; using namespace df::enums; using namespace Gui; +using namespace df::global; extern std::queue keyQueue; +void GetBuildingSize( + int16_t type, + int16_t subtype, + int16_t custom, + int16_t &x_min, + int16_t &y_min, + int16_t &x_max, + int16_t &y_max +) +{ + x_min = 0; + y_min = 0; + x_max = 0; + y_max = 0; + df::building_def* customBuilding = 0; + switch (type) + { + case building_type::FarmPlot: + case building_type::Bridge: + case building_type::RoadDirt: + case building_type::RoadPaved: + case building_type::Stockpile: + case building_type::Civzone: + case building_type::ScrewPump: + case building_type::Construction: + case building_type::AxleHorizontal: + case building_type::WaterWheel: + case building_type::Rollers: + bool widthOdd = world->building_width % 2; + x_min = world->building_width / 2; + if(widthOdd) + x_max = world->building_width / 2; + else + x_max = (world->building_width / 2) - 1; + bool heightOdd = world->building_width % 2; + y_min = world->building_height / 2; + if (widthOdd) + y_max = world->building_height / 2; + else + y_max = (world->building_height / 2) - 1; + return; + case building_type::Furnace: + if (subtype != furnace_type::Custom) + { + x_min = y_min = x_max = y_max = 1; + return; + } + customBuilding = binsearch_in_vector(world->raws.buildings.furnaces, custom); + break; + case building_type::TradeDepot: + case building_type::Shop: + x_min = y_min = x_max = y_max = 2; + return; + case building_type::Workshop: + switch (subtype) + { + case workshop_type::Carpenters: + case workshop_type::Farmers: + case workshop_type::Masons: + case workshop_type::Craftsdwarfs: + case workshop_type::Jewelers: + case workshop_type::MetalsmithsForge: + case workshop_type::MagmaForge: + case workshop_type::Bowyers: + case workshop_type::Mechanics: + case workshop_type::Butchers: + case workshop_type::Leatherworks: + case workshop_type::Tanners: + case workshop_type::Clothiers: + case workshop_type::Fishery: + case workshop_type::Still: + case workshop_type::Loom: + case workshop_type::Kitchen: + case workshop_type::Ashery: + case workshop_type::Dyers: + x_min = y_min = x_max = y_max = 1; + return; + case workshop_type::Siege: + case workshop_type::Kennels: + x_min = y_min = x_max = y_max = 2; + return; + case workshop_type::Custom: + customBuilding = binsearch_in_vector(world->raws.buildings.workshops, custom); + break; + default: + return; + } + break; + case building_type::SiegeEngine: + case building_type::Wagon: + case building_type::Windmill: + x_min = y_min = x_max = y_max = 1; + return; + default: + return; + } + if (customBuilding) + { + x_min = customBuilding->workloc_x; + y_min = customBuilding->workloc_y; + x_max = customBuilding->dim_x - x_min - 1; + y_max = customBuilding->dim_y - y_min - 1; + return; + } +} + command_result SendDigCommand(color_ostream &stream, const DigCommand *in) { MapExtras::MapCache mc; From c4891476570861927c8e438fca4a29e49b60e672 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Mon, 2 Jul 2018 00:37:02 +0530 Subject: [PATCH 014/109] Enabled building buildings through RFR --- plugins/proto/DwarfControl.proto | 6 ++ .../remotefortressreader/dwarf_control.cpp | 89 +++++++++++++------ 2 files changed, 66 insertions(+), 29 deletions(-) diff --git a/plugins/proto/DwarfControl.proto b/plugins/proto/DwarfControl.proto index 5c0b9cebe..ec261b57d 100644 --- a/plugins/proto/DwarfControl.proto +++ b/plugins/proto/DwarfControl.proto @@ -53,6 +53,7 @@ message SidebarCommand optional proto.enums.ui_sidebar_mode.ui_sidebar_mode mode = 1; optional int32 menu_index = 2; optional MenuAction action = 3; + optional RemoteFortressReader.Coord selection_coord = 4; } message BuiildReqChoice @@ -80,4 +81,9 @@ message BuildSelector repeated BuildItemReq requirements = 5; optional int32 req_index = 6; repeated string errors = 7; + optional int32 radius_x_low = 8; + optional int32 radius_y_low = 9; + optional int32 radius_x_high = 10; + optional int32 radius_y_high = 11; + optional RemoteFortressReader.Coord cursor = 12; } diff --git a/plugins/remotefortressreader/dwarf_control.cpp b/plugins/remotefortressreader/dwarf_control.cpp index 01c892887..bb342c575 100644 --- a/plugins/remotefortressreader/dwarf_control.cpp +++ b/plugins/remotefortressreader/dwarf_control.cpp @@ -41,16 +41,16 @@ void GetBuildingSize( int16_t type, int16_t subtype, int16_t custom, - int16_t &x_min, - int16_t &y_min, - int16_t &x_max, - int16_t &y_max + int16_t &rad_x_low, + int16_t &rad_y_low, + int16_t &rad_x_high, + int16_t &rad_y_high ) { - x_min = 0; - y_min = 0; - x_max = 0; - y_max = 0; + rad_x_low = 0; + rad_y_low = 0; + rad_x_high = 0; + rad_y_high = 0; df::building_def* customBuilding = 0; switch (type) { @@ -65,30 +65,32 @@ void GetBuildingSize( case building_type::AxleHorizontal: case building_type::WaterWheel: case building_type::Rollers: + { bool widthOdd = world->building_width % 2; - x_min = world->building_width / 2; + rad_x_low = world->building_width / 2; if(widthOdd) - x_max = world->building_width / 2; + rad_x_high = world->building_width / 2; else - x_max = (world->building_width / 2) - 1; + rad_x_high = (world->building_width / 2) - 1; bool heightOdd = world->building_width % 2; - y_min = world->building_height / 2; + rad_y_low = world->building_height / 2; if (widthOdd) - y_max = world->building_height / 2; + rad_y_high = world->building_height / 2; else - y_max = (world->building_height / 2) - 1; + rad_y_high = (world->building_height / 2) - 1; + } return; case building_type::Furnace: if (subtype != furnace_type::Custom) { - x_min = y_min = x_max = y_max = 1; + rad_x_low = rad_y_low = rad_x_high = rad_y_high = 1; return; } - customBuilding = binsearch_in_vector(world->raws.buildings.furnaces, custom); + customBuilding = world->raws.buildings.furnaces[custom]; break; case building_type::TradeDepot: case building_type::Shop: - x_min = y_min = x_max = y_max = 2; + rad_x_low = rad_y_low = rad_x_high = rad_y_high = 2; return; case building_type::Workshop: switch (subtype) @@ -112,14 +114,14 @@ void GetBuildingSize( case workshop_type::Kitchen: case workshop_type::Ashery: case workshop_type::Dyers: - x_min = y_min = x_max = y_max = 1; + rad_x_low = rad_y_low = rad_x_high = rad_y_high = 1; return; case workshop_type::Siege: case workshop_type::Kennels: - x_min = y_min = x_max = y_max = 2; + rad_x_low = rad_y_low = rad_x_high = rad_y_high = 2; return; case workshop_type::Custom: - customBuilding = binsearch_in_vector(world->raws.buildings.workshops, custom); + customBuilding = world->raws.buildings.workshops[custom]; break; default: return; @@ -128,17 +130,17 @@ void GetBuildingSize( case building_type::SiegeEngine: case building_type::Wagon: case building_type::Windmill: - x_min = y_min = x_max = y_max = 1; + rad_x_low = rad_y_low = rad_x_high = rad_y_high = 1; return; default: return; } if (customBuilding) { - x_min = customBuilding->workloc_x; - y_min = customBuilding->workloc_y; - x_max = customBuilding->dim_x - x_min - 1; - y_max = customBuilding->dim_y - y_min - 1; + rad_x_low = customBuilding->workloc_x; + rad_y_low = customBuilding->workloc_y; + rad_x_high = customBuilding->dim_x - rad_x_low - 1; + rad_y_high = customBuilding->dim_y - rad_y_low - 1; return; } } @@ -276,6 +278,19 @@ void CopyBuildMenu(DwarfControl::SidebarState * out) send_choice->set_num_candidates(choice->getNumCandidates()); send_choice->set_used_count(choice->getUsedCount()); } + int16_t x_low, y_low, x_high, y_high; + GetBuildingSize(build_selector->building_type, build_selector->building_subtype, build_selector->custom_type, x_low, y_low, x_high, y_high); + send_selector->set_radius_x_low(x_low); + send_selector->set_radius_y_low(y_low); + send_selector->set_radius_x_high(x_high); + send_selector->set_radius_y_high(y_high); + if (build_selector->stage >= 1) + { + auto send_cursor = send_selector->mutable_cursor(); + send_cursor->set_x(cursor->x); + send_cursor->set_y(cursor->y); + send_cursor->set_z(cursor->z); + } } } @@ -428,12 +443,28 @@ command_result SetSideMenu(DFHack::color_ostream &stream, const DwarfControl::Si case ui_sidebar_mode::Build: if (in->has_action()) { + int index = 0; if (in->has_menu_index()) - df::global::ui_sidebar_menus->building.cursor = in->menu_index(); - else - df::global::ui_sidebar_menus->building.cursor = 0; - break; + index = in->menu_index(); + if(ui_build_selector->building_type == -1) + df::global::ui_sidebar_menus->building.cursor = index; + if (ui_build_selector->stage == 2) + { + ui_build_selector->sel_index = index; + } + } + if (ui_build_selector->stage == 1) + { + if (in->has_selection_coord()) + { + df::global::cursor->x = in->selection_coord().x(); + df::global::cursor->y = in->selection_coord().y(); + df::global::cursor->z = in->selection_coord().z(); + getCurViewscreen()->feed_key(interface_key::CURSOR_LEFT); + getCurViewscreen()->feed_key(interface_key::CURSOR_RIGHT); + } } + break; default: break; } From 7fd23d46f03bf74cdf4c988cb3ce2ae4468fab84 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Mon, 2 Jul 2018 22:04:47 +0530 Subject: [PATCH 015/109] Send the building preview over RFR --- plugins/proto/DwarfControl.proto | 1 + plugins/remotefortressreader/dwarf_control.cpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/plugins/proto/DwarfControl.proto b/plugins/proto/DwarfControl.proto index ec261b57d..707651079 100644 --- a/plugins/proto/DwarfControl.proto +++ b/plugins/proto/DwarfControl.proto @@ -86,4 +86,5 @@ message BuildSelector optional int32 radius_x_high = 10; optional int32 radius_y_high = 11; optional RemoteFortressReader.Coord cursor = 12; + repeated int32 tiles = 13; } diff --git a/plugins/remotefortressreader/dwarf_control.cpp b/plugins/remotefortressreader/dwarf_control.cpp index bb342c575..57c770301 100644 --- a/plugins/remotefortressreader/dwarf_control.cpp +++ b/plugins/remotefortressreader/dwarf_control.cpp @@ -291,6 +291,12 @@ void CopyBuildMenu(DwarfControl::SidebarState * out) send_cursor->set_y(cursor->y); send_cursor->set_z(cursor->z); } + + for (int y = 0; y < (y_low + y_high + 1); y++) + for (int x = 0; x < (x_low + x_high + 1); x++) + { + send_selector->add_tiles(build_selector->tiles[x][y]); + } } } From 0a0cbdf2de988fb6d3de9a169eb4cf56cf163acc Mon Sep 17 00:00:00 2001 From: JapaMala Date: Sat, 28 Jul 2018 18:39:45 +0530 Subject: [PATCH 016/109] Add creature flags to RFR creature raws. --- plugins/proto/RemoteFortressReader.proto | 1 + plugins/remotefortressreader/remotefortressreader.cpp | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/plugins/proto/RemoteFortressReader.proto b/plugins/proto/RemoteFortressReader.proto index 3298d42fb..9dee8e884 100644 --- a/plugins/proto/RemoteFortressReader.proto +++ b/plugins/proto/RemoteFortressReader.proto @@ -749,6 +749,7 @@ message CreatureRaw optional int32 adultsize = 9; repeated CasteRaw caste = 10; repeated TissueRaw tissues = 11; + repeated bool flags = 12; } message CreatureRawList diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index 7c009f4f5..f7d0b9b50 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -2794,6 +2794,11 @@ static command_result GetPartialCreatureRaws(color_ostream &stream, const ListRe CopyMat(send_tissue->mutable_material(), orig_tissue->mat_type, orig_tissue->mat_index); } + + for (int i = 0; i <= ENUM_LAST_ITEM(creature_raw_flags); i++) + { + send_creature->add_flags(orig_creature->flags.is_set((creature_raw_flags::creature_raw_flags)i)); + } } return CR_OK; From efe4926df0f20a8b22a4ef7ef0d758f001684c2f Mon Sep 17 00:00:00 2001 From: JapaMala Date: Thu, 2 Aug 2018 21:50:29 +0530 Subject: [PATCH 017/109] Send equipped item bodypart attachments over RFR --- library/xml | 2 +- plugins/proto/RemoteFortressReader.proto | 1 + plugins/remotefortressreader/remotefortressreader.cpp | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/library/xml b/library/xml index 579283113..de83a453d 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 57928311390bb67fe0cd5deec14e2d4621b13a58 +Subproject commit de83a453d7e55aa48ffc92c8f4c147b1a1acd525 diff --git a/plugins/proto/RemoteFortressReader.proto b/plugins/proto/RemoteFortressReader.proto index b60dcb996..b1ae33cc0 100644 --- a/plugins/proto/RemoteFortressReader.proto +++ b/plugins/proto/RemoteFortressReader.proto @@ -426,6 +426,7 @@ message InventoryItem { optional InventoryMode mode = 1; optional Item item = 2; + optional int32 body_part_id = 3; } message UnitDefinition diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index f7d0b9b50..084b4dbbb 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -1807,6 +1807,7 @@ static command_result GetUnitListInside(color_ostream &stream, const BlockReques auto inventory_item = unit->inventory[j]; auto sent_item = send_unit->add_inventory(); sent_item->set_mode((InventoryMode)inventory_item->mode); + sent_item->set_body_part_id(inventory_item->body_part_id); CopyItem(sent_item->mutable_item(), inventory_item->item); } From 78b115db7367d38ff45cf39f46ab685fa02cbb5b Mon Sep 17 00:00:00 2001 From: JapaMala Date: Thu, 2 Aug 2018 22:17:21 +0530 Subject: [PATCH 018/109] update jsoncpp --- depends/jsoncpp-sub | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/depends/jsoncpp-sub b/depends/jsoncpp-sub index ddabf50f7..2baad4923 160000 --- a/depends/jsoncpp-sub +++ b/depends/jsoncpp-sub @@ -1 +1 @@ -Subproject commit ddabf50f72cf369bf652a95c4d9fe31a1865a781 +Subproject commit 2baad4923e6d9a7e09982cfa4b1c5fd0b67ebd87 From f2664f7926ebead1b7320b71f0323d51ba34b9e8 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Fri, 3 Aug 2018 23:18:02 +0530 Subject: [PATCH 019/109] Add unit facing and sub-tile position when moving. --- plugins/proto/RemoteFortressReader.proto | 1 + .../remotefortressreader.cpp | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/plugins/proto/RemoteFortressReader.proto b/plugins/proto/RemoteFortressReader.proto index b1ae33cc0..2dc0448b6 100644 --- a/plugins/proto/RemoteFortressReader.proto +++ b/plugins/proto/RemoteFortressReader.proto @@ -454,6 +454,7 @@ message UnitDefinition optional float subpos_x = 21; optional float subpos_y = 22; optional float subpos_z = 23; + optional Coord facing = 24; } message UnitList diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index 084b4dbbb..cd9837f6c 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -1703,6 +1703,11 @@ static command_result GetUnitList(color_ostream &stream, const EmptyMessage *in, return GetUnitListInside(stream, NULL, out); } +float lerp(float a, float b, float f) +{ + return a + f * (b - a); +} + static command_result GetUnitListInside(color_ostream &stream, const BlockRequest *in, UnitList *out) { auto world = df::global::world; @@ -1823,6 +1828,35 @@ static command_result GetUnitListInside(color_ostream &stream, const BlockReques send_unit->set_subpos_x(item->pos_x / 100000.0); send_unit->set_subpos_y(item->pos_y / 100000.0); send_unit->set_subpos_z(item->pos_z / 140000.0); + auto facing = send_unit->mutable_facing(); + facing->set_x(item->speed_x); + facing->set_y(item->speed_x); + facing->set_z(item->speed_x); + break; + } + } + else + { + for (int i = 0; i < unit->actions.size(); i++) + { + auto action = unit->actions[i]; + switch (action->type) + { + case unit_action_type::Move: + send_unit->set_subpos_x(lerp(0, unit->path.path.x[0] - unit->pos.x, (float)(action->data.move.timer_init - action->data.move.timer) / action->data.move.timer_init)); + send_unit->set_subpos_y(lerp(0, unit->path.path.y[0] - unit->pos.y, (float)(action->data.move.timer_init - action->data.move.timer) / action->data.move.timer_init)); + send_unit->set_subpos_z(lerp(0, unit->path.path.z[0] - unit->pos.z, (float)(action->data.move.timer_init - action->data.move.timer) / action->data.move.timer_init)); + break; + default: + break; + } + } + if (unit->path.path.x.size() > 0) + { + auto facing = send_unit->mutable_facing(); + facing->set_x(unit->path.path.x[0] - unit->pos.x); + facing->set_y(unit->path.path.y[0] - unit->pos.y); + facing->set_z(unit->path.path.z[0] - unit->pos.z); } } } From 4b8cf7f65edfbfb1636499fe66336045a64d09bc Mon Sep 17 00:00:00 2001 From: JapaMala Date: Sun, 5 Aug 2018 21:29:40 +0530 Subject: [PATCH 020/109] Added armor raw info. --- plugins/proto/RemoteFortressReader.proto | 11 +++ plugins/remotefortressreader/item_reader.cpp | 71 +++++++++++++++++++- 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/plugins/proto/RemoteFortressReader.proto b/plugins/proto/RemoteFortressReader.proto index 2dc0448b6..108605aa7 100644 --- a/plugins/proto/RemoteFortressReader.proto +++ b/plugins/proto/RemoteFortressReader.proto @@ -201,6 +201,14 @@ enum InventoryMode Strapped = 10; } +enum ArmorLayer +{ + LAYER_UNDER = 0; + LAYER_OVER = 1; + LAYER_ARMOR = 2; + LAYER_COVER = 3; +} + message Coord { optional int32 x = 1; @@ -371,6 +379,9 @@ message MaterialDefinition{ optional string name = 3; optional ColorDefinition state_color = 4; //Simplifying colors to assume room temperature. optional ItemdefInstrument.InstrumentDef instrument = 5; + optional int32 up_step = 6; + optional int32 down_step = 7; + optional ArmorLayer layer = 8; } message BuildingType diff --git a/plugins/remotefortressreader/item_reader.cpp b/plugins/remotefortressreader/item_reader.cpp index 3884d269f..71867767b 100644 --- a/plugins/remotefortressreader/item_reader.cpp +++ b/plugins/remotefortressreader/item_reader.cpp @@ -26,7 +26,13 @@ #include "df/item_statuest.h" #include "df/item_threadst.h" #include "df/item_toolst.h" +#include "df/itemdef_armorst.h" +#include "df/itemdef_glovesst.h" +#include "df/itemdef_helmst.h" #include "df/itemdef_instrumentst.h" +#include "df/itemdef_pantsst.h" +#include "df/itemdef_shieldst.h" +#include "df/itemdef_shoesst.h" #include "df/itemdef_toolst.h" #include "df/itemimprovement.h" #include "df/itemimprovement_art_imagest.h" @@ -658,13 +664,76 @@ DFHack::command_result GetItemList(DFHack::color_ostream &stream, const DFHack:: reg->set_pitch_range_max(instrument->registers[j]->pitch_range_max); } send_instrument->set_description(DF2UTF(instrument->description)); - break; } + break; case df::enums::item_type::TOOL: { VIRTUAL_CAST_VAR(tool, df::itemdef_toolst, item); mat_def->set_name(DF2UTF(tool->name)); } + break; + case df::enums::item_type::ARMOR: + { + VIRTUAL_CAST_VAR(armor, df::itemdef_armorst, item); + if (armor) + { + mat_def->set_up_step(armor->ubstep); + mat_def->set_down_step(armor->lbstep); + mat_def->set_layer((ArmorLayer)armor->props.layer); + } + } + break; + case df::enums::item_type::SHOES: + { + VIRTUAL_CAST_VAR(armor, df::itemdef_shoesst, item); + if (armor) + { + mat_def->set_up_step(armor->upstep); + mat_def->set_down_step(10000); + mat_def->set_layer((ArmorLayer)armor->props.layer); + } + } + break; + case df::enums::item_type::SHIELD: + { + VIRTUAL_CAST_VAR(armor, df::itemdef_shieldst, item); + if (armor) + { + mat_def->set_up_step(armor->upstep); + mat_def->set_down_step(10000); + } + } + break; + case df::enums::item_type::HELM: + { + VIRTUAL_CAST_VAR(armor, df::itemdef_helmst, item); + if (armor) + { + mat_def->set_layer((ArmorLayer)armor->props.layer); + } + } + break; + case df::enums::item_type::GLOVES: + { + VIRTUAL_CAST_VAR(armor, df::itemdef_glovesst, item); + if (armor) + { + mat_def->set_up_step(armor->upstep); + mat_def->set_down_step(10000); + mat_def->set_layer((ArmorLayer)armor->props.layer); + } + } + break; + case df::enums::item_type::PANTS: + { + VIRTUAL_CAST_VAR(armor, df::itemdef_pantsst, item); + if (armor) + { + mat_def->set_down_step(armor->lbstep); + mat_def->set_layer((ArmorLayer)armor->props.layer); + } + } + break; default: break; } From 4979b41870eacba2912ae9efd9b1af668df460db Mon Sep 17 00:00:00 2001 From: JapaMala Date: Sun, 5 Aug 2018 21:44:54 +0530 Subject: [PATCH 021/109] update xmls --- library/xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/xml b/library/xml index de83a453d..efa179476 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit de83a453d7e55aa48ffc92c8f4c147b1a1acd525 +Subproject commit efa17947676ed05476929d4f0cf2cb260ef3aa7a From 59d70d66879b9fe1c1666300b22012b6e56e2731 Mon Sep 17 00:00:00 2001 From: Kelly Kinkade Date: Wed, 15 Aug 2018 20:28:18 -0500 Subject: [PATCH 022/109] Add function to infer biome type to Maps module This moves code intended to infer biome type currently living in a couple of plugins into the Maps module, so that this code can be shared more easily by multiple plugins, as discussed in #1392. --- library/include/modules/Maps.h | 7 + library/modules/Maps.cpp | 396 +++++++++++++++++++++++++++++++++ 2 files changed, 403 insertions(+) diff --git a/library/include/modules/Maps.h b/library/include/modules/Maps.h index 0c41bf7f6..f33abf4e0 100644 --- a/library/include/modules/Maps.h +++ b/library/include/modules/Maps.h @@ -36,6 +36,7 @@ distribution. #include "BitArray.h" #include "modules/Materials.h" +#include "df/biome_type.h" #include "df/block_flags.h" #include "df/feature_type.h" #include "df/flow_type.h" @@ -333,6 +334,12 @@ extern DFHACK_EXPORT bool RemoveBlockEvent(uint32_t x, uint32_t y, uint32_t z, d DFHACK_EXPORT bool canWalkBetween(df::coord pos1, df::coord pos2); DFHACK_EXPORT bool canStepBetween(df::coord pos1, df::coord pos2); + +DFHACK_EXPORT df::enums::biome_type::biome_type GetBiomeType(int world_coord_x, int world_coord_y); +DFHACK_EXPORT df::enums::biome_type::biome_type GetBiomeTypeWithRef(int world_coord_x, int world_coord_y, int world_ref_y_coord); + } + + } #endif diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp index 54f314db8..ecf68d5f7 100644 --- a/library/modules/Maps.cpp +++ b/library/modules/Maps.cpp @@ -46,6 +46,7 @@ using namespace std; #include "modules/MapCache.h" #include "modules/Maps.h" +#include "df/biome_type.h" #include "df/block_burrow.h" #include "df/block_burrow_link.h" #include "df/block_square_event_grassst.h" @@ -711,3 +712,398 @@ bool Maps::canStepBetween(df::coord pos1, df::coord pos2) return false; } + +/* The code below is a heavily refactored version of code found at + https://github.com/ragundo/exportmaps/blob/master/cpp/df_utils/biome_type.cpp. +*/ + +/* +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +namespace { + //----------------------------------------------------------------------------// + // Utility function + // + //----------------------------------------------------------------------------// + std::pair check_tropicality(df::region_map_entry& region, + int y_pos + ) + { + int flip_latitude = df::global::world->world_data->flip_latitude; + + bool is_possible_tropical_area_by_latitude = false; + bool is_tropical_area_by_latitude = false; + + if (flip_latitude == -1) // NO POLES + { + + // If there're no poles, tropical area is determined by temperature + is_possible_tropical_area_by_latitude = region.temperature >= 75; + is_tropical_area_by_latitude = region.temperature >= 85; + + } + + else + { + int v6; + + df::world_data* wdata = df::global::world->world_data; + + if (flip_latitude == 0) // NORTH POLE ONLY + { + v6 = y_pos; + } + + else if (flip_latitude == 1) // SOUTH_POLE ONLY + { + v6 = df::global::world->world_data->world_height - y_pos - 1; + } + + else if (flip_latitude == 2) // BOTH POLES + { + if (y_pos < wdata->world_height / 2) + v6 = 2 * y_pos; + else + { + v6 = wdata->world_height + 2 * (wdata->world_height / 2 - y_pos) - 1; + if (v6 < 0) + v6 = 0; + if (v6 >= wdata->world_height) + v6 = wdata->world_height - 1; + } + + } + + if (wdata->world_height == 17) + v6 *= 16; + else if (wdata->world_height == 33) + v6 *= 8; + else if (wdata->world_height == 65) + v6 *= 4; + else if (wdata->world_height == 129) + v6 *= 2; + + is_possible_tropical_area_by_latitude = v6 > 170; + is_tropical_area_by_latitude = v6 >= 200; + + } + + return std::pair(is_possible_tropical_area_by_latitude, + is_tropical_area_by_latitude + ); + } + + + //----------------------------------------------------------------------------// + // Utility function + // + // return some unknow parameter as a percentage + //----------------------------------------------------------------------------// + int get_region_parameter(int y, + int x + ) + { + int world_height = df::global::world->world_data->world_height; + if (world_height > 65) // Medium and large worlds + { + // access to region 2D array + df::region_map_entry& region = df::global::world->world_data->region_map[x][y]; + int flip_latitude = df::global::world->world_data->flip_latitude; + int rainfall = region.rainfall; + int result; + int y_pos = y; + int ypos = y_pos; + + if (flip_latitude == -1) // NO POLES + return 100; + + else if (flip_latitude == 1) // SOUTH POLE + ypos = world_height - y_pos - 1; + else if (flip_latitude == 2) // NORTH & SOUTH POLE + { + if (ypos < world_height / 2) + ypos *= 2; + else + { + ypos = world_height + 2 * (world_height / 2 - ypos) - 1; + if (ypos < 0) + ypos = 0; + if (ypos >= world_height) + ypos = world_height - 1; + } + } + + int latitude; // 0 - 256 (size of a large world) + switch (world_height) + { + case 17: // Pocket world + latitude = 16 * ypos; + break; + case 33: // Smaller world + latitude = 8 * ypos; + break; + case 65: // Small world + latitude = 4 * ypos; + break; + case 129: // Medium world + latitude = 2 * ypos; + break; + default: // Large world + latitude = ypos; + break; + } + + // latitude > 220 + if ((latitude - 171) > 49) + return 100; + + + // Latitude between 191 and 200 + if ((latitude > 190) && (latitude < 201)) + return 0; + + // Latitude between 201 and 220 + if ((latitude > 190) && (latitude >= 201)) + result = rainfall + 16 * (latitude - 207); + else + // Latitude between 0 and 190 + result = (16 * (184 - latitude) - rainfall); + + if (result < 0) + return 0; + + if (result > 100) + return 100; + + return result; + } + + return 100; + } +} + + +/***************************************************************************** +Module main function. +Return the biome type, given a position coordinate expressed in world_tiles +The world ref coordinates are used for tropicality determination and may refer +to a tile neighboring the "official" one. +*****************************************************************************/ +df::enums::biome_type::biome_type Maps::GetBiomeTypeWithRef(int world_coord_x, + int world_coord_y, + int world_ref_coord_y +) +{ + // Biome is per region, so get the region where this biome exists + df::region_map_entry& region = df::global::world->world_data->region_map[world_coord_x][world_coord_y]; + + // Check if the y reference position coordinate belongs to a tropical area + std::pair p = check_tropicality(region, + world_ref_coord_y + ); + bool is_possible_tropical_area_by_latitude = p.first; + bool is_tropical_area_by_latitude = p.second; + + int parameter = get_region_parameter(world_coord_y, world_coord_x); + + // Begin the discrimination + if (region.flags.is_set(df::region_map_entry_flags::is_lake)) // is it a lake? + { + // salinity values tell us the lake type + // greater than 66 is a salt water lake + // between 33 and 65 is a brackish water lake + // less than 33 is a fresh water lake + if (region.salinity < 33) + if (is_possible_tropical_area_by_latitude) + return df::enums::biome_type::biome_type::LAKE_TROPICAL_FRESHWATER; // 39 + else + return df::enums::biome_type::biome_type::LAKE_TEMPERATE_FRESHWATER; // 36 + else if (region.salinity < 66) + if (is_possible_tropical_area_by_latitude) + return df::enums::biome_type::biome_type::LAKE_TROPICAL_BRACKISHWATER; // 40 + else + return df::enums::biome_type::biome_type::LAKE_TEMPERATE_BRACKISHWATER; // 37 + else // salinity >= 66 + if (is_possible_tropical_area_by_latitude) + return df::enums::biome_type::biome_type::LAKE_TROPICAL_SALTWATER;// 41 + else + return df::enums::biome_type::biome_type::LAKE_TEMPERATE_SALTWATER; // 38 + } + + // Not a lake. Check elevation + // Elevation greater then 149 means a mountain biome + // Elevation below 100 means a ocean biome + // Elevation between 100 and 149 are land biomes + + if (region.elevation >= 150) // is it a mountain? + return df::enums::biome_type::biome_type::MOUNTAIN; // 0 + + if (region.elevation < 100) // is it a ocean? + { + if (is_tropical_area_by_latitude) + return df::enums::biome_type::biome_type::OCEAN_TROPICAL; // 27 + else if (region.temperature <= -5) + return df::enums::biome_type::biome_type::OCEAN_ARCTIC; // 29 + else + return df::enums::biome_type::biome_type::OCEAN_TEMPERATE; // 28 + } + + // land biome. Elevation between 100 and 149 + + if (region.temperature <= -5) + { + if (region.drainage < 75) + return df::enums::biome_type::biome_type::TUNDRA; // 2 + else + return df::enums::biome_type::biome_type::GLACIER; // 1 + } + + // Not a lake, mountain, ocean, glacier or tundra + // Vegetation determines the biome type + + if (region.vegetation < 10) + { + if (region.drainage < 33) + return df::enums::biome_type::biome_type::DESERT_SAND; // 26 + else if (region.drainage < 66) + return df::enums::biome_type::biome_type::DESERT_ROCK; // 25 + else // drainage >= 66 + return df::enums::biome_type::biome_type::DESERT_BADLAND; // 24 + } + else if (region.vegetation < 20) + { + if ((is_possible_tropical_area_by_latitude && (parameter < 66)) || is_tropical_area_by_latitude) + return df::enums::biome_type::biome_type::GRASSLAND_TROPICAL; // 21 + else + return df::enums::biome_type::biome_type::GRASSLAND_TEMPERATE; //18; + } + else if (region.vegetation < 33) + { + // vegetation between 20 and 32 + if ((is_possible_tropical_area_by_latitude && (parameter <= 6)) || is_tropical_area_by_latitude) + return df::enums::biome_type::biome_type::SAVANNA_TROPICAL; // 22 + else + return df::enums::biome_type::biome_type::SAVANNA_TEMPERATE; //19; + } + else if (region.vegetation < 66) + { + if (region.drainage >= 33) + { + if (is_possible_tropical_area_by_latitude && (parameter < 66 || is_tropical_area_by_latitude)) + return df::enums::biome_type::biome_type::SHRUBLAND_TROPICAL; // 23 + else + return df::enums::biome_type::biome_type::SHRUBLAND_TEMPERATE; // 20 + } + // drainage < 33 + { + if (region.salinity < 66) + { + if ((is_possible_tropical_area_by_latitude && (parameter < 66)) || is_tropical_area_by_latitude) + return df::enums::biome_type::biome_type::MARSH_TROPICAL_FRESHWATER; // 10 + else + return df::enums::biome_type::biome_type::MARSH_TEMPERATE_FRESHWATER; // 5 + } + else // drainage < 33, salinity >= 66 + { + if ((is_possible_tropical_area_by_latitude && (parameter < 66)) || is_tropical_area_by_latitude) + return df::enums::biome_type::biome_type::MARSH_TROPICAL_SALTWATER; // 11 + else + return df::enums::biome_type::biome_type::MARSH_TEMPERATE_SALTWATER; // 6 + } + } + } + + // Not a lake, mountain, ocean, glacier, tundra, desert, grassland or savanna + // vegetation >= 66 + else if (region.drainage >= 33) + { + // drainage >= 33, not tropical area + if (!is_possible_tropical_area_by_latitude) + { + if ((region.rainfall < 75) || (region.temperature < 65)) + { + if (region.temperature >= 10) + return df::enums::biome_type::biome_type::FOREST_TEMPERATE_CONIFER; // 13 + else + return df::enums::biome_type::biome_type::FOREST_TAIGA; // 12 + } + else + return df::enums::biome_type::biome_type::FOREST_TEMPERATE_BROADLEAF; // 14 + } + else // drainage >= 33, tropical area + { + if (((parameter < 66) || is_tropical_area_by_latitude) && (region.rainfall < 75)) + return df::enums::biome_type::biome_type::FOREST_TROPICAL_CONIFER; // 15 + if (parameter < 66) + return df::enums::biome_type::biome_type::FOREST_TROPICAL_DRY_BROADLEAF; // 16 + if (is_tropical_area_by_latitude) + return df::enums::biome_type::biome_type::FOREST_TROPICAL_MOIST_BROADLEAF; // 17 + else + { + if ((region.rainfall < 75) || (region.temperature < 65)) + { + if (region.temperature >= 10) + return df::enums::biome_type::biome_type::FOREST_TEMPERATE_CONIFER; // 13 + else + return df::enums::biome_type::biome_type::FOREST_TAIGA; // 12 + } + else + return df::enums::biome_type::biome_type::FOREST_TEMPERATE_BROADLEAF; // 14 + } + } + } + + // Not a lake, mountain, ocean, glacier, tundra, desert, grassland, savanna or forest + // vegetation >= 66, drainage < 33 + + else if (is_possible_tropical_area_by_latitude) + { + if (region.salinity < 66) + { + if ((parameter < 66) || is_tropical_area_by_latitude) + return df::enums::biome_type::biome_type::SWAMP_TROPICAL_FRESHWATER; // 7 + else + return df::enums::biome_type::biome_type::SWAMP_TEMPERATE_FRESHWATER;// 3 + } + else // elevation between 100 and 149, vegetation >= 66, drainage < 33, salinity >= 66 + { + if ((parameter < 66) || is_tropical_area_by_latitude) + if (region.drainage < 10) + return df::enums::biome_type::biome_type::SWAMP_MANGROVE; //9 + else // drainage >= 10 + return df::enums::biome_type::biome_type::SWAMP_TROPICAL_SALTWATER; // 8 + else + return df::enums::biome_type::biome_type::SWAMP_TEMPERATE_SALTWATER; // 4 + } + } + + else if (region.salinity >= 66) + // elevation between 100 and 149, vegetation >= 66, drainage < 33, not tropical area + return df::enums::biome_type::biome_type::SWAMP_TEMPERATE_SALTWATER; // 4 + else + return df::enums::biome_type::biome_type::SWAMP_TEMPERATE_FRESHWATER; // 3 + +} + +/***************************************************************************** +Module main function. +Return the biome type, given a position coordinate expressed in world_tiles +*****************************************************************************/ +df::enums::biome_type::biome_type Maps::GetBiomeType(int world_coord_x, int world_coord_y) +{ + return Maps::GetBiomeTypeWithRef(world_coord_x, world_coord_y, world_coord_y); +} + From 338572d2702e2d87b3e9f63c069dd2af836e1815 Mon Sep 17 00:00:00 2001 From: Kelly Kinkade Date: Thu, 16 Aug 2018 12:15:56 -0500 Subject: [PATCH 023/109] resolve uninitialized variable warning --- library/modules/Maps.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp index ecf68d5f7..d91ee7e1d 100644 --- a/library/modules/Maps.cpp +++ b/library/modules/Maps.cpp @@ -758,7 +758,7 @@ namespace { else { - int v6; + int v6 = 0; df::world_data* wdata = df::global::world->world_data; From 3817773b5a6affd55f3942c3f6b8c4c8e097759b Mon Sep 17 00:00:00 2001 From: Kelly Kinkade Date: Tue, 11 Sep 2018 17:32:33 -0500 Subject: [PATCH 024/109] eliminate stray whitespace --- library/modules/Maps.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp index d91ee7e1d..c40326195 100644 --- a/library/modules/Maps.cpp +++ b/library/modules/Maps.cpp @@ -753,7 +753,6 @@ namespace { // If there're no poles, tropical area is determined by temperature is_possible_tropical_area_by_latitude = region.temperature >= 75; is_tropical_area_by_latitude = region.temperature >= 85; - } else @@ -784,7 +783,6 @@ namespace { if (v6 >= wdata->world_height) v6 = wdata->world_height - 1; } - } if (wdata->world_height == 17) @@ -798,7 +796,6 @@ namespace { is_possible_tropical_area_by_latitude = v6 > 170; is_tropical_area_by_latitude = v6 >= 200; - } return std::pair(is_possible_tropical_area_by_latitude, @@ -1095,7 +1092,6 @@ df::enums::biome_type::biome_type Maps::GetBiomeTypeWithRef(int world_coord_x, return df::enums::biome_type::biome_type::SWAMP_TEMPERATE_SALTWATER; // 4 else return df::enums::biome_type::biome_type::SWAMP_TEMPERATE_FRESHWATER; // 3 - } /***************************************************************************** From 3351d78864a9b62933474b522d2719fec59b8abd Mon Sep 17 00:00:00 2001 From: Kelly Kinkade Date: Tue, 11 Sep 2018 18:27:44 -0500 Subject: [PATCH 025/109] Change embark-assistant to biome type from Maps See #1392 --- plugins/embark-assistant/CMakeLists.txt | 2 - plugins/embark-assistant/biome_type.cpp | 754 ------------------------ plugins/embark-assistant/biome_type.h | 7 - plugins/embark-assistant/survey.cpp | 4 +- 4 files changed, 2 insertions(+), 765 deletions(-) delete mode 100644 plugins/embark-assistant/biome_type.cpp delete mode 100644 plugins/embark-assistant/biome_type.h diff --git a/plugins/embark-assistant/CMakeLists.txt b/plugins/embark-assistant/CMakeLists.txt index 917d2ec5a..dfc1a294f 100644 --- a/plugins/embark-assistant/CMakeLists.txt +++ b/plugins/embark-assistant/CMakeLists.txt @@ -1,7 +1,6 @@ PROJECT (embark-assistant) # A list of source files SET(PROJECT_SRCS - biome_type.cpp embark-assistant.cpp finder_ui.cpp help_ui.cpp @@ -12,7 +11,6 @@ SET(PROJECT_SRCS ) # A list of headers SET(PROJECT_HDRS - biome_type.h defs.h embark-assistant.h finder_ui.h diff --git a/plugins/embark-assistant/biome_type.cpp b/plugins/embark-assistant/biome_type.cpp deleted file mode 100644 index 01bc0044a..000000000 --- a/plugins/embark-assistant/biome_type.cpp +++ /dev/null @@ -1,754 +0,0 @@ -/* The code is copied from Ragundo's repo referenced below. -The changes are: -- The addition of a .h file reference. -- The simplification of the code using ofsub to remove the use of (and - .h reference to) that function (analysis of the code showed the - simplified code is the result, as the ofsub expressions will never be - true given the range of the values it can be passed in these functions). -- The change of the main function to take a separate y coordinate for - use in the tropicality determination to allow proper determination of - the tropicality of mid level tiles ("region tiles") referencing a - neighboring world tile's biome. -*/ -/* -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: -1. The origin of this software must not be misrepresented; you must not -claim that you wrote the original software. If you use this software -in a product, an acknowledgment in the product documentation would be -appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be -misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -// You can always find the latest version of this plugin in Github -// https://github.com/ragundo/exportmaps - -#include - -#include "DataDefs.h" -#include -#include -#include -#include - -#include "biome_type.h" - -/***************************************************************************** -Local functions forward declaration -*****************************************************************************/ -std::pair check_tropicality(df::region_map_entry& region, - int a1 -); - -int get_lake_biome(df::region_map_entry& region, - bool is_possible_tropical_area_by_latitude -); - -int get_ocean_biome(df::region_map_entry& region, - bool is_tropical_area_by_latitude -); - -int get_desert_biome(df::region_map_entry& region); - -int get_biome_grassland(bool is_possible_tropical_area_by_latitude, - bool is_tropical_area_by_latitude, - int y, - int x -); - -int get_biome_savanna(bool is_possible_tropical_area_by_latitude, - bool is_tropical_area_by_latitude, - int y, - int x -); - -int get_biome_shrubland(bool is_possible_tropical_area_by_latitude, - bool is_tropical_area_by_latitude, - int y, - int x -); - -int get_biome_marsh(df::region_map_entry& region, - bool is_possible_tropical_area_by_latitude, - bool is_tropical_area_by_latitude, - int y, - int x -); - -int get_biome_forest(df::region_map_entry& region, - bool is_possible_tropical_area_by_latitude, - bool is_tropical_area_by_latitude, - int y, - int x -); - -int get_biome_swamp(df::region_map_entry& region, - bool is_possible_tropical_area_by_latitude, - bool is_tropical_area_by_latitude, - int y, - int x -); - -int get_biome_desert_or_grassland_or_savanna(df::region_map_entry& region, - bool is_possible_tropical_area_by_latitude, - bool is_tropical_area_by_latitude, - int y, - int x -); - -int get_biome_shrubland_or_marsh(df::region_map_entry& region, - bool is_possible_tropical_area_by_latitude, - bool is_tropical_area_by_latitude, - int y, - int x -); - -/***************************************************************************** -Module main function. -Return the biome type, given a position coordinate expressed in world_tiles -The world ref coordinates are used for tropicality determination and may refer -to a tile neighboring the "official" one. -*****************************************************************************/ -int get_biome_type(int world_coord_x, - int world_coord_y, - int world_ref_coord_y -) -{ - // Biome is per region, so get the region where this biome exists - df::region_map_entry& region = df::global::world->world_data->region_map[world_coord_x][world_coord_y]; - - // Check if the y reference position coordinate belongs to a tropical area - std::pair p = check_tropicality(region, - world_ref_coord_y - ); - bool is_possible_tropical_area_by_latitude = p.first; - bool is_tropical_area_by_latitude = p.second; - - // Begin the discrimination - if (region.flags.is_set(df::region_map_entry_flags::is_lake)) // is it a lake? - return get_lake_biome(region, - is_possible_tropical_area_by_latitude - ); - - // Not a lake. Check elevation - // Elevation greater then 149 means a mountain biome - // Elevation below 100 means a ocean biome - // Elevation between 100 and 149 are land biomes - - if (region.elevation >= 150) // is it a mountain? - return df::enums::biome_type::biome_type::MOUNTAIN; // 0 - - if (region.elevation < 100) // is it a ocean? - return get_ocean_biome(region, - is_possible_tropical_area_by_latitude - ); - - // land biome. Elevation between 100 and 149 - if (region.temperature <= -5) - { - if (region.drainage < 75) - return df::enums::biome_type::biome_type::TUNDRA; // 2 - else - return df::enums::biome_type::biome_type::GLACIER; // 1 - } - - // Not a lake, mountain, ocean, glacier or tundra - // Vegetation determines the biome type - if (region.vegetation < 66) - { - if (region.vegetation < 33) - return get_biome_desert_or_grassland_or_savanna(region, - is_possible_tropical_area_by_latitude, - is_tropical_area_by_latitude, - world_coord_y, - world_coord_x - ); - else // vegetation between 33 and 65 - return get_biome_shrubland_or_marsh(region, - is_possible_tropical_area_by_latitude, - is_tropical_area_by_latitude, - world_coord_y, - world_coord_x - ); - } - - // Not a lake, mountain, ocean, glacier, tundra, desert, grassland or savanna - // vegetation >= 66 - if (region.drainage >= 33) - return get_biome_forest(region, - is_possible_tropical_area_by_latitude, - is_tropical_area_by_latitude, - world_coord_y, - world_coord_x - ); - - // Not a lake, mountain, ocean, glacier, tundra, desert, grassland, savanna or forest - // vegetation >= 66, drainage < 33 - return get_biome_swamp(region, - is_possible_tropical_area_by_latitude, - is_tropical_area_by_latitude, - world_coord_y, - world_coord_x); -} - - - -//----------------------------------------------------------------------------// -// Utility function -// -//----------------------------------------------------------------------------// -std::pair check_tropicality_no_poles_world(df::region_map_entry& region, - int y_pos -) -{ - bool is_possible_tropical_area_by_latitude = false; - bool is_tropical_area_by_latitude = false; - - // If there're no poles, tropical area is determined by temperature - if (region.temperature >= 75) - is_possible_tropical_area_by_latitude = true; - is_tropical_area_by_latitude = region.temperature >= 85; - - return std::pair(is_possible_tropical_area_by_latitude, - is_tropical_area_by_latitude - ); -} - -//----------------------------------------------------------------------------// -// Utility function -// -//----------------------------------------------------------------------------// -std::pair check_tropicality_north_pole_only_world(df::region_map_entry& region, - int y_pos -) -{ - int v6; - bool is_possible_tropical_area_by_latitude = false; - bool is_tropical_area_by_latitude = false; - df::world_data* wdata = df::global::world->world_data; - - // Scale the smaller worlds to the big one - if (wdata->world_height == 17) - v6 = 16 * y_pos; - else if (wdata->world_height == 33) - v6 = 8 * y_pos; - else if (wdata->world_height == 65) - v6 = 4 * y_pos; - else if (wdata->world_height == 129) - v6 = 2 * y_pos; - else - v6 = y_pos; - - is_possible_tropical_area_by_latitude = v6 > 170; - is_tropical_area_by_latitude = v6 >= 200; - - return std::pair(is_possible_tropical_area_by_latitude, - is_tropical_area_by_latitude - ); -} - -//----------------------------------------------------------------------------// -// Utility function -// -//----------------------------------------------------------------------------// -std::pair check_tropicality_south_pole_only_world(df::region_map_entry& region, - int y_pos -) -{ - int v6 = df::global::world->world_data->world_height - y_pos - 1; - bool is_possible_tropical_area_by_latitude = false; - bool is_tropical_area_by_latitude = false; - df::world_data* wdata = df::global::world->world_data; - - if (wdata->world_height == 17) - v6 *= 16; - else if (wdata->world_height == 33) - v6 *= 8; - else if (wdata->world_height == 65) - v6 *= 4; - else if (wdata->world_height == 129) - v6 *= 2; - else - v6 *= 1; - - is_possible_tropical_area_by_latitude = v6 > 170; - is_tropical_area_by_latitude = v6 >= 200; - - return std::pair(is_possible_tropical_area_by_latitude, - is_tropical_area_by_latitude - ); -} - -//----------------------------------------------------------------------------// -// Utility function -// -//----------------------------------------------------------------------------// -std::pair check_tropicality_both_poles_world(df::region_map_entry& region, - int y_pos -) -{ - int v6; - bool is_possible_tropical_area_by_latitude = false; - bool is_tropical_area_by_latitude = false; - df::world_data* wdata = df::global::world->world_data; - - if (y_pos < wdata->world_height / 2) - v6 = 2 * y_pos; - else - { - v6 = wdata->world_height + 2 * (wdata->world_height / 2 - y_pos) - 1; - if (v6 < 0) - v6 = 0; - if (v6 >= wdata->world_height) - v6 = wdata->world_height - 1; - } - - if (wdata->world_height == 17) - v6 *= 16; - else if (wdata->world_height == 33) - v6 *= 8; - else if (wdata->world_height == 65) - v6 *= 4; - else if (wdata->world_height == 129) - v6 *= 2; - else - v6 *= 1; - - is_possible_tropical_area_by_latitude = v6 > 170; - is_tropical_area_by_latitude = v6 >= 200; - - return std::pair(is_possible_tropical_area_by_latitude, - is_tropical_area_by_latitude - ); -} - -//----------------------------------------------------------------------------// -// Utility function -// -//----------------------------------------------------------------------------// -std::pair check_tropicality(df::region_map_entry& region, - int y_pos -) -{ - int flip_latitude = df::global::world->world_data->flip_latitude; - - if (flip_latitude == -1) // NO POLES - return check_tropicality_no_poles_world(region, - y_pos - ); - - else if (flip_latitude == 0) // NORTH POLE ONLY - return check_tropicality_north_pole_only_world(region, - y_pos - ); - - else if (flip_latitude == 1) // SOUTH_POLE ONLY - return check_tropicality_south_pole_only_world(region, - y_pos - ); - - else if (flip_latitude == 2) // BOTH POLES - return check_tropicality_both_poles_world(region, - y_pos - ); - - return std::pair(false, false); -} - -//----------------------------------------------------------------------------// -// Utility function -// -//----------------------------------------------------------------------------// -int get_parameter_percentage(int flip_latitude, - int y_pos, - int rainfall, - int world_height -) -{ - int result; - int ypos = y_pos; - - if (flip_latitude == -1) // NO POLES - return 100; - - else if (flip_latitude == 1) // SOUTH POLE - ypos = world_height - y_pos - 1; - else if (flip_latitude == 2) // NORTH & SOUTH POLE - { - if (ypos < world_height / 2) - ypos *= 2; - else - { - ypos = world_height + 2 * (world_height / 2 - ypos) - 1; - if (ypos < 0) - ypos = 0; - if (ypos >= world_height) - ypos = world_height - 1; - } - } - - int latitude; // 0 - 256 (size of a large world) - switch (world_height) - { - case 17: // Pocket world - latitude = 16 * ypos; - break; - case 33: // Smaller world - latitude = 8 * ypos; - break; - case 65: // Small world - latitude = 4 * ypos; - break; - case 129: // Medium world - latitude = 2 * ypos; - break; - default: // Large world - latitude = ypos; - break; - } - - // latitude > 220 - if ((latitude - 171) > 49) - return 100; - - - // Latitude between 191 and 200 - if ((latitude > 190) && (latitude < 201)) - return 0; - - // Latitude between 201 and 220 - if ((latitude > 190) && (latitude >= 201)) - result = rainfall + 16 * (latitude - 207); - else - // Latitude between 0 and 190 - result = (16 * (184 - latitude) - rainfall); - - if (result < 0) - return 0; - - if (result > 100) - return 100; - - return result; -} - -//----------------------------------------------------------------------------// -// Utility function -// -// return some unknow parameter as a percentage -//----------------------------------------------------------------------------// -int get_region_parameter(int y, - int x, - char a4 -) -{ - int result = 100; - - if ((df::global::cur_season && *df::global::cur_season != 1) || !a4) - { - int world_height = df::global::world->world_data->world_height; - if (world_height > 65) // Medium and large worlds - { - // access to region 2D array - df::region_map_entry& region = df::global::world->world_data->region_map[x][y]; - return get_parameter_percentage(df::global::world->world_data->flip_latitude, - y, - region.rainfall, - world_height - ); - } - } - return result; -} - -//----------------------------------------------------------------------------// -// Utility function -// -//----------------------------------------------------------------------------// -int get_lake_biome(df::region_map_entry& region, - bool is_possible_tropical_area_by_latitude -) -{ - // salinity values tell us the lake type - // greater than 66 is a salt water lake - // between 33 and 65 is a brackish water lake - // less than 33 is a fresh water lake - if (region.salinity < 66) - { - if (region.salinity < 33) - if (is_possible_tropical_area_by_latitude) - return df::enums::biome_type::biome_type::LAKE_TROPICAL_FRESHWATER; // 39 - else - return df::enums::biome_type::biome_type::LAKE_TEMPERATE_FRESHWATER; // 36 - else // salinity >= 33 - if (is_possible_tropical_area_by_latitude) - return df::enums::biome_type::biome_type::LAKE_TROPICAL_BRACKISHWATER; // 40 - else - return df::enums::biome_type::biome_type::LAKE_TEMPERATE_BRACKISHWATER; // 37 - } - else // salinity >= 66 - { - if (is_possible_tropical_area_by_latitude) - return df::enums::biome_type::biome_type::LAKE_TROPICAL_SALTWATER;// 41 - else - return df::enums::biome_type::biome_type::LAKE_TEMPERATE_SALTWATER; // 38 - } -} - -//----------------------------------------------------------------------------// -// Utility function -// -//----------------------------------------------------------------------------// -int get_ocean_biome(df::region_map_entry& region, - bool is_tropical_area_by_latitude -) -{ - if (is_tropical_area_by_latitude) - return df::enums::biome_type::biome_type::OCEAN_TROPICAL; // 27 - else - if (region.temperature <= -5) - return df::enums::biome_type::biome_type::OCEAN_ARCTIC; // 29 - else - return df::enums::biome_type::biome_type::OCEAN_TEMPERATE; // 28 -} - -//----------------------------------------------------------------------------// -// Utility function -// -//----------------------------------------------------------------------------// -int get_desert_biome(df::region_map_entry& region) -{ - if (region.drainage < 66) - { - if (region.drainage < 33) - return df::enums::biome_type::biome_type::DESERT_SAND; // 26 - else // drainage between 33 and 65 - return df::enums::biome_type::biome_type::DESERT_ROCK; // 25 - } - // drainage >= 66 - return df::enums::biome_type::biome_type::DESERT_BADLAND; // 24 -} - -//----------------------------------------------------------------------------// -// Utility function -// -//----------------------------------------------------------------------------// -int get_biome_grassland(bool is_possible_tropical_area_by_latitude, - bool is_tropical_area_by_latitude, - int y, - int x -) -{ - if ((is_possible_tropical_area_by_latitude && (get_region_parameter(y, x, 0) < 66)) || is_tropical_area_by_latitude) - return df::enums::biome_type::biome_type::GRASSLAND_TROPICAL; // 21 - else - return df::enums::biome_type::biome_type::GRASSLAND_TEMPERATE; //18; -} - -//----------------------------------------------------------------------------// -// Utility function -// -//----------------------------------------------------------------------------// -int get_biome_savanna(bool is_possible_tropical_area_by_latitude, - bool is_tropical_area_by_latitude, - int y, - int x -) -{ - if ((is_possible_tropical_area_by_latitude && (get_region_parameter(y, x, 0) <= 6)) || is_tropical_area_by_latitude) - return df::enums::biome_type::biome_type::SAVANNA_TROPICAL; // 22 - else - return df::enums::biome_type::biome_type::SAVANNA_TEMPERATE; //19; - -} - -//----------------------------------------------------------------------------// -// Utility function -// -//----------------------------------------------------------------------------// -int get_biome_desert_or_grassland_or_savanna(df::region_map_entry& region, - bool is_possible_tropical_area_by_latitude, - bool is_tropical_area_by_latitude, - int y, - int x -) -{ - if (region.vegetation < 20) - { - if (region.vegetation < 10) - return get_desert_biome(region); - else // vegetation between 10 and 19 - return get_biome_grassland(is_possible_tropical_area_by_latitude, is_tropical_area_by_latitude, y, x); - } - // vegetation between 20 and 32 - return get_biome_savanna(is_possible_tropical_area_by_latitude, is_tropical_area_by_latitude, y, x); -} - -//----------------------------------------------------------------------------// -// Utility function -// -//----------------------------------------------------------------------------// -int get_biome_shrubland(bool is_possible_tropical_area_by_latitude, - bool is_tropical_area_by_latitude, - int y, - int x -) -{ - if (is_possible_tropical_area_by_latitude && (get_region_parameter(y, x, 0) < 66 || is_tropical_area_by_latitude)) - return df::enums::biome_type::biome_type::SHRUBLAND_TROPICAL; // 23 - else - return df::enums::biome_type::biome_type::SHRUBLAND_TEMPERATE; // 20 -} - -//----------------------------------------------------------------------------// -// Utility function -// -//----------------------------------------------------------------------------// -int get_biome_marsh(df::region_map_entry& region, - bool is_possible_tropical_area_by_latitude, - bool is_tropical_area_by_latitude, - int y, - int x -) -{ - if (region.salinity < 66) - { - if ((is_possible_tropical_area_by_latitude && (get_region_parameter(y, x, 0) < 66)) || is_tropical_area_by_latitude) - return df::enums::biome_type::biome_type::MARSH_TROPICAL_FRESHWATER; // 10 - else - return df::enums::biome_type::biome_type::MARSH_TEMPERATE_FRESHWATER; // 5 - } - else // drainage < 33, salinity >= 66 - { - if ((is_possible_tropical_area_by_latitude && (get_region_parameter(y, x, 0) < 66)) || is_tropical_area_by_latitude) - return df::enums::biome_type::biome_type::MARSH_TROPICAL_SALTWATER; // 11 - else - return df::enums::biome_type::biome_type::MARSH_TEMPERATE_SALTWATER; // 6 - } -} - -//----------------------------------------------------------------------------// -// Utility function -// -//----------------------------------------------------------------------------// -int get_biome_shrubland_or_marsh(df::region_map_entry& region, - bool is_possible_tropical_area_by_latitude, - bool is_tropical_area_by_latitude, - int y, - int x -) -{ - if (region.drainage >= 33) - return get_biome_shrubland(is_possible_tropical_area_by_latitude, - is_tropical_area_by_latitude, - y, - x - ); - // drainage < 33 - return get_biome_marsh(region, - is_possible_tropical_area_by_latitude, - is_tropical_area_by_latitude, - y, - x - ); -} - - -//----------------------------------------------------------------------------// -// Utility function -// -//----------------------------------------------------------------------------// -int get_biome_forest(df::region_map_entry& region, - bool is_possible_tropical_area_by_latitude, - bool is_tropical_area_by_latitude, - int y, - int x -) -{ - int parameter = get_region_parameter(y, x, 0); - - // drainage >= 33, not tropical area - if (!is_possible_tropical_area_by_latitude) - { - if ((region.rainfall < 75) || (region.temperature < 65)) - { - if (region.temperature >= 10) - return df::enums::biome_type::biome_type::FOREST_TEMPERATE_CONIFER; // 13 - else - return df::enums::biome_type::biome_type::FOREST_TAIGA; // 12 - } - else - return df::enums::biome_type::biome_type::FOREST_TEMPERATE_BROADLEAF; // 14 - } - else // drainage >= 33, tropical area - { - if (((parameter < 66) || is_tropical_area_by_latitude) && (region.rainfall < 75)) - return df::enums::biome_type::biome_type::FOREST_TROPICAL_CONIFER; // 15 - if (parameter < 66) - return df::enums::biome_type::biome_type::FOREST_TROPICAL_DRY_BROADLEAF; // 16 - if (is_tropical_area_by_latitude) - return df::enums::biome_type::biome_type::FOREST_TROPICAL_MOIST_BROADLEAF; // 17 - else - { - if ((region.rainfall < 75) || (region.temperature < 65)) - { - if (region.temperature >= 10) - return df::enums::biome_type::biome_type::FOREST_TEMPERATE_CONIFER; // 13 - else - return df::enums::biome_type::biome_type::FOREST_TAIGA; // 12 - } - else - return df::enums::biome_type::biome_type::FOREST_TEMPERATE_BROADLEAF; // 14 - } - } -} - -//----------------------------------------------------------------------------// -// Utility function -// -//----------------------------------------------------------------------------// -int get_biome_swamp(df::region_map_entry& region, - bool is_possible_tropical_area_by_latitude, - bool is_tropical_area_by_latitude, - int y, - int x -) -{ - int parameter = get_region_parameter(y, x, 0); - - if (is_possible_tropical_area_by_latitude) - { - if (region.salinity < 66) - { - if ((parameter < 66) || is_tropical_area_by_latitude) - return df::enums::biome_type::biome_type::SWAMP_TROPICAL_FRESHWATER; // 7 - else - return df::enums::biome_type::biome_type::SWAMP_TEMPERATE_FRESHWATER;// 3 - } - else // elevation between 100 and 149, vegetation >= 66, drainage < 33, salinity >= 66 - { - if ((parameter < 66) || is_tropical_area_by_latitude) - { - if (region.drainage < 10) - return df::enums::biome_type::biome_type::SWAMP_MANGROVE; //9 - else // drainage >= 10 - return df::enums::biome_type::biome_type::SWAMP_TROPICAL_SALTWATER; // 8 - } - else - return df::enums::biome_type::biome_type::SWAMP_TEMPERATE_SALTWATER; // 4 - } - } - else // elevation between 100 and 149, vegetation >= 66, drainage < 33, not tropical area - { - if (region.salinity >= 66) - return df::enums::biome_type::biome_type::SWAMP_TEMPERATE_SALTWATER; // 4 - else - return df::enums::biome_type::biome_type::SWAMP_TEMPERATE_FRESHWATER; // 3 - } -} \ No newline at end of file diff --git a/plugins/embark-assistant/biome_type.h b/plugins/embark-assistant/biome_type.h deleted file mode 100644 index 9ea562749..000000000 --- a/plugins/embark-assistant/biome_type.h +++ /dev/null @@ -1,7 +0,0 @@ -// world_coord_x/y is the location of the tile "owning" the biome, while world_ref_coord_y is the -// location of the tile the biome appears on. They differ when a mid level tile ("region tile") -// refers to a neighboring tile for the biome parameters. The difference can affect the tropicality -// determination. Since Tropicality is determined by latitude, the x coordinate of the reference is -// omitted. -// -int get_biome_type(int world_coord_x, int world_coord_y, int world_ref_coord_y); diff --git a/plugins/embark-assistant/survey.cpp b/plugins/embark-assistant/survey.cpp index 4071d78b3..682551bc2 100644 --- a/plugins/embark-assistant/survey.cpp +++ b/plugins/embark-assistant/survey.cpp @@ -8,6 +8,7 @@ #include #include "modules/Materials.h" +#include "modules/Maps.h" #include "DataDefs.h" #include "df/coord2d.h" @@ -51,7 +52,6 @@ #include "df/world_site_type.h" #include "df/world_underground_region.h" -#include "biome_type.h" #include "defs.h" #include "survey.h" @@ -552,7 +552,7 @@ void embark_assist::survey::high_level_world_survey(embark_assist::defs::geo_dat offset_count++; results.biome_index[l] = world_data->region_map[adjusted.x][adjusted.y].region_id; - results.biome[l] = get_biome_type(adjusted.x, adjusted.y, k); + results.biome[l] = DFHack::Maps::GetBiomeTypeWithRef(adjusted.x, adjusted.y, k); temperature = world_data->region_map[adjusted.x][adjusted.y].temperature; negative = temperature < 0; From 02f047e9f1a7970a51ed6c16451d20374cdd3f54 Mon Sep 17 00:00:00 2001 From: Kelly Kinkade Date: Tue, 11 Sep 2018 18:41:32 -0500 Subject: [PATCH 026/109] a pox on whitespace --- library/modules/Maps.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp index c40326195..361ada0f1 100644 --- a/library/modules/Maps.cpp +++ b/library/modules/Maps.cpp @@ -749,7 +749,6 @@ namespace { if (flip_latitude == -1) // NO POLES { - // If there're no poles, tropical area is determined by temperature is_possible_tropical_area_by_latitude = region.temperature >= 75; is_tropical_area_by_latitude = region.temperature >= 85; From cb9c964722ebe10ac313a61f853b0960b0094e15 Mon Sep 17 00:00:00 2001 From: Warmist Date: Fri, 12 Oct 2018 10:40:20 +0300 Subject: [PATCH 027/109] Rename twbt-utils to map-render --- plugins/CMakeLists.txt | 2 +- plugins/{twbt-utils.cpp => map-render.cpp} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename plugins/{twbt-utils.cpp => map-render.cpp} (99%) diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 7a26188b5..f2e2ee030 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -135,6 +135,7 @@ if (BUILD_SUPPORTED) 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) @@ -151,7 +152,6 @@ if (BUILD_SUPPORTED) add_subdirectory(rendermax) DFHACK_PLUGIN(resume resume.cpp) DFHACK_PLUGIN(reveal reveal.cpp) - DFHACK_PLUGIN(twbt-utils twbt-utils.cpp LINK_LIBRARIES lua) DFHACK_PLUGIN(search search.cpp) DFHACK_PLUGIN(seedwatch seedwatch.cpp) DFHACK_PLUGIN(showmood showmood.cpp) diff --git a/plugins/twbt-utils.cpp b/plugins/map-render.cpp similarity index 99% rename from plugins/twbt-utils.cpp rename to plugins/map-render.cpp index 4dbe3ca45..c3506ff59 100644 --- a/plugins/twbt-utils.cpp +++ b/plugins/map-render.cpp @@ -20,7 +20,7 @@ using std::vector; using namespace DFHack; using namespace df::enums; -DFHACK_PLUGIN("twbt-utils"); +DFHACK_PLUGIN("map-render"); REQUIRE_GLOBAL(window_x) REQUIRE_GLOBAL(window_y) REQUIRE_GLOBAL(window_z) From f74ee143ddbc8b09169813430d963f583b71bc50 Mon Sep 17 00:00:00 2001 From: Warmist Date: Fri, 12 Oct 2018 10:40:44 +0300 Subject: [PATCH 028/109] Might as well use REQUIRE_GLOBAL --- plugins/map-render.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/map-render.cpp b/plugins/map-render.cpp index c3506ff59..52a7f7699 100644 --- a/plugins/map-render.cpp +++ b/plugins/map-render.cpp @@ -36,13 +36,13 @@ REQUIRE_GLOBAL_NO_USE(twbt_render_map) void render_map(){ _render_map(0); } #else -REQUIRE_GLOBAL_NO_USE(map_renderer) +REQUIRE_GLOBAL(map_renderer) typedef void(*RENDER_MAP)(void*, int); RENDER_MAP _render_map; - void render_map(){ _render_map(df::global::map_renderer,0); } + void render_map(){ _render_map(map_renderer,0); } #endif static int render_map_rect(lua_State* L) { From d9d470e4b6d474f6d4b2347a5e1b21dc6369d237 Mon Sep 17 00:00:00 2001 From: Warmist Date: Fri, 12 Oct 2018 10:41:43 +0300 Subject: [PATCH 029/109] Missing REQUIRE_GLOBAL(init) --- plugins/map-render.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/plugins/map-render.cpp b/plugins/map-render.cpp index 52a7f7699..1de871741 100644 --- a/plugins/map-render.cpp +++ b/plugins/map-render.cpp @@ -27,6 +27,7 @@ REQUIRE_GLOBAL(window_z) REQUIRE_GLOBAL_NO_USE(gps) REQUIRE_GLOBAL_NO_USE(enabler) REQUIRE_GLOBAL_NO_USE(twbt_render_map) +REQUIRE_GLOBAL(init) #ifdef WIN32 // On Windows there's no parameter pointing to the map_renderer structure @@ -59,10 +60,10 @@ static int render_map_rect(lua_State* L) int32_t was_x = *window_x; int32_t was_y = *window_y; int32_t was_z = *window_z; - int32_t gx = df::global::init->display.grid_x; - int32_t gy = df::global::init->display.grid_y; - df::global::init->display.grid_x = w+1; - df::global::init->display.grid_y = h+1; + int32_t gx = init->display.grid_x; + int32_t gy = init->display.grid_y; + init->display.grid_x = w+1; + init->display.grid_y = h+1; *window_x = x; *window_y = y; *window_z = z; @@ -82,8 +83,8 @@ static int render_map_rect(lua_State* L) *window_x = was_x; *window_y = was_y; *window_z = was_z; - df::global::init->display.grid_x = gx; - df::global::init->display.grid_y = gy; + init->display.grid_x = gx; + init->display.grid_y = gy; lua_createtable(L,w*h*4,0); From 5c1b7030e739ddf32683cd9d3e87086ab93bd7c5 Mon Sep 17 00:00:00 2001 From: Warmist Date: Fri, 12 Oct 2018 10:44:56 +0300 Subject: [PATCH 030/109] Also rename the plugin lua file --- plugins/lua/{twbt-utils.lua => map-render.lua} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename plugins/lua/{twbt-utils.lua => map-render.lua} (63%) diff --git a/plugins/lua/twbt-utils.lua b/plugins/lua/map-render.lua similarity index 63% rename from plugins/lua/twbt-utils.lua rename to plugins/lua/map-render.lua index 56bdb0b19..9785c365e 100644 --- a/plugins/lua/twbt-utils.lua +++ b/plugins/lua/map-render.lua @@ -1,4 +1,4 @@ -local _ENV = mkmodule('plugins.twbt-utils') +local _ENV = mkmodule('plugins.map-render') --[[ From ff452f9181ed51dd3be1d05640cf78f0096330f1 Mon Sep 17 00:00:00 2001 From: Warmist Date: Fri, 12 Oct 2018 13:37:49 +0300 Subject: [PATCH 031/109] Add more comments --- plugins/map-render.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/map-render.cpp b/plugins/map-render.cpp index 1de871741..d299c237c 100644 --- a/plugins/map-render.cpp +++ b/plugins/map-render.cpp @@ -54,8 +54,9 @@ static int render_map_rect(lua_State* L) int z = luaL_checkint(L, 3); int w = luaL_checkint(L, 4); int h = luaL_checkint(L, 5); + uint8_t *s = df::global::gps->screen; //backup state - uint8_t *s = df::global::gps->screen; + //TODO: figure out if we can replace screen with other pointer. That way it could be a bit more tidy int32_t win_h = df::global::gps->dimy; int32_t was_x = *window_x; int32_t was_y = *window_y; @@ -69,6 +70,7 @@ static int render_map_rect(lua_State* L) *window_z = z; //force full redraw df::global::gps->force_full_display_count = 1; + //this modifies screen so it REALLY wants to redraw stuff for (int ty = 0; ty < h; ty++) for (int tx = 0; tx < w; tx++) { From 96d11d1f543883bfb63147bfaefce9df16a812b2 Mon Sep 17 00:00:00 2001 From: Warmist Date: Fri, 12 Oct 2018 13:48:53 +0300 Subject: [PATCH 032/109] Add to docs --- docs/Lua API.rst | 16 ++++++++++++++++ docs/Plugins.rst | 1 + 2 files changed, 17 insertions(+) diff --git a/docs/Lua API.rst b/docs/Lua API.rst index 3eb053e73..a5894a3a5 100644 --- a/docs/Lua API.rst +++ b/docs/Lua API.rst @@ -3920,6 +3920,22 @@ A class with all the tcp functionality. Tries connecting to that address and port. Returns ``client`` object. + +.. _map-render: + +map-render +========== + +A way to ask df to render a slice of map. This uses native df rendering function so it's highly dependant on +df settings (e.g. used tileset, colors, if using graphics or not and so on...) + +Functions +--------- + +- ``render_map_rect(x,y,z,w,h)`` + + returns a table with w*h*4 entries of rendered tiles. The format is same as ``df.global.gps.screen`` (tile,foreground,bright,background). + .. _cxxrandom: cxxrandom diff --git a/docs/Plugins.rst b/docs/Plugins.rst index 62ddf29e6..458a43722 100644 --- a/docs/Plugins.rst +++ b/docs/Plugins.rst @@ -2745,4 +2745,5 @@ in the `lua-api` file under `lua-plugins`: * `eventful` * `building-hacks` * `luasocket` +* `map-render` * `cxxrandom` From 3cfff2114945974abc521c77e464c3f848d81a09 Mon Sep 17 00:00:00 2001 From: Japa Mala Illo Date: Mon, 22 Oct 2018 18:23:43 -0500 Subject: [PATCH 033/109] Update XMLs --- library/xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/xml b/library/xml index efa179476..11faf4afe 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit efa17947676ed05476929d4f0cf2cb260ef3aa7a +Subproject commit 11faf4afe03b8810fe3c681e0c1e660c0abd5afd From 7b6b83bdcf0d1c9b4a7a18b25bfd2e6d371131c3 Mon Sep 17 00:00:00 2001 From: Japa Mala Illo Date: Sun, 28 Oct 2018 02:01:01 -0500 Subject: [PATCH 034/109] added a command to dump all trees in the map for debug. --- .vscode/settings.json | 6 + .../remotefortressreader.cpp | 258 +++++++++++++++++- 2 files changed, 257 insertions(+), 7 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..e0ac3c845 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "files.associations": { + "vector": "cpp", + "fstream": "cpp" + } +} \ No newline at end of file diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index cd9837f6c..8c1c9c33a 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -255,6 +255,247 @@ command_result dump_bp_mods(color_ostream &out, vector & parameters) return CR_OK; } +command_result Dump_Trees(color_ostream &out, vector ¶meters) +{ + char filename[255]; + for(int columnIndex = 0; columnIndex < world->map.map_block_columns.size(); columnIndex++) + { + auto column = world->map.map_block_columns[columnIndex]; + if(!column) + continue; + if(column->plants.size() == 0) + continue; + for(int plantIndex = 0; plantIndex < column->plants.size(); plantIndex++) + { + auto plant = column->plants[plantIndex]; + if(!plant) + continue; + if(!plant->tree_info) + continue; + sprintf(filename, "plant_%03d,%03d,%03d.txt", plant->pos.z, plant->pos.y, plant->pos.x); + remove(filename); + ofstream output; + output.open(filename); + output << "Pos: " << plant->pos.x << ", " << plant->pos.y << ", " << plant->pos.z << endl; + output << "Material: " << plant->material << endl; + output << "Grow Counter: " << plant->grow_counter << endl; + output << "Damage Flags: "; + if(plant->damage_flags.bits.is_burning) + output << "is_burning, "; + if(plant->damage_flags.bits.is_drowning) + output << "is_drowning, "; + if(plant->damage_flags.bits.anon_1) + output << "anon_1, "; + output << endl; + output << "HP: " << plant->hitpoints << endl; + output << "Update Order: " << plant->update_order << endl; + output << "Site ID: " << plant->site_id << endl; + output << "SRB ID: " << plant->srb_id << endl; + auto treeInfo = plant->tree_info; + output << "Dim X: " << treeInfo->dim_x << endl; + output << "Dim Y: " << treeInfo->dim_y << endl; + output << "Dim Z: " << treeInfo->body_height << endl; + for(int z = 0; z < treeInfo->body_height; z++) + { + for(int y = -1; y < treeInfo->dim_y; y++) + { + for(int x = -1; x < treeInfo->dim_x; x++) + { + if(x < 0) + { + if(y < 0) + { + output << " "; + continue; + } + output << y%9; + continue; + } + if(y < 0) + { + output << x%9; + continue; + } + auto tile = treeInfo->body[z][x + treeInfo->dim_x*y]; + if(tile.bits.blocked) + output << "x"; + else if(tile.bits.twigs) + output << "░"; + else if(tile.bits.branches) + { + if(tile.bits.thick_branches_1) // East Connection + { + if(tile.bits.thick_branches_2) // South Connection + { + if(tile.bits.thick_branches_3) // West Connection + { + if(tile.bits.thick_branches_4) // North Connection + { + if(tile.bits.trunk) + output << "╬"; + else + output << "┼"; + } + else + { + if(tile.bits.trunk) + output << "╦"; + else + output << "┬"; + } + } + else + { + if(tile.bits.thick_branches_4) // North Connection + { + if(tile.bits.trunk) + output << "╠"; + else + output << "├"; + } + else + { + if(tile.bits.trunk) + output << "╔"; + else + output << "┌"; + } + } + } + else + { + if(tile.bits.thick_branches_3) // West Connection + { + if(tile.bits.thick_branches_4) // North Connection + { + if(tile.bits.trunk) + output << "╩"; + else + output << "┴"; + } + else + { + if(tile.bits.trunk) + output << "═"; + else + output << "─"; + } + } + else + { + if(tile.bits.thick_branches_4) // North Connection + { + if(tile.bits.trunk) + output << "╚"; + else + output << "└"; + } + else + { + if(tile.bits.trunk) + output << "╞"; + else + output << ">"; + } + } + } + } + else + { + if(tile.bits.thick_branches_2) // South Connection + { + if(tile.bits.thick_branches_3) // West Connection + { + if(tile.bits.thick_branches_4) // North Connection + { + if(tile.bits.trunk) + output << "╣"; + else + output << "┤"; + } + else + { + if(tile.bits.trunk) + output << "╗"; + else + output << "┐"; + } + } + else + { + if(tile.bits.thick_branches_4) // North Connection + { + if(tile.bits.trunk) + output << "║"; + else + output << "│"; + } + else + { + if(tile.bits.trunk) + output << "╥"; + else + output << "v"; + } + } + } + else + { + if(tile.bits.thick_branches_3) // West Connection + { + if(tile.bits.thick_branches_4) // North Connection + { + if(tile.bits.trunk) + output << "╝"; + else + output << "┘"; + } + else + { + if(tile.bits.trunk) + output << "╡"; + else + output << "<"; + } + } + else + { + if(tile.bits.thick_branches_4) // North Connection + { + if(tile.bits.trunk) + output << "╨"; + else + output << "^"; + } + else + { + if(tile.bits.trunk) + output << "o"; + else + output << "▒"; + } + } + } + } + } + else if(tile.bits.trunk) + output << "O"; + else if(tile.whole > 0) + output << +tile.whole; + else + output << " "; + } + output << endl; + } + output << endl; + } + //... + output.close(); + } + } + return CR_OK; +} + command_result RemoteFortressReader_version(color_ostream &out, vector ¶meters) { out.print(RFR_VERSION); @@ -271,12 +512,15 @@ DFhackCExport command_result plugin_init(color_ostream &out, std::vector Date: Sun, 28 Oct 2018 09:33:26 -0500 Subject: [PATCH 035/109] Changed the plant tiles to more descriptive names. --- .vscode/c_cpp_properties.json | 21 +++++++++++++ library/xml | 2 +- .../remotefortressreader.cpp | 30 +++++++++---------- 3 files changed, 37 insertions(+), 16 deletions(-) create mode 100644 .vscode/c_cpp_properties.json diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 000000000..7d2c32d7d --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,21 @@ +{ + "configurations": [ + { + "name": "Win32", + "includePath": [ + "${workspaceFolder}/**" + ], + "defines": [ + "_DEBUG", + "UNICODE", + "_UNICODE" + ], + "windowsSdkVersion": "10.0.17134.0", + "compilerPath": "C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.15.26726/bin/Hostx64/x64/cl.exe", + "cStandard": "c11", + "cppStandard": "c++17", + "intelliSenseMode": "msvc-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/library/xml b/library/xml index 11faf4afe..8f5955b08 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 11faf4afe03b8810fe3c681e0c1e660c0abd5afd +Subproject commit 8f5955b08c0dab7f2fd7d6432df054b82a3c4f4b diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index 8c1c9c33a..96ea6b5eb 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -323,13 +323,13 @@ command_result Dump_Trees(color_ostream &out, vector ¶meters) output << "░"; else if(tile.bits.branches) { - if(tile.bits.thick_branches_1) // East Connection + if(tile.bits.connection_east)// East Connection { - if(tile.bits.thick_branches_2) // South Connection + if(tile.bits.connection_south) // South Connection { - if(tile.bits.thick_branches_3) // West Connection + if(tile.bits.connection_west) // West Connection { - if(tile.bits.thick_branches_4) // North Connection + if(tile.bits.connection_north) // North Connection { if(tile.bits.trunk) output << "╬"; @@ -346,7 +346,7 @@ command_result Dump_Trees(color_ostream &out, vector ¶meters) } else { - if(tile.bits.thick_branches_4) // North Connection + if(tile.bits.connection_north) // North Connection { if(tile.bits.trunk) output << "╠"; @@ -364,9 +364,9 @@ command_result Dump_Trees(color_ostream &out, vector ¶meters) } else { - if(tile.bits.thick_branches_3) // West Connection + if(tile.bits.connection_west) // West Connection { - if(tile.bits.thick_branches_4) // North Connection + if(tile.bits.connection_north) // North Connection { if(tile.bits.trunk) output << "╩"; @@ -383,7 +383,7 @@ command_result Dump_Trees(color_ostream &out, vector ¶meters) } else { - if(tile.bits.thick_branches_4) // North Connection + if(tile.bits.connection_north) // North Connection { if(tile.bits.trunk) output << "╚"; @@ -402,11 +402,11 @@ command_result Dump_Trees(color_ostream &out, vector ¶meters) } else { - if(tile.bits.thick_branches_2) // South Connection + if(tile.bits.connection_south) // South Connection { - if(tile.bits.thick_branches_3) // West Connection + if(tile.bits.connection_west) // West Connection { - if(tile.bits.thick_branches_4) // North Connection + if(tile.bits.connection_north) // North Connection { if(tile.bits.trunk) output << "╣"; @@ -423,7 +423,7 @@ command_result Dump_Trees(color_ostream &out, vector ¶meters) } else { - if(tile.bits.thick_branches_4) // North Connection + if(tile.bits.connection_north) // North Connection { if(tile.bits.trunk) output << "║"; @@ -441,9 +441,9 @@ command_result Dump_Trees(color_ostream &out, vector ¶meters) } else { - if(tile.bits.thick_branches_3) // West Connection + if(tile.bits.connection_west) // West Connection { - if(tile.bits.thick_branches_4) // North Connection + if(tile.bits.connection_north) // North Connection { if(tile.bits.trunk) output << "╝"; @@ -460,7 +460,7 @@ command_result Dump_Trees(color_ostream &out, vector ¶meters) } else { - if(tile.bits.thick_branches_4) // North Connection + if(tile.bits.connection_north) // North Connection { if(tile.bits.trunk) output << "╨"; From d6778801312732658dc26c70ce9b80fb8e0473eb Mon Sep 17 00:00:00 2001 From: Japa Mala Illo Date: Sun, 28 Oct 2018 10:22:03 -0500 Subject: [PATCH 036/109] Fix issues with missing onbreak flag --- plugins/autolabor.cpp | 2 +- plugins/dwarfmonitor.cpp | 2 +- plugins/search.cpp | 2 +- plugins/siege-engine.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/autolabor.cpp b/plugins/autolabor.cpp index 09a756642..f28b1e343 100644 --- a/plugins/autolabor.cpp +++ b/plugins/autolabor.cpp @@ -1206,7 +1206,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out ) for (auto p = dwarfs[dwarf]->status.misc_traits.begin(); p < dwarfs[dwarf]->status.misc_traits.end(); p++) { - if ((*p)->id == misc_trait_type::Migrant || (*p)->id == misc_trait_type::OnBreak) + if ((*p)->id == misc_trait_type::Migrant /*|| (*p)->id == misc_trait_type::OnBreak*/) is_on_break = true; } diff --git a/plugins/dwarfmonitor.cpp b/plugins/dwarfmonitor.cpp index 471850025..c3f348367 100644 --- a/plugins/dwarfmonitor.cpp +++ b/plugins/dwarfmonitor.cpp @@ -1744,7 +1744,7 @@ static bool is_at_leisure(df::unit *unit) { for (auto p = unit->status.misc_traits.begin(); p < unit->status.misc_traits.end(); p++) { - if ((*p)->id == misc_trait_type::Migrant || (*p)->id == misc_trait_type::OnBreak) + if ((*p)->id == misc_trait_type::Migrant /*|| (*p)->id == misc_trait_type::OnBreak*/) return true; } diff --git a/plugins/search.cpp b/plugins/search.cpp index b43daa942..be7c78dbe 100644 --- a/plugins/search.cpp +++ b/plugins/search.cpp @@ -1122,7 +1122,7 @@ private: return ""; for (auto p = unit->status.misc_traits.begin(); p < unit->status.misc_traits.end(); p++) { - if ((*p)->id == misc_trait_type::Migrant || (*p)->id == misc_trait_type::OnBreak) + if ((*p)->id == misc_trait_type::Migrant /*|| (*p)->id == misc_trait_type::OnBreak*/) { int i = (*p)->value; return ".on break"; diff --git a/plugins/siege-engine.cpp b/plugins/siege-engine.cpp index 3df9edf29..7c89be714 100644 --- a/plugins/siege-engine.cpp +++ b/plugins/siege-engine.cpp @@ -1492,7 +1492,7 @@ static void releaseTiredWorker(EngineInfo *engine, df::job *job, df::unit *worke if (unit == worker || unit->job.current_job || !unit->status.labors[unit_labor::SIEGEOPERATE] || - !Units::isCitizen(unit) || Units::getMiscTrait(unit, misc_trait_type::OnBreak) || + !Units::isCitizen(unit) /*|| Units::getMiscTrait(unit, misc_trait_type::OnBreak)*/ || isTired(unit) || !Maps::canWalkBetween(job->pos, unit->pos)) continue; From 85a4fef1d80dafaaaf2ad8dc27778f37edb64114 Mon Sep 17 00:00:00 2001 From: Japa Mala Illo Date: Sun, 28 Oct 2018 10:22:55 -0500 Subject: [PATCH 037/109] Added unknowns to saved tree export. --- plugins/remotefortressreader/remotefortressreader.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index 96ea6b5eb..4828d5a02 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -487,6 +487,11 @@ command_result Dump_Trees(color_ostream &out, vector ¶meters) } output << endl; } + output << " " << treeInfo->unk1[z]; + output << " " << treeInfo->unk2[z]; + output << " " << treeInfo->unk3[z]; + output << " " << treeInfo->unk4[z]; + output << endl; } //... From 2445559c3056b13fb12bb7e8a30d3dfc64c07ab8 Mon Sep 17 00:00:00 2001 From: Japa Mala Illo Date: Sun, 28 Oct 2018 10:34:19 -0500 Subject: [PATCH 038/109] update XML --- library/xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/xml b/library/xml index 8f5955b08..559fbda06 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 8f5955b08c0dab7f2fd7d6432df054b82a3c4f4b +Subproject commit 559fbda0638e6c367b08314c19d31d13a98189b1 From 6aea842f1bbfe1e06f3ba8c84c0c0c2fa9aba8c7 Mon Sep 17 00:00:00 2001 From: Japa Mala Illo Date: Sun, 28 Oct 2018 10:45:32 -0500 Subject: [PATCH 039/109] Added tree info data to protos, not used yet. --- plugins/proto/RemoteFortressReader.proto | 25 ++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/plugins/proto/RemoteFortressReader.proto b/plugins/proto/RemoteFortressReader.proto index 108605aa7..26a01738e 100644 --- a/plugins/proto/RemoteFortressReader.proto +++ b/plugins/proto/RemoteFortressReader.proto @@ -328,6 +328,31 @@ message Item optional ArtImage image = 18; } +message PlantTile +{ + optional bool trunk = 1; + optional bool connection_east = 2; + optional bool connection_south = 3; + optional bool connection_west = 4; + optional bool connection_north = 5; + optional bool branches = 6; + optional bool twigs = 7; + optional TiletypeSpecial tile_type = 8; +} + +message TreeInfo +{ + optional Coord size = 1; + repeated PlantTile tiles = 2; +} + +message PlantInstance +{ + optional int32 plant_type = 1; + optional Coord pos = 2; + optional TreeInfo tree_info = 3; +} + message MapBlock { required int32 map_x = 1; From 67ce858772578476787e3a96dfffb2a1be3d8e5f Mon Sep 17 00:00:00 2001 From: Japa Mala Illo Date: Sun, 11 Nov 2018 16:21:15 -0600 Subject: [PATCH 040/109] Changed some debug stuff to use new variable names from the xmls --- plugins/remotefortressreader/remotefortressreader.cpp | 8 ++++---- plugins/stonesense | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index 4828d5a02..83856ba7d 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -487,10 +487,10 @@ command_result Dump_Trees(color_ostream &out, vector ¶meters) } output << endl; } - output << " " << treeInfo->unk1[z]; - output << " " << treeInfo->unk2[z]; - output << " " << treeInfo->unk3[z]; - output << " " << treeInfo->unk4[z]; + output << "extent_east: " << treeInfo->extent_east[z]; + output << "extent_south: " << treeInfo->extent_south[z]; + output << "extent_west: " << treeInfo->extent_west[z]; + output << "extent_north: " << treeInfo->extent_north[z]; output << endl; } diff --git a/plugins/stonesense b/plugins/stonesense index 4a1953f27..4a0f63e04 160000 --- a/plugins/stonesense +++ b/plugins/stonesense @@ -1 +1 @@ -Subproject commit 4a1953f27c6acd1ceeb2d5447613c106e708c26c +Subproject commit 4a0f63e044d02532c948d67780dfd128fbd6d043 From e5d14fe8c13960b2825d08d113db3510459b1970 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Sun, 2 Dec 2018 08:51:32 -0600 Subject: [PATCH 041/109] Remove VSCode junk --- .vscode/c_cpp_properties.json | 21 --------------------- .vscode/settings.json | 6 ------ 2 files changed, 27 deletions(-) delete mode 100644 .vscode/c_cpp_properties.json delete mode 100644 .vscode/settings.json diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json deleted file mode 100644 index 7d2c32d7d..000000000 --- a/.vscode/c_cpp_properties.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "configurations": [ - { - "name": "Win32", - "includePath": [ - "${workspaceFolder}/**" - ], - "defines": [ - "_DEBUG", - "UNICODE", - "_UNICODE" - ], - "windowsSdkVersion": "10.0.17134.0", - "compilerPath": "C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.15.26726/bin/Hostx64/x64/cl.exe", - "cStandard": "c11", - "cppStandard": "c++17", - "intelliSenseMode": "msvc-x64" - } - ], - "version": 4 -} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index e0ac3c845..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "files.associations": { - "vector": "cpp", - "fstream": "cpp" - } -} \ No newline at end of file From f8f5615691f17dcc771e43b88b24b2c5bc389873 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Sun, 2 Dec 2018 08:52:32 -0600 Subject: [PATCH 042/109] Update structures. --- library/xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/xml b/library/xml index 559fbda06..4ba769450 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 559fbda0638e6c367b08314c19d31d13a98189b1 +Subproject commit 4ba769450e3b238cae8d04ef7889cefd1df63bdc From b43ecf5fb1f9ea69088ac55ff95cba9b8667a930 Mon Sep 17 00:00:00 2001 From: Warmist Date: Thu, 6 Dec 2018 15:20:33 +0200 Subject: [PATCH 043/109] Update Lua API.rst Remove trailing whitespace --- docs/Lua API.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Lua API.rst b/docs/Lua API.rst index a5894a3a5..a4130096b 100644 --- a/docs/Lua API.rst +++ b/docs/Lua API.rst @@ -3926,7 +3926,7 @@ A class with all the tcp functionality. map-render ========== -A way to ask df to render a slice of map. This uses native df rendering function so it's highly dependant on +A way to ask df to render a slice of map. This uses native df rendering function so it's highly dependant on df settings (e.g. used tileset, colors, if using graphics or not and so on...) Functions From b1f9486edde856f43542259c860c9861e57f33fe Mon Sep 17 00:00:00 2001 From: Warmist Date: Thu, 6 Dec 2018 15:21:19 +0200 Subject: [PATCH 044/109] Update map-render.cpp Remove tabs --- plugins/map-render.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/map-render.cpp b/plugins/map-render.cpp index d299c237c..f89d8ab4e 100644 --- a/plugins/map-render.cpp +++ b/plugins/map-render.cpp @@ -54,9 +54,9 @@ static int render_map_rect(lua_State* L) int z = luaL_checkint(L, 3); int w = luaL_checkint(L, 4); int h = luaL_checkint(L, 5); - uint8_t *s = df::global::gps->screen; + uint8_t *s = df::global::gps->screen; //backup state - //TODO: figure out if we can replace screen with other pointer. That way it could be a bit more tidy + //TODO: figure out if we can replace screen with other pointer. That way it could be a bit more tidy int32_t win_h = df::global::gps->dimy; int32_t was_x = *window_x; int32_t was_y = *window_y; @@ -70,7 +70,7 @@ static int render_map_rect(lua_State* L) *window_z = z; //force full redraw df::global::gps->force_full_display_count = 1; - //this modifies screen so it REALLY wants to redraw stuff + //this modifies screen so it REALLY wants to redraw stuff for (int ty = 0; ty < h; ty++) for (int tx = 0; tx < w; tx++) { From 95d3086fe62db7b2094b45e7a888754c0d39c90d Mon Sep 17 00:00:00 2001 From: JapaMala Date: Wed, 26 Dec 2018 00:05:17 -0600 Subject: [PATCH 045/109] Remove tabs --- plugins/remotefortressreader/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/remotefortressreader/CMakeLists.txt b/plugins/remotefortressreader/CMakeLists.txt index 954dbcbbf..ee6a6210b 100644 --- a/plugins/remotefortressreader/CMakeLists.txt +++ b/plugins/remotefortressreader/CMakeLists.txt @@ -4,14 +4,14 @@ SET(PROJECT_SRCS remotefortressreader.cpp adventure_control.cpp building_reader.cpp - dwarf_control.cpp + dwarf_control.cpp item_reader.cpp ) # A list of headers SET(PROJECT_HDRS adventure_control.h building_reader.h - dwarf_control.h + dwarf_control.h item_reader.h df_version_int.h ) From 701ac66f8e361f0166c4317168937f6da4366857 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Wed, 26 Dec 2018 00:06:49 -0600 Subject: [PATCH 046/109] Update DF version define. (mainly used to be able to keep backwards compatibility) --- plugins/remotefortressreader/df_version_int.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/remotefortressreader/df_version_int.h b/plugins/remotefortressreader/df_version_int.h index 5c89d88c4..d83fa7548 100644 --- a/plugins/remotefortressreader/df_version_int.h +++ b/plugins/remotefortressreader/df_version_int.h @@ -1,2 +1,2 @@ #pragma once -#define DF_VERSION_INT 44010 +#define DF_VERSION_INT 44012 From 4b7e0d3c56f37981373ea988f24a2cd04ea604ae Mon Sep 17 00:00:00 2001 From: JapaMala Date: Wed, 26 Dec 2018 00:11:08 -0600 Subject: [PATCH 047/109] Convert unicode to escaped characters, and some formatting niceness --- .../remotefortressreader.cpp | 274 +++++++++--------- 1 file changed, 137 insertions(+), 137 deletions(-) diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index 83856ba7d..45f6a1846 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -258,19 +258,19 @@ command_result dump_bp_mods(color_ostream &out, vector & parameters) command_result Dump_Trees(color_ostream &out, vector ¶meters) { char filename[255]; - for(int columnIndex = 0; columnIndex < world->map.map_block_columns.size(); columnIndex++) + for (int columnIndex = 0; columnIndex < world->map.map_block_columns.size(); columnIndex++) { auto column = world->map.map_block_columns[columnIndex]; - if(!column) + if (!column) continue; - if(column->plants.size() == 0) + if (column->plants.size() == 0) continue; - for(int plantIndex = 0; plantIndex < column->plants.size(); plantIndex++) + for (int plantIndex = 0; plantIndex < column->plants.size(); plantIndex++) { auto plant = column->plants[plantIndex]; - if(!plant) + if (!plant) continue; - if(!plant->tree_info) + if (!plant->tree_info) continue; sprintf(filename, "plant_%03d,%03d,%03d.txt", plant->pos.z, plant->pos.y, plant->pos.x); remove(filename); @@ -280,11 +280,11 @@ command_result Dump_Trees(color_ostream &out, vector ¶meters) output << "Material: " << plant->material << endl; output << "Grow Counter: " << plant->grow_counter << endl; output << "Damage Flags: "; - if(plant->damage_flags.bits.is_burning) + if (plant->damage_flags.bits.is_burning) output << "is_burning, "; - if(plant->damage_flags.bits.is_drowning) + if (plant->damage_flags.bits.is_drowning) output << "is_drowning, "; - if(plant->damage_flags.bits.anon_1) + if (plant->damage_flags.bits.anon_1) output << "anon_1, "; output << endl; output << "HP: " << plant->hitpoints << endl; @@ -295,192 +295,192 @@ command_result Dump_Trees(color_ostream &out, vector ¶meters) output << "Dim X: " << treeInfo->dim_x << endl; output << "Dim Y: " << treeInfo->dim_y << endl; output << "Dim Z: " << treeInfo->body_height << endl; - for(int z = 0; z < treeInfo->body_height; z++) + for (int z = 0; z < treeInfo->body_height; z++) { - for(int y = -1; y < treeInfo->dim_y; y++) + for (int y = -1; y < treeInfo->dim_y; y++) { - for(int x = -1; x < treeInfo->dim_x; x++) + for (int x = -1; x < treeInfo->dim_x; x++) { - if(x < 0) + if (x < 0) { - if(y < 0) + if (y < 0) { output << " "; continue; } - output << y%9; + output << y % 9; continue; } - if(y < 0) + if (y < 0) { - output << x%9; + output << x % 9; continue; } auto tile = treeInfo->body[z][x + treeInfo->dim_x*y]; - if(tile.bits.blocked) + if (tile.bits.blocked) output << "x"; - else if(tile.bits.twigs) - output << "░"; - else if(tile.bits.branches) + else if (tile.bits.twigs) + output << "\u2591"; + else if (tile.bits.branches) { - if(tile.bits.connection_east)// East Connection + if (tile.bits.connection_east)// East Connection { - if(tile.bits.connection_south) // South Connection + if (tile.bits.connection_south) // South Connection { - if(tile.bits.connection_west) // West Connection + if (tile.bits.connection_west) // West Connection { - if(tile.bits.connection_north) // North Connection - { - if(tile.bits.trunk) - output << "╬"; - else - output << "┼"; - } + if (tile.bits.connection_north) // North Connection + { + if (tile.bits.trunk) + output << "\u256c"; + else + output << "\u253c"; + } else - { - if(tile.bits.trunk) - output << "╦"; - else - output << "┬"; - } + { + if (tile.bits.trunk) + output << "\u2566"; + else + output << "\u252c"; + } } else { - if(tile.bits.connection_north) // North Connection - { - if(tile.bits.trunk) - output << "╠"; - else - output << "├"; - } + if (tile.bits.connection_north) // North Connection + { + if (tile.bits.trunk) + output << "\u2560"; + else + output << "\u251c"; + } else - { - if(tile.bits.trunk) - output << "╔"; - else - output << "┌"; - } + { + if (tile.bits.trunk) + output << "\u2554"; + else + output << "\u250c"; + } } } else { - if(tile.bits.connection_west) // West Connection + if (tile.bits.connection_west) // West Connection { - if(tile.bits.connection_north) // North Connection - { - if(tile.bits.trunk) - output << "╩"; - else - output << "┴"; - } + if (tile.bits.connection_north) // North Connection + { + if (tile.bits.trunk) + output << "\u2569"; + else + output << "\u2534"; + } else - { - if(tile.bits.trunk) - output << "═"; - else - output << "─"; - } + { + if (tile.bits.trunk) + output << "\u2550"; + else + output << "\u2500"; + } } else { - if(tile.bits.connection_north) // North Connection - { - if(tile.bits.trunk) - output << "╚"; - else - output << "└"; - } + if (tile.bits.connection_north) // North Connection + { + if (tile.bits.trunk) + output << "\u255a"; + else + output << "\u2514"; + } else - { - if(tile.bits.trunk) - output << "╞"; - else - output << ">"; - } + { + if (tile.bits.trunk) + output << "\u255e"; + else + output << ">"; + } } } } else { - if(tile.bits.connection_south) // South Connection + if (tile.bits.connection_south) // South Connection { - if(tile.bits.connection_west) // West Connection + if (tile.bits.connection_west) // West Connection { - if(tile.bits.connection_north) // North Connection - { - if(tile.bits.trunk) - output << "╣"; - else - output << "┤"; - } + if (tile.bits.connection_north) // North Connection + { + if (tile.bits.trunk) + output << "\u2563"; + else + output << "\u2524"; + } else - { - if(tile.bits.trunk) - output << "╗"; - else - output << "┐"; - } + { + if (tile.bits.trunk) + output << "\u2557"; + else + output << "\u2510"; + } } else { - if(tile.bits.connection_north) // North Connection - { - if(tile.bits.trunk) - output << "║"; - else - output << "│"; - } + if (tile.bits.connection_north) // North Connection + { + if (tile.bits.trunk) + output << "\u2551"; + else + output << "\u2502"; + } else - { - if(tile.bits.trunk) - output << "╥"; - else - output << "v"; - } + { + if (tile.bits.trunk) + output << "\u2565"; + else + output << "v"; + } } } else { - if(tile.bits.connection_west) // West Connection + if (tile.bits.connection_west) // West Connection { - if(tile.bits.connection_north) // North Connection - { - if(tile.bits.trunk) - output << "╝"; - else - output << "┘"; - } + if (tile.bits.connection_north) // North Connection + { + if (tile.bits.trunk) + output << "\u255d"; + else + output << "\u2518"; + } else - { - if(tile.bits.trunk) - output << "╡"; - else - output << "<"; - } + { + if (tile.bits.trunk) + output << "\u2561"; + else + output << "<"; + } } else { - if(tile.bits.connection_north) // North Connection - { - if(tile.bits.trunk) - output << "╨"; - else - output << "^"; - } + if (tile.bits.connection_north) // North Connection + { + if (tile.bits.trunk) + output << "\u2568"; + else + output << "^"; + } else - { - if(tile.bits.trunk) - output << "o"; - else - output << "▒"; - } + { + if (tile.bits.trunk) + output << "o"; + else + output << "\u2592"; + } } } } } - else if(tile.bits.trunk) + else if (tile.bits.trunk) output << "O"; - else if(tile.whole > 0) + else if (tile.whole > 0) output << +tile.whole; else output << " "; @@ -519,13 +519,13 @@ DFhackCExport command_result plugin_init(color_ostream &out, std::vector flows.size() > 0) nonAir = true; if (nonAir || firstBlock) From d73124ebf7896cdbd96619aa108e05fda57a465a Mon Sep 17 00:00:00 2001 From: JapaMala Date: Wed, 26 Dec 2018 00:14:38 -0600 Subject: [PATCH 048/109] Use FOR_ENUM_ITEMS instead of the silly for loop I had. --- plugins/remotefortressreader/remotefortressreader.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index 45f6a1846..c1bc77829 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -3078,10 +3078,9 @@ static command_result GetPartialCreatureRaws(color_ostream &stream, const ListRe CopyMat(send_tissue->mutable_material(), orig_tissue->mat_type, orig_tissue->mat_index); } - - for (int i = 0; i <= ENUM_LAST_ITEM(creature_raw_flags); i++) + FOR_ENUM_ITEMS(creature_raw_flags, flag) { - send_creature->add_flags(orig_creature->flags.is_set((creature_raw_flags::creature_raw_flags)i)); + send_creature->add_flags(orig_creature->flags.is_set(flag)); } } From 09e7fd62bbb5947b2007122b3ed1f7505634ab23 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Wed, 26 Dec 2018 00:22:25 -0600 Subject: [PATCH 049/109] Updated changelog. --- docs/changelog.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/changelog.txt b/docs/changelog.txt index 901ae8b67..6a0951ebb 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -51,6 +51,9 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: ## Misc Improvements - `devel/export-dt-ini`: added viewscreen offsets for DT 40.1.2 - `labormanager`: now takes nature value into account when assigning jobs +- `RemoteFortressReader`: + - added basic framework for controlling and reading the menus in DF, currently only supports the building menu. + - added support for reading item raws. ## Internals - Linux/macOS: changed recommended build backend from Make to Ninja (Make builds will be significantly slower now) @@ -72,6 +75,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: - ``incident_sub6_performance``: made performance_event an enum - ``incident_sub6_performance.participants``: named performance_event and role_index - ``incident_sub6_performance``: named poetic_form_id, musical_form_id, and dance_form_id +- ``treeInfo``: added correct flags for branch direction ================================================================================ From bacd3e6790a64d89949d46c84e2726c4fee2ad2e Mon Sep 17 00:00:00 2001 From: JapaMala Date: Wed, 26 Dec 2018 00:35:24 -0600 Subject: [PATCH 050/109] Revert jsoncpp update that wasdone by mistake. --- depends/jsoncpp-sub | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/depends/jsoncpp-sub b/depends/jsoncpp-sub index 2baad4923..ddabf50f7 160000 --- a/depends/jsoncpp-sub +++ b/depends/jsoncpp-sub @@ -1 +1 @@ -Subproject commit 2baad4923e6d9a7e09982cfa4b1c5fd0b67ebd87 +Subproject commit ddabf50f72cf369bf652a95c4d9fe31a1865a781 From e6f7900c5298ed9689e0e34cec983694b58bfbb1 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Wed, 26 Dec 2018 00:39:16 -0600 Subject: [PATCH 051/109] Force UTF-8 string literals. --- .../remotefortressreader.cpp | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index c1bc77829..4537a6282 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -320,7 +320,7 @@ command_result Dump_Trees(color_ostream &out, vector ¶meters) if (tile.bits.blocked) output << "x"; else if (tile.bits.twigs) - output << "\u2591"; + output << u8"\u2591"; else if (tile.bits.branches) { if (tile.bits.connection_east)// East Connection @@ -332,16 +332,16 @@ command_result Dump_Trees(color_ostream &out, vector ¶meters) if (tile.bits.connection_north) // North Connection { if (tile.bits.trunk) - output << "\u256c"; + output << u8"\u256c"; else - output << "\u253c"; + output << u8"\u253c"; } else { if (tile.bits.trunk) - output << "\u2566"; + output << u8"\u2566"; else - output << "\u252c"; + output << u8"\u252c"; } } else @@ -349,16 +349,16 @@ command_result Dump_Trees(color_ostream &out, vector ¶meters) if (tile.bits.connection_north) // North Connection { if (tile.bits.trunk) - output << "\u2560"; + output << u8"\u2560"; else - output << "\u251c"; + output << u8"\u251c"; } else { if (tile.bits.trunk) - output << "\u2554"; + output << u8"\u2554"; else - output << "\u250c"; + output << u8"\u250c"; } } } @@ -369,16 +369,16 @@ command_result Dump_Trees(color_ostream &out, vector ¶meters) if (tile.bits.connection_north) // North Connection { if (tile.bits.trunk) - output << "\u2569"; + output << u8"\u2569"; else - output << "\u2534"; + output << u8"\u2534"; } else { if (tile.bits.trunk) - output << "\u2550"; + output << u8"\u2550"; else - output << "\u2500"; + output << u8"\u2500"; } } else @@ -386,14 +386,14 @@ command_result Dump_Trees(color_ostream &out, vector ¶meters) if (tile.bits.connection_north) // North Connection { if (tile.bits.trunk) - output << "\u255a"; + output << u8"\u255a"; else - output << "\u2514"; + output << u8"\u2514"; } else { if (tile.bits.trunk) - output << "\u255e"; + output << u8"\u255e"; else output << ">"; } @@ -409,16 +409,16 @@ command_result Dump_Trees(color_ostream &out, vector ¶meters) if (tile.bits.connection_north) // North Connection { if (tile.bits.trunk) - output << "\u2563"; + output << u8"\u2563"; else - output << "\u2524"; + output << u8"\u2524"; } else { if (tile.bits.trunk) - output << "\u2557"; + output << u8"\u2557"; else - output << "\u2510"; + output << u8"\u2510"; } } else @@ -426,14 +426,14 @@ command_result Dump_Trees(color_ostream &out, vector ¶meters) if (tile.bits.connection_north) // North Connection { if (tile.bits.trunk) - output << "\u2551"; + output << u8"\u2551"; else - output << "\u2502"; + output << u8"\u2502"; } else { if (tile.bits.trunk) - output << "\u2565"; + output << u8"\u2565"; else output << "v"; } @@ -446,14 +446,14 @@ command_result Dump_Trees(color_ostream &out, vector ¶meters) if (tile.bits.connection_north) // North Connection { if (tile.bits.trunk) - output << "\u255d"; + output << u8"\u255d"; else - output << "\u2518"; + output << u8"\u2518"; } else { if (tile.bits.trunk) - output << "\u2561"; + output << u8"\u2561"; else output << "<"; } @@ -463,7 +463,7 @@ command_result Dump_Trees(color_ostream &out, vector ¶meters) if (tile.bits.connection_north) // North Connection { if (tile.bits.trunk) - output << "\u2568"; + output << u8"\u2568"; else output << "^"; } @@ -472,7 +472,7 @@ command_result Dump_Trees(color_ostream &out, vector ¶meters) if (tile.bits.trunk) output << "o"; else - output << "\u2592"; + output << u8"\u2592"; } } } From 9d9b6b377b58724f8b07f02a269aec3b3e387273 Mon Sep 17 00:00:00 2001 From: Japa Date: Wed, 26 Dec 2018 00:42:12 -0600 Subject: [PATCH 052/109] Update changelog.txt --- docs/changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog.txt b/docs/changelog.txt index 8de2aee88..2f8375078 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -57,6 +57,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: - `RemoteFortressReader`: - added basic framework for controlling and reading the menus in DF, currently only supports the building menu. - added support for reading item raws. + - added a debug function to dump a file of every tree in the currently loaded map. ## Internals - Linux/macOS: changed recommended build backend from Make to Ninja (Make builds will be significantly slower now) From 84578d705249b207621a5475eebc92fe72eaacfc Mon Sep 17 00:00:00 2001 From: JapaMala Date: Wed, 26 Dec 2018 01:04:31 -0600 Subject: [PATCH 053/109] Remove both debug dump functions. They aren't needed anymore. --- docs/changelog.txt | 2 +- .../remotefortressreader.cpp | 307 ------------------ 2 files changed, 1 insertion(+), 308 deletions(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index 2f8375078..830674f59 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -57,7 +57,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: - `RemoteFortressReader`: - added basic framework for controlling and reading the menus in DF, currently only supports the building menu. - added support for reading item raws. - - added a debug function to dump a file of every tree in the currently loaded map. + - removed a debug function that's not needed anymore. ## Internals - Linux/macOS: changed recommended build backend from Make to Ninja (Make builds will be significantly slower now) diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index 4537a6282..3b62a7783 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -207,300 +207,6 @@ command_result loadArtImageChunk(color_ostream &out, vector & parameter return CR_OK; } -command_result dump_bp_mods(color_ostream &out, vector & parameters) -{ - remove("bp_appearance_mods.csv"); - ofstream output; - output.open("bp_appearance_mods.csv"); - - output << "Race Index;Race;Caste;Bodypart Token;Bodypart Name;Tissue Layer;Modifier Type;Range\n"; - - for (size_t creatureIndex = 0; creatureIndex < world->raws.creatures.all.size(); creatureIndex++) - { - auto creatureRaw = world->raws.creatures.all[creatureIndex]; - for (size_t casteIndex = 0; casteIndex < creatureRaw->caste.size(); casteIndex++) - { - df::caste_raw *casteRaw = creatureRaw->caste[casteIndex]; - for (size_t partIndex = 0; partIndex < casteRaw->bp_appearance.part_idx.size(); partIndex++) - { - output << creatureIndex << ";"; - output << creatureRaw->creature_id << ";"; - output << casteRaw->caste_id << ";"; - output << casteRaw->body_info.body_parts[casteRaw->bp_appearance.part_idx[partIndex]]->token << ";"; - output << casteRaw->body_info.body_parts[casteRaw->bp_appearance.part_idx[partIndex]]->name_singular[0]->c_str() << ";"; - int layer = casteRaw->bp_appearance.layer_idx[partIndex]; - if (layer < 0) - output << "N/A;"; - else - output << casteRaw->body_info.body_parts[casteRaw->bp_appearance.part_idx[partIndex]]->layers[layer]->layer_name << ";"; - output << ENUM_KEY_STR(appearance_modifier_type, casteRaw->bp_appearance.modifiers[casteRaw->bp_appearance.modifier_idx[partIndex]]->type) << ";"; - auto appMod = casteRaw->bp_appearance.modifiers[casteRaw->bp_appearance.modifier_idx[partIndex]]; -#if DF_VERSION_INT > 34011 - if (appMod->growth_rate > 0) - { - output << appMod->growth_min << " - " << appMod->growth_max << "\n"; - } - else -#endif - { - output << casteRaw->bp_appearance.modifiers[casteRaw->bp_appearance.modifier_idx[partIndex]]->ranges[0] << " - "; - output << casteRaw->bp_appearance.modifiers[casteRaw->bp_appearance.modifier_idx[partIndex]]->ranges[6] << "\n"; - } - } - } - } - - output.close(); - - return CR_OK; -} - -command_result Dump_Trees(color_ostream &out, vector ¶meters) -{ - char filename[255]; - for (int columnIndex = 0; columnIndex < world->map.map_block_columns.size(); columnIndex++) - { - auto column = world->map.map_block_columns[columnIndex]; - if (!column) - continue; - if (column->plants.size() == 0) - continue; - for (int plantIndex = 0; plantIndex < column->plants.size(); plantIndex++) - { - auto plant = column->plants[plantIndex]; - if (!plant) - continue; - if (!plant->tree_info) - continue; - sprintf(filename, "plant_%03d,%03d,%03d.txt", plant->pos.z, plant->pos.y, plant->pos.x); - remove(filename); - ofstream output; - output.open(filename); - output << "Pos: " << plant->pos.x << ", " << plant->pos.y << ", " << plant->pos.z << endl; - output << "Material: " << plant->material << endl; - output << "Grow Counter: " << plant->grow_counter << endl; - output << "Damage Flags: "; - if (plant->damage_flags.bits.is_burning) - output << "is_burning, "; - if (plant->damage_flags.bits.is_drowning) - output << "is_drowning, "; - if (plant->damage_flags.bits.anon_1) - output << "anon_1, "; - output << endl; - output << "HP: " << plant->hitpoints << endl; - output << "Update Order: " << plant->update_order << endl; - output << "Site ID: " << plant->site_id << endl; - output << "SRB ID: " << plant->srb_id << endl; - auto treeInfo = plant->tree_info; - output << "Dim X: " << treeInfo->dim_x << endl; - output << "Dim Y: " << treeInfo->dim_y << endl; - output << "Dim Z: " << treeInfo->body_height << endl; - for (int z = 0; z < treeInfo->body_height; z++) - { - for (int y = -1; y < treeInfo->dim_y; y++) - { - for (int x = -1; x < treeInfo->dim_x; x++) - { - if (x < 0) - { - if (y < 0) - { - output << " "; - continue; - } - output << y % 9; - continue; - } - if (y < 0) - { - output << x % 9; - continue; - } - auto tile = treeInfo->body[z][x + treeInfo->dim_x*y]; - if (tile.bits.blocked) - output << "x"; - else if (tile.bits.twigs) - output << u8"\u2591"; - else if (tile.bits.branches) - { - if (tile.bits.connection_east)// East Connection - { - if (tile.bits.connection_south) // South Connection - { - if (tile.bits.connection_west) // West Connection - { - if (tile.bits.connection_north) // North Connection - { - if (tile.bits.trunk) - output << u8"\u256c"; - else - output << u8"\u253c"; - } - else - { - if (tile.bits.trunk) - output << u8"\u2566"; - else - output << u8"\u252c"; - } - } - else - { - if (tile.bits.connection_north) // North Connection - { - if (tile.bits.trunk) - output << u8"\u2560"; - else - output << u8"\u251c"; - } - else - { - if (tile.bits.trunk) - output << u8"\u2554"; - else - output << u8"\u250c"; - } - } - } - else - { - if (tile.bits.connection_west) // West Connection - { - if (tile.bits.connection_north) // North Connection - { - if (tile.bits.trunk) - output << u8"\u2569"; - else - output << u8"\u2534"; - } - else - { - if (tile.bits.trunk) - output << u8"\u2550"; - else - output << u8"\u2500"; - } - } - else - { - if (tile.bits.connection_north) // North Connection - { - if (tile.bits.trunk) - output << u8"\u255a"; - else - output << u8"\u2514"; - } - else - { - if (tile.bits.trunk) - output << u8"\u255e"; - else - output << ">"; - } - } - } - } - else - { - if (tile.bits.connection_south) // South Connection - { - if (tile.bits.connection_west) // West Connection - { - if (tile.bits.connection_north) // North Connection - { - if (tile.bits.trunk) - output << u8"\u2563"; - else - output << u8"\u2524"; - } - else - { - if (tile.bits.trunk) - output << u8"\u2557"; - else - output << u8"\u2510"; - } - } - else - { - if (tile.bits.connection_north) // North Connection - { - if (tile.bits.trunk) - output << u8"\u2551"; - else - output << u8"\u2502"; - } - else - { - if (tile.bits.trunk) - output << u8"\u2565"; - else - output << "v"; - } - } - } - else - { - if (tile.bits.connection_west) // West Connection - { - if (tile.bits.connection_north) // North Connection - { - if (tile.bits.trunk) - output << u8"\u255d"; - else - output << u8"\u2518"; - } - else - { - if (tile.bits.trunk) - output << u8"\u2561"; - else - output << "<"; - } - } - else - { - if (tile.bits.connection_north) // North Connection - { - if (tile.bits.trunk) - output << u8"\u2568"; - else - output << "^"; - } - else - { - if (tile.bits.trunk) - output << "o"; - else - output << u8"\u2592"; - } - } - } - } - } - else if (tile.bits.trunk) - output << "O"; - else if (tile.whole > 0) - output << +tile.whole; - else - output << " "; - } - output << endl; - } - output << "extent_east: " << treeInfo->extent_east[z]; - output << "extent_south: " << treeInfo->extent_south[z]; - output << "extent_west: " << treeInfo->extent_west[z]; - output << "extent_north: " << treeInfo->extent_north[z]; - - output << endl; - } - //... - output.close(); - } - } - return CR_OK; -} - command_result RemoteFortressReader_version(color_ostream &out, vector ¶meters) { out.print(RFR_VERSION); @@ -512,19 +218,6 @@ DFHACK_PLUGIN_IS_ENABLED(enableUpdates); // Mandatory init function. If you have some global state, create it here. DFhackCExport command_result plugin_init(color_ostream &out, std::vector &commands) { - //// Fill the command list with your commands. - commands.push_back(PluginCommand( - "dump-bp-mods", "Dump bodypart mods for debugging", - dump_bp_mods, false, /* true means that the command can't be used from non-interactive user interface */ - // Extended help string. Used by CR_WRONG_USAGE and the help command: - " Saves every possible body part appearance modifier to bp_appearance_mods.csv\n" - )); - commands.push_back(PluginCommand( - "dump-trees", "Dump trees for debugging", - Dump_Trees, false, /* true means that the command can't be used from non-interactive user interface */ - // Extended help string. Used by CR_WRONG_USAGE and the help command: - " saves each tree on the map to a separate text file.\n" - )); commands.push_back(PluginCommand("RemoteFortressReader_version", "List the loaded RemoteFortressReader version", RemoteFortressReader_version, false, "This is used for plugin version checking.")); commands.push_back(PluginCommand( "load-art-image-chunk", From 368d70c2d78350161dccf92f5ae9ebabc18a93a5 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Wed, 26 Dec 2018 01:10:51 -0600 Subject: [PATCH 054/109] Use VIRTUAL_CAST_VAR correctly. --- plugins/remotefortressreader/item_reader.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/plugins/remotefortressreader/item_reader.cpp b/plugins/remotefortressreader/item_reader.cpp index 71867767b..620e06310 100644 --- a/plugins/remotefortressreader/item_reader.cpp +++ b/plugins/remotefortressreader/item_reader.cpp @@ -674,8 +674,7 @@ DFHack::command_result GetItemList(DFHack::color_ostream &stream, const DFHack:: break; case df::enums::item_type::ARMOR: { - VIRTUAL_CAST_VAR(armor, df::itemdef_armorst, item); - if (armor) + if (VIRTUAL_CAST_VAR(armor, df::itemdef_armorst, item)) { mat_def->set_up_step(armor->ubstep); mat_def->set_down_step(armor->lbstep); @@ -685,8 +684,7 @@ DFHack::command_result GetItemList(DFHack::color_ostream &stream, const DFHack:: break; case df::enums::item_type::SHOES: { - VIRTUAL_CAST_VAR(armor, df::itemdef_shoesst, item); - if (armor) + if (VIRTUAL_CAST_VAR(armor, df::itemdef_shoesst, item)) { mat_def->set_up_step(armor->upstep); mat_def->set_down_step(10000); @@ -696,8 +694,7 @@ DFHack::command_result GetItemList(DFHack::color_ostream &stream, const DFHack:: break; case df::enums::item_type::SHIELD: { - VIRTUAL_CAST_VAR(armor, df::itemdef_shieldst, item); - if (armor) + if (VIRTUAL_CAST_VAR(armor, df::itemdef_shieldst, item)) { mat_def->set_up_step(armor->upstep); mat_def->set_down_step(10000); @@ -706,8 +703,7 @@ DFHack::command_result GetItemList(DFHack::color_ostream &stream, const DFHack:: break; case df::enums::item_type::HELM: { - VIRTUAL_CAST_VAR(armor, df::itemdef_helmst, item); - if (armor) + if (VIRTUAL_CAST_VAR(armor, df::itemdef_helmst, item)) { mat_def->set_layer((ArmorLayer)armor->props.layer); } @@ -715,8 +711,7 @@ DFHack::command_result GetItemList(DFHack::color_ostream &stream, const DFHack:: break; case df::enums::item_type::GLOVES: { - VIRTUAL_CAST_VAR(armor, df::itemdef_glovesst, item); - if (armor) + if (VIRTUAL_CAST_VAR(armor, df::itemdef_glovesst, item)) { mat_def->set_up_step(armor->upstep); mat_def->set_down_step(10000); @@ -726,8 +721,7 @@ DFHack::command_result GetItemList(DFHack::color_ostream &stream, const DFHack:: break; case df::enums::item_type::PANTS: { - VIRTUAL_CAST_VAR(armor, df::itemdef_pantsst, item); - if (armor) + if (VIRTUAL_CAST_VAR(armor, df::itemdef_pantsst, item)) { mat_def->set_down_step(armor->lbstep); mat_def->set_layer((ArmorLayer)armor->props.layer); From 26934e6185a71ad708c9960c599e53d8f8bae833 Mon Sep 17 00:00:00 2001 From: Lethosor Date: Fri, 28 Dec 2018 15:22:34 -0500 Subject: [PATCH 055/109] Fix typo in changelog --- docs/changelog.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index bf16081ca..1819301aa 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -37,7 +37,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: ================================================================================ # Future -## Mic Improvements +## Misc Improvements - `RemoteFortressReader`: - added basic framework for controlling and reading the menus in DF, currently only supports the building menu. - added support for reading item raws. From f127645799b22f67449e6312a4a0e0616cf2057c Mon Sep 17 00:00:00 2001 From: Golias Date: Sat, 9 Feb 2019 06:36:53 -0500 Subject: [PATCH 056/109] Added command to install dependencies for Fedora (Linux) --- docs/Compile.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/Compile.rst b/docs/Compile.rst index 30fab6154..8c2a56626 100644 --- a/docs/Compile.rst +++ b/docs/Compile.rst @@ -158,6 +158,10 @@ Here are some package install commands for various platforms: apt-get install gcc cmake ninja-build git zlib1g-dev libsdl1.2-dev libxml-libxml-perl libxml-libxslt-perl +* On Fedora:: + + yum install gcc-c++ cmake ninja-build git zlib-devel SDL-devel perl-core perl-XML-LibXML perl-XML-LibXSLT ruby + * Debian and derived distros should have similar requirements to Ubuntu. From eeef058684c42fe62ef079124d30ad796c46c543 Mon Sep 17 00:00:00 2001 From: Golias Date: Sat, 9 Feb 2019 06:40:47 -0500 Subject: [PATCH 057/109] Improved .gitignore. Added all files generated in build with ninja, so that the rep remains clean after a complete build + install. --- .gitignore | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitignore b/.gitignore index 6a447a40e..0a614b082 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,10 @@ build/install_manifest.txt build/_CPack_Packages build/dfhack-*.zip build/dfhack-*.bz2 +build/*ninja* +build/compile_commands.json +build/dfhack_setarch.txt +build/ImportExecutables.cmake # Python binding binaries *.pyc @@ -58,5 +62,8 @@ tags /build/win32/DF_PATH.txt /.vs +# CLion +.idea + # custom plugins /plugins/CMakeLists.custom.txt From 064b6959e4a4054c051fd58faa47e401592a6b5b Mon Sep 17 00:00:00 2001 From: JapaMala Date: Sun, 17 Mar 2019 18:05:12 -0500 Subject: [PATCH 058/109] Fixed a crash when a unit has a move action queued, but the path is zero length --- plugins/remotefortressreader/remotefortressreader.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index 3b62a7783..91ebc0d55 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -1785,9 +1785,12 @@ static command_result GetUnitListInside(color_ostream &stream, const BlockReques switch (action->type) { case unit_action_type::Move: - send_unit->set_subpos_x(lerp(0, unit->path.path.x[0] - unit->pos.x, (float)(action->data.move.timer_init - action->data.move.timer) / action->data.move.timer_init)); - send_unit->set_subpos_y(lerp(0, unit->path.path.y[0] - unit->pos.y, (float)(action->data.move.timer_init - action->data.move.timer) / action->data.move.timer_init)); - send_unit->set_subpos_z(lerp(0, unit->path.path.z[0] - unit->pos.z, (float)(action->data.move.timer_init - action->data.move.timer) / action->data.move.timer_init)); + if (unit->path.path.x.size() > 0) + { + send_unit->set_subpos_x(lerp(0, unit->path.path.x[0] - unit->pos.x, (float)(action->data.move.timer_init - action->data.move.timer) / action->data.move.timer_init)); + send_unit->set_subpos_y(lerp(0, unit->path.path.y[0] - unit->pos.y, (float)(action->data.move.timer_init - action->data.move.timer) / action->data.move.timer_init)); + send_unit->set_subpos_z(lerp(0, unit->path.path.z[0] - unit->pos.z, (float)(action->data.move.timer_init - action->data.move.timer) / action->data.move.timer_init)); + } break; default: break; From 571ce0f616a375d300db734ddff430b83dcfed78 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Fri, 22 Mar 2019 22:52:59 -0500 Subject: [PATCH 059/109] Repport if the game is not safe to interact with, namely while saving or loading the game. --- .../remotefortressreader.cpp | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index 91ebc0d55..db5778b9d 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -93,6 +93,8 @@ #include "df/unit.h" #include "df/unit_inventory_item.h" #include "df/viewscreen_choose_start_sitest.h" +#include "df/viewscreen_loadgamest.h" +#include "df/viewscreen_savegamest.h" #include "df/vehicle.h" #include "df/world.h" #include "df/world_data.h" @@ -166,7 +168,7 @@ static command_result GetPauseState(color_ostream & stream, const EmptyMessage * static command_result GetVersionInfo(color_ostream & stream, const EmptyMessage * in, RemoteFortressReader::VersionInfo * out); static command_result GetReports(color_ostream & stream, const EmptyMessage * in, RemoteFortressReader::Status * out); static command_result GetLanguage(color_ostream & stream, const EmptyMessage * in, RemoteFortressReader::Language * out); - +static command_result GetGameValidity(color_ostream &stream, const EmptyMessage * in, SingleBool *out); void CopyBlock(df::map_block * DfBlock, RemoteFortressReader::MapBlock * NetBlock, MapExtras::MapCache * MC, DFCoord pos); @@ -272,6 +274,7 @@ DFhackCExport RPCService *plugin_rpcconnect(color_ostream &) svc->addFunction("GetLanguage", GetLanguage, SF_ALLOW_REMOTE); svc->addFunction("GetSideMenu", GetSideMenu, SF_ALLOW_REMOTE); svc->addFunction("SetSideMenu", SetSideMenu, SF_ALLOW_REMOTE); + svc->addFunction("GetGameValidity", GetGameValidity, SF_ALLOW_REMOTE); return svc; } @@ -2884,6 +2887,23 @@ static command_result GetPauseState(color_ostream &stream, const EmptyMessage *i return CR_OK; } +static command_result GetGameValidity(color_ostream &stream, const EmptyMessage * in, SingleBool *out) +{ + auto viewScreen = Gui::getCurViewscreen(); + if (strict_virtual_cast(viewScreen)) + { + out->set_value(false); + return CR_OK; + } + else if (strict_virtual_cast(viewScreen)) + { + out->set_value(false); + return CR_OK; + } + out->set_value(true); + return CR_OK; +} + static command_result GetVersionInfo(color_ostream & stream, const EmptyMessage * in, RemoteFortressReader::VersionInfo * out) { out->set_dfhack_version(DFHACK_VERSION); From 61396a57abadbdaa5ba648ab7a33ad3e36bea47f Mon Sep 17 00:00:00 2001 From: JapaMala Date: Sun, 7 Apr 2019 22:52:50 -0500 Subject: [PATCH 060/109] Push over dwarf's ages through protos --- plugins/proto/RemoteFortressReader.proto | 1 + .../remotefortressreader.cpp | 21 ++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/plugins/proto/RemoteFortressReader.proto b/plugins/proto/RemoteFortressReader.proto index 26a01738e..c83c71ea4 100644 --- a/plugins/proto/RemoteFortressReader.proto +++ b/plugins/proto/RemoteFortressReader.proto @@ -491,6 +491,7 @@ message UnitDefinition optional float subpos_y = 22; optional float subpos_z = 23; optional Coord facing = 24; + optional int32 age = 25; } message UnitList diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index db5778b9d..246f8ad28 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -63,7 +63,7 @@ #include "df/flow_guide_item_cloudst.h" #include "df/graphic.h" #include "df/historical_figure.h" - +#include "df/identity.h" #include "df/job.h" #include "df/job_type.h" #include "df/job_item.h" @@ -1675,6 +1675,25 @@ static command_result GetUnitListInside(color_ostream &stream, const BlockReques if (unit->pos.y < in->min_y() * 16 || unit->pos.y >= in->max_y() * 16) continue; } + + using df::global::cur_year; + using df::global::cur_year_tick; + + int year_ticks = 403200; + int birth_time = unit->birth_year * year_ticks + unit->birth_time; + int cur_time = *cur_year * year_ticks + *cur_year_tick; + + if (unit->curse_year >= 0) + { + if (auto identity = Units::getIdentity(unit)) + { + if (identity->histfig_id < 0) + birth_time = identity->birth_year * year_ticks + identity->birth_second; + } + } + + send_unit->set_age(cur_time - birth_time); + ConvertDfColor(Units::getProfessionColor(unit), send_unit->mutable_profession_color()); send_unit->set_flags1(unit->flags1.whole); send_unit->set_flags2(unit->flags2.whole); From 1d147015a624ffe7c0547ea0207561f4b2601272 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Sun, 7 Apr 2019 23:05:35 -0500 Subject: [PATCH 061/109] Bump RFR api version --- plugins/remotefortressreader/remotefortressreader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index 246f8ad28..bd21e6d87 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -1,5 +1,5 @@ #include "df_version_int.h" -#define RFR_VERSION "0.19.1" +#define RFR_VERSION "0.20.0" #include #include From 85879d96d69a1bc23e775254bf4ae4e080f2fe8e Mon Sep 17 00:00:00 2001 From: JapaMala Date: Sun, 7 Apr 2019 23:34:50 -0500 Subject: [PATCH 062/109] Update changelog --- docs/changelog.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/changelog.txt b/docs/changelog.txt index 8aeca3ff0..ffede6607 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -41,6 +41,9 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: - `RemoteFortressReader`: - added basic framework for controlling and reading the menus in DF, currently only supports the building menu. - added support for reading item raws. + - added a check for wheather or not the game is currently saving or loading, for utilities to check if it's safe to read from DF. + - guestimate unit facing direction, and position within tiles. + - get unit age. ## Internals - Fixed some OpenGL build issues with `stonesense` From 9e3b2fce490c60ef2a5be64519cb5f4de825e91b Mon Sep 17 00:00:00 2001 From: JapaMala Date: Sat, 13 Apr 2019 23:52:05 -0500 Subject: [PATCH 063/109] Update scripts and stonesense --- plugins/stonesense | 2 +- scripts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/stonesense b/plugins/stonesense index 4a0f63e04..6b4df3995 160000 --- a/plugins/stonesense +++ b/plugins/stonesense @@ -1 +1 @@ -Subproject commit 4a0f63e044d02532c948d67780dfd128fbd6d043 +Subproject commit 6b4df3995f53e0579fc590a78d68e54fc2ca2b81 diff --git a/scripts b/scripts index 87cc0fcad..4b38ccc83 160000 --- a/scripts +++ b/scripts @@ -1 +1 @@ -Subproject commit 87cc0fcad57a3a8ff7b558be9f3523101ac2f69d +Subproject commit 4b38ccc83b074e87cedddf3941eb144cf45de020 From ffab2d83b96c13e0943f98af2468176fb0d0ed99 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Sun, 14 Apr 2019 00:23:47 -0500 Subject: [PATCH 064/109] Update protobuf metadata --- plugins/proto/DwarfControl.proto | 6 ++++++ plugins/proto/RemoteFortressReader.proto | 1 + 2 files changed, 7 insertions(+) diff --git a/plugins/proto/DwarfControl.proto b/plugins/proto/DwarfControl.proto index 707651079..7cb31f1a3 100644 --- a/plugins/proto/DwarfControl.proto +++ b/plugins/proto/DwarfControl.proto @@ -4,9 +4,15 @@ package DwarfControl; //Attempts to provide a complete framework for reading everything from a fortress needed for vizualization option optimize_for = LITE_RUNTIME; +// Plugin: RemoteFortressReader + import "ui_sidebar_mode.proto"; import "RemoteFortressReader.proto"; +// RPC GetSideMenu : EmptyMessage -> SidebarState +// RPC GetSideMenu : SidebarCommand -> EmptyMessage + + enum BuildCategory { NotCategory = 0; diff --git a/plugins/proto/RemoteFortressReader.proto b/plugins/proto/RemoteFortressReader.proto index c83c71ea4..89d34c365 100644 --- a/plugins/proto/RemoteFortressReader.proto +++ b/plugins/proto/RemoteFortressReader.proto @@ -42,6 +42,7 @@ import "ItemdefInstrument.proto"; // RPC MovementSelectCommand : IntMessage -> EmptyMessage // RPC MiscMoveCommand : MiscMoveParams -> EmptyMessage // RPC GetLanguage : EmptyMessage -> Language +// RPC GetGameValidity : EmptyMessage -> SingleBool //We use shapes, etc, because the actual tiletypes may differ between DF versions. enum TiletypeShape From e8624aa814840a640640f13c386ecc118056ad99 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Sun, 14 Apr 2019 01:14:46 -0500 Subject: [PATCH 065/109] Fixed a typo. --- plugins/proto/DwarfControl.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/proto/DwarfControl.proto b/plugins/proto/DwarfControl.proto index 7cb31f1a3..9bd63b8d3 100644 --- a/plugins/proto/DwarfControl.proto +++ b/plugins/proto/DwarfControl.proto @@ -10,7 +10,7 @@ import "ui_sidebar_mode.proto"; import "RemoteFortressReader.proto"; // RPC GetSideMenu : EmptyMessage -> SidebarState -// RPC GetSideMenu : SidebarCommand -> EmptyMessage +// RPC SetSideMenu : SidebarCommand -> EmptyMessage enum BuildCategory From 435f92d1bbee09f94e57a0add7080678df6926e6 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Thu, 18 Apr 2019 21:48:36 -0500 Subject: [PATCH 066/109] Add protobuf files to the build solution so they show up in visual studio --- plugins/Plugins.cmake | 1 + plugins/remotefortressreader/CMakeLists.txt | 24 ++++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/plugins/Plugins.cmake b/plugins/Plugins.cmake index 4468140f7..3aefde807 100644 --- a/plugins/Plugins.cmake +++ b/plugins/Plugins.cmake @@ -111,6 +111,7 @@ MACRO(DFHACK_PLUGIN) SET_SOURCE_FILES_PROPERTIES( ${PLUGIN_PROTO_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE ) LIST(APPEND PLUGIN_SOURCES ${PLUGIN_PROTO_HDRS}) LIST(APPEND PLUGIN_SOURCES ${PLUGIN_PROTO_SRCS}) + LIST(APPEND PLUGIN_SOURCES ${PLUGIN_PROTOS}) IF(UNIX) SET(PLUGIN_COMPILE_FLAGS "${PLUGIN_COMPILE_FLAGS} -include Export.h") diff --git a/plugins/remotefortressreader/CMakeLists.txt b/plugins/remotefortressreader/CMakeLists.txt index ee6a6210b..3e998ffb5 100644 --- a/plugins/remotefortressreader/CMakeLists.txt +++ b/plugins/remotefortressreader/CMakeLists.txt @@ -17,18 +17,26 @@ SET(PROJECT_HDRS ) #proto files to include. SET(PROJECT_PROTO - ${CMAKE_CURRENT_SOURCE_DIR}/../proto/RemoteFortressReader.pb.cc - ${CMAKE_CURRENT_SOURCE_DIR}/../proto/AdventureControl.pb.cc - ${CMAKE_CURRENT_SOURCE_DIR}/../proto/ItemdefInstrument.pb.cc - ${CMAKE_CURRENT_SOURCE_DIR}/../proto/DwarfControl.pb.cc - ${CMAKE_CURRENT_SOURCE_DIR}/../proto/ui_sidebar_mode.pb.cc + RemoteFortressReader + AdventureControl + ItemdefInstrument + DwarfControl + ui_sidebar_mode ) -SET_SOURCE_FILES_PROPERTIES( ${PROJECT_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE) -SET_SOURCE_FILES_PROPERTIES( ${PROJECT_PROTO} PROPERTIES GENERATED TRUE) +SET(PLUGIN_PROTOS) +FOREACH(pbuf ${PROJECT_PROTO}) + LIST(APPEND PLUGIN_PROTOS ${CMAKE_CURRENT_SOURCE_DIR}/../proto/${pbuf}.proto) +ENDFOREACH() + +STRING(REPLACE ".proto" ".pb.cc" PLUGIN_PROTO_SRCS "${PLUGIN_PROTOS}") +STRING(REPLACE ".proto" ".pb.h" PLUGIN_PROTO_HDRS "${PLUGIN_PROTOS}") +SET_SOURCE_FILES_PROPERTIES(${PLUGIN_PROTO_SRCS} ${PLUGIN_PROTO_HDRS} PROPERTIES GENERATED TRUE) + +SET_SOURCE_FILES_PROPERTIES( ${PROJECT_HDRS} ${PLUGIN_PROTO_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE) # mash them together (headers are marked as headers and nothing will try to compile them) -LIST(APPEND PROJECT_SRCS ${PROJECT_HDRS};${PROJECT_PROTO}) +LIST(APPEND PROJECT_SRCS ${PROJECT_HDRS} ${PLUGIN_PROTOS} ${PLUGIN_PROTO_SRCS} ${PLUGIN_PROTO_HDRS}) IF(UNIX AND NOT APPLE) SET(PROJECT_LIBS ${PROJECT_LIBS} SDL) From 6565a3a2ba6589ff190fdfda2cabfecc378bebe0 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Thu, 18 Apr 2019 21:49:18 -0500 Subject: [PATCH 067/109] Add wounds to RFR --- plugins/proto/RemoteFortressReader.proto | 14 +++++++++++++ .../remotefortressreader.cpp | 20 ++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/plugins/proto/RemoteFortressReader.proto b/plugins/proto/RemoteFortressReader.proto index 89d34c365..ed7557a2f 100644 --- a/plugins/proto/RemoteFortressReader.proto +++ b/plugins/proto/RemoteFortressReader.proto @@ -466,6 +466,19 @@ message InventoryItem optional int32 body_part_id = 3; } +message WoundPart +{ + optional int32 global_layer_idx = 1; + optional int32 body_part_id = 2; + optional int32 layer_idx = 3; +} + +message UnitWound +{ + repeated WoundPart parts = 1; + optional bool severed_part = 2; +} + message UnitDefinition { required int32 id = 1; @@ -493,6 +506,7 @@ message UnitDefinition optional float subpos_z = 23; optional Coord facing = 24; optional int32 age = 25; + repeated UnitWound wounds = 26; } message UnitList diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index bd21e6d87..f4bf13e2c 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -1,5 +1,5 @@ #include "df_version_int.h" -#define RFR_VERSION "0.20.0" +#define RFR_VERSION "0.20.1" #include #include @@ -92,6 +92,7 @@ #include "df/ui.h" #include "df/unit.h" #include "df/unit_inventory_item.h" +#include "df/unit_wound.h" #include "df/viewscreen_choose_start_sitest.h" #include "df/viewscreen_loadgamest.h" #include "df/viewscreen_savegamest.h" @@ -1653,6 +1654,19 @@ float lerp(float a, float b, float f) return a + f * (b - a); } +void GetWounds(df::unit_wound * wound, UnitWound * send_wound) +{ + for (size_t i = 0; i < wound->parts.size(); i++) + { + auto part = wound->parts[i]; + auto send_part = send_wound->add_parts(); + send_part->set_global_layer_idx(part->global_layer_idx); + send_part->set_body_part_id(part->body_part_id); + send_part->set_layer_idx(part->layer_idx); + } + send_wound->set_severed_part(wound->flags.bits.severed_part); +} + static command_result GetUnitListInside(color_ostream &stream, const BlockRequest *in, UnitList *out) { auto world = df::global::world; @@ -1826,6 +1840,10 @@ static command_result GetUnitListInside(color_ostream &stream, const BlockReques facing->set_z(unit->path.path.z[0] - unit->pos.z); } } + for (size_t i = 0; i < unit->body.wounds.size(); i++) + { + GetWounds(unit->body.wounds[i], send_unit->add_wounds()); + } } return CR_OK; } From 4347fb0be75856872c4b8a88e1122d628813218f Mon Sep 17 00:00:00 2001 From: JapaMala Date: Thu, 18 Apr 2019 23:30:03 -0500 Subject: [PATCH 068/109] Use size_t for vector size comparisons. --- plugins/remotefortressreader/dwarf_control.cpp | 6 +++--- plugins/remotefortressreader/remotefortressreader.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/remotefortressreader/dwarf_control.cpp b/plugins/remotefortressreader/dwarf_control.cpp index 57c770301..98b51175f 100644 --- a/plugins/remotefortressreader/dwarf_control.cpp +++ b/plugins/remotefortressreader/dwarf_control.cpp @@ -235,7 +235,7 @@ void CopyBuildMenu(DwarfControl::SidebarState * out) auto menus = df::global::ui_sidebar_menus; auto build_selector = df::global::ui_build_selector; if (build_selector->building_type == -1) - for (int i = 0; i < menus->building.choices_visible.size(); i++) + for (size_t i = 0; i < menus->building.choices_visible.size(); i++) { auto menu_item = menus->building.choices_visible[i]; auto send_item = out->add_menu_items(); @@ -262,12 +262,12 @@ void CopyBuildMenu(DwarfControl::SidebarState * out) send_bld->set_building_subtype(build_selector->building_subtype); send_bld->set_building_custom(build_selector->custom_type); send_selector->set_stage((DwarfControl::BuildSelectorStage)build_selector->stage); - for (int i = 0; i < build_selector->errors.size(); i++) + for (size_t i = 0; i < build_selector->errors.size(); i++) { if (build_selector->errors[i]) send_selector->add_errors(*build_selector->errors[i]); } - for (int i = 0; i < build_selector->choices.size(); i++) + for (size_t i = 0; i < build_selector->choices.size(); i++) { auto choice = build_selector->choices[i]; auto send_choice = send_selector->add_choices(); diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index f4bf13e2c..0177305d7 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -1815,7 +1815,7 @@ static command_result GetUnitListInside(color_ostream &stream, const BlockReques } else { - for (int i = 0; i < unit->actions.size(); i++) + for (size_t i = 0; i < unit->actions.size(); i++) { auto action = unit->actions[i]; switch (action->type) From b64fba5822b293053067a6864be86400e98023cb Mon Sep 17 00:00:00 2001 From: JapaMala Date: Fri, 19 Apr 2019 09:25:06 -0500 Subject: [PATCH 069/109] Update changelog --- docs/changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog.txt b/docs/changelog.txt index ffede6607..ef2fc825d 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -44,6 +44,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: - added a check for wheather or not the game is currently saving or loading, for utilities to check if it's safe to read from DF. - guestimate unit facing direction, and position within tiles. - get unit age. + - get unit wounds. ## Internals - Fixed some OpenGL build issues with `stonesense` From 19772b7a437a7647d70cf6fd1493a1a2b098f636 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Sat, 4 May 2019 10:29:02 -0500 Subject: [PATCH 070/109] bump version number for future AV updates to pick up on. --- plugins/remotefortressreader/remotefortressreader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index 0177305d7..f984fc05a 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -1,5 +1,5 @@ #include "df_version_int.h" -#define RFR_VERSION "0.20.1" +#define RFR_VERSION "0.20.2" #include #include From ae91e17e3e9ddddca714086b24d8ad3d507b5c10 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Sat, 4 May 2019 14:35:28 -0500 Subject: [PATCH 071/109] Consider the unit's current job for facing. --- plugins/remotefortressreader/remotefortressreader.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index f984fc05a..4c415e590 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -1828,6 +1828,13 @@ static command_result GetUnitListInside(color_ostream &stream, const BlockReques send_unit->set_subpos_z(lerp(0, unit->path.path.z[0] - unit->pos.z, (float)(action->data.move.timer_init - action->data.move.timer) / action->data.move.timer_init)); } break; + case unit_action_type::Job: + { + auto facing = send_unit->mutable_facing(); + facing->set_x(action->data.job.x - unit->pos.x); + facing->set_y(action->data.job.y - unit->pos.y); + facing->set_z(action->data.job.z - unit->pos.z); + } default: break; } From 860be4a04aec423bc9cd609e99df749546d7d661 Mon Sep 17 00:00:00 2001 From: JapaMala Date: Sun, 12 May 2019 17:05:02 -0500 Subject: [PATCH 072/109] Fix issues with following the screen when using TWBT --- plugins/remotefortressreader/remotefortressreader.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index 4c415e590..cd9ebd87e 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -1875,6 +1875,14 @@ static command_result GetViewInfo(color_ostream &stream, const EmptyMessage *in, } #endif + auto dims = Gui::getDwarfmodeViewDims(); + + x += dims.map_x1; + y += dims.map_y1; + + w = dims.map_x2 - dims.map_x1; + h = dims.map_y2 - dims.map_y1; + out->set_view_pos_x(x); out->set_view_pos_y(y); out->set_view_pos_z(z); From cddfb87e22a2086d72ae4e4ccdac54a700475f10 Mon Sep 17 00:00:00 2001 From: "Joel \"The Merciless\" Meador" Date: Tue, 21 May 2019 09:25:57 -0400 Subject: [PATCH 073/109] Make unit_ishostile always return a non-nil value Have been messing with this function in the dfhack repl and when it returns nil it's hard to know what that means unless you have also already read the code. So this handles a couple spots in `unit_ishostile` that previously just returned false-ey `nil`s to return `false` --- plugins/ruby/unit.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/ruby/unit.rb b/plugins/ruby/unit.rb index 848e0f471..b27f2f0c3 100644 --- a/plugins/ruby/unit.rb +++ b/plugins/ruby/unit.rb @@ -134,7 +134,7 @@ module DFHack # does not include ghosts / wildlife def unit_ishostile(u) # return true if u.flags3.ghostly and not u.flags1.inactive - return unless unit_category(u) == :Others + return false unless unit_category(u) == :Others case unit_other_category(u) when :Berserk, :Undead, :Hostile, :Invader, :Underworld @@ -152,6 +152,8 @@ module DFHack case unit_checkdiplomacy_hf_ent(histfig, group) when 4, 5 true + else + false end elsif diplo = u.civ_tg.unknown1b.diplomacy.binsearch(df.ui.group_id, :group_id) From 195db1bad9697f75672838127ad435112ee72491 Mon Sep 17 00:00:00 2001 From: lethosor Date: Tue, 21 May 2019 20:22:49 -0400 Subject: [PATCH 074/109] Remove issue and PR badges from README.md githubbadges.herokuapp.com has been down for some time, and these badges repeated information that was already visible on https://github.com/dfhack/dfhack (and they weren't included in the generated docs either). --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 9ea1ccb04..fd95e1e5e 100644 --- a/README.md +++ b/README.md @@ -3,15 +3,13 @@ [![Build Status](https://travis-ci.org/DFHack/dfhack.svg?branch=develop)](https://travis-ci.org/DFHack/dfhack) [![Documentation Status](https://readthedocs.org/projects/dfhack/badge)](https://dfhack.readthedocs.org) [![License](https://img.shields.io/badge/license-ZLib-blue.svg)](https://en.wikipedia.org/wiki/Zlib_License) -[![Github Issues](http://githubbadges.herokuapp.com/DFHack/dfhack/issues)](https://github.com/DFHack/dfhack/issues) -[![Open Pulls](http://githubbadges.herokuapp.com/DFHack/dfhack/pulls)](https://github.com/DFHack/dfhack/pulls) DFHack is a Dwarf Fortress memory access library, distributed with scripts and plugins implementing a wide variety of useful functions and tools. The full documentation [is available online here](https://dfhack.readthedocs.org), from the README.html page in the DFHack distribution, or as raw text in the `./docs` folder. -If you're an end-user, modder, or interested in contributing to DFHack - +If you're an end-user, modder, or interested in contributing to DFHack - go read those docs. If that's unclear or you need more help, try From f668914db85570c266dca3017e0a7ea39050583b Mon Sep 17 00:00:00 2001 From: lethosor Date: Sat, 1 Jun 2019 17:30:26 -0400 Subject: [PATCH 075/109] kittens: fix compiling on Windows thanks to @ragundo --- plugins/devel/kittens.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/plugins/devel/kittens.cpp b/plugins/devel/kittens.cpp index 26a2655e8..b978fab7f 100644 --- a/plugins/devel/kittens.cpp +++ b/plugins/devel/kittens.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -20,6 +21,11 @@ #include "df/creature_raw.h" #include "df/world.h" +// for MSVC alignas(64) issues +#ifdef WIN32 +#define _DISABLE_EXTENDED_ALIGNED_STORAGE +#endif + using std::vector; using std::string; using namespace DFHack; @@ -220,7 +226,7 @@ struct ClearMem : public ConnectedBase { }; struct Connected : public ClearMem { - using Sig = Signal; + using Sig = Signal; std::array con; Sig signal; weak other; @@ -245,7 +251,7 @@ struct Connected : public ClearMem { // Externally synchronized object destruction is only safe to this // connect. con[pos] = b->signal.connect( - [this](int) { + [this](uint32_t) { uint32_t old = callee.fetch_add(1); assert(old != 0xDEDEDEDE); std::this_thread::sleep_for(delay); @@ -272,7 +278,7 @@ struct Connected : public ClearMem { if (!sig) return; con[pos] = sig->connect(b, - [this](int) { + [this](uint32_t) { uint32_t old = callee.fetch_add(1); assert(old != 0xDEDEDEDE); std::this_thread::sleep_for(delay); @@ -284,7 +290,7 @@ struct Connected : public ClearMem { out = &o; count = c; con[pos] = b->signal.connect(a, - [this](int) { + [this](uint32_t) { uint32_t old = callee.fetch_add(1); assert(old != 0xDEDEDEDE); std::this_thread::sleep_for(delay); @@ -345,13 +351,13 @@ command_result sharedsignal (color_ostream &out, vector & parameters) TRACE(command, out) << "Thread " << c->id << " started." << std::endl; weak ref = c; for (;c->caller < c->count; ++c->caller) { - c->signal(c->caller); + c->signal(std::move(c->caller)); } TRACE(command, out) << "Thread " << c->id << " resets shared." << std::endl; c.reset(); while((c = ref.lock())) { ++c->caller; - c->signal(c->caller); + c->signal(std::move(c->caller)); c.reset(); std::this_thread::sleep_for(delay*25); } @@ -363,7 +369,7 @@ command_result sharedsignal (color_ostream &out, vector & parameters) } TRACE(command, out) << "running " << std::endl; for (;external->caller < external->count; ++external->caller) { - external->signal(external->caller); + external->signal(std::move(external->caller)); external->reconnect(1); } TRACE(command, out) << "join " << std::endl; From cde8ffd0fd0e6a1c0a7d09ed1a76389555870238 Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Thu, 6 Jun 2019 20:56:47 +0200 Subject: [PATCH 076/109] Fixed materials vector length determination --- plugins/embark-assistant/embark-assistant.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/embark-assistant/embark-assistant.cpp b/plugins/embark-assistant/embark-assistant.cpp index cfd44a30b..13d202b7e 100644 --- a/plugins/embark-assistant/embark-assistant.cpp +++ b/plugins/embark-assistant/embark-assistant.cpp @@ -224,7 +224,7 @@ command_result embark_assistant(color_ostream &out, std::vector & // Find the end of the normal inorganic definitions. embark_assist::main::state->max_inorganic = 0; for (uint16_t i = 0; i < world->raws.inorganics.size(); i++) { - if (world->raws.inorganics[i]->flags.is_set(df::inorganic_flags::GENERATED)) embark_assist::main::state->max_inorganic = i; + if (!world->raws.inorganics[i]->flags.is_set(df::inorganic_flags::GENERATED)) embark_assist::main::state->max_inorganic = i; } embark_assist::main::state->max_inorganic++; // To allow it to be used as size() replacement From f09f3a2d253e36e93ef68262fb3e35fe352cd658 Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Thu, 6 Jun 2019 20:57:21 +0200 Subject: [PATCH 077/109] Prettified by adding a blank --- plugins/embark-assistant/survey.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/embark-assistant/survey.cpp b/plugins/embark-assistant/survey.cpp index f19f3cd4a..00f60d51d 100644 --- a/plugins/embark-assistant/survey.cpp +++ b/plugins/embark-assistant/survey.cpp @@ -203,7 +203,7 @@ namespace embark_assist { } for (uint16_t m = 0; m < state->coals.size(); m++) { - if (vein== state->coals[m]) { + if (vein == state->coals[m]) { geo_summary->at(i).coal_absent = false; break; } From a72d25475b632ab39cb2acb2b1f4aa718067b104 Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Thu, 6 Jun 2019 21:18:54 +0200 Subject: [PATCH 078/109] Added Enbark-Assistant entry --- docs/changelog.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/changelog.txt b/docs/changelog.txt index 17c766f75..61eed0e0e 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -37,6 +37,9 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: ================================================================================ # Future +## Fixes +- `embark-assistant`: fixed bug causing crash on worlds without generated metals (as well as pruning vectors as originally intended). + ## Internals - Fixed some OpenGL build issues with `stonesense` From b1a544b99c10cc953db33dc77048a5a033800775 Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Thu, 20 Jun 2019 15:48:51 +0200 Subject: [PATCH 079/109] Added embark-assistant bug fix note --- docs/changelog.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index 61eed0e0e..c003ef936 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -38,7 +38,10 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: # Future ## Fixes -- `embark-assistant`: fixed bug causing crash on worlds without generated metals (as well as pruning vectors as originally intended). +- `embark-assistant`: + - fixed bug causing crash on worlds without generated metals (as well as pruning vectors as originally intended). + - fixed bug causing mineral matching to fail to cut off at the magma sea, reporting presence of things that + aren't (like DF does currently). ## Internals - Fixed some OpenGL build issues with `stonesense` From 488f1cd8a1f1babca570393858c16ac9ced01862 Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Thu, 20 Jun 2019 15:50:11 +0200 Subject: [PATCH 080/109] Fixed bug causing minerals below magma sea being reported --- plugins/embark-assistant/survey.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/plugins/embark-assistant/survey.cpp b/plugins/embark-assistant/survey.cpp index 00f60d51d..9df34bc86 100644 --- a/plugins/embark-assistant/survey.cpp +++ b/plugins/embark-assistant/survey.cpp @@ -667,7 +667,7 @@ void embark_assist::survey::high_level_world_survey(embark_assist::defs::geo_dat void embark_assist::survey::survey_mid_level_tile(embark_assist::defs::geo_data *geo_summary, embark_assist::defs::world_tile_data *survey_results, embark_assist::defs::mid_level_tiles *mlt) { - // color_ostream_proxy out(Core::getInstance().getConsole()); +// color_ostream_proxy out(Core::getInstance().getConsole()); auto screen = Gui::getViewscreenByType(0); int16_t x = screen->location.region_pos.x; int16_t y = screen->location.region_pos.y; @@ -853,12 +853,12 @@ void embark_assist::survey::survey_mid_level_tile(embark_assist::defs::geo_data if (layer->type == df::geo_layer_type::SOIL || layer->type == df::geo_layer_type::SOIL_SAND) { int16_t size = layer->top_height - layer->bottom_height - 1; - // Comment copied from prospector.cpp(like the logic)... + // Comment copied from prospector.cpp (like the logic)... // This is to replicate the behavior of a probable bug in the - // map generation code : if a layer is partially eroded, the - // removed levels are in fact transferred to the layer below, + // map generation code : if a layer is partially eroded, the + // removed levels are in fact transferred to the layer below, // because unlike the case of removing the whole layer, the code - // does not execute a loop to shift the lower part of the stack up. + // does not execute a loop to shift the lower part of the stack up. if (size > soil_erosion) { cur_shift = cur_shift - soil_erosion; } @@ -880,6 +880,8 @@ void embark_assist::survey::survey_mid_level_tile(embark_assist::defs::geo_data } if (top_z >= bottom_z) { + last_bottom = bottom_z; + mlt->at(i).at(k).minerals[layer->mat_index] = true; end_check_m = static_cast(world->raws.inorganics[layer->mat_index]->metal_ore.mat_index.size()); From 9c3edac499701a2fc0f973f5275ad0ae8d9ab024 Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Thu, 20 Jun 2019 15:59:08 +0200 Subject: [PATCH 081/109] Added embark-assistant bug fix note --- docs/changelog.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index c003ef936..b29ee59f6 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -40,8 +40,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: ## Fixes - `embark-assistant`: - fixed bug causing crash on worlds without generated metals (as well as pruning vectors as originally intended). - - fixed bug causing mineral matching to fail to cut off at the magma sea, reporting presence of things that - aren't (like DF does currently). + - fixed bug causing mineral matching to fail to cut off at the magma sea, reporting presence of things that aren't (like DF does currently). ## Internals - Fixed some OpenGL build issues with `stonesense` From aee7e2e4817ab4497e1896e3fcd9d6f7f93f1777 Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Sun, 23 Jun 2019 18:34:21 +0200 Subject: [PATCH 082/109] Mentioned Enbark-Assistant Flat detection modification --- docs/changelog.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/changelog.txt b/docs/changelog.txt index b29ee59f6..12faed5a2 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -42,6 +42,9 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: - fixed bug causing crash on worlds without generated metals (as well as pruning vectors as originally intended). - fixed bug causing mineral matching to fail to cut off at the magma sea, reporting presence of things that aren't (like DF does currently). +## Misc Improvements +- `embark-assistant`: Changed Flat detection to allow search for verified flat terrain by checking surrounding Mid Level Tiles or just mostly/probably flat terrain by checking embark tiles only + ## Internals - Fixed some OpenGL build issues with `stonesense` From b5e38451de86c6cacce8b2d4580fe24c282f7279 Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Sun, 23 Jun 2019 18:35:11 +0200 Subject: [PATCH 083/109] Modified Flat detection options --- plugins/embark-assistant/defs.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/plugins/embark-assistant/defs.h b/plugins/embark-assistant/defs.h index f7a9ed680..46ef75041 100644 --- a/plugins/embark-assistant/defs.h +++ b/plugins/embark-assistant/defs.h @@ -23,6 +23,12 @@ namespace embark_assist { Major }; + enum class flatnesses { + Flat_Verified, + Mostly_Flat, + Uneven + }; + struct mid_level_tile { bool aquifer = false; bool clay = false; @@ -111,7 +117,7 @@ namespace embark_assist { bool aquifer_full; uint8_t min_soil; uint8_t max_soil; - bool flat; + flatnesses flatness; bool waterfall; bool clay; bool sand; @@ -174,6 +180,13 @@ namespace embark_assist { Major }; + enum class flatness_ranges : int8_t { + NA = -1, + Flat_Verified, + Mostly_Flat, + Uneven + }; + // For possible future use. That's the level of data actually collected. // enum class adamantine_ranges : int8_t { // NA = -1, @@ -253,7 +266,7 @@ namespace embark_assist { river_ranges min_river; river_ranges max_river; yes_no_ranges waterfall; - yes_no_ranges flat; + flatness_ranges flatness; present_absent_ranges clay; present_absent_ranges sand; present_absent_ranges flux; From 3e97643b37821ca6bc9d218106c1ba0467cb8720 Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Sun, 23 Jun 2019 18:35:28 +0200 Subject: [PATCH 084/109] Modified Flat detection options --- plugins/embark-assistant/finder_ui.cpp | 47 +++++++++++++++++++++----- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/plugins/embark-assistant/finder_ui.cpp b/plugins/embark-assistant/finder_ui.cpp index 5c7cc9046..59aa0783a 100644 --- a/plugins/embark-assistant/finder_ui.cpp +++ b/plugins/embark-assistant/finder_ui.cpp @@ -40,7 +40,7 @@ namespace embark_assist { min_river, max_river, waterfall, - flat, + flatness, clay, sand, flux, @@ -246,7 +246,7 @@ namespace embark_assist { fclose(infile); - // Checking done. No do the work. + // Checking done. Now do the work. infile = fopen(profile_file_name, "r"); i = first_fields; @@ -453,7 +453,6 @@ namespace embark_assist { break; case fields::waterfall: - case fields::flat: case fields::blood_rain: { embark_assist::defs::yes_no_ranges k = embark_assist::defs::yes_no_ranges::NA; @@ -482,6 +481,38 @@ namespace embark_assist { break; + case fields::flatness: + { + embark_assist::defs::flatness_ranges k = embark_assist::defs::flatness_ranges::NA; + while (true) { + switch (k) { + case embark_assist::defs::flatness_ranges::NA: + element->list.push_back({ "N/A", static_cast(k) }); + break; + + case embark_assist::defs::flatness_ranges::Flat_Verified: + element->list.push_back({ "Flat Verified", static_cast(k) }); + break; + + case embark_assist::defs::flatness_ranges::Mostly_Flat: + element->list.push_back({ "Mostly Flat", static_cast(k) }); + break; + + case embark_assist::defs::flatness_ranges::Uneven: + element->list.push_back({ "Uneven", static_cast(k) }); + break; + } + + if (k == embark_assist::defs::flatness_ranges::Uneven) { + break; + } + + k = static_cast (static_cast(k) + 1); + } + } + + break; + case fields::soil_min_everywhere: { embark_assist::defs::all_present_ranges k = embark_assist::defs::all_present_ranges::All; @@ -959,8 +990,8 @@ namespace embark_assist { state->finder_list.push_back({ "Waterfall", static_cast(i) }); break; - case fields::flat: - state->finder_list.push_back({ "Flat", static_cast(i) }); + case fields::flatness: + state->finder_list.push_back({ "Flatness", static_cast(i) }); break; case fields::soil_min_everywhere: @@ -1189,9 +1220,9 @@ namespace embark_assist { static_cast(state->ui[static_cast(i)]->current_value); break; - case fields::flat: - finder.flat = - static_cast(state->ui[static_cast(i)]->current_value); + case fields::flatness: + finder.flatness = + static_cast(state->ui[static_cast(i)]->current_value); break; case fields::soil_min_everywhere: From 3f7d11d1c754422381c199e1015d362d1f856575 Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Sun, 23 Jun 2019 18:35:48 +0200 Subject: [PATCH 085/109] Modified Flat detection options --- plugins/embark-assistant/help_ui.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/plugins/embark-assistant/help_ui.cpp b/plugins/embark-assistant/help_ui.cpp index e92ae67c0..3d281b145 100644 --- a/plugins/embark-assistant/help_ui.cpp +++ b/plugins/embark-assistant/help_ui.cpp @@ -163,6 +163,9 @@ namespace embark_assist{ help_text.push_back("Clay, if present"); help_text.push_back("Min and Max soil depth in the embark rectangle."); help_text.push_back("Flat indicator if all the tiles in the embark have the same elevation."); + help_text.push_back(" 'Mostly Flat' = Condition above met. 'Flat Verified' = All surrounding tiles"); + help_text.push_back(" also satisfy condition so no biome spill over may result in an"); + help_text.push_back(" elevation difference."); help_text.push_back("Aquifer indicator, color coded as blue if all tiles have an aquifer and light"); help_text.push_back("blue if some, but not all, tiles have one."); help_text.push_back("Waterfall, if the embark has river elevation differences."); @@ -252,7 +255,7 @@ namespace embark_assist{ help_text.push_back("- The biome determination logic comes from code provided by Ragundo,"); help_text.push_back(" with only marginal changes by the author. References can be found in"); help_text.push_back(" the source file."); - help_text.push_back("- Thralling is determined by weather material interactions causing"); + help_text.push_back("- Thralling is determined by whether material interactions causes"); help_text.push_back(" blinking, which the author believes is one of 4 thralling changes."); help_text.push_back("- The geo information is gathered by code which is essentially a"); help_text.push_back(" copy of parts of prospector's code adapted for this plugin."); @@ -263,7 +266,13 @@ namespace embark_assist{ help_text.push_back(" reaching caverns that have been removed at world gen to fail to be"); help_text.push_back(" generated at all. It's likely this bug also affects magma pools."); help_text.push_back(" This plugin does not address this but scripts can correct it."); - help_text.push_back("Version 0.8 2018-12-04"); + help_text.push_back("- 'Flat Verified' vs 'Mostly Flat': There's no known way to detect"); + help_text.push_back(" if an adjacent Mid Level Tile's biome 'spills over' into a tile."); + help_text.push_back(" 'Flat Verified' means neighbors have the same elevation so spill overs"); + help_text.push_back(" don't matter. 'Mostly Flat' means spill overs may ruin a completely"); + help_text.push_back(" level embark, but might not. Can be used to 'rescue' a world where"); + help_text.push_back(" a 'Flat Verified' match failed."); + help_text.push_back("Version 0.9 2019-06-23"); break; } From 8259243d2aaa3b65add4b34c298cfdd5de58ee4e Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Sun, 23 Jun 2019 18:35:59 +0200 Subject: [PATCH 086/109] Modified Flat detection options --- plugins/embark-assistant/matcher.cpp | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/plugins/embark-assistant/matcher.cpp b/plugins/embark-assistant/matcher.cpp index 7b3d385cb..26463f011 100644 --- a/plugins/embark-assistant/matcher.cpp +++ b/plugins/embark-assistant/matcher.cpp @@ -83,6 +83,12 @@ namespace embark_assist { for (uint8_t i = 0; i <= ENUM_LAST_ITEM(world_region_type); i++) region_types[i] = false; + if (finder->flatness == embark_assist::defs::flatness_ranges::Flat_Verified && + (start_x == 0 || + start_x + finder->x_dim == 16 || + start_y == 0 || + start_y + finder->y_dim == 16)) return false; + for (uint16_t i = start_x; i < start_x + finder->x_dim; i++) { for (uint16_t k = start_y; k < start_y + finder->y_dim; k++) { @@ -151,8 +157,9 @@ namespace embark_assist { river_elevation = mlt->at(i).at(k).river_elevation; } - // Flat - if (finder->flat == embark_assist::defs::yes_no_ranges::Yes && + // Flatness + if ((finder->flatness == embark_assist::defs::flatness_ranges::Flat_Verified || + finder->flatness == embark_assist::defs::flatness_ranges::Mostly_Flat) && elevation != mlt->at(i).at(k).elevation) return false; if (elevation != mlt->at(i).at(k).elevation) uneven = true; @@ -330,8 +337,20 @@ namespace embark_assist { if (!river_found && finder->min_river > embark_assist::defs::river_ranges::None) return false; if (finder->waterfall == embark_assist::defs::yes_no_ranges::Yes && !waterfall_found) return false; - // Flat - if (!uneven && finder->flat == embark_assist::defs::yes_no_ranges::No) return false; + // Flatness + if (!uneven && finder->flatness == embark_assist::defs::flatness_ranges::Uneven) return false; + + if (finder->flatness == embark_assist::defs::flatness_ranges::Flat_Verified) { + for (uint16_t i = start_x - 1; i < start_x + finder->x_dim + 1; i++) { + if (elevation != mlt->at(i).at(start_y - 1).elevation || + elevation != mlt->at(i).at(start_y + finder->y_dim).elevation) return false; + } + + for (uint16_t k = start_y; k < start_y + finder->y_dim; k++) { + if (elevation != mlt->at(start_x - 1).at(k).elevation || + elevation != mlt->at(start_x + finder->x_dim).at(k).elevation) return false; + } + } // Clay if (finder->clay == embark_assist::defs::present_absent_ranges::Present && !clay_found) return false; From 3139d0d3c73115eaec57d90d19b33af5792d3d9c Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Sun, 23 Jun 2019 18:36:10 +0200 Subject: [PATCH 087/109] Modified Flat detection options --- plugins/embark-assistant/overlay.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/embark-assistant/overlay.cpp b/plugins/embark-assistant/overlay.cpp index c25859ccb..cf25eddf3 100644 --- a/plugins/embark-assistant/overlay.cpp +++ b/plugins/embark-assistant/overlay.cpp @@ -345,8 +345,12 @@ void embark_assist::overlay::set_embark(embark_assist::defs::site_infos *site_in state->embark_info.push_back({ Screen::Pen(' ', COLOR_BROWN), "Soil " + std::to_string(site_info->min_soil) + " - " + std::to_string(site_info->max_soil) }); - if (site_info->flat) { - state->embark_info.push_back({ Screen::Pen(' ', COLOR_BROWN), "Flat" }); + if (site_info->flatness == embark_assist::defs::flatnesses::Flat_Verified) { + state->embark_info.push_back({ Screen::Pen(' ', COLOR_BROWN), "Flat Verified" }); + } + else if (site_info->flatness == embark_assist::defs::flatnesses::Mostly_Flat) + { + state->embark_info.push_back({ Screen::Pen(' ', COLOR_BROWN), "Mostly Flat" }); } if (site_info->aquifer) { From 716fe903122ded39b3aa75997cacb917a6727f6a Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Sun, 23 Jun 2019 18:36:18 +0200 Subject: [PATCH 088/109] Modified Flat detection options --- plugins/embark-assistant/survey.cpp | 39 ++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/plugins/embark-assistant/survey.cpp b/plugins/embark-assistant/survey.cpp index 9df34bc86..d79396118 100644 --- a/plugins/embark-assistant/survey.cpp +++ b/plugins/embark-assistant/survey.cpp @@ -1197,7 +1197,7 @@ void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles * embark_assist::defs::site_infos *site_info, bool use_cache) { - // color_ostream_proxy out(Core::getInstance().getConsole()); + //color_ostream_proxy out(Core::getInstance().getConsole()); auto screen = Gui::getViewscreenByType(0); int16_t elevation = 0; uint16_t x = screen->location.region_pos.x; @@ -1207,6 +1207,7 @@ void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles * std::vector metals(state->max_inorganic); std::vector economics(state->max_inorganic); std::vector minerals(state->max_inorganic); + bool flatness_verification_failed; if (!use_cache) { // For some reason DF scrambles these values on world tile movements (at least in Lua...). state->local_min_x = screen->location.embark_pos_min.x; @@ -1222,7 +1223,7 @@ void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles * site_info->aquifer_full = true; site_info->min_soil = 10; site_info->max_soil = 0; - site_info->flat = true; + site_info->flatness = embark_assist::defs::flatnesses::Mostly_Flat; site_info->waterfall = false; site_info->clay = false; site_info->sand = false; @@ -1253,7 +1254,7 @@ void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles * elevation = mlt->at(i).at(k).elevation; } else if (elevation != mlt->at(i).at(k).elevation) { - site_info->flat = false; + site_info->flatness = embark_assist::defs::flatnesses::Uneven; } if (mlt->at(i).at(k).river_present) { @@ -1291,6 +1292,38 @@ void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles * } } } + + if (site_info->flatness == embark_assist::defs::flatnesses::Mostly_Flat && + state->local_min_x > 0 && + state->local_max_x < 15 && + state->local_min_y > 0 && + state->local_max_y < 15) + { + flatness_verification_failed = false; + + for (uint8_t i = state->local_min_x - 1; i <= state->local_max_x + 1; i++) { + if (mlt->at(i).at(state->local_min_y - 1).elevation != elevation || + mlt->at(i).at(state->local_max_y + 1).elevation != elevation) { + flatness_verification_failed = true; + break; + } + } + + if (!flatness_verification_failed) { + for (uint8_t k = state->local_min_y; k <= state->local_max_y; k++) { + if (mlt->at(state->local_min_x - 1).at(k).elevation != elevation || + mlt->at(state->local_max_x + 1).at(k).elevation != elevation) { + flatness_verification_failed = true; + break; + } + } + } + + if (!flatness_verification_failed) { + site_info->flatness = embark_assist::defs::flatnesses::Flat_Verified; + } + } + for (uint16_t l = 0; l < state->max_inorganic; l++) { if (metals[l]) { site_info->metals.push_back(l); From fd722332f83660d090be1756af526a2868c21b04 Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Mon, 1 Jul 2019 13:27:39 +0200 Subject: [PATCH 089/109] Embark-Assistant Waterfall detection change added --- docs/changelog.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index 12faed5a2..88b0d59d3 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -43,7 +43,9 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: - fixed bug causing mineral matching to fail to cut off at the magma sea, reporting presence of things that aren't (like DF does currently). ## Misc Improvements -- `embark-assistant`: Changed Flat detection to allow search for verified flat terrain by checking surrounding Mid Level Tiles or just mostly/probably flat terrain by checking embark tiles only +- `embark-assistant`: + - Changed Flat detection to allow search for verified flat terrain by checking surrounding Mid Level Tiles or just mostly/probably flat terrain by checking embark tiles only. + - Changed Waterfall detection to look for level drop rather than just presence. ## Internals - Fixed some OpenGL build issues with `stonesense` From 092c9f965b3d52bef3fed1b795c61df4ed50e5e9 Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Mon, 1 Jul 2019 13:28:40 +0200 Subject: [PATCH 090/109] Waterfall detection changed --- plugins/embark-assistant/defs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/embark-assistant/defs.h b/plugins/embark-assistant/defs.h index 46ef75041..da03c1d7e 100644 --- a/plugins/embark-assistant/defs.h +++ b/plugins/embark-assistant/defs.h @@ -61,7 +61,7 @@ namespace embark_assist { uint16_t coal_count = 0; uint8_t min_region_soil = 10; uint8_t max_region_soil = 0; - bool waterfall = false; + uint8_t max_waterfall = 0; river_sizes river_size; int16_t biome_index[10]; // Indexed through biome_offset; -1 = null, Index of region, [0] not used int16_t biome[10]; // Indexed through biome_offset; -1 = null, df::biome_type, [0] not used @@ -118,7 +118,7 @@ namespace embark_assist { uint8_t min_soil; uint8_t max_soil; flatnesses flatness; - bool waterfall; + uint8_t max_waterfall; bool clay; bool sand; bool flux; @@ -265,7 +265,7 @@ namespace embark_assist { aquifer_ranges aquifer; river_ranges min_river; river_ranges max_river; - yes_no_ranges waterfall; + int8_t min_waterfall; // N/A(-1), Absent, 1-9 flatness_ranges flatness; present_absent_ranges clay; present_absent_ranges sand; From 242f6fbc383e005bde7bf82b65af9fcdd21090b3 Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Mon, 1 Jul 2019 13:28:54 +0200 Subject: [PATCH 091/109] Waterfall detection changed --- plugins/embark-assistant/embark-assistant.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/embark-assistant/embark-assistant.cpp b/plugins/embark-assistant/embark-assistant.cpp index 13d202b7e..972da12f9 100644 --- a/plugins/embark-assistant/embark-assistant.cpp +++ b/plugins/embark-assistant/embark-assistant.cpp @@ -253,7 +253,7 @@ command_result embark_assistant(color_ostream &out, std::vector & embark_assist::main::state->survey_results[i][k].flux_count = 0; embark_assist::main::state->survey_results[i][k].min_region_soil = 10; embark_assist::main::state->survey_results[i][k].max_region_soil = 0; - embark_assist::main::state->survey_results[i][k].waterfall = false; + embark_assist::main::state->survey_results[i][k].max_waterfall = 0; embark_assist::main::state->survey_results[i][k].river_size = embark_assist::defs::river_sizes::None; for (uint8_t l = 1; l < 10; l++) { From fae5e894ae9a2fcdd749cf27dbe65cf504fde491 Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Mon, 1 Jul 2019 13:29:07 +0200 Subject: [PATCH 092/109] Waterfall detection changed --- plugins/embark-assistant/finder_ui.cpp | 27 +++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/plugins/embark-assistant/finder_ui.cpp b/plugins/embark-assistant/finder_ui.cpp index 59aa0783a..6e710f3bd 100644 --- a/plugins/embark-assistant/finder_ui.cpp +++ b/plugins/embark-assistant/finder_ui.cpp @@ -39,7 +39,7 @@ namespace embark_assist { aquifer, min_river, max_river, - waterfall, + min_waterfall, flatness, clay, sand, @@ -452,7 +452,21 @@ namespace embark_assist { break; - case fields::waterfall: + case fields::min_waterfall: + for (int16_t k = -1; k <= 9; k++) { + if (k == -1) { + element->list.push_back({ "N/A", k }); + } + else if (k == 0) { + element->list.push_back({ "Absent", k }); + } + else { + element->list.push_back({ std::to_string(k), k }); + } + } + + break; + case fields::blood_rain: { embark_assist::defs::yes_no_ranges k = embark_assist::defs::yes_no_ranges::NA; @@ -986,8 +1000,8 @@ namespace embark_assist { state->finder_list.push_back({ "Max River", static_cast(i) }); break; - case fields::waterfall: - state->finder_list.push_back({ "Waterfall", static_cast(i) }); + case fields::min_waterfall: + state->finder_list.push_back({ "Min Waterfall Drop", static_cast(i) }); break; case fields::flatness: @@ -1215,9 +1229,8 @@ namespace embark_assist { static_cast(state->ui[static_cast(i)]->current_value); break; - case fields::waterfall: - finder.waterfall = - static_cast(state->ui[static_cast(i)]->current_value); + case fields::min_waterfall: + finder.min_waterfall = state->ui[static_cast(i)]->current_value; break; case fields::flatness: From bcb62697c94ed9a47b6cfa98ca21aa9669fa0f79 Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Mon, 1 Jul 2019 13:29:19 +0200 Subject: [PATCH 093/109] Waterfall detection changed --- plugins/embark-assistant/matcher.cpp | 51 ++++++++++++++++------------ 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/plugins/embark-assistant/matcher.cpp b/plugins/embark-assistant/matcher.cpp index 26463f011..3b483ef18 100644 --- a/plugins/embark-assistant/matcher.cpp +++ b/plugins/embark-assistant/matcher.cpp @@ -40,8 +40,7 @@ namespace embark_assist { bool evilness_found[3] = { false, false, false }; uint16_t aquifer_count = 0; bool river_found = false; - bool waterfall_found = false; - uint16_t river_elevation = 0xffff; + uint8_t max_waterfall = 0; uint16_t elevation = mlt->at(start_x).at(start_y).elevation; bool clay_found = false; bool sand_found = false; @@ -149,12 +148,23 @@ namespace embark_assist { if (finder->max_river != embark_assist::defs::river_ranges::NA && finder->max_river < static_cast(survey_results->at(x).at(y).river_size)) return false; - if (river_found && river_elevation != mlt->at(i).at(k).river_elevation) { - if (finder->waterfall == embark_assist::defs::yes_no_ranges::No) return false; - waterfall_found = true; + if (i < start_x + finder->x_dim - 2 && + mlt->at(i + 1).at(k).river_present && + abs(mlt->at(i).at(k).river_elevation - mlt->at(i + 1).at(k).river_elevation) > max_waterfall) { + if (finder->min_waterfall == 0) return false; // 0 = Absent + max_waterfall = + abs(mlt->at(i).at(k).river_elevation - mlt->at(i + 1).at(k).river_elevation); } + + if (k < start_y + finder->y_dim - 2 && + mlt->at(i).at(k + 1).river_present && + abs(mlt->at(i).at(k).river_elevation - mlt->at(i).at(k + 1).river_elevation) > max_waterfall) { + if (finder->min_waterfall == 0) return false; // 0 = Absent + max_waterfall = + abs(mlt->at(i).at(k).river_elevation - mlt->at(i).at(k + 1).river_elevation); + } + river_found = true; - river_elevation = mlt->at(i).at(k).river_elevation; } // Flatness @@ -335,7 +345,7 @@ namespace embark_assist { // River & Waterfall if (!river_found && finder->min_river > embark_assist::defs::river_ranges::None) return false; - if (finder->waterfall == embark_assist::defs::yes_no_ranges::Yes && !waterfall_found) return false; + if (max_waterfall < finder->min_waterfall) return false; // N/A = -1 is always smaller, so no additional check needed. // Flatness if (!uneven && finder->flatness == embark_assist::defs::flatness_ranges::Uneven) return false; @@ -576,19 +586,10 @@ namespace embark_assist { } // Waterfall - switch (finder->waterfall) { - case embark_assist::defs::yes_no_ranges::NA: - break; // No restriction - - case embark_assist::defs::yes_no_ranges::Yes: - if (!tile->waterfall) return false; - break; - - case embark_assist::defs::yes_no_ranges::No: - if (tile->waterfall && - embark_size == 256) return false; - break; - } + if (finder->min_waterfall > tile->max_waterfall) return false; // N/A = -1 is always smaller + if (finder->min_waterfall == 0 && // Absent + embark_size == 256 && + tile->max_waterfall > 0) return false; // Flat. No world tile checks. Need to look at the details @@ -1060,7 +1061,7 @@ namespace embark_assist { } // Waterfall - if (finder->waterfall == embark_assist::defs::yes_no_ranges::Yes && + if (finder->min_waterfall > 0 && tile->river_size == embark_assist::defs::river_sizes::None) return false; // Flat. No world tile checks. Need to look at the details @@ -1548,7 +1549,7 @@ uint16_t embark_assist::matcher::find(embark_assist::defs::match_iterators *iter return 0; } - if (iterator->finder.waterfall == embark_assist::defs::yes_no_ranges::Yes && + if (iterator->finder.min_waterfall > 0 && iterator->finder.max_river == embark_assist::defs::river_ranges::None) { out.printerr("matcher::find: Will never find any waterfalls with None as max river\n"); return 0; @@ -1560,6 +1561,12 @@ uint16_t embark_assist::matcher::find(embark_assist::defs::match_iterators *iter return 0; } + if (iterator->finder.flatness == embark_assist::defs::flatness_ranges::Flat_Verified && + (iterator->finder.x_dim > 14 || + iterator->finder.y_dim > 14)) { + out.printerr("matcher::find: Can never verify flatness without border around embark\n"); + } + if (iterator->finder.spire_count_max < iterator->finder.spire_count_min && iterator->finder.spire_count_max != -1) { out.printerr("matcher::find: Will never find any matches with max spires < min spires\n"); From 134bcf09a90fd02c26bfa23db9cb36051dae0ef5 Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Mon, 1 Jul 2019 13:29:53 +0200 Subject: [PATCH 094/109] Waterfall detection changed. Aquifer display changed --- plugins/embark-assistant/overlay.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/embark-assistant/overlay.cpp b/plugins/embark-assistant/overlay.cpp index cf25eddf3..494dbcd4a 100644 --- a/plugins/embark-assistant/overlay.cpp +++ b/plugins/embark-assistant/overlay.cpp @@ -355,16 +355,16 @@ void embark_assist::overlay::set_embark(embark_assist::defs::site_infos *site_in if (site_info->aquifer) { if (site_info->aquifer_full) { - state->embark_info.push_back({ Screen::Pen(' ', COLOR_BLUE), "Aquifer" }); + state->embark_info.push_back({ Screen::Pen(' ', COLOR_LIGHTBLUE), "Full Aquifer" }); } else { - state->embark_info.push_back({ Screen::Pen(' ', COLOR_LIGHTBLUE), "Aquifer" }); + state->embark_info.push_back({ Screen::Pen(' ', COLOR_LIGHTBLUE), "Part. Aquifer" }); } } - if (site_info->waterfall) { - state->embark_info.push_back({ Screen::Pen(' ', COLOR_BLUE), "Waterfall" }); + if (site_info->max_waterfall > 0) { + state->embark_info.push_back({ Screen::Pen(' ', COLOR_LIGHTBLUE), "Waterfall " + std::to_string(site_info->max_waterfall) }); } if (site_info->flux) { From 53cf1136fb59f7bbcb55f60c92d169e31853fced Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Mon, 1 Jul 2019 13:30:16 +0200 Subject: [PATCH 095/109] Waterfall detection changed --- plugins/embark-assistant/survey.cpp | 50 ++++++++++++++++------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/plugins/embark-assistant/survey.cpp b/plugins/embark-assistant/survey.cpp index d79396118..42a766674 100644 --- a/plugins/embark-assistant/survey.cpp +++ b/plugins/embark-assistant/survey.cpp @@ -567,7 +567,7 @@ void embark_assist::survey::high_level_world_survey(embark_assist::defs::geo_dat results.coal_count = 0; results.min_region_soil = 10; results.max_region_soil = 0; - results.waterfall = false; + results.max_waterfall = 0; results.savagery_count[0] = 0; results.savagery_count[1] = 0; results.savagery_count[2] = 0; @@ -976,9 +976,6 @@ void embark_assist::survey::survey_mid_level_tile(embark_assist::defs::geo_data survey_results->at(x).at(y).evilness_count[1] = 0; survey_results->at(x).at(y).evilness_count[2] = 0; - bool river_elevation_found = false; - int16_t river_elevation = 0; - for (uint8_t i = 0; i < 16; i++) { for (uint8_t k = 0; k < 16; k++) { if (mlt->at(i).at(k).aquifer) { survey_results->at(x).at(y).aquifer_count++; } @@ -996,15 +993,20 @@ void embark_assist::survey::survey_mid_level_tile(embark_assist::defs::geo_data } if (mlt->at(i).at(k).river_present) { - if (river_elevation_found) { - if (mlt->at(i).at(k).river_elevation != river_elevation) - { - survey_results->at(x).at(y).waterfall = true; - } + if (i < 15 && + mlt->at(i + 1).at(k).river_present && + abs (mlt->at(i).at(k).river_elevation - mlt->at(i + 1).at(k).river_elevation) > + survey_results->at(x).at(y).max_waterfall) { + survey_results->at(x).at(y).max_waterfall = + abs(mlt->at(i).at(k).river_elevation - mlt->at(i + 1).at(k).river_elevation); } - else { - river_elevation_found = true; - river_elevation = mlt->at(i).at(k).river_elevation; + + if (k < 15 && + mlt->at(i).at(k + 1).river_present && + abs(mlt->at(i).at(k).river_elevation - mlt->at(i).at(k + 1).river_elevation) > + survey_results->at(x).at(y).max_waterfall) { + survey_results->at(x).at(y).max_waterfall = + abs(mlt->at(i).at(k).river_elevation - mlt->at(i).at(k + 1).river_elevation); } } @@ -1202,8 +1204,6 @@ void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles * int16_t elevation = 0; uint16_t x = screen->location.region_pos.x; uint16_t y = screen->location.region_pos.y; - bool river_found = false; - int16_t river_elevation = 0; std::vector metals(state->max_inorganic); std::vector economics(state->max_inorganic); std::vector minerals(state->max_inorganic); @@ -1224,7 +1224,7 @@ void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles * site_info->min_soil = 10; site_info->max_soil = 0; site_info->flatness = embark_assist::defs::flatnesses::Mostly_Flat; - site_info->waterfall = false; + site_info->max_waterfall = 0; site_info->clay = false; site_info->sand = false; site_info->flux = false; @@ -1258,14 +1258,20 @@ void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles * } if (mlt->at(i).at(k).river_present) { - if (river_found) { - if (river_elevation != mlt->at(i).at(k).river_elevation) { - site_info->waterfall = true; - } + if (i < 15 && + mlt->at(i + 1).at(k).river_present && + abs(mlt->at(i).at(k).river_elevation - mlt->at(i + 1).at(k).river_elevation) > + site_info->max_waterfall) { + site_info->max_waterfall = + abs(mlt->at(i).at(k).river_elevation - mlt->at(i + 1).at(k).river_elevation); } - else { - river_elevation = mlt->at(i).at(k).river_elevation; - river_found = true; + + if (k < 15 && + mlt->at(i).at(k + 1).river_present && + abs(mlt->at(i).at(k).river_elevation - mlt->at(i).at(k + 1).river_elevation) > + site_info->max_waterfall) { + site_info->max_waterfall = + abs(mlt->at(i).at(k).river_elevation - mlt->at(i).at(k + 1).river_elevation); } } From c1259267272675f3ec7edbf0d998be01e7dab40c Mon Sep 17 00:00:00 2001 From: lethosor Date: Wed, 10 Jul 2019 19:21:23 -0400 Subject: [PATCH 096/109] Update submodules and Authors.rst Ref #1432 Ref dfhack/stonesense#54 Ref dfhack/scripts#93 --- docs/Authors.rst | 2 ++ library/xml | 2 +- plugins/stonesense | 2 +- scripts | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/Authors.rst b/docs/Authors.rst index 963d65fde..5c3aae2fd 100644 --- a/docs/Authors.rst +++ b/docs/Authors.rst @@ -69,6 +69,7 @@ Kris Parker kaypy Kromtec Kromtec Kurik Amudnil Lethosor lethosor +LordGolias LordGolias Mason11987 Mason11987 Matt Regul mattregul Matthew Cline @@ -87,6 +88,7 @@ Milo Christiansen milochristiansen MithrilTuxedo MithrilTuxedo mizipzor mizipzor moversti moversti +napagokc napagokc Neil Little nmlittle Nick Rart nickrart comestible Nikolay Amiantov abbradar diff --git a/library/xml b/library/xml index 2be1fc4af..c192f9798 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 2be1fc4afea4d3345b9b76d0f27f56087ac9b6e0 +Subproject commit c192f9798b5d134e777b1f37c8ebc0df4bd53bda diff --git a/plugins/stonesense b/plugins/stonesense index 6b4df3995..03e96477c 160000 --- a/plugins/stonesense +++ b/plugins/stonesense @@ -1 +1 @@ -Subproject commit 6b4df3995f53e0579fc590a78d68e54fc2ca2b81 +Subproject commit 03e96477ca84e42c87db93bd2d781c73687795a8 diff --git a/scripts b/scripts index c8394fa75..189d0d8f6 160000 --- a/scripts +++ b/scripts @@ -1 +1 @@ -Subproject commit c8394fa75ff20abcdcdbe975dbf157d21882172e +Subproject commit 189d0d8f63b5d34ac3f779254b6ab5ff4763459a From 8248832cbcb9e8993ce0e559b44fb47c9c43d43a Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Fri, 12 Jul 2019 22:09:03 +0200 Subject: [PATCH 097/109] Added detection and use of incursions into embark tiles --- build/win64/install-debug.bat | 4 +- docs/changelog.txt | 4 +- plugins/embark-assistant/defs.h | 34 +- plugins/embark-assistant/embark-assistant.cpp | 9 +- plugins/embark-assistant/finder_ui.cpp | 45 +- plugins/embark-assistant/help_ui.cpp | 136 +- plugins/embark-assistant/matcher.cpp | 993 ++++++++++++--- plugins/embark-assistant/overlay.cpp | 61 +- plugins/embark-assistant/survey.cpp | 1117 ++++++++++++++++- plugins/embark-assistant/survey.h | 43 + 10 files changed, 2141 insertions(+), 305 deletions(-) diff --git a/build/win64/install-debug.bat b/build/win64/install-debug.bat index 34668945c..64b5ae850 100644 --- a/build/win64/install-debug.bat +++ b/build/win64/install-debug.bat @@ -1,4 +1,4 @@ -call "%ProgramFiles(x86)%\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64 +call "D:\Program (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64 cd VC2015 msbuild /m /p:Platform=x64 /p:Configuration=RelWithDebInfo INSTALL.vcxproj -cd .. +cd .. \ No newline at end of file diff --git a/docs/changelog.txt b/docs/changelog.txt index 88b0d59d3..69436490c 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -44,8 +44,10 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: ## Misc Improvements - `embark-assistant`: - - Changed Flat detection to allow search for verified flat terrain by checking surrounding Mid Level Tiles or just mostly/probably flat terrain by checking embark tiles only. - Changed Waterfall detection to look for level drop rather than just presence. + - Changed matching to take incursions, i.e. parts of other biomes, into consideration when evaluating tiles. This allows for e.g. finding multiple biomes on single tile embarks. + - Changed overlay display to show when incursion surveying is incomplete. + - Changed overlay display to show Evil Weather. ## Internals - Fixed some OpenGL build issues with `stonesense` diff --git a/plugins/embark-assistant/defs.h b/plugins/embark-assistant/defs.h index da03c1d7e..9d1c8e888 100644 --- a/plugins/embark-assistant/defs.h +++ b/plugins/embark-assistant/defs.h @@ -3,6 +3,7 @@ #include #include #include +#include "df/world_region_type.h" using namespace std; using std::array; @@ -23,12 +24,6 @@ namespace embark_assist { Major }; - enum class flatnesses { - Flat_Verified, - Mostly_Flat, - Uneven - }; - struct mid_level_tile { bool aquifer = false; bool clay = false; @@ -88,6 +83,16 @@ namespace embark_assist { std::vector metals; std::vector economics; std::vector minerals; + mid_level_tile north_row[16]; + mid_level_tile south_row[16]; + mid_level_tile west_column[16]; + mid_level_tile east_column[16]; + uint8_t north_corner_selection[16]; // 0 - 3. For some reason DF stores everything needed for incursion + uint8_t west_corner_selection[16]; // detection in 17:th row/colum data in the region details except + // this info, so we have to go to neighboring world tiles to fetch it. + df::world_region_type region_type[16][16]; // Required for incursion override detection. We could store only the + // edges, but storing it for every tile allows for a unified fetching + // logic. }; struct geo_datum { @@ -113,16 +118,22 @@ namespace embark_assist { }; struct site_infos { + bool incursions_processed; bool aquifer; bool aquifer_full; uint8_t min_soil; uint8_t max_soil; - flatnesses flatness; + bool flat; uint8_t max_waterfall; bool clay; bool sand; bool flux; bool coal; + bool blood_rain; + bool permanent_syndrome_rain; + bool temporary_syndrome_rain; + bool reanimating; + bool thralling; std::vector metals; std::vector economics; std::vector minerals; @@ -180,13 +191,6 @@ namespace embark_assist { Major }; - enum class flatness_ranges : int8_t { - NA = -1, - Flat_Verified, - Mostly_Flat, - Uneven - }; - // For possible future use. That's the level of data actually collected. // enum class adamantine_ranges : int8_t { // NA = -1, @@ -266,7 +270,7 @@ namespace embark_assist { river_ranges min_river; river_ranges max_river; int8_t min_waterfall; // N/A(-1), Absent, 1-9 - flatness_ranges flatness; + yes_no_ranges flat; present_absent_ranges clay; present_absent_ranges sand; present_absent_ranges flux; diff --git a/plugins/embark-assistant/embark-assistant.cpp b/plugins/embark-assistant/embark-assistant.cpp index 972da12f9..22dd21298 100644 --- a/plugins/embark-assistant/embark-assistant.cpp +++ b/plugins/embark-assistant/embark-assistant.cpp @@ -62,7 +62,10 @@ namespace embark_assist { &state->survey_results, &mlt); - embark_assist::survey::survey_embark(&mlt, &state->site_info, false); + embark_assist::survey::survey_embark(&mlt, + &state->survey_results, + &state->site_info, + false); embark_assist::overlay::set_embark(&state->site_info); embark_assist::survey::survey_region_sites(&state->region_sites); @@ -272,7 +275,7 @@ command_result embark_assistant(color_ostream &out, std::vector & } embark_assist::main::state->survey_results[i][k].metals.resize(embark_assist::main::state->max_inorganic); embark_assist::main::state->survey_results[i][k].economics.resize(embark_assist::main::state->max_inorganic); - embark_assist::main::state->survey_results[i][k].minerals.resize(embark_assist::main::state->max_inorganic); + embark_assist::main::state->survey_results[i][k].minerals.resize(embark_assist::main::state->max_inorganic); } } @@ -291,7 +294,7 @@ command_result embark_assistant(color_ostream &out, std::vector & embark_assist::defs::mid_level_tiles mlt; embark_assist::survey::survey_mid_level_tile(&embark_assist::main::state->geo_summary, &embark_assist::main::state->survey_results, &mlt); - embark_assist::survey::survey_embark(&mlt, &embark_assist::main::state->site_info, false); + embark_assist::survey::survey_embark(&mlt, &embark_assist::main::state->survey_results, &embark_assist::main::state->site_info, false); embark_assist::overlay::set_embark(&embark_assist::main::state->site_info); return CR_OK; diff --git a/plugins/embark-assistant/finder_ui.cpp b/plugins/embark-assistant/finder_ui.cpp index 6e710f3bd..80c61dc6e 100644 --- a/plugins/embark-assistant/finder_ui.cpp +++ b/plugins/embark-assistant/finder_ui.cpp @@ -40,7 +40,7 @@ namespace embark_assist { min_river, max_river, min_waterfall, - flatness, + flat, clay, sand, flux, @@ -468,6 +468,7 @@ namespace embark_assist { break; case fields::blood_rain: + case fields::flat: { embark_assist::defs::yes_no_ranges k = embark_assist::defs::yes_no_ranges::NA; while (true) { @@ -495,38 +496,6 @@ namespace embark_assist { break; - case fields::flatness: - { - embark_assist::defs::flatness_ranges k = embark_assist::defs::flatness_ranges::NA; - while (true) { - switch (k) { - case embark_assist::defs::flatness_ranges::NA: - element->list.push_back({ "N/A", static_cast(k) }); - break; - - case embark_assist::defs::flatness_ranges::Flat_Verified: - element->list.push_back({ "Flat Verified", static_cast(k) }); - break; - - case embark_assist::defs::flatness_ranges::Mostly_Flat: - element->list.push_back({ "Mostly Flat", static_cast(k) }); - break; - - case embark_assist::defs::flatness_ranges::Uneven: - element->list.push_back({ "Uneven", static_cast(k) }); - break; - } - - if (k == embark_assist::defs::flatness_ranges::Uneven) { - break; - } - - k = static_cast (static_cast(k) + 1); - } - } - - break; - case fields::soil_min_everywhere: { embark_assist::defs::all_present_ranges k = embark_assist::defs::all_present_ranges::All; @@ -1004,8 +973,8 @@ namespace embark_assist { state->finder_list.push_back({ "Min Waterfall Drop", static_cast(i) }); break; - case fields::flatness: - state->finder_list.push_back({ "Flatness", static_cast(i) }); + case fields::flat: + state->finder_list.push_back({ "Flat", static_cast(i) }); break; case fields::soil_min_everywhere: @@ -1233,9 +1202,9 @@ namespace embark_assist { finder.min_waterfall = state->ui[static_cast(i)]->current_value; break; - case fields::flatness: - finder.flatness = - static_cast(state->ui[static_cast(i)]->current_value); + case fields::flat: + finder.flat = + static_cast(state->ui[static_cast(i)]->current_value); break; case fields::soil_min_everywhere: diff --git a/plugins/embark-assistant/help_ui.cpp b/plugins/embark-assistant/help_ui.cpp index 3d281b145..ef1bc2b39 100644 --- a/plugins/embark-assistant/help_ui.cpp +++ b/plugins/embark-assistant/help_ui.cpp @@ -18,7 +18,8 @@ namespace embark_assist{ Intro, General, Finder, - Caveats + Caveats_1, + Caveats_2 }; class ViewscreenHelpUi : public dfhack_viewscreen @@ -56,10 +57,14 @@ namespace embark_assist{ break; case pages::Finder: - current_page = pages::Caveats; + current_page = pages::Caveats_1; break; - case pages::Caveats: + case pages::Caveats_1: + current_page = pages::Caveats_2; + break; + + case pages::Caveats_2: current_page = pages::Intro; break; } @@ -67,7 +72,7 @@ namespace embark_assist{ else if (input->count(df::interface_key::SEC_CHANGETAB)) { switch (current_page) { case pages::Intro: - current_page = pages::Caveats; + current_page = pages::Caveats_2; break; case pages::General: @@ -78,8 +83,12 @@ namespace embark_assist{ current_page = pages::General; break; - case pages::Caveats: - current_page = pages::Intro; + case pages::Caveats_1: + current_page = pages::Finder; + break; + + case pages::Caveats_2: + current_page = pages::Caveats_1; break; } } @@ -135,6 +144,8 @@ namespace embark_assist{ help_text.push_back(" embarking."); help_text.push_back("Below this a Matching World Tiles count is displayed. It shows the number"); help_text.push_back("of World Tiles that have at least one embark matching the Find criteria."); + help_text.push_back("Note that World Tiles are the ones shown on the 'Region' map: the 'World'"); + help_text.push_back("typically merges several World Tiles into each of its tiles."); break; @@ -156,23 +167,25 @@ namespace embark_assist{ help_text.push_back("DF's display of resources in the region DF currently displays. Secondly, the"); help_text.push_back("DF display doesn't take elevation based soil erosion or the magma sea depth"); help_text.push_back("into consideration, so it can display resources that actually are cut away."); - help_text.push_back("(It can be noted that the DFHack Sand indicator does take these elements into"); - help_text.push_back("account)."); + help_text.push_back("Thirdly, it takes 'intrusions', i.e. small sections of neighboring tiles'"); + help_text.push_back("biomes into consideration for many fields."); + help_text.push_back("(It can be noted that the DFHack Sand indicator does take the first two"); + help_text.push_back("elements into account)."); help_text.push_back("The info the Embark Assistant displays is:"); - help_text.push_back("Sand, if present"); - help_text.push_back("Clay, if present"); - help_text.push_back("Min and Max soil depth in the embark rectangle."); - help_text.push_back("Flat indicator if all the tiles in the embark have the same elevation."); - help_text.push_back(" 'Mostly Flat' = Condition above met. 'Flat Verified' = All surrounding tiles"); - help_text.push_back(" also satisfy condition so no biome spill over may result in an"); - help_text.push_back(" elevation difference."); - help_text.push_back("Aquifer indicator, color coded as blue if all tiles have an aquifer and light"); - help_text.push_back("blue if some, but not all, tiles have one."); - help_text.push_back("Waterfall, if the embark has river elevation differences."); - help_text.push_back("Flux, if present"); - help_text.push_back("A list of all metals present in the embark."); + help_text.push_back("Incompl. Survey if all intrusions couldn't be examined because that requires"); + help_text.push_back("info from neighboring world tiles that haven't been surveyed."); + help_text.push_back("Sand, if present, including through intrusions."); + help_text.push_back("Clay, if present, including thorugh intrusions."); + help_text.push_back("Min and Max soil depth in the embark rectangle, including intrusions."); + help_text.push_back("Flat indicator if all the tiles and intrusions have the same elevation."); + help_text.push_back("Aquifer indicator: Part(ial) or Full, when present, including intrusions."); + help_text.push_back("Waterfall and largest Z level drop if the river has elevation differences"); + help_text.push_back("Evil weather, when present: BR = Blood Rain, TS = Temporary Syndrome"); + help_text.push_back("PS = Permanent Syndrome, Re = Reanimating, and Th = Thralling. Intrusions."); + help_text.push_back("Flux, if present. NOT allowing for small intrusion bits."); + help_text.push_back("A list of all metals present in the embark. Not intrusions."); help_text.push_back("A list of all economic minerals present in the embark. Both clays and flux"); - help_text.push_back("stones are economic, so they show up here as well."); + help_text.push_back("stones are economic, so they show up here as well. Not intrusions."); help_text.push_back("In addition to the above, the Find functionality can also produce blinking"); help_text.push_back("overlays over the Local, Region, and World maps to indicate where"); help_text.push_back("matching embarks are found. The Local display marks the top left corner of"); @@ -208,15 +221,17 @@ namespace embark_assist{ help_text.push_back("as long as at least one tile doesn't have one, but it doesn't have to have"); help_text.push_back("any at all."); help_text.push_back("Min/Max rivers should be self explanatory. The Yes and No values of"); - help_text.push_back("Waterfall, Flat, etc. means one has to be Present and Absent respectivey."); + help_text.push_back("Clay, etc. means one has to be Present and Absent respectivey."); + help_text.push_back("Min Waterfall Drop finds embarks with drops of at least that number"); + help_text.push_back("of Z levels, but Absent = no waterfall at all."); help_text.push_back("Min/Max soil uses the same terminology as DF for 1-4. The Min Soil"); help_text.push_back("Everywhere toggles the Min Soil parameter between acting as All and"); - help_text.push_back("and Present."); + help_text.push_back("Present."); help_text.push_back("Freezing allows you to select embarks to select/avoid various freezing"); help_text.push_back("conditions. Note that the minimum temperature is held for only 10 ticks"); help_text.push_back("in many embarks."); help_text.push_back("Syndrome Rain allows you to search for Permanent and Temporary syndromes,"); - help_text.push_back("where Permanent allows for Temporary ones as well, but not the reverse, as"); + help_text.push_back("where Permanent allows for Temporary ones as well, but not the reverse, and"); help_text.push_back("Not Permanent matches everything except Permanent syndromes."); help_text.push_back("Reanimation packages thralling and reanimation into a single search"); help_text.push_back("criterion. Not Tralling means nothing and just reanimation is matched."); @@ -227,16 +242,28 @@ namespace embark_assist{ help_text.push_back("list. Note that Find is a fairly time consuming task (as it is in vanilla)."); break; - case pages::Caveats: - Screen::drawBorder(" Embark Assistant Help/Info Caveats Page "); + case pages::Caveats_1: + Screen::drawBorder(" Embark Assistant Help/Info Caveats 1 Page "); - help_text.push_back("Find searching first does a sanity check (e.g. max < min) and then a rough"); + help_text.push_back("The plugin surveys world tiles through two actions: using the 'f'ind"); + help_text.push_back("function and through manual movement of the embark rectangle between world"); + help_text.push_back("tiles. In both cases the whole world tile is surveyed, regardless of which"); + help_text.push_back("tiles the embark rectangle covers."); + help_text.push_back("'Find' searching first does a sanity check (e.g. max < min) and then a rough"); help_text.push_back("world tile match to find tiles that may have matching embarks. This results"); - help_text.push_back("in an overlay of inverted yellow X on top of the middle world map. Then"); + help_text.push_back("in overlays of inverted yellow X on top of the Region and World maps. Then"); help_text.push_back("those tiles are scanned in detail, one feature shell (16*16 world tile"); help_text.push_back("block) at a time, and the results are displayed as green inverted X on"); - help_text.push_back("the same map (replacing or erasing the yellow ones). region map overlay"); + help_text.push_back("the same map (replacing or erasing the yellow ones). Local map overlay"); help_text.push_back("data is generated as well."); + help_text.push_back("Since 'intrusion' processing requires that the neighboring tiles that may"); + help_text.push_back("provide them are surveyed before the current tile and tiles have to be"); + help_text.push_back("surveyed in some order, the find function can not perform a complete"); + help_text.push_back("survey of prospective embarks that border world tiles yet to be surveyed"); + help_text.push_back("so the very first 'find' will fail to mark such embarks that actually do"); + help_text.push_back("match, while the second and following 'find' operations will locate them"); + help_text.push_back("because critical information from the first scan is kept for subsequent"); + help_text.push_back("ones."); help_text.push_back(""); help_text.push_back("Caveats & technical stuff:"); help_text.push_back("- The Find searching uses simulated cursor movement input to DF to get it"); @@ -245,8 +272,8 @@ namespace embark_assist{ help_text.push_back("- The search strategy causes detailed region data to update surveyed"); help_text.push_back(" world info, and this can cause a subsequent search to generate a smaller"); help_text.push_back(" set of preliminary matches (yellow tiles) than a previous search."); - help_text.push_back(" However, this is a bug only if it causes the search to fail to find"); - help_text.push_back(" actual existing matches."); + help_text.push_back(" Note that the first search can miss a fair number of matches for"); + help_text.push_back(" technical reasons discussed above and below."); help_text.push_back("- The site info is deduced by the author, so there may be errors and"); help_text.push_back(" there are probably site types that end up not being identified."); help_text.push_back("- Aquifer indications are based on the author's belief that they occur"); @@ -258,7 +285,7 @@ namespace embark_assist{ help_text.push_back("- Thralling is determined by whether material interactions causes"); help_text.push_back(" blinking, which the author believes is one of 4 thralling changes."); help_text.push_back("- The geo information is gathered by code which is essentially a"); - help_text.push_back(" copy of parts of prospector's code adapted for this plugin."); + help_text.push_back(" copy of parts of Prospector's code adapted for this plugin."); help_text.push_back("- Clay determination is made by finding the reaction MAKE_CLAY_BRICKS."); help_text.push_back("- Flux determination is made by finding the reaction PIG_IRON_MAKING."); help_text.push_back("- Coal is detected by finding COAL producing reactions on minerals."); @@ -266,13 +293,39 @@ namespace embark_assist{ help_text.push_back(" reaching caverns that have been removed at world gen to fail to be"); help_text.push_back(" generated at all. It's likely this bug also affects magma pools."); help_text.push_back(" This plugin does not address this but scripts can correct it."); - help_text.push_back("- 'Flat Verified' vs 'Mostly Flat': There's no known way to detect"); - help_text.push_back(" if an adjacent Mid Level Tile's biome 'spills over' into a tile."); - help_text.push_back(" 'Flat Verified' means neighbors have the same elevation so spill overs"); - help_text.push_back(" don't matter. 'Mostly Flat' means spill overs may ruin a completely"); - help_text.push_back(" level embark, but might not. Can be used to 'rescue' a world where"); - help_text.push_back(" a 'Flat Verified' match failed."); - help_text.push_back("Version 0.9 2019-06-23"); + + break; + + case pages::Caveats_2: + Screen::drawBorder(" Embark Assistant Help/Info Caveats 2 Page "); + + help_text.push_back("- The plugin detects 'incursions' of neighboring tiles into embarks, but"); + help_text.push_back(" this functionality is incomplete when the incursion comes from a"); + help_text.push_back(" neighboring tile that hasn't been surveyed yet. The embark info displays"); + help_text.push_back(" what it can, while indicating if it is incomplete, while the first 'f'ind"); + help_text.push_back(" will automatically fail to match any embarks that can not be analyzed"); + help_text.push_back(" fully. Such failures only appear on embarks that touch an edge of the"); + help_text.push_back(" world tile, and a second (and all subsequent) searches will be complete."); + help_text.push_back(" Since searches can take considerable time, it's left to the user to decide"); + help_text.push_back(" whether to make a second, completing, search."); + help_text.push_back("- Incursions are taken into consideration when looking for Aquifers,"); + help_text.push_back(" Clay, Sand, Min Soil when Everywhere, Biomes, Regions, Evil Weather,"); + help_text.push_back(" Savagery, Evilness, Freezing and Flatness, but ignored for metals/"); + help_text.push_back(" economics/minerals (including Flux and Coal) as any volumes are typically"); + help_text.push_back(" too small to be of interest. Rivers, Waterfalls, Spires, and Magma Pools"); + help_text.push_back(" are not incursion related features."); + help_text.push_back("- There are special rules for handing of intrusions from Lakes and Oceans,"); + help_text.push_back(" as well as Mountains into everything that isn't a Lake or Ocean, and the"); + help_text.push_back(" rules state that these intrusions should be reversed (i.e. 'normal' biomes"); + help_text.push_back(" should push into Lakes, Oceans, and Mountains, even when the indicators"); + help_text.push_back(" say otherwise). This rule is clear for edges, but not for corners, as it"); + help_text.push_back(" does not specify which of the potentially multiple 'superior' biomes"); + help_text.push_back(" should be used. The plugin uses the arbitrarily selected rule that the"); + help_text.push_back(" touching corner to the NW should be selected if eligible, then the one to"); + help_text.push_back(" the N, followed by the one to the W, and lastly the one acting as the"); + help_text.push_back(" reference. This means there's a risk embarks with such 'trouble' corners"); + help_text.push_back(" may get affected corner(s) evaluated incorrectly."); + help_text.push_back("Version 0.9 2019-07-12"); break; } @@ -320,7 +373,10 @@ namespace embark_assist{ embark_assist::screen::paintString(pen_lr, 3, 9, DFHack::Screen::getKeyDisplay(df::interface_key::CUSTOM_L).c_str()); break; - case pages::Caveats: + case pages::Caveats_1: + break; + + case pages::Caveats_2: break; } dfhack_viewscreen::render(); diff --git a/plugins/embark-assistant/matcher.cpp b/plugins/embark-assistant/matcher.cpp index 3b483ef18..a3975a980 100644 --- a/plugins/embark-assistant/matcher.cpp +++ b/plugins/embark-assistant/matcher.cpp @@ -12,6 +12,7 @@ #include "df/world_data.h" #include "df/world_raws.h" #include "df/world_region.h" +#include "df/world_region_details.h" #include "df/world_region_type.h" #include "matcher.h" @@ -24,32 +25,22 @@ namespace embark_assist { //======================================================================================= - //======================================================================================= - - bool embark_match(embark_assist::defs::world_tile_data *survey_results, - embark_assist::defs::mid_level_tiles *mlt, - uint16_t x, - uint16_t y, - uint16_t start_x, - uint16_t start_y, - embark_assist::defs::finders *finder) { - -// color_ostream_proxy out(Core::getInstance().getConsole()); - df::world_data *world_data = world->world_data; + struct matcher_info { bool savagery_found[3] = { false, false, false }; bool evilness_found[3] = { false, false, false }; - uint16_t aquifer_count = 0; + bool aquifer_absence_found = false; + bool aquifer_presence_found = false; bool river_found = false; uint8_t max_waterfall = 0; - uint16_t elevation = mlt->at(start_x).at(start_y).elevation; + uint16_t elevation; bool clay_found = false; bool sand_found = false; bool flux_found = false; bool coal_found = false; uint8_t max_soil = 0; bool uneven = false; - int16_t min_temperature = survey_results->at(x).at(y).min_temperature[mlt->at(start_x).at(start_y).biome_offset]; - int16_t max_temperature = survey_results->at(x).at(y).max_temperature[mlt->at(start_x).at(start_y).biome_offset]; + int16_t min_temperature; + int16_t max_temperature; bool blood_rain_found = false; bool permanent_syndrome_rain_found = false; bool temporary_syndrome_rain_found = false; @@ -60,15 +51,449 @@ namespace embark_assist { bool biomes[ENUM_LAST_ITEM(biome_type) + 1]; bool region_types[ENUM_LAST_ITEM(world_region_type) + 1]; uint8_t biome_count; - bool metal_1 = finder->metal_1 == -1; - bool metal_2 = finder->metal_2 == -1; - bool metal_3 = finder->metal_3 == -1; - bool economic_1 = finder->economic_1 == -1; - bool economic_2 = finder->economic_2 == -1; - bool economic_3 = finder->economic_3 == -1; - bool mineral_1 = finder->mineral_1 == -1; - bool mineral_2 = finder->mineral_2 == -1; - bool mineral_3 = finder->mineral_3 == -1; + bool metal_1; + bool metal_2; + bool metal_3; + bool economic_1; + bool economic_2; + bool economic_3; + bool mineral_1; + bool mineral_2; + bool mineral_3; + }; + + //======================================================================================= + + void process_embark_incursion(matcher_info *result, + embark_assist::defs::world_tile_data *survey_results, + embark_assist::defs::mid_level_tile *mlt, // Note this is a single tile, as opposed to most usages of this variable name. + embark_assist::defs::finders *finder, + int16_t elevation, + uint16_t x, + uint16_t y, + bool *failed_match) { + + df::world_data *world_data = world->world_data; + + // Savagery & Evilness + { + result->savagery_found[mlt->savagery_level] = true; + result->evilness_found[mlt->evilness_level] = true; + + embark_assist::defs::evil_savagery_ranges l = embark_assist::defs::evil_savagery_ranges::Low; + while (true) { + if (mlt->savagery_level == static_cast(l)) { + if (finder->savagery[static_cast (l)] == + embark_assist::defs::evil_savagery_values::Absent) { + *failed_match = true; + return; + } + } + else { + if (finder->savagery[static_cast (l)] == + embark_assist::defs::evil_savagery_values::All) { + *failed_match = true; + return; + } + } + + if (mlt->evilness_level == static_cast(l)) { + if (finder->evilness[static_cast (l)] == + embark_assist::defs::evil_savagery_values::Absent) { + *failed_match = true; + return; + } + } + else { + if (finder->evilness[static_cast (l)] == + embark_assist::defs::evil_savagery_values::All) { + *failed_match = true; + return; + } + } + + if (l == embark_assist::defs::evil_savagery_ranges::High) break; + l = static_cast (static_cast(l) + 1); + } + } + + // Aquifer + switch (finder->aquifer) { + case embark_assist::defs::aquifer_ranges::NA: + break; + + case embark_assist::defs::aquifer_ranges::All: + if (!mlt->aquifer) { + *failed_match = true; + return; + } + break; + + case embark_assist::defs::aquifer_ranges::Present: + case embark_assist::defs::aquifer_ranges::Partial: + case embark_assist::defs::aquifer_ranges::Not_All: + if (mlt->aquifer) { + result->aquifer_presence_found = true; + } + else { + result->aquifer_absence_found = true; + } + + break; + + case embark_assist::defs::aquifer_ranges::Absent: + if (mlt->aquifer) { + *failed_match = true; + return; + } + break; + } + + // River & Waterfall. N/A for incursions. + + // Flat + if (finder->flat == embark_assist::defs::yes_no_ranges::Yes && + result->elevation != mlt->elevation) { + *failed_match = true; + return; + } + + // Clay + if (mlt->clay) { + if (finder->clay == embark_assist::defs::present_absent_ranges::Absent) { + *failed_match = true; + return; + } + result->clay_found = true; + } + + // Sand + if (mlt->sand) { + if (finder->sand == embark_assist::defs::present_absent_ranges::Absent) { + *failed_match = true; + return; + } + result->sand_found = true; + } + + // Flux. N/A for intrusions. + // Coal. N/A for intrusions + + // Min Soil + if (finder->soil_min != embark_assist::defs::soil_ranges::NA && + mlt->soil_depth < static_cast(finder->soil_min) && + finder->soil_min_everywhere == embark_assist::defs::all_present_ranges::All) { + *failed_match = true; + return; + } + + if (result->max_soil < mlt->soil_depth) { + result->max_soil = mlt->soil_depth; + } + + // Max Soil + if (finder->soil_max != embark_assist::defs::soil_ranges::NA && + mlt->soil_depth > static_cast(finder->soil_max)) { + *failed_match = true; + return; + } + + // Freezing + if (result->min_temperature > survey_results->at(x).at(y).min_temperature[mlt->biome_offset]) { + result->min_temperature = survey_results->at(x).at(y).min_temperature[mlt->biome_offset]; + } + + if (result->max_temperature < survey_results->at(x).at(y).max_temperature[mlt->biome_offset]) { + result->max_temperature = survey_results->at(x).at(y).max_temperature[mlt->biome_offset]; + } + + if (result->min_temperature <= 0 && + finder->freezing == embark_assist::defs::freezing_ranges::Never) { + *failed_match = true; + return; + } + + if (result->max_temperature > 0 && + finder->freezing == embark_assist::defs::freezing_ranges::Permanent) { + *failed_match = true; + return; + } + + // Blood Rain + if (survey_results->at(x).at(y).blood_rain[mlt->biome_offset]) { + if (finder->blood_rain == embark_assist::defs::yes_no_ranges::No) { + *failed_match = true; + return; + } + result->blood_rain_found = true; + } + + // Syndrome Rain, Permanent + if (survey_results->at(x).at(y).permanent_syndrome_rain[mlt->biome_offset]) { + if (finder->syndrome_rain == embark_assist::defs::syndrome_rain_ranges::Temporary || + finder->syndrome_rain == embark_assist::defs::syndrome_rain_ranges::Not_Permanent || + finder->syndrome_rain == embark_assist::defs::syndrome_rain_ranges::None) { + *failed_match = true; + return; + } + result->permanent_syndrome_rain_found = true; + } + + // Syndrome Rain, Temporary + if (survey_results->at(x).at(y).temporary_syndrome_rain[mlt->biome_offset]) { + if (finder->syndrome_rain == embark_assist::defs::syndrome_rain_ranges::Permanent || + finder->syndrome_rain == embark_assist::defs::syndrome_rain_ranges::None) { + *failed_match = true; + return; + } + result->temporary_syndrome_rain_found = true; + } + + // Reanmation + if (survey_results->at(x).at(y).reanimating[mlt->biome_offset]) { + if (finder->reanimation == embark_assist::defs::reanimation_ranges::Thralling || + finder->reanimation == embark_assist::defs::reanimation_ranges::None) { + *failed_match = true; + return; + } + result->reanimation_found = true; + } + + // Thralling + if (survey_results->at(x).at(y).thralling[mlt->biome_offset]) { + if (finder->reanimation == embark_assist::defs::reanimation_ranges::Reanimation || + finder->reanimation == embark_assist::defs::reanimation_ranges::Not_Thralling || + finder->reanimation == embark_assist::defs::reanimation_ranges::None) { + *failed_match = true; + return; + } + result->thralling_found = true; + } + + // Spires. N/A for intrusions + // Magma. N/A for intrusions + // Biomes + + result->biomes[survey_results->at(x).at(y).biome[mlt->biome_offset]] = true; + + // Region Type + result->region_types[world_data->regions[survey_results->at(x).at(y).biome_index[mlt->biome_offset]]->type] = true; + + // Metals. N/A for intrusions + // Economics. N/A for intrusions + } + + //======================================================================================= + + + void process_embark_incursion_mid_level_tile(uint8_t from_direction, + matcher_info *result, + embark_assist::defs::world_tile_data *survey_results, + embark_assist::defs::mid_level_tiles *mlt, + embark_assist::defs::finders *finder, + uint16_t x, + uint16_t y, + uint8_t i, + uint8_t k, + bool *failed_match) { + int8_t fetch_i = i; + int8_t fetch_k = k; + int16_t fetch_x = x; + int16_t fetch_y = y; + df::world_data *world_data = world->world_data; + + // Logic can be implemented with modulo and division, but that's harder to read. + switch (from_direction) { + case 0: + fetch_i = i - 1; + fetch_k = k - 1; + break; + + case 1: + fetch_k = k - 1; + break; + + case 2: + fetch_i = i + 1; + fetch_k = k - 1; + break; + + case 3: + fetch_i = i - 1; + break; + + case 4: + return; // Own tile provides the data, so there's no incursion. + break; + + case 5: + fetch_i = i + 1; + break; + + case 6: + fetch_i = i - 1; + fetch_k = k + 1; + break; + + case 7: + fetch_k = k + 1; + break; + + case 8: + fetch_i = i + 1; + fetch_k = k + 1; + } + + if (fetch_i < 0) { + fetch_x = x - 1; + } + else if (fetch_i > 15) { + fetch_x = x + 1; + } + + if (fetch_k < 0) { + fetch_y = y - 1; + } + else if (fetch_k > 15) { + fetch_y = y + 1; + } + + if (fetch_x < 0 || + fetch_x == world_data->world_width || + fetch_y < 0 || + fetch_y == world_data->world_height) { + return; // We're at the world edge, so no incursions from the outside. + } + + if (!&survey_results->at(fetch_x).at(fetch_y).surveyed) { + *failed_match = true; + return; + } + + if (fetch_k < 0) { + if (fetch_i < 0) { + process_embark_incursion(result, + survey_results, + &survey_results->at(fetch_x).at(fetch_y).south_row[15], + finder, + mlt->at(i).at(k).elevation, + fetch_x, + fetch_y, + failed_match); + } + else if (fetch_i > 15) { + process_embark_incursion(result, + survey_results, + &survey_results->at(fetch_x).at(fetch_y).south_row[0], + finder, + mlt->at(i).at(k).elevation, + fetch_x, + fetch_y, + failed_match); + } + else { + process_embark_incursion(result, + survey_results, + &survey_results->at(fetch_x).at(fetch_y).south_row[i], + finder, + mlt->at(i).at(k).elevation, + fetch_x, + fetch_y, + failed_match); + } + } + else if (fetch_k > 15) { + if (fetch_i < 0) { + process_embark_incursion(result, + survey_results, + &survey_results->at(fetch_x).at(fetch_y).north_row[15], + finder, + mlt->at(i).at(k).elevation, + fetch_x, + fetch_y, + failed_match); + } + else if (fetch_i > 15) { + process_embark_incursion(result, + survey_results, + &survey_results->at(fetch_x).at(fetch_y).north_row[0], + finder, + mlt->at(i).at(k).elevation, + fetch_x, + fetch_y, + failed_match); + } + else { + process_embark_incursion(result, + survey_results, + &survey_results->at(fetch_x).at(fetch_y).north_row[i], + finder, + mlt->at(i).at(k).elevation, + fetch_x, + fetch_y, + failed_match); + } + } + else { + if (fetch_i < 0) { + process_embark_incursion(result, + survey_results, + &survey_results->at(fetch_x).at(fetch_y).east_column[k], + finder, + mlt->at(i).at(k).elevation, + fetch_x, + fetch_y, + failed_match); + } + else if (fetch_i > 15) { + process_embark_incursion(result, + survey_results, + &survey_results->at(fetch_x).at(fetch_y).west_column[k], + finder, + mlt->at(i).at(k).elevation, + fetch_x, + fetch_y, + failed_match); + } + else { + process_embark_incursion(result, + survey_results, + &mlt->at(fetch_i).at(fetch_k), + finder, + mlt->at(i).at(k).elevation, + fetch_x, + fetch_y, + failed_match); + } + } + } + + //======================================================================================= + + bool embark_match(embark_assist::defs::world_tile_data *survey_results, + embark_assist::defs::mid_level_tiles *mlt, + uint16_t x, + uint16_t y, + uint16_t start_x, + uint16_t start_y, + embark_assist::defs::finders *finder) { + +// color_ostream_proxy out(Core::getInstance().getConsole()); + df::world_data *world_data = world->world_data; + matcher_info result; + result.elevation = mlt->at(start_x).at(start_y).elevation; + result.min_temperature = survey_results->at(x).at(y).min_temperature[mlt->at(start_x).at(start_y).biome_offset]; + result.max_temperature = survey_results->at(x).at(y).max_temperature[mlt->at(start_x).at(start_y).biome_offset]; + result.metal_1 = finder->metal_1 == -1; + result.metal_2 = finder->metal_2 == -1; + result.metal_3 = finder->metal_3 == -1; + result.economic_1 = finder->economic_1 == -1; + result.economic_2 = finder->economic_2 == -1; + result.economic_3 = finder->economic_3 == -1; + result.mineral_1 = finder->mineral_1 == -1; + result.mineral_2 = finder->mineral_2 == -1; + result.mineral_3 = finder->mineral_3 == -1; + bool failed_match = false; const uint16_t embark_size = finder->x_dim * finder->y_dim; @@ -77,24 +502,18 @@ namespace embark_assist { finder->biome_1 != -1 || finder->biome_2 != -1 || finder->biome_3 != -1) { - for (uint8_t i = 0; i <= ENUM_LAST_ITEM(biome_type); i++) biomes[i] = false; + for (uint8_t i = 0; i <= ENUM_LAST_ITEM(biome_type); i++) result.biomes[i] = false; } - for (uint8_t i = 0; i <= ENUM_LAST_ITEM(world_region_type); i++) region_types[i] = false; - - if (finder->flatness == embark_assist::defs::flatness_ranges::Flat_Verified && - (start_x == 0 || - start_x + finder->x_dim == 16 || - start_y == 0 || - start_y + finder->y_dim == 16)) return false; + for (uint8_t i = 0; i <= ENUM_LAST_ITEM(world_region_type); i++) result.region_types[i] = false; for (uint16_t i = start_x; i < start_x + finder->x_dim; i++) { for (uint16_t k = start_y; k < start_y + finder->y_dim; k++) { // Savagery & Evilness { - savagery_found[mlt->at(i).at(k).savagery_level] = true; - evilness_found[mlt->at(i).at(k).evilness_level] = true; + result.savagery_found[mlt->at(i).at(k).savagery_level] = true; + result.evilness_found[mlt->at(i).at(k).evilness_level] = true; embark_assist::defs::evil_savagery_ranges l = embark_assist::defs::evil_savagery_ranges::Low; while (true) { @@ -128,17 +547,23 @@ namespace embark_assist { case embark_assist::defs::aquifer_ranges::All: if (!mlt->at(i).at(k).aquifer) return false; - aquifer_count++; + result.aquifer_presence_found = true; break; case embark_assist::defs::aquifer_ranges::Present: case embark_assist::defs::aquifer_ranges::Partial: case embark_assist::defs::aquifer_ranges::Not_All: - if (mlt->at(i).at(k).aquifer) aquifer_count++; + if (mlt->at(i).at(k).aquifer) { + result.aquifer_presence_found = true; + } + else { + result.aquifer_absence_found = true; + } break; case embark_assist::defs::aquifer_ranges::Absent: if (mlt->at(i).at(k).aquifer) return false; + result.aquifer_presence_found = true; break; } @@ -150,52 +575,51 @@ namespace embark_assist { if (i < start_x + finder->x_dim - 2 && mlt->at(i + 1).at(k).river_present && - abs(mlt->at(i).at(k).river_elevation - mlt->at(i + 1).at(k).river_elevation) > max_waterfall) { + abs(mlt->at(i).at(k).river_elevation - mlt->at(i + 1).at(k).river_elevation) > result.max_waterfall) { if (finder->min_waterfall == 0) return false; // 0 = Absent - max_waterfall = + result.max_waterfall = abs(mlt->at(i).at(k).river_elevation - mlt->at(i + 1).at(k).river_elevation); } if (k < start_y + finder->y_dim - 2 && mlt->at(i).at(k + 1).river_present && - abs(mlt->at(i).at(k).river_elevation - mlt->at(i).at(k + 1).river_elevation) > max_waterfall) { + abs(mlt->at(i).at(k).river_elevation - mlt->at(i).at(k + 1).river_elevation) > result.max_waterfall) { if (finder->min_waterfall == 0) return false; // 0 = Absent - max_waterfall = + result.max_waterfall = abs(mlt->at(i).at(k).river_elevation - mlt->at(i).at(k + 1).river_elevation); } - river_found = true; + result.river_found = true; } - // Flatness - if ((finder->flatness == embark_assist::defs::flatness_ranges::Flat_Verified || - finder->flatness == embark_assist::defs::flatness_ranges::Mostly_Flat) && - elevation != mlt->at(i).at(k).elevation) return false; + // Flat + if (finder->flat == embark_assist::defs::yes_no_ranges::Yes && + result.elevation != mlt->at(i).at(k).elevation) return false; - if (elevation != mlt->at(i).at(k).elevation) uneven = true; + if (result.elevation != mlt->at(i).at(k).elevation) result.uneven = true; // Clay if (mlt->at(i).at(k).clay) { if (finder->clay == embark_assist::defs::present_absent_ranges::Absent) return false; - clay_found = true; + result.clay_found = true; } // Sand if (mlt->at(i).at(k).sand) { if (finder->sand == embark_assist::defs::present_absent_ranges::Absent) return false; - sand_found = true; + result.sand_found = true; } // Flux if (mlt->at(i).at(k).flux) { if (finder->flux == embark_assist::defs::present_absent_ranges::Absent) return false; - flux_found = true; + result.flux_found = true; } // Coal if (mlt->at(i).at(k).coal) { if (finder->coal == embark_assist::defs::present_absent_ranges::Absent) return false; - coal_found = true; + result.coal_found = true; } // Min Soil @@ -203,8 +627,8 @@ namespace embark_assist { mlt->at(i).at(k).soil_depth < static_cast(finder->soil_min) && finder->soil_min_everywhere == embark_assist::defs::all_present_ranges::All) return false; - if (max_soil < mlt->at(i).at(k).soil_depth) { - max_soil = mlt->at(i).at(k).soil_depth; + if (result.max_soil < mlt->at(i).at(k).soil_depth) { + result.max_soil = mlt->at(i).at(k).soil_depth; } // Max Soil @@ -212,24 +636,24 @@ namespace embark_assist { mlt->at(i).at(k).soil_depth > static_cast(finder->soil_max)) return false; // Freezing - if (min_temperature > survey_results->at(x).at(y).min_temperature[mlt->at(i).at(k).biome_offset]) { - min_temperature = survey_results->at(x).at(y).min_temperature[mlt->at(i).at(k).biome_offset]; + if (result.min_temperature > survey_results->at(x).at(y).min_temperature[mlt->at(i).at(k).biome_offset]) { + result.min_temperature = survey_results->at(x).at(y).min_temperature[mlt->at(i).at(k).biome_offset]; } - if (max_temperature < survey_results->at(x).at(y).max_temperature[mlt->at(i).at(k).biome_offset]) { - max_temperature = survey_results->at(x).at(y).max_temperature[mlt->at(i).at(k).biome_offset]; + if (result.max_temperature < survey_results->at(x).at(y).max_temperature[mlt->at(i).at(k).biome_offset]) { + result.max_temperature = survey_results->at(x).at(y).max_temperature[mlt->at(i).at(k).biome_offset]; } - if (min_temperature <= 0 && + if (result.min_temperature <= 0 && finder->freezing == embark_assist::defs::freezing_ranges::Never) return false; - if (max_temperature > 0 && + if (result.max_temperature > 0 && finder->freezing == embark_assist::defs::freezing_ranges::Permanent) return false; // Blood Rain if (survey_results->at(x).at(y).blood_rain[mlt->at(i).at(k).biome_offset]) { if (finder->blood_rain == embark_assist::defs::yes_no_ranges::No) return false; - blood_rain_found = true; + result.blood_rain_found = true; } // Syndrome Rain, Permanent @@ -237,21 +661,21 @@ namespace embark_assist { if (finder->syndrome_rain == embark_assist::defs::syndrome_rain_ranges::Temporary || finder->syndrome_rain == embark_assist::defs::syndrome_rain_ranges::Not_Permanent || finder->syndrome_rain == embark_assist::defs::syndrome_rain_ranges::None) return false; - permanent_syndrome_rain_found = true; + result.permanent_syndrome_rain_found = true; } // Syndrome Rain, Temporary if (survey_results->at(x).at(y).temporary_syndrome_rain[mlt->at(i).at(k).biome_offset]) { if (finder->syndrome_rain == embark_assist::defs::syndrome_rain_ranges::Permanent || finder->syndrome_rain == embark_assist::defs::syndrome_rain_ranges::None) return false; - temporary_syndrome_rain_found = true; + result.temporary_syndrome_rain_found = true; } // Reanmation if (survey_results->at(x).at(y).reanimating[mlt->at(i).at(k).biome_offset]) { if (finder->reanimation == embark_assist::defs::reanimation_ranges::Thralling || finder->reanimation == embark_assist::defs::reanimation_ranges::None) return false; - reanimation_found = true; + result.reanimation_found = true; } // Thralling @@ -259,50 +683,345 @@ namespace embark_assist { if (finder->reanimation == embark_assist::defs::reanimation_ranges::Reanimation || finder->reanimation == embark_assist::defs::reanimation_ranges::Not_Thralling || finder->reanimation == embark_assist::defs::reanimation_ranges::None) return false; - thralling_found = true; + result.thralling_found = true; } // Spires if (mlt->at(i).at(k).adamantine_level != -1) { - spire_count++; + result.spire_count++; if (finder->spire_count_max != -1 && - finder->spire_count_max < spire_count) return false; + finder->spire_count_max < result.spire_count) return false; } // Magma if (mlt->at(i).at(k).magma_level != -1) { - if (mlt->at(i).at(k).magma_level > magma_level) + if (mlt->at(i).at(k).magma_level > result.magma_level) { - magma_level = mlt->at(i).at(k).magma_level; + result.magma_level = mlt->at(i).at(k).magma_level; if (finder->magma_max != embark_assist::defs::magma_ranges::NA && - static_cast(finder->magma_max) < magma_level) return false; + static_cast(finder->magma_max) < result.magma_level) return false; } } // Biomes - biomes[survey_results->at(x).at(y).biome[mlt->at(i).at(k).biome_offset]] = true; + result.biomes[survey_results->at(x).at(y).biome[mlt->at(i).at(k).biome_offset]] = true; // Region Type - region_types[world_data->regions[survey_results->at(x).at(y).biome_index[mlt->at(i).at(k).biome_offset]]->type] = true; + result.region_types[world_data->regions[survey_results->at(x).at(y).biome_index[mlt->at(i).at(k).biome_offset]]->type] = true; // Metals - metal_1 = metal_1 || mlt->at(i).at(k).metals[finder->metal_1]; - metal_2 = metal_2 || mlt->at(i).at(k).metals[finder->metal_2]; - metal_3 = metal_3 || mlt->at(i).at(k).metals[finder->metal_3]; + result.metal_1 = result.metal_1 || mlt->at(i).at(k).metals[finder->metal_1]; + result.metal_2 = result.metal_2 || mlt->at(i).at(k).metals[finder->metal_2]; + result.metal_3 = result.metal_3 || mlt->at(i).at(k).metals[finder->metal_3]; // Economics - economic_1 = economic_1 || mlt->at(i).at(k).economics[finder->economic_1]; - economic_2 = economic_2 || mlt->at(i).at(k).economics[finder->economic_2]; - economic_3 = economic_3 || mlt->at(i).at(k).economics[finder->economic_3]; + result.economic_1 = result.economic_1 || mlt->at(i).at(k).economics[finder->economic_1]; + result.economic_2 = result.economic_2 || mlt->at(i).at(k).economics[finder->economic_2]; + result.economic_3 = result.economic_3 || mlt->at(i).at(k).economics[finder->economic_3]; // Minerals - mineral_1 = mineral_1 || mlt->at(i).at(k).minerals[finder->mineral_1]; - mineral_2 = mineral_2 || mlt->at(i).at(k).minerals[finder->mineral_2]; - mineral_3 = mineral_3 || mlt->at(i).at(k).minerals[finder->mineral_3]; + result.mineral_1 = result.mineral_1 || mlt->at(i).at(k).minerals[finder->mineral_1]; + result.mineral_2 = result.mineral_2 || mlt->at(i).at(k).minerals[finder->mineral_2]; + result.mineral_3 = result.mineral_3 || mlt->at(i).at(k).minerals[finder->mineral_3]; } } + // Take incursions into account. + + for (int8_t i = start_x; i < start_x + finder->x_dim; i++) { + + // NW corner, north row + if ((i == 0 && start_y == 0 && x - 1 >= 0 && y - 1 >= 0 && !survey_results->at(x - 1).at(y - 1).surveyed) || + (i == 0 && x - 1 >= 0 && !survey_results->at(x - 1).at(y).surveyed) || + (start_y == 0 && y - 1 >= 0 && !survey_results->at(x).at(y - 1).surveyed)) { + failed_match = true; + } + else { + process_embark_incursion_mid_level_tile + (embark_assist::survey::translate_corner(survey_results, + 4, + x, + y, + i, + start_y), + &result, + survey_results, + mlt, + finder, + x, + y, + i, + start_y, + &failed_match); + } + + // N edge, north row + if (start_y == 0 && y - 1 >= 0 && !survey_results->at(x).at(y - 1).surveyed) { + failed_match = true; + } + else { + process_embark_incursion_mid_level_tile + (embark_assist::survey::translate_ns_edge(survey_results, + true, + x, + y, + i, + start_y), + &result, + survey_results, + mlt, + finder, + x, + y, + i, + start_y, + &failed_match); + } + + // NE corner, north row + if ((i == 15 && start_y == 0 && x + 1 < world_data->world_width && y - 1 >= 0 && !survey_results->at(x + 1).at(y - 1).surveyed) || + (i == 15 && x + 1 < world_data->world_width && !survey_results->at(x + 1).at(y).surveyed) || + (start_y == 0 && y - 1 >= 0 && !survey_results->at(x).at(y - 1).surveyed)) { + failed_match = true; + } + else { + process_embark_incursion_mid_level_tile + (embark_assist::survey::translate_corner(survey_results, + 5, + x, + y, + i, + start_y), + &result, + survey_results, + mlt, + finder, + x, + y, + i, + start_y, + &failed_match); + } + + // SW corner, south row + if ((i == 0 && start_y + finder->y_dim == 16 && x - 1 >= 0 && y + 1 < world_data->world_height && !survey_results->at(x - 1).at(y + 1).surveyed) || + (i == 0 && x - 1 >= 0 && !survey_results->at(x - 1).at(y).surveyed) || + (start_y + finder->y_dim == 16 && y + 1 < world_data->world_height && !survey_results->at(x).at(y + 1).surveyed)) { + failed_match = true; + } + else { + process_embark_incursion_mid_level_tile + (embark_assist::survey::translate_corner(survey_results, + 7, + x, + y, + i, + start_y + finder->y_dim - 1), + &result, + survey_results, + mlt, + finder, + x, + y, + i, + start_y + finder->y_dim - 1, + &failed_match); + } + + // S edge, south row + if (start_y + finder->y_dim == 16 && y + 1 < world_data->world_height && !survey_results->at(x).at(y + 1).surveyed) { + failed_match = true; + } + else { + process_embark_incursion_mid_level_tile + (embark_assist::survey::translate_ns_edge(survey_results, + false, + x, + y, + i, + start_y + finder->y_dim - 1), + &result, + survey_results, + mlt, + finder, + x, + y, + i, + start_y + finder->y_dim - 1, + &failed_match); + } + + // SE corner south row + if ((i == 15 && start_y + finder->y_dim == 16 && x + 1 < world_data->world_width && y + 1 < world_data->world_height && !survey_results->at(x + 1).at(y + 1).surveyed) || + (i == 15 && x + 1 < world_data->world_width && !survey_results->at(x + 1).at(y).surveyed) || + (start_y + finder->y_dim == 16 && y + 1 < world_data->world_height && !survey_results->at(x).at(y + 1).surveyed)) { + failed_match = true; + } + else { + process_embark_incursion_mid_level_tile + (embark_assist::survey::translate_corner(survey_results, + 8, + x, + y, + i, + start_y + finder->y_dim - 1), + &result, + survey_results, + mlt, + finder, + x, + y, + i, + start_y + finder->y_dim - 1, + &failed_match); + } + + if (failed_match) return false; + } + + for (int8_t k = start_y; k < start_y + finder->y_dim; k++) { + // NW corner, west side + if ((start_x == 0 && x - 1 >= 0 && !survey_results->at(x - 1).at(y).surveyed)) { + failed_match = true; + } + else if (k > start_y) { // We've already covered the NW corner of the NW, with its complications. + process_embark_incursion_mid_level_tile + (embark_assist::survey::translate_corner(survey_results, + 4, + x, + y, + start_x, + k), + &result, + survey_results, + mlt, + finder, + x, + y, + start_x, + k, + &failed_match); + } + + // W edge, west side + if (start_x == 0 && x - 1 >= 0 && !survey_results->at(x - 1).at(y).surveyed) { + failed_match = true; + } + else { + process_embark_incursion_mid_level_tile + (embark_assist::survey::translate_ew_edge(survey_results, + true, + x, + y, + start_x, + k), + &result, + survey_results, + mlt, + finder, + x, + y, + start_x, + k, + &failed_match); + } + + // SW corner, west side + if (start_x == 0 && x - 1 >= 0 && !survey_results->at(x - 1).at(y).surveyed) { + failed_match = true; + } + else if (k < start_y + finder->y_dim - 1) { // We've already covered the SW corner of the SW tile, with its complicatinons. + process_embark_incursion_mid_level_tile + (embark_assist::survey::translate_corner(survey_results, + 7, + x, + y, + start_x, + k), + &result, + survey_results, + mlt, + finder, + x, + y, + start_x, + k, + &failed_match); + } + + // NE corner, east side + if ((start_x + finder->x_dim == 16 && x + 1 < world_data->world_width && !survey_results->at(x + 1).at(y).surveyed)) { + failed_match = true; + } + else if (k > start_y) { // We've already covered the NE tile's NE corner, with its complications. + process_embark_incursion_mid_level_tile + (embark_assist::survey::translate_corner(survey_results, + 5, + x, + y, + start_x + finder->x_dim - 1, + k), + &result, + survey_results, + mlt, + finder, + x, + y, + start_x + finder->x_dim - 1, + k, + &failed_match); + } + + // E edge, east side + if (start_x + finder->y_dim == 16 && x + 1 < world_data->world_width && !survey_results->at(x + 1).at(y).surveyed) { + failed_match = true; + } + else { + process_embark_incursion_mid_level_tile + (embark_assist::survey::translate_ew_edge(survey_results, + false, + x, + y, + start_x + finder->x_dim - 1, + k), + &result, + survey_results, + mlt, + finder, + x, + y, + start_x + finder->x_dim - 1, + k, + &failed_match); + } + + // SE corner, east side + if (start_x + finder->x_dim == 16 && x + 1 < world_data->world_width && !survey_results->at(x + 1).at(y).surveyed) { + failed_match = true; + } + else if (k < start_y + finder->y_dim - 1) { // We've already covered the SE tile's SE corner, with its complications. + process_embark_incursion_mid_level_tile + (embark_assist::survey::translate_corner(survey_results, + 8, + x, + y, + start_x + finder->x_dim - 1, + k), + &result, + survey_results, + mlt, + finder, + x, + y, + start_x + finder->x_dim - 1, + k, + &failed_match); + } + + if (failed_match) return false; + } + // Summary section, for all the stuff that require the complete picture // // Savagery & Evilness @@ -312,11 +1031,11 @@ namespace embark_assist { while (true) { if (finder->savagery[static_cast (l)] == embark_assist::defs::evil_savagery_values::Present && - !savagery_found[static_cast(l)]) return false; + !result.savagery_found[static_cast(l)]) return false; if (finder->evilness[static_cast (l)] == embark_assist::defs::evil_savagery_values::Present && - !evilness_found[static_cast(l)]) return false; + !result.evilness_found[static_cast(l)]) return false; if (l == embark_assist::defs::evil_savagery_ranges::High) break; l = static_cast (static_cast(l) + 1); @@ -331,119 +1050,107 @@ namespace embark_assist { break; case embark_assist::defs::aquifer_ranges::Present: - if (aquifer_count == 0) return false; + if (!result.aquifer_presence_found) return false; break; case embark_assist::defs::aquifer_ranges::Partial: - if (aquifer_count == 0 || aquifer_count == embark_size) return false; + if (!result.aquifer_absence_found || !result.aquifer_presence_found) return false; break; case embark_assist::defs::aquifer_ranges::Not_All: - if (aquifer_count == embark_size) return false; + if (!result.aquifer_absence_found) return false; break; } // River & Waterfall - if (!river_found && finder->min_river > embark_assist::defs::river_ranges::None) return false; - if (max_waterfall < finder->min_waterfall) return false; // N/A = -1 is always smaller, so no additional check needed. - - // Flatness - if (!uneven && finder->flatness == embark_assist::defs::flatness_ranges::Uneven) return false; + if (!result.river_found && finder->min_river > embark_assist::defs::river_ranges::None) return false; + if (result.max_waterfall < finder->min_waterfall) return false; // N/A = -1 is always smaller, so no additional check needed. - if (finder->flatness == embark_assist::defs::flatness_ranges::Flat_Verified) { - for (uint16_t i = start_x - 1; i < start_x + finder->x_dim + 1; i++) { - if (elevation != mlt->at(i).at(start_y - 1).elevation || - elevation != mlt->at(i).at(start_y + finder->y_dim).elevation) return false; - } - - for (uint16_t k = start_y; k < start_y + finder->y_dim; k++) { - if (elevation != mlt->at(start_x - 1).at(k).elevation || - elevation != mlt->at(start_x + finder->x_dim).at(k).elevation) return false; - } - } + // Flat + if (!result.uneven && finder->flat == embark_assist::defs::yes_no_ranges::No) return false; // Clay - if (finder->clay == embark_assist::defs::present_absent_ranges::Present && !clay_found) return false; + if (finder->clay == embark_assist::defs::present_absent_ranges::Present && !result.clay_found) return false; // Sand - if (finder->sand == embark_assist::defs::present_absent_ranges::Present && !sand_found) return false; + if (finder->sand == embark_assist::defs::present_absent_ranges::Present && !result.sand_found) return false; // Flux - if (finder->flux == embark_assist::defs::present_absent_ranges::Present && !flux_found) return false; + if (finder->flux == embark_assist::defs::present_absent_ranges::Present && !result.flux_found) return false; // Coal - if (finder->coal == embark_assist::defs::present_absent_ranges::Present && !coal_found) return false; + if (finder->coal == embark_assist::defs::present_absent_ranges::Present && !result.coal_found) return false; // Min Soil if (finder->soil_min != embark_assist::defs::soil_ranges::NA && finder->soil_min_everywhere == embark_assist::defs::all_present_ranges::Present && - max_soil < static_cast(finder->soil_min)) return false; + result.max_soil < static_cast(finder->soil_min)) return false; // Freezing if (finder->freezing == embark_assist::defs::freezing_ranges::At_Least_Partial && - min_temperature > 0) return false; + result.min_temperature > 0) return false; if (finder->freezing == embark_assist::defs::freezing_ranges::Partial && - (min_temperature > 0 || - max_temperature <= 0)) return false; + (result.min_temperature > 0 || + result.max_temperature <= 0)) return false; if (finder->freezing == embark_assist::defs::freezing_ranges::At_Most_Partial && - max_temperature <= 0) return false; + result.max_temperature <= 0) return false; // Blood Rain - if (finder->blood_rain == embark_assist::defs::yes_no_ranges::Yes && !blood_rain_found) return false; + if (finder->blood_rain == embark_assist::defs::yes_no_ranges::Yes && !result.blood_rain_found) return false; // Syndrome Rain - if (finder->syndrome_rain == embark_assist::defs::syndrome_rain_ranges::Any && !permanent_syndrome_rain_found && !temporary_syndrome_rain_found) return false; - if (finder->syndrome_rain == embark_assist::defs::syndrome_rain_ranges::Permanent && !permanent_syndrome_rain_found) return false; - if (finder->syndrome_rain == embark_assist::defs::syndrome_rain_ranges::Temporary && !temporary_syndrome_rain_found) return false; + if (finder->syndrome_rain == embark_assist::defs::syndrome_rain_ranges::Any && !result.permanent_syndrome_rain_found && !result.temporary_syndrome_rain_found) return false; + if (finder->syndrome_rain == embark_assist::defs::syndrome_rain_ranges::Permanent && !result.permanent_syndrome_rain_found) return false; + if (finder->syndrome_rain == embark_assist::defs::syndrome_rain_ranges::Temporary && !result.temporary_syndrome_rain_found) return false; // Reanimation - if (finder->reanimation == embark_assist::defs::reanimation_ranges::Both && !(reanimation_found && thralling_found)) return false; - if (finder->reanimation == embark_assist::defs::reanimation_ranges::Any && !reanimation_found && !thralling_found) return false; - if (finder->reanimation == embark_assist::defs::reanimation_ranges::Thralling && !thralling_found) return false; - if (finder->reanimation == embark_assist::defs::reanimation_ranges::Reanimation && !reanimation_found) return false; + if (finder->reanimation == embark_assist::defs::reanimation_ranges::Both && !(result.reanimation_found && result.thralling_found)) return false; + if (finder->reanimation == embark_assist::defs::reanimation_ranges::Any && !result.reanimation_found && !result.thralling_found) return false; + if (finder->reanimation == embark_assist::defs::reanimation_ranges::Thralling && !result.thralling_found) return false; + if (finder->reanimation == embark_assist::defs::reanimation_ranges::Reanimation && !result.reanimation_found) return false; // Spires - if (finder->spire_count_min != -1 && finder->spire_count_min > spire_count) return false; - if (finder->spire_count_max != -1 && finder->spire_count_max < spire_count) return false; + if (finder->spire_count_min != -1 && finder->spire_count_min > result.spire_count) return false; + if (finder->spire_count_max != -1 && finder->spire_count_max < result.spire_count) return false; // Magma if (// finder->magma_min != embark_assist::defs::magma_ranges::NA && // This check is redundant. - finder->magma_min > static_cast(magma_level)) return false; + finder->magma_min > static_cast(result.magma_level)) return false; // Biomes if (finder->biome_count_min != -1 || finder->biome_count_max != -1) { - biome_count = 0; + result.biome_count = 0; for (uint8_t i = 0; i <= ENUM_LAST_ITEM(biome_type); i++) { - if (biomes[i]) biome_count++; + if (result.biomes[i]) result.biome_count++; } - if (biome_count < finder->biome_count_min || + if (result.biome_count < finder->biome_count_min || (finder->biome_count_max != -1 && - finder->biome_count_max < biome_count)) return false; + finder->biome_count_max < result.biome_count)) return false; } - if (finder->biome_1 != -1 && !biomes[finder->biome_1]) return false; - if (finder->biome_2 != -1 && !biomes[finder->biome_2]) return false; - if (finder->biome_3 != -1 && !biomes[finder->biome_3]) return false; + if (finder->biome_1 != -1 && !result.biomes[finder->biome_1]) return false; + if (finder->biome_2 != -1 && !result.biomes[finder->biome_2]) return false; + if (finder->biome_3 != -1 && !result.biomes[finder->biome_3]) return false; // Region Type - if (finder->region_type_1 != -1 && !region_types[finder->region_type_1]) return false; - if (finder->region_type_2 != -1 && !region_types[finder->region_type_2]) return false; - if (finder->region_type_3 != -1 && !region_types[finder->region_type_3]) return false; + if (finder->region_type_1 != -1 && !result.region_types[finder->region_type_1]) return false; + if (finder->region_type_2 != -1 && !result.region_types[finder->region_type_2]) return false; + if (finder->region_type_3 != -1 && !result.region_types[finder->region_type_3]) return false; // Metals, Economics, and Minerals - if (!metal_1 || - !metal_2 || - !metal_3 || - !economic_1 || - !economic_2 || - !economic_3 || - !mineral_1 || - !mineral_2 || - !mineral_3) return false; + if (!result.metal_1 || + !result.metal_2 || + !result.metal_3 || + !result.economic_1 || + !result.economic_2 || + !result.economic_3 || + !result.mineral_1 || + !result.mineral_2 || + !result.mineral_3) return false; return true; } @@ -1561,12 +2268,6 @@ uint16_t embark_assist::matcher::find(embark_assist::defs::match_iterators *iter return 0; } - if (iterator->finder.flatness == embark_assist::defs::flatness_ranges::Flat_Verified && - (iterator->finder.x_dim > 14 || - iterator->finder.y_dim > 14)) { - out.printerr("matcher::find: Can never verify flatness without border around embark\n"); - } - if (iterator->finder.spire_count_max < iterator->finder.spire_count_min && iterator->finder.spire_count_max != -1) { out.printerr("matcher::find: Will never find any matches with max spires < min spires\n"); diff --git a/plugins/embark-assistant/overlay.cpp b/plugins/embark-assistant/overlay.cpp index 494dbcd4a..a0defd0d5 100644 --- a/plugins/embark-assistant/overlay.cpp +++ b/plugins/embark-assistant/overlay.cpp @@ -331,6 +331,10 @@ void embark_assist::overlay::match_progress(uint16_t count, embark_assist::defs: void embark_assist::overlay::set_embark(embark_assist::defs::site_infos *site_info) { state->embark_info.clear(); + if (!site_info->incursions_processed) { + state->embark_info.push_back({ Screen::Pen(' ', COLOR_LIGHTRED), "Incomp. Survey" }); + } + if (site_info->sand) { state->embark_info.push_back({ Screen::Pen(' ', COLOR_YELLOW), "Sand" }); } @@ -345,12 +349,8 @@ void embark_assist::overlay::set_embark(embark_assist::defs::site_infos *site_in state->embark_info.push_back({ Screen::Pen(' ', COLOR_BROWN), "Soil " + std::to_string(site_info->min_soil) + " - " + std::to_string(site_info->max_soil) }); - if (site_info->flatness == embark_assist::defs::flatnesses::Flat_Verified) { - state->embark_info.push_back({ Screen::Pen(' ', COLOR_BROWN), "Flat Verified" }); - } - else if (site_info->flatness == embark_assist::defs::flatnesses::Mostly_Flat) - { - state->embark_info.push_back({ Screen::Pen(' ', COLOR_BROWN), "Mostly Flat" }); + if (site_info->flat) { + state->embark_info.push_back({ Screen::Pen(' ', COLOR_BROWN), "Flat" }); } if (site_info->aquifer) { @@ -367,6 +367,55 @@ void embark_assist::overlay::set_embark(embark_assist::defs::site_infos *site_in state->embark_info.push_back({ Screen::Pen(' ', COLOR_LIGHTBLUE), "Waterfall " + std::to_string(site_info->max_waterfall) }); } + if (site_info->blood_rain || + site_info->permanent_syndrome_rain || + site_info->temporary_syndrome_rain || + site_info->reanimating || + site_info->thralling) { + std::string blood_rain; + std::string permanent_syndrome_rain; + std::string temporary_syndrome_rain; + std::string reanimating; + std::string thralling; + + if (site_info->blood_rain) { + blood_rain = "BR "; + } + else { + blood_rain = " "; + } + + if (site_info->permanent_syndrome_rain) { + permanent_syndrome_rain = "PS "; + } + else { + permanent_syndrome_rain = " "; + } + + if (site_info->temporary_syndrome_rain) { + temporary_syndrome_rain = "TS "; + } + else { + permanent_syndrome_rain = " "; + } + + if (site_info->reanimating) { + reanimating = "Re "; + } + else { + reanimating = " "; + } + + if (site_info->thralling) { + thralling = "Th"; + } + else { + thralling = " "; + } + + state->embark_info.push_back({ Screen::Pen(' ', COLOR_LIGHTRED), blood_rain + temporary_syndrome_rain + permanent_syndrome_rain + reanimating + thralling }); + } + if (site_info->flux) { state->embark_info.push_back({ Screen::Pen(' ', COLOR_WHITE), "Flux" }); } diff --git a/plugins/embark-assistant/survey.cpp b/plugins/embark-assistant/survey.cpp index 42a766674..a2942d415 100644 --- a/plugins/embark-assistant/survey.cpp +++ b/plugins/embark-assistant/survey.cpp @@ -50,6 +50,7 @@ #include "df/world_region.h" #include "df/world_region_details.h" #include "df/world_region_feature.h" +#include "df/world_region_type.h" #include "df/world_river.h" #include "df/world_site.h" #include "df/world_site_type.h" @@ -112,7 +113,7 @@ namespace embark_assist { for (uint16_t i = 0; i < world->raws.inorganics.size(); i++) { for (uint16_t k = 0; k < world->raws.inorganics[i]->economic_uses.size(); k++) { for (uint16_t l = 0; l < world->raws.reactions.reactions[world->raws.inorganics[i]->economic_uses[k]]->products.size(); l++) { - df::reaction_product_itemst *product = static_cast(world->raws.reactions.reactions[world->raws.inorganics[i]->economic_uses[k]]->products[l]); + df::reaction_product_itemst *product = static_cast(world->raws.reactions.reactions[world->raws.inorganics[i]->economic_uses[k]]->products[l]); if (product->mat_type == df::builtin_mats::COAL) { state->coals.push_back(i); @@ -172,7 +173,7 @@ namespace embark_assist { } } - for (uint16_t l = 0; l < state->coals.size(); l++) { + for (uint16_t l = 0; l < state->coals.size(); l++) { if (layer->mat_index == state->coals[l]) { geo_summary->at(i).coal_absent = false; break; @@ -229,7 +230,7 @@ namespace embark_assist { //================================================================================= void survey_rivers(embark_assist::defs::world_tile_data *survey_results) { -// color_ostream_proxy out(Core::getInstance().getConsole()); + // color_ostream_proxy out(Core::getInstance().getConsole()); df::world_data *world_data = world->world_data; int16_t x; int16_t y; @@ -327,23 +328,23 @@ namespace embark_assist { thralling = true; } else if (ce_type == df::creature_interaction_effect_type::PAIN || - ce_type == df::creature_interaction_effect_type::SWELLING || - ce_type == df::creature_interaction_effect_type::OOZING || - ce_type == df::creature_interaction_effect_type::BRUISING || - ce_type == df::creature_interaction_effect_type::BLISTERS || - ce_type == df::creature_interaction_effect_type::NUMBNESS || - ce_type == df::creature_interaction_effect_type::PARALYSIS || - ce_type == df::creature_interaction_effect_type::FEVER || - ce_type == df::creature_interaction_effect_type::BLEEDING || - ce_type == df::creature_interaction_effect_type::COUGH_BLOOD || - ce_type == df::creature_interaction_effect_type::VOMIT_BLOOD || - ce_type == df::creature_interaction_effect_type::NAUSEA || - ce_type == df::creature_interaction_effect_type::UNCONSCIOUSNESS || - ce_type == df::creature_interaction_effect_type::NECROSIS || - ce_type == df::creature_interaction_effect_type::IMPAIR_FUNCTION || - ce_type == df::creature_interaction_effect_type::DROWSINESS || - ce_type == df::creature_interaction_effect_type::DIZZINESS || - ce_type == df::creature_interaction_effect_type::ERRATIC_BEHAVIOR) { // Doubtful if possible for region. + ce_type == df::creature_interaction_effect_type::SWELLING || + ce_type == df::creature_interaction_effect_type::OOZING || + ce_type == df::creature_interaction_effect_type::BRUISING || + ce_type == df::creature_interaction_effect_type::BLISTERS || + ce_type == df::creature_interaction_effect_type::NUMBNESS || + ce_type == df::creature_interaction_effect_type::PARALYSIS || + ce_type == df::creature_interaction_effect_type::FEVER || + ce_type == df::creature_interaction_effect_type::BLEEDING || + ce_type == df::creature_interaction_effect_type::COUGH_BLOOD || + ce_type == df::creature_interaction_effect_type::VOMIT_BLOOD || + ce_type == df::creature_interaction_effect_type::NAUSEA || + ce_type == df::creature_interaction_effect_type::UNCONSCIOUSNESS || + ce_type == df::creature_interaction_effect_type::NECROSIS || + ce_type == df::creature_interaction_effect_type::IMPAIR_FUNCTION || + ce_type == df::creature_interaction_effect_type::DROWSINESS || + ce_type == df::creature_interaction_effect_type::DIZZINESS || + ce_type == df::creature_interaction_effect_type::ERRATIC_BEHAVIOR) { // Doubtful if possible for region. if (ce->end == -1) { permanent_syndrome_rain = true; } @@ -446,7 +447,7 @@ namespace embark_assist { } else if (world->world_data->flip_latitude == df::world_data::T_flip_latitude::North || - world->world_data->flip_latitude == df::world_data::T_flip_latitude::South) { + world->world_data->flip_latitude == df::world_data::T_flip_latitude::South) { steps = world->world_data->world_height / 2; if (latitude > steps) { @@ -485,7 +486,7 @@ namespace embark_assist { divisor = (63 / steps * lat); } else if (world->world_data->world_height == 129 || - world->world_data->world_height == 257) { + world->world_data->world_height == 257) { divisor = (64 / steps * lat); } else { @@ -494,6 +495,222 @@ namespace embark_assist { return max_temperature - ceil(divisor * 3 / 4); } + + //================================================================================= + + void process_embark_incursion(embark_assist::defs::site_infos *site_info, + embark_assist::defs::world_tile_data *survey_results, + embark_assist::defs::mid_level_tile *mlt, // Note this is a single tile, as opposed to most usages of this variable name. + int16_t elevation, + uint16_t x, + uint16_t y) { + + if (mlt->aquifer) { + site_info->aquifer = true; + } + else { + site_info->aquifer_full = false; + } + + if (mlt->soil_depth < site_info->min_soil) { + site_info->min_soil = mlt->soil_depth; + } + + if (mlt->soil_depth > site_info->max_soil) { + site_info->max_soil = mlt->soil_depth; + } + + if (elevation != mlt->elevation) { + site_info->flat = false; + } + + if (mlt->clay) { + site_info->clay = true; + } + + if (mlt->sand) { + site_info->sand = true; + } + + if (survey_results->at(x).at(y).blood_rain [mlt->biome_offset]) { + site_info->blood_rain = true; + } + + if (survey_results->at(x).at(y).permanent_syndrome_rain[mlt->biome_offset]) { + site_info->permanent_syndrome_rain = true; + } + + if (survey_results->at(x).at(y).temporary_syndrome_rain[mlt->biome_offset]) { + site_info->temporary_syndrome_rain = true; + } + + if (survey_results->at(x).at(y).reanimating[mlt->biome_offset]) { + site_info->reanimating = true; + } + + if (survey_results->at(x).at(y).thralling[mlt->biome_offset]) { + site_info->thralling = true; + } + } + + //================================================================================= + + void process_embark_incursion_mid_level_tile(uint8_t from_direction, + embark_assist::defs::site_infos *site_info, + embark_assist::defs::world_tile_data *survey_results, + embark_assist::defs::mid_level_tiles *mlt, + uint8_t i, + uint8_t k) { + + int8_t fetch_i = i; + int8_t fetch_k = k; + int16_t fetch_x = state->x; + int16_t fetch_y = state->y; + df::world_data *world_data = world->world_data; + + // Logic can be implemented with modulo and division, but that's harder to read. + switch (from_direction) { + case 0: + fetch_i = i - 1; + fetch_k = k - 1; + break; + + case 1: + fetch_k = k - 1; + break; + + case 2: + fetch_i = i + 1; + fetch_k = k - 1; + break; + + case 3: + fetch_i = i - 1; + break; + + case 4: + return; // Own tile provides the data, so there's no incursion. + break; + + case 5: + fetch_i = i + 1; + break; + + case 6: + fetch_i = i - 1; + fetch_k = k + 1; + break; + + case 7: + fetch_k = k + 1; + break; + + case 8: + fetch_i = i + 1; + fetch_k = k + 1; + break; + } + + if (fetch_i < 0) { + fetch_x = state->x - 1; + } + else if (fetch_i > 15) { + fetch_x = state->x + 1; + } + + if (fetch_k < 0) { + fetch_y = state->y - 1; + } + else if (fetch_k > 15) { + fetch_y = state->y + 1; + } + + if (fetch_x < 0 || + fetch_x == world_data->world_width || + fetch_y < 0 || + fetch_y == world_data->world_height) { + return; // We're at the world edge, so no incursions from the outside. + } + + if (fetch_k < 0) { + if (fetch_i < 0) { + process_embark_incursion(site_info, + survey_results, + &survey_results->at(fetch_x).at(fetch_y).south_row[15], + mlt->at(i).at(k).elevation, + fetch_x, + fetch_y); + } + else if (fetch_i > 15) { + process_embark_incursion(site_info, + survey_results, + &survey_results->at(fetch_x).at(fetch_y).south_row[0], + mlt->at(i).at(k).elevation, + fetch_x, + fetch_y); + } + else { + process_embark_incursion(site_info, + survey_results, + &survey_results->at(fetch_x).at(fetch_y).south_row[i], + mlt->at(i).at(k).elevation, + fetch_x, + fetch_y); + } + } + else if (fetch_k > 15) { + if (fetch_i < 0) { + process_embark_incursion(site_info, + survey_results, + &survey_results->at(fetch_x).at(fetch_y).north_row[15], + mlt->at(i).at(k).elevation, + fetch_x, + fetch_y); + } + else if (fetch_i > 15) { + process_embark_incursion(site_info, + survey_results, + &survey_results->at(fetch_x).at(fetch_y).north_row[0], + mlt->at(i).at(k).elevation, + fetch_x, + fetch_y); + } + else { + process_embark_incursion(site_info, + survey_results, + &survey_results->at(fetch_x).at(fetch_y).north_row[i], + mlt->at(i).at(k).elevation, + fetch_x, + fetch_y); + } + } + else { + if (fetch_i < 0) { + process_embark_incursion(site_info, + survey_results, + &survey_results->at(fetch_x).at(fetch_y).east_column[k], + mlt->at(i).at(k).elevation, + fetch_x, + fetch_y); + } + else if (fetch_i > 15) { + process_embark_incursion(site_info, + survey_results, + &survey_results->at(fetch_x).at(fetch_y).west_column[k], + mlt->at(i).at(k).elevation, + fetch_x, + fetch_y); + } + else { + process_embark_incursion(site_info, + survey_results, + &mlt->at(fetch_i).at(fetch_k), + mlt->at(i).at(k).elevation, + fetch_x, + fetch_y); + } + } + } } } @@ -1051,8 +1268,111 @@ void embark_assist::survey::survey_mid_level_tile(embark_assist::defs::geo_data } tile->biome_count = count; + + for (uint8_t i = 0; i < 16; i++) { + tile->north_row[i].aquifer = mlt->at(i).at(0).aquifer; + tile->south_row[i].aquifer = mlt->at(i).at(15).aquifer; + tile->west_column[i].aquifer = mlt->at(0).at(i).aquifer; + tile->east_column[i].aquifer = mlt->at(15).at(i).aquifer; + + tile->north_row[i].clay= mlt->at(i).at(0).clay; + tile->south_row[i].clay = mlt->at(i).at(15).clay; + tile->west_column[i].clay = mlt->at(0).at(i).clay; + tile->east_column[i].clay = mlt->at(15).at(i).clay; + + tile->north_row[i].sand = mlt->at(i).at(0).sand; + tile->south_row[i].sand = mlt->at(i).at(15).sand; + tile->west_column[i].sand = mlt->at(0).at(i).sand; + tile->east_column[i].sand = mlt->at(15).at(i).sand; + + tile->north_row[i].flux = mlt->at(i).at(0).flux; // Not used + tile->south_row[i].flux = mlt->at(i).at(15).flux; + tile->west_column[i].flux = mlt->at(0).at(i).flux; + tile->east_column[i].flux = mlt->at(15).at(i).flux; + + tile->north_row[i].coal = mlt->at(i).at(0).coal; // Not used + tile->south_row[i].coal = mlt->at(i).at(15).coal; + tile->west_column[i].coal = mlt->at(0).at(i).coal; + tile->east_column[i].coal = mlt->at(15).at(i).coal; + + tile->north_row[i].soil_depth = mlt->at(i).at(0).soil_depth; + tile->south_row[i].soil_depth = mlt->at(i).at(15).soil_depth; + tile->west_column[i].soil_depth = mlt->at(0).at(i).soil_depth; + tile->east_column[i].soil_depth = mlt->at(15).at(i).soil_depth; + + tile->north_row[i].offset = mlt->at(i).at(0).offset; // Not used + tile->south_row[i].offset = mlt->at(i).at(15).offset; + tile->west_column[i].offset = mlt->at(0).at(i).offset; + tile->east_column[i].offset = mlt->at(15).at(i).offset; + + tile->north_row[i].elevation = mlt->at(i).at(0).elevation; + tile->south_row[i].elevation = mlt->at(i).at(15).elevation; + tile->west_column[i].elevation = mlt->at(0).at(i).elevation; + tile->east_column[i].elevation = mlt->at(15).at(i).elevation; + + tile->north_row[i].river_present = mlt->at(i).at(0).river_present; // Not used + tile->south_row[i].river_present = mlt->at(i).at(15).river_present; + tile->west_column[i].river_present = mlt->at(0).at(i).river_present; + tile->east_column[i].river_present = mlt->at(15).at(i).river_present; + + tile->north_row[i].river_elevation = mlt->at(i).at(0).river_elevation; // Not used + tile->south_row[i].river_elevation = mlt->at(i).at(15).river_elevation; + tile->west_column[i].river_elevation = mlt->at(0).at(i).river_elevation; + tile->east_column[i].river_elevation = mlt->at(15).at(i).river_elevation; + + tile->north_row[i].adamantine_level = mlt->at(i).at(0).adamantine_level; // Not used + tile->south_row[i].adamantine_level = mlt->at(i).at(15).adamantine_level; + tile->west_column[i].adamantine_level = mlt->at(0).at(i).adamantine_level; + tile->east_column[i].adamantine_level = mlt->at(15).at(i).adamantine_level; + + tile->north_row[i].magma_level = mlt->at(i).at(0).magma_level; // Not used + tile->south_row[i].magma_level = mlt->at(i).at(15).magma_level; + tile->west_column[i].magma_level = mlt->at(0).at(i).magma_level; + tile->east_column[i].magma_level = mlt->at(15).at(i).magma_level; + + tile->north_row[i].biome_offset = mlt->at(i).at(0).biome_offset; + tile->south_row[i].biome_offset = mlt->at(i).at(15).biome_offset; + tile->west_column[i].biome_offset = mlt->at(0).at(i).biome_offset; + tile->east_column[i].biome_offset = mlt->at(15).at(i).biome_offset; + + tile->north_row[i].savagery_level = mlt->at(i).at(0).savagery_level; + tile->south_row[i].savagery_level = mlt->at(i).at(15).savagery_level; + tile->west_column[i].savagery_level = mlt->at(0).at(i).savagery_level; + tile->east_column[i].savagery_level = mlt->at(15).at(i).savagery_level; + + tile->north_row[i].evilness_level = mlt->at(i).at(0).evilness_level; + tile->south_row[i].evilness_level = mlt->at(i).at(15).evilness_level; + tile->west_column[i].evilness_level = mlt->at(0).at(i).evilness_level; + tile->east_column[i].evilness_level = mlt->at(15).at(i).evilness_level; + + tile->north_row[i].metals.resize(0); // Not used + tile->south_row[i].metals.resize(0); + tile->west_column[i].metals.resize(0); + tile->east_column[i].metals.resize(0); + + tile->north_row[i].economics.resize(0); // Not used + tile->south_row[i].economics.resize(0); + tile->west_column[i].economics.resize(0); + tile->east_column[i].economics.resize(0); + + tile->north_row[i].minerals.resize(0); // Not used + tile->south_row[i].minerals.resize(0); + tile->west_column[i].minerals.resize(0); + tile->east_column[i].minerals.resize(0); + + tile->north_corner_selection[i] = world_data->region_details[0]->edges.biome_corner[i][0]; + tile->west_corner_selection[i] = world_data->region_details[0]->edges.biome_corner[0][i]; + } + + for (uint8_t i = 0; i < 16; i++) { + for (uint8_t k = 0; k < 16; k++) { + tile->region_type[i][k] = world_data->regions[tile->biome[mlt->at(i).at(k).biome_offset]]->type; + } + } + tile->surveyed = true; } + //================================================================================= df::coord2d embark_assist::survey::apply_offset(uint16_t x, uint16_t y, int8_t offset) { @@ -1124,6 +1444,454 @@ df::coord2d embark_assist::survey::apply_offset(uint16_t x, uint16_t y, int8_t o //================================================================================= +void adjust_coordinates(int16_t *x, int16_t *y, int8_t *i, int8_t *k) { + if (*i < 0) { + *x = *x - 1; + *i = *i + 16; + } + else if (*i > 15) { + *x = *x + 1; + *i = *i - 16; + } + + if (*k < 0) { + *y = *y - 1; + *k = *k + 16; + } + else if (*k > 15) { + *y = *y + 1; + *k = *k - 16; + } +} + +//================================================================================= + +df::world_region_type embark_assist::survey::region_type_of(embark_assist::defs::world_tile_data *survey_results, + int16_t x, + int16_t y, + int8_t i, + int8_t k) { + + df::world_data *world_data = world->world_data; + int16_t effective_x = x; + int16_t effective_y = y; + int8_t effective_i = i; + int8_t effective_k = k; + adjust_coordinates(&effective_x, &effective_y, &effective_i, &effective_i); + + if (effective_x < 0 || + effective_x >= world_data->world_width || + effective_y < 0 || + effective_y >= world_data->world_height) { + return df::world_region_type::Lake; // Essentially dummy value, yielding to everything. It will + // be handled properly later anyway. + } + + return survey_results->at(effective_x).at(effective_y).region_type[effective_i][effective_k]; +} + +//================================================================================= + +uint8_t embark_assist::survey::translate_corner(embark_assist::defs::world_tile_data *survey_results, + uint8_t corner_location, + uint16_t x, + uint16_t y, + uint8_t i, + uint8_t k) { + + df::world_data *world_data = world->world_data; + df::world_region_type nw_region_type; + df::world_region_type n_region_type; + df::world_region_type w_region_type; + df::world_region_type home_region_type; + + int16_t effective_x = x; + int16_t effective_y = y; + int8_t effective_i = i; + int8_t effective_k = k; + + uint8_t effective_corner; + bool nw_region_type_active; + bool n_region_type_active; + bool w_region_type_active; + bool home_region_type_active; + uint8_t nw_region_type_level; + uint8_t n_region_type_level; + uint8_t w_region_type_level; + uint8_t home_region_type_level; + + if (corner_location == 4) { // We're the reference. No change. + } + else if (corner_location == 5) { // Tile to the east is the reference + effective_i = i + 1; + } + else if (corner_location == 7) { // Tile to the south is the reference + effective_k = k + 1; + } + else { // 8, tile to the southeast is the reference. + effective_i = i + 1; + effective_k = k + 1; + } + + adjust_coordinates(&effective_x, &effective_y, &effective_i, &effective_i); + + if (effective_x < 0 || effective_x == world_data->world_width || + effective_y < 0 || effective_y == world_data->world_height) { + effective_x = x; + effective_y = y; + effective_i = i; + effective_k = k; + } + + if (effective_x == x && effective_y == y) { + effective_corner = world_data->region_details[0]->edges.biome_corner[effective_i][effective_k]; + } + else if (effective_y != y) { + effective_corner = survey_results->at(effective_x).at(effective_y).north_corner_selection[effective_i]; + } + else { + effective_corner = survey_results->at(effective_x).at(effective_y).west_corner_selection[effective_k]; + } + + nw_region_type = embark_assist::survey::region_type_of(survey_results, x, y, effective_i - 1, effective_k - 1); + n_region_type = embark_assist::survey::region_type_of(survey_results, x, y, effective_i, effective_k - 1); + w_region_type = embark_assist::survey::region_type_of(survey_results, x, y, effective_i - 1, effective_k); + home_region_type = embark_assist::survey::region_type_of(survey_results, x, y, effective_i, effective_k); + + if (nw_region_type == df::world_region_type::Lake || + nw_region_type == df::world_region_type::Ocean) { + nw_region_type_level = 0; + } + else if (nw_region_type == df::world_region_type::Mountains) { + nw_region_type_level = 1; + } + else { + nw_region_type_level = 2; + } + + if (n_region_type == df::world_region_type::Lake || + n_region_type == df::world_region_type::Ocean) { + n_region_type_level = 0; + } + else if (n_region_type == df::world_region_type::Mountains) { + n_region_type_level = 1; + } + else { + n_region_type_level = 2; + } + + if (w_region_type == df::world_region_type::Lake || + w_region_type == df::world_region_type::Ocean) { + w_region_type_level = 0; + } + else if (w_region_type == df::world_region_type::Mountains) { + w_region_type_level = 1; + } + else { + w_region_type_level = 2; + } + + if (home_region_type == df::world_region_type::Lake || + home_region_type == df::world_region_type::Ocean) { + home_region_type_level = 0; + } + else if (n_region_type == df::world_region_type::Mountains) { + home_region_type_level = 1; + } + else { + home_region_type_level = 2; + } + + nw_region_type_active = nw_region_type_level >= n_region_type_level && + nw_region_type_level >= w_region_type_level && + nw_region_type_level >= home_region_type_level; + + n_region_type_active = n_region_type_level >= nw_region_type_level && + n_region_type_level >= w_region_type_level && + n_region_type_level >= home_region_type_level; + + w_region_type_active = w_region_type_level >= nw_region_type_level && + w_region_type_level >= n_region_type_level && + w_region_type_level >= home_region_type_level; + + home_region_type_active = home_region_type_level >= nw_region_type_level && + home_region_type_level >= n_region_type_level && + home_region_type_level >= w_region_type_level; + + if ((effective_corner == 0 && !nw_region_type_active) || + (effective_corner == 1 && !n_region_type_active) || + (effective_corner == 2 && !w_region_type_active) || + (effective_corner == 3 && !home_region_type_active)) { + //### The designated corner is suppressed, but we do not have any + // knowledge of how to select a replacement. Thus, the presedence + // list used is fairly arbitrary: Use the lowest number available. + if (nw_region_type_active) { + effective_corner = 0; + } + else if (n_region_type_active) { + effective_corner = 1; + } + else if (w_region_type_active) { + effective_corner = 2; + } + else { + effective_corner = 3; + } + } + + switch (effective_corner) { + case 0: + return corner_location - 4; + break; + + case 1: + return corner_location - 3; + break; + + case 2: + return corner_location - 1; + break; + + case 3: + return corner_location; + break; + } + + return -1; // Should never happen + + /* The logic that's reduced to the code above. + switch (corner_location) { + case 0: // N/A Not to the north or west + case 1: // N/A + case 2: // N/A + case 3: // N/A + case 6: // N/A + return -1; // Should never happen + break; + + case 4: // Self + switch (corner) { + case 0: + return 0; // Northwest + break; + + case 1: + return 1; // North + break; + + case 2: + return 3; // West + break; + + case 3: + return 4; // Self + } + + case 5: // East + switch (corner) { + case 0: + return 1; // North + break; + + case 1: + return 2; // Northeast + break; + + case 2: + return 4; // Self + break; + + case 3: + return 5; // East + } + case 7: // South + switch (corner) { + case 0: + return 3; // West + break; + + case 1: + return 4; // Self + break; + + case 2: + return 6; // Southwest + break; + + case 3: + return 7; // South + } + + case 8: // Southeast + switch (corner) { + case 0: + return 4; // Self + break; + + case 1: + return 5; // East + break; + + case 2: + return 7; // South + break; + + case 3: + return 8; // Southeast + } + } + */ +} + +//================================================================================= + +uint8_t embark_assist::survey::translate_ns_edge(embark_assist::defs::world_tile_data *survey_results, + bool own_edge, + uint16_t x, + uint16_t y, + uint8_t i, + uint8_t k) { + + df::world_data *world_data = world->world_data; + uint8_t effective_edge; + df::world_region_type north_region_type; + df::world_region_type south_region_type; + + if (own_edge) { + effective_edge = world_data->region_details[0]->edges.biome_x[i][k]; + south_region_type = embark_assist::survey::region_type_of(survey_results, x, y, i, k); + north_region_type = embark_assist::survey::region_type_of(survey_results, x, y, i, k - 1); + } + else { + effective_edge = world_data->region_details[0]->edges.biome_x[i][k + 1]; + north_region_type = embark_assist::survey::region_type_of(survey_results, x, y, i, k); + south_region_type = embark_assist::survey::region_type_of(survey_results, x, y, i, k + 1); + } + + // Apply rules for Ocean && Lake to yield to everything else, + // and Mountain to everything but those. + // + if ((north_region_type == df::world_region_type::Lake || + north_region_type == df::world_region_type::Ocean) && + south_region_type != df::world_region_type::Lake && + south_region_type != df::world_region_type::Ocean) { + effective_edge = 1; + } + + if ((south_region_type == df::world_region_type::Lake || + south_region_type == df::world_region_type::Ocean) && + north_region_type != df::world_region_type::Lake && + north_region_type != df::world_region_type::Ocean) { + effective_edge = 0; + } + + if (north_region_type == df::world_region_type::Mountains && + south_region_type != df::world_region_type::Lake && + south_region_type != df::world_region_type::Ocean && + south_region_type != df::world_region_type::Mountains) { + effective_edge = 1; + } + + if (south_region_type == df::world_region_type::Mountains && + north_region_type != df::world_region_type::Lake && + north_region_type != df::world_region_type::Ocean && + north_region_type != df::world_region_type::Mountains) { + effective_edge = 0; + } + + if (effective_edge == 0) { + if (own_edge) { + return 1; + } + else { + return 4; + } + } + else { + if (own_edge) { + return 4; + } + else { + return 7; + } + } +} + +//================================================================================= + +uint8_t embark_assist::survey::translate_ew_edge(embark_assist::defs::world_tile_data *survey_results, + bool own_edge, + uint16_t x, + uint16_t y, + uint8_t i, + uint8_t k) { + + df::world_data *world_data = world->world_data; + uint8_t effective_edge; + df::world_region_type west_region_type; + df::world_region_type east_region_type; + + if (own_edge) { + effective_edge = world_data->region_details[0]->edges.biome_x[i][k]; + east_region_type = embark_assist::survey::region_type_of(survey_results, x, y, i, k); + west_region_type = embark_assist::survey::region_type_of(survey_results, x, y, i - 1, k); + } + else { + effective_edge = world_data->region_details[0]->edges.biome_x[i + 1][k]; + west_region_type = embark_assist::survey::region_type_of(survey_results, x, y, i, k); + east_region_type = embark_assist::survey::region_type_of(survey_results, x, y, i + 1, k); + } + + // Apply rules for Ocean && Lake to yield to everything else, + // and Mountain to everything but those. + // + if ((west_region_type == df::world_region_type::Lake || + west_region_type == df::world_region_type::Ocean) && + east_region_type != df::world_region_type::Lake && + east_region_type != df::world_region_type::Ocean) { + effective_edge = 1; + } + + if ((east_region_type == df::world_region_type::Lake || + east_region_type == df::world_region_type::Ocean) && + west_region_type != df::world_region_type::Lake && + west_region_type != df::world_region_type::Ocean) { + effective_edge = 0; + } + + if (west_region_type == df::world_region_type::Mountains && + west_region_type != df::world_region_type::Lake && + east_region_type != df::world_region_type::Ocean && + east_region_type != df::world_region_type::Mountains) { + effective_edge = 1; + } + + if (east_region_type == df::world_region_type::Mountains && + east_region_type != df::world_region_type::Lake && + west_region_type != df::world_region_type::Ocean && + west_region_type != df::world_region_type::Mountains) { + effective_edge = 0; + } + if (effective_edge == 0) { + if (own_edge) { + return 3; + } + else { + return 4; + } + } + else { + if (own_edge) { + return 4; + } + else { + return 5; + } + } +} + +//================================================================================= + void embark_assist::survey::survey_region_sites(embark_assist::defs::site_lists *site_list) { // color_ostream_proxy out(Core::getInstance().getConsole()); auto screen = Gui::getViewscreenByType(0); @@ -1196,6 +1964,7 @@ void embark_assist::survey::survey_region_sites(embark_assist::defs::site_lists //================================================================================= void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles *mlt, + embark_assist::defs::world_tile_data *survey_results, embark_assist::defs::site_infos *site_info, bool use_cache) { @@ -1207,7 +1976,8 @@ void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles * std::vector metals(state->max_inorganic); std::vector economics(state->max_inorganic); std::vector minerals(state->max_inorganic); - bool flatness_verification_failed; + bool incursion_processing_failed = false; + df::world_data *world_data = world->world_data; if (!use_cache) { // For some reason DF scrambles these values on world tile movements (at least in Lua...). state->local_min_x = screen->location.embark_pos_min.x; @@ -1219,16 +1989,22 @@ void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles * state->x = x; state->y = y; + site_info->incursions_processed = true; site_info->aquifer = false; site_info->aquifer_full = true; site_info->min_soil = 10; site_info->max_soil = 0; - site_info->flatness = embark_assist::defs::flatnesses::Mostly_Flat; + site_info->flat = true; site_info->max_waterfall = 0; site_info->clay = false; site_info->sand = false; site_info->flux = false; site_info->coal = false; + site_info->blood_rain = false; + site_info->permanent_syndrome_rain = false; + site_info->temporary_syndrome_rain = false; + site_info->reanimating = false; + site_info->thralling = false; site_info->metals.clear(); site_info->economics.clear(); site_info->metals.clear(); @@ -1254,7 +2030,7 @@ void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles * elevation = mlt->at(i).at(k).elevation; } else if (elevation != mlt->at(i).at(k).elevation) { - site_info->flatness = embark_assist::defs::flatnesses::Uneven; + site_info->flat = false; } if (mlt->at(i).at(k).river_present) { @@ -1291,42 +2067,31 @@ void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles * site_info->coal = true; } - for (uint16_t l = 0; l < state->max_inorganic; l++) { - metals[l] = metals[l] || mlt->at(i).at(k).metals[l]; - economics[l] = economics[l] || mlt->at(i).at(k).economics[l]; - minerals[l] = minerals[l] || mlt->at(i).at(k).minerals[l]; + if (survey_results->at(x).at(y).blood_rain[mlt->at(i).at(k).biome_offset]) { + site_info->blood_rain = true; } - } - } - if (site_info->flatness == embark_assist::defs::flatnesses::Mostly_Flat && - state->local_min_x > 0 && - state->local_max_x < 15 && - state->local_min_y > 0 && - state->local_max_y < 15) - { - flatness_verification_failed = false; + if (survey_results->at(x).at(y).permanent_syndrome_rain[mlt->at(i).at(k).biome_offset]) { + site_info->permanent_syndrome_rain = true; + } - for (uint8_t i = state->local_min_x - 1; i <= state->local_max_x + 1; i++) { - if (mlt->at(i).at(state->local_min_y - 1).elevation != elevation || - mlt->at(i).at(state->local_max_y + 1).elevation != elevation) { - flatness_verification_failed = true; - break; + if (survey_results->at(x).at(y).temporary_syndrome_rain[mlt->at(i).at(k).biome_offset]) { + site_info->temporary_syndrome_rain = true; } - } - if (!flatness_verification_failed) { - for (uint8_t k = state->local_min_y; k <= state->local_max_y; k++) { - if (mlt->at(state->local_min_x - 1).at(k).elevation != elevation || - mlt->at(state->local_max_x + 1).at(k).elevation != elevation) { - flatness_verification_failed = true; - break; - } + if (survey_results->at(x).at(y).reanimating[mlt->at(i).at(k).biome_offset]) { + site_info->reanimating = true; + } + + if (survey_results->at(x).at(y).thralling[mlt->at(i).at(k).biome_offset]) { + site_info->thralling = true; } - } - if (!flatness_verification_failed) { - site_info->flatness = embark_assist::defs::flatnesses::Flat_Verified; + for (uint16_t l = 0; l < state->max_inorganic; l++) { + metals[l] = metals[l] || mlt->at(i).at(k).metals[l]; + economics[l] = economics[l] || mlt->at(i).at(k).economics[l]; + minerals[l] = minerals[l] || mlt->at(i).at(k).minerals[l]; + } } } @@ -1343,6 +2108,250 @@ void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles * site_info->minerals.push_back(l); } } + + // Take incursions into account. + + for (int8_t i = state->local_min_x; i <= state->local_max_x; i++) { + // NW corner, north row + if ((i == 0 && state->local_min_y == 0 && x - 1 >= 0 && y - 1 >= 0 && !survey_results->at(x - 1).at (y - 1).surveyed) || + (i == 0 && x - 1 >= 0 && !survey_results->at(x - 1).at(y).surveyed) || + (state->local_min_y == 0 && y - 1 >= 0 && !survey_results->at(x).at(y - 1).surveyed)) { + incursion_processing_failed = true; + } + else { + process_embark_incursion_mid_level_tile + (translate_corner(survey_results, + 4, + x, + y, + i, + state->local_min_y), + site_info, + survey_results, + mlt, + i, + state->local_min_y); + } + + // N edge, north row + if (state->local_min_y == 0 && y - 1 >= 0 && !survey_results->at(x).at(y - 1).surveyed) { + incursion_processing_failed = true; + } + else { + process_embark_incursion_mid_level_tile + (translate_ns_edge(survey_results, + true, + x, + y, + i, + state->local_min_y), + site_info, + survey_results, + mlt, + i, + state->local_min_y); + } + + // NE corner, north row + if ((i == 15 && state->local_min_y == 0 && x + 1 < world_data->world_width && y - 1 >= 0 && !survey_results->at(x + 1).at(y - 1).surveyed) || + (i == 15 && x + 1 < world_data->world_width && !survey_results->at(x + 1).at(y).surveyed) || + (state->local_min_y == 0 && y - 1 >= 0 && !survey_results->at(x).at(y - 1).surveyed)) { + incursion_processing_failed = true; + } + else { + process_embark_incursion_mid_level_tile + (translate_corner(survey_results, + 5, + x, + y, + i, + state->local_min_y), + site_info, + survey_results, + mlt, + i, + state->local_min_y); + } + + // SW corner, south row + if ((i == 0 && state->local_max_y == 15 && x - 1 >= 0 && y + 1 < world_data->world_height && !survey_results->at(x - 1).at(y + 1).surveyed) || + (i == 0 && x - 1 >= 0 && !survey_results->at(x - 1).at(y).surveyed) || + (state->local_max_y == 15 && y + 1 < world_data->world_height && !survey_results->at(x).at(y + 1).surveyed)) { + incursion_processing_failed = true; + } + else { + process_embark_incursion_mid_level_tile + (translate_corner(survey_results, + 7, + x, + y, + i, + state->local_max_y), + site_info, + survey_results, + mlt, + i, + state->local_max_y); + } + + // S edge, south row + if (state->local_max_y == 15 && y + 1 < world_data->world_height && !survey_results->at(x).at(y + 1).surveyed) { + incursion_processing_failed = true; + } + else { + process_embark_incursion_mid_level_tile + (translate_ns_edge(survey_results, + false, + x, + y, + i, + state->local_max_y), + site_info, + survey_results, + mlt, + i, + state->local_max_y); + } + + // SE corner south row + if ((i == 15 && state->local_max_y == 15 && x + 1 < world_data->world_width && y + 1 < world_data->world_height && !survey_results->at(x + 1).at(y + 1).surveyed) || + (i == 15 && x + 1 < world_data->world_width && !survey_results->at(x + 1).at(y).surveyed) || + (state->local_max_y == 15 && y + 1 < world_data->world_height && !survey_results->at(x).at(y + 1).surveyed)) { + incursion_processing_failed = true; + } + else { + process_embark_incursion_mid_level_tile + (translate_corner(survey_results, + 8, + x, + y, + i, + state->local_max_y), + site_info, + survey_results, + mlt, + i, + state->local_max_y); + } + } + + for (int8_t k = state->local_min_y; k <= state->local_max_y; k++) { + // NW corner, west side + if ((state->local_min_x == 0 && x - 1 >= 0 && !survey_results->at(x - 1).at(y).surveyed)) { + incursion_processing_failed = true; + } + else if (k > state->local_min_y) { // We've already covered the NW corner of the NW, with its complications. + process_embark_incursion_mid_level_tile + (translate_corner(survey_results, + 4, + x, + y, + state->local_min_x, + k), + site_info, + survey_results, + mlt, + state->local_min_x, + k); + } + + // W edge, west side + if (state->local_min_x == 0 && x - 1 >= 0 && !survey_results->at(x - 1).at(y).surveyed) { + incursion_processing_failed = true; + } + else { + process_embark_incursion_mid_level_tile + (translate_ns_edge(survey_results, + true, + x, + y, + state->local_min_x, + k), + site_info, + survey_results, + mlt, + state->local_min_x, + k); + } + + // SW corner, west side + if (state->local_min_x == 0 && x - 1 >= 0 && !survey_results->at(x - 1).at(y).surveyed) { + incursion_processing_failed = true; + } + else if (k < state->local_max_y) { // We've already covered the SW corner of the SW tile, with its complicatinons. + process_embark_incursion_mid_level_tile + (translate_corner(survey_results, + 7, + x, + y, + state->local_min_x, + k), + site_info, + survey_results, + mlt, + state->local_min_x, + k); + } + + // NE corner, east side + if ((state->local_max_x == 15 && x + 1 < world_data->world_width && !survey_results->at(x + 1).at(y).surveyed)) { + incursion_processing_failed = true; + } + else if (k > state->local_min_y) { // We've already covered the NE tile's NE corner, with its complications. + process_embark_incursion_mid_level_tile + (translate_corner(survey_results, + 5, + x, + y, + state->local_max_x, + k), + site_info, + survey_results, + mlt, + state->local_max_x, + k); + } + + // E edge, east side + if (state->local_max_x == 15 && x + 1 < world_data->world_width && !survey_results->at(x + 1).at(y).surveyed) { + incursion_processing_failed = true; + } + else { + process_embark_incursion_mid_level_tile + (translate_ns_edge(survey_results, + false, + x, + y, + state->local_max_x, + k), + site_info, + survey_results, + mlt, + state->local_max_x, + k); + } + + // SE corner, east side + if (state->local_max_x == 15 && x + 1 < world_data->world_width && !survey_results->at(x + 1).at(y).surveyed) { + incursion_processing_failed = true; + } + else if (k < state->local_max_y) { // We've already covered the SE tile's SE corner, with its complications. + process_embark_incursion_mid_level_tile + (translate_corner(survey_results, + 8, + x, + y, + state->local_max_x, + k), + site_info, + survey_results, + mlt, + state->local_max_x, + k); + } + } + + if (incursion_processing_failed) site_info->incursions_processed = false; } //================================================================================= diff --git a/plugins/embark-assistant/survey.h b/plugins/embark-assistant/survey.h index 03d2d9a03..5f201b04f 100644 --- a/plugins/embark-assistant/survey.h +++ b/plugins/embark-assistant/survey.h @@ -27,9 +27,52 @@ namespace embark_assist { df::coord2d apply_offset(uint16_t x, uint16_t y, int8_t offset); + df::world_region_type region_type_of(embark_assist::defs::world_tile_data *survey_results, + int16_t x, + int16_t y, + int8_t i, + int8_t k); + + // Returns the direction from which data should be read using DF's + // 0 - 8 range direction indication. + // "corner_location" uses the 0 - 8 notation to indicate the reader's + // relation to the data read. Only some values are legal, as the set of + // relations is limited by how the corners are defined. + // x, y, i, k are the world tile/mid level tile coordinates of the + // tile the results should be applied to. + // Deals with references outside of the world map by returning "yield" + // results, but requires all world tiles affected by the corner to have + // been surveyed. + // + uint8_t translate_corner(embark_assist::defs::world_tile_data *survey_results, + uint8_t corner_location, + uint16_t x, + uint16_t y, + uint8_t i, + uint8_t k); + + // Same logic and restrictions as for translate_corner. + // + uint8_t translate_ns_edge(embark_assist::defs::world_tile_data *survey_results, + bool own_edge, + uint16_t x, + uint16_t y, + uint8_t i, + uint8_t k); + + // Same logic and restrictions as for translate_corner. + // + uint8_t translate_ew_edge(embark_assist::defs::world_tile_data *survey_results, + bool own_edge, + uint16_t x, + uint16_t y, + uint8_t i, + uint8_t k); + void survey_region_sites(embark_assist::defs::site_lists *site_list); void survey_embark(embark_assist::defs::mid_level_tiles *mlt, + embark_assist::defs::world_tile_data *survey_results, embark_assist::defs::site_infos *site_info, bool use_cache); From 6f5abc79e96e9dbe42dd1091c40223fdee1c472d Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Fri, 12 Jul 2019 22:38:12 +0200 Subject: [PATCH 098/109] Restored install-debug contents and removed offensive white space --- build/win64/install-debug.bat | 2 +- plugins/embark-assistant/embark-assistant.cpp | 2 +- plugins/embark-assistant/survey.cpp | 2 +- plugins/embark-assistant/survey.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/win64/install-debug.bat b/build/win64/install-debug.bat index 64b5ae850..d149a5d86 100644 --- a/build/win64/install-debug.bat +++ b/build/win64/install-debug.bat @@ -1,4 +1,4 @@ -call "D:\Program (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64 +call "%ProgramFiles(x86)%\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64 cd VC2015 msbuild /m /p:Platform=x64 /p:Configuration=RelWithDebInfo INSTALL.vcxproj cd .. \ No newline at end of file diff --git a/plugins/embark-assistant/embark-assistant.cpp b/plugins/embark-assistant/embark-assistant.cpp index 22dd21298..1eed98593 100644 --- a/plugins/embark-assistant/embark-assistant.cpp +++ b/plugins/embark-assistant/embark-assistant.cpp @@ -275,7 +275,7 @@ command_result embark_assistant(color_ostream &out, std::vector & } embark_assist::main::state->survey_results[i][k].metals.resize(embark_assist::main::state->max_inorganic); embark_assist::main::state->survey_results[i][k].economics.resize(embark_assist::main::state->max_inorganic); - embark_assist::main::state->survey_results[i][k].minerals.resize(embark_assist::main::state->max_inorganic); + embark_assist::main::state->survey_results[i][k].minerals.resize(embark_assist::main::state->max_inorganic); } } diff --git a/plugins/embark-assistant/survey.cpp b/plugins/embark-assistant/survey.cpp index a2942d415..30ba9d441 100644 --- a/plugins/embark-assistant/survey.cpp +++ b/plugins/embark-assistant/survey.cpp @@ -1745,7 +1745,7 @@ uint8_t embark_assist::survey::translate_corner(embark_assist::defs::world_tile //================================================================================= -uint8_t embark_assist::survey::translate_ns_edge(embark_assist::defs::world_tile_data *survey_results, +uint8_t embark_assist::survey::translate_ns_edge(embark_assist::defs::world_tile_data *survey_results, bool own_edge, uint16_t x, uint16_t y, diff --git a/plugins/embark-assistant/survey.h b/plugins/embark-assistant/survey.h index 5f201b04f..14cc8a468 100644 --- a/plugins/embark-assistant/survey.h +++ b/plugins/embark-assistant/survey.h @@ -53,7 +53,7 @@ namespace embark_assist { // Same logic and restrictions as for translate_corner. // - uint8_t translate_ns_edge(embark_assist::defs::world_tile_data *survey_results, + uint8_t translate_ns_edge(embark_assist::defs::world_tile_data *survey_results, bool own_edge, uint16_t x, uint16_t y, From b60faa8021d06700fa3d97bfb955232fa7d454c9 Mon Sep 17 00:00:00 2001 From: lethosor Date: Sat, 13 Jul 2019 15:51:46 -0400 Subject: [PATCH 099/109] dfhack-run: add note about installation when called with no arguments --- library/dfhack-run.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/library/dfhack-run.cpp b/library/dfhack-run.cpp index abe34f34d..af00e4c04 100644 --- a/library/dfhack-run.cpp +++ b/library/dfhack-run.cpp @@ -63,7 +63,20 @@ int main (int argc, char *argv[]) if (argc <= 1) { - fprintf(stderr, "Usage: dfhack-run [args...]\n"); + fprintf(stderr, "Usage: dfhack-run [args...]\n\n"); + fprintf(stderr, "Note: this command does not start DFHack; it is intended to connect\n" + "to a running DFHack instance. If you were trying to start DFHack, run\n" +#ifdef _WIN32 + " Dwarf Fortress.exe\n" +#else + " ./dfhack\n" +#endif + "or see the documentation in hack/docs/index.html for more help.\n" + ); +#ifdef _WIN32 + fprintf(stderr, "\nPress Enter to quit.\n"); + fgetc(stdin); +#endif return 2; } From af26f7dc6e30fde1cd87be10cc026f6d2f6d10c8 Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Sun, 14 Jul 2019 16:11:51 +0200 Subject: [PATCH 100/109] Added intrusion calculations for world edges --- plugins/embark-assistant/survey.cpp | 50 +++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/plugins/embark-assistant/survey.cpp b/plugins/embark-assistant/survey.cpp index 30ba9d441..5bed173fa 100644 --- a/plugins/embark-assistant/survey.cpp +++ b/plugins/embark-assistant/survey.cpp @@ -1535,12 +1535,26 @@ uint8_t embark_assist::survey::translate_corner(embark_assist::defs::world_tile adjust_coordinates(&effective_x, &effective_y, &effective_i, &effective_i); - if (effective_x < 0 || effective_x == world_data->world_width || - effective_y < 0 || effective_y == world_data->world_height) { - effective_x = x; - effective_y = y; - effective_i = i; - effective_k = k; + if (effective_x == world_data->world_width) { + if (effective_y == world_data->world_height) { // Only the SE corner of the SE most tile of the world can reference this. + return 4; + } + else { // East side corners of the east edge of the world + if (corner_location == 5) { + return 1; + } + else { // Can only be corner_location == 8 + return 4; + } + } + } + else if (effective_y == world_data->world_height) { + if (corner_location == 7) { + return 4; + } + else { // Can only be corner_location == 8 + return 3; + } } if (effective_x == x && effective_y == y) { @@ -1602,6 +1616,25 @@ uint8_t embark_assist::survey::translate_corner(embark_assist::defs::world_tile home_region_type_level = 2; } + if (effective_x == 0 && effective_i == 0) { // West edge of the world + if (effective_y == 0 && effective_k == 0) { + return 4; // Only a single reference to this info, the own tile. + } + else { + nw_region_type_level = -1; // Knock out the unreachable corners + w_region_type_level = -1; + } + } + + if (effective_y == 0 && effective_k == 0) { // North edge of the world + nw_region_type_level = -1; // Knock out the unreachable corners + n_region_type_level = -1; + + if (corner_location == 4 && effective_corner == 1) { // The logic below would select the wrong alternative. + effective_corner = 3; + } + } + nw_region_type_active = nw_region_type_level >= n_region_type_level && nw_region_type_level >= w_region_type_level && nw_region_type_level >= home_region_type_level; @@ -1622,9 +1655,8 @@ uint8_t embark_assist::survey::translate_corner(embark_assist::defs::world_tile (effective_corner == 1 && !n_region_type_active) || (effective_corner == 2 && !w_region_type_active) || (effective_corner == 3 && !home_region_type_active)) { - //### The designated corner is suppressed, but we do not have any - // knowledge of how to select a replacement. Thus, the presedence - // list used is fairly arbitrary: Use the lowest number available. + // The designated corner is suppressed. The precedence list below seems + // to match what DF produces except in the case adjusted above. if (nw_region_type_active) { effective_corner = 0; } From ea37eecfb116f0579c2935be0ee9a94874b7e078 Mon Sep 17 00:00:00 2001 From: lethosor Date: Tue, 16 Jul 2019 19:33:33 -0400 Subject: [PATCH 101/109] Document and warn about old CMake versions with Ninja Resolves #1369 --- CMakeLists.txt | 6 ++++++ docs/Compile.rst | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 689618637..575f40288 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,12 @@ OPTION(REMOVE_SYMBOLS_FROM_DF_STUBS "Remove debug symbols from DF stubs. (Reduce cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) project(dfhack) +if("${CMAKE_GENERATOR}" STREQUAL Ninja) + if("${CMAKE_VERSION}" VERSION_LESS 3.9) + message(WARNING "You are using an old version of CMake (${CMAKE_VERSION}) with Ninja. This may result in ninja errors - see docs/Compile.rst for more details. Upgrading your CMake version is recommended.") + endif() +endif() + macro(CHECK_GCC COMPILER_PATH) execute_process(COMMAND ${COMPILER_PATH} -dumpversion OUTPUT_VARIABLE GCC_VERSION_OUT) string(STRIP "${GCC_VERSION_OUT}" GCC_VERSION_OUT) diff --git a/docs/Compile.rst b/docs/Compile.rst index 8c2a56626..fd8079861 100644 --- a/docs/Compile.rst +++ b/docs/Compile.rst @@ -68,6 +68,10 @@ and more, please see `contributing-code`. Build settings ============== +This section describes build configuration options that apply to all platforms. +If you don't have a working build environment set up yet, follow the instructions +in the platform-specific sections below first, then come back here. + Generator --------- @@ -86,6 +90,12 @@ much slower than Ninja builds. generator cannot be changed after ``cmake`` has been run without creating a new build folder. Do not forget to specify this option. + CMake versions 3.6 and older, and possibly as recent as 3.9, are known to + produce project files with dependency cycles that fail to build + (see :issue:`1369`). Obtaining a recent version of CMake is recommended, either from + `cmake.org `_ or through a package manager. See + the sections below for more platform-specific directions for installing CMake. + Build type ---------- From a90a6b2a7ba4648b0e597accbab05763660b7d93 Mon Sep 17 00:00:00 2001 From: Pauli Date: Thu, 5 Jul 2018 21:16:50 +0300 Subject: [PATCH 102/109] Make lua data race free Fixes tsan trace report between lua viewscreen and other threads running lua without CoreSuspender lock. But I would assume similar races exists when using lua from console thread, remote thread and vmethods same time. --- depends/lua/CMakeLists.txt | 7 +++++ depends/lualimit.h | 61 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 depends/lualimit.h diff --git a/depends/lua/CMakeLists.txt b/depends/lua/CMakeLists.txt index 7dcae8068..97b62dca6 100644 --- a/depends/lua/CMakeLists.txt +++ b/depends/lua/CMakeLists.txt @@ -95,6 +95,13 @@ LIST(APPEND SRC_LIBLUA ${HDR_LIBLUA}) ADD_LIBRARY ( lua SHARED ${SRC_LIBLUA} ) TARGET_LINK_LIBRARIES ( lua ${LIBS}) +target_include_directories(lua PRIVATE ../) +if (MSVC) + target_compile_options(lua PRIVATE /FI lualimit.h) +else () + target_compile_options(lua PRIVATE -include lualimit.h) +endif () + install(TARGETS lua LIBRARY DESTINATION ${DFHACK_LIBRARY_DESTINATION} RUNTIME DESTINATION ${DFHACK_LIBRARY_DESTINATION}) diff --git a/depends/lualimit.h b/depends/lualimit.h new file mode 100644 index 000000000..009501cce --- /dev/null +++ b/depends/lualimit.h @@ -0,0 +1,61 @@ +/** +Copyright © 2018 Pauli + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. + */ + +#pragma once + +#ifdef _MSC_VER +#include +#else +#include +#endif + +#include + +/*! \file lualimit.h + * dfhack specific lua porting header that overrides lua defaults for thread + * safety. + */ + +#ifdef _MSC_VER +typedef CRITICAL_SECTION mutex_t; +#else +typedef pthread_mutex_t mutex_t; +#endif + +struct lua_extra_state { + mutex_t* mutex; +}; + +#define luai_mutex(L) ((lua_extra_state*)lua_getextraspace(L))->mutex + +#ifdef _MSC_VER +#define luai_userstateopen(L) luai_mutex(L) = (mutex_t*)malloc(sizeof(mutex_t)); InitializeCriticalSection(luai_mutex(L)) +#define luai_userstateclose(L) lua_unlock(L); DeleteCriticalSection(luai_mutex(L)); free(luai_mutex(L)) +#define lua_lock(L) EnterCriticalSection(luai_mutex(L)) +#define lua_unlock(L) LeaveCriticalSection(luai_mutex(L)) +#else +#define luai_userstateopen(L) luai_mutex(L) = (mutex_t*)malloc(sizeof(mutex_t)); *luai_mutex(L) = PTHREAD_MUTEX_INITIALIZER +#define luai_userstateclose(L) lua_unlock(L); pthread_mutex_destroy(luai_mutex(L)); free(luai_mutex(L)) +#define lua_lock(L) pthread_mutex_lock(luai_mutex(L)) +#define lua_unlock(L) pthread_mutex_unlock(luai_mutex(L)) +#endif From 0ed5c8db39ee51d5dd40f68f9cb68e91aed270c4 Mon Sep 17 00:00:00 2001 From: Pauli Date: Thu, 5 Jul 2018 21:18:49 +0300 Subject: [PATCH 103/109] Fix data race between threaded init and EventManager The initial run_dfhack_init loads shared state information that is used by EventManager when state changes. There is a small risk that EventManager can handle events while run_dfhack_init is still running. --- library/Core.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/library/Core.cpp b/library/Core.cpp index c406fb6c0..c724a0fcc 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -1427,6 +1427,7 @@ 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) { out.printerr("Key globals are missing, skipping loading dfhack.init.\n"); From 0605b9601ca94243d4d66f87d8602ec0e1e64994 Mon Sep 17 00:00:00 2001 From: Pauli Date: Sat, 7 Jul 2018 13:13:55 +0300 Subject: [PATCH 104/109] Make Core::started thread safe --- library/Core.cpp | 3 ++- library/include/Core.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/library/Core.cpp b/library/Core.cpp index c724a0fcc..222680f62 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -1529,6 +1529,7 @@ Core::Core() : HotkeyMutex{}, HotkeyCond{}, alias_mutex{}, + started{false}, misc_data_mutex{}, CoreSuspendMutex{}, CoreWakeup{}, @@ -1538,7 +1539,7 @@ Core::Core() : // init the console. This must be always the first step! plug_mgr = 0; errorstate = false; - started = false; + vinfo = 0; memset(&(s_mods), 0, sizeof(s_mods)); // set up hotkey capture diff --git a/library/include/Core.h b/library/include/Core.h index 0fec2774d..7c3bc5578 100644 --- a/library/include/Core.h +++ b/library/include/Core.h @@ -283,7 +283,7 @@ namespace DFHack df::viewscreen *top_viewscreen; bool last_pause_state; // Very important! - bool started; + std::atomic started; // Additional state change scripts std::vector state_change_scripts; From 49f3de979f41a20ab1a84d04953f2042e0b1e677 Mon Sep 17 00:00:00 2001 From: Pauli Date: Sat, 7 Jul 2018 13:13:55 +0300 Subject: [PATCH 105/109] Make ServerMain and ServerConnection data race free RemoteServer and PluginManager side would need complete redesign to be data race free and concurrent. But as that would be unlikely to be required from DFHack I decided simpler solution that is fixing data ownership to a thread and all ServerConnection share a single lock which allows access to PluginManager and Core. --- library/Core.cpp | 9 +-- library/RemoteServer.cpp | 127 +++++++++++++++++++++------------ library/include/Core.h | 1 - library/include/RemoteServer.h | 21 +++--- 4 files changed, 98 insertions(+), 60 deletions(-) diff --git a/library/Core.cpp b/library/Core.cpp index 222680f62..15d4be72c 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -1549,7 +1549,6 @@ Core::Core() : last_pause_state = false; top_viewscreen = NULL; screen_window = NULL; - server = NULL; color_ostream::log_errors_to_stderr = true; @@ -1767,6 +1766,8 @@ bool Core::Init() // create plugin manager plug_mgr = new PluginManager(this); plug_mgr->init(); + cerr << "Starting the TCP listener.\n"; + auto listen = ServerMain::listen(RemoteClient::GetDefaultPort()); IODATA *temp = new IODATA; temp->core = this; temp->plug_mgr = plug_mgr; @@ -1791,9 +1792,7 @@ bool Core::Init() started = true; modstate = 0; - cerr << "Starting the TCP listener.\n"; - server = new ServerMain(); - if (!server->listen(RemoteClient::GetDefaultPort())) + if (!listen.get()) cerr << "TCP listen failed.\n"; if (df::global::ui_sidebar_menus) @@ -2296,6 +2295,8 @@ int Core::Shutdown ( void ) HotkeyCond.notify_one(); } + ServerMain::block(); + d->hotkeythread.join(); d->iothread.join(); diff --git a/library/RemoteServer.cpp b/library/RemoteServer.cpp index 86ef9f40c..523058d55 100644 --- a/library/RemoteServer.cpp +++ b/library/RemoteServer.cpp @@ -57,12 +57,11 @@ POSSIBILITY OF SUCH DAMAGE. #include #include +#include #include "json/json.h" -#include "tinythread.h" using namespace DFHack; -using namespace tthread; using dfproto::CoreTextNotification; using dfproto::CoreTextFragment; @@ -72,6 +71,30 @@ bool readFullBuffer(CSimpleSocket *socket, void *buf, int size); bool sendRemoteMessage(CSimpleSocket *socket, int16_t id, const ::google::protobuf::MessageLite *msg, bool size_ready); +std::mutex ServerMain::access_{}; +bool ServerMain::blocked_{}; + +namespace { + struct BlockedException : std::exception { + const char* what() const noexcept override + { + return "Core has blocked all connection. This should have been catched."; + } + }; +} + +namespace DFHack { + + struct BlockGuard { + std::lock_guard lock; + BlockGuard() : + lock{ServerMain::access_} + { + if (ServerMain::blocked_) + throw BlockedException{}; + } + }; +} RPCService::RPCService() { @@ -134,9 +157,6 @@ ServerConnection::ServerConnection(CActiveSocket *socket) core_service = new CoreService(); core_service->finalize(this, &functions); - - thread = new tthread::thread(threadFn, (void*)this); - thread->detach(); } ServerConnection::~ServerConnection() @@ -144,7 +164,6 @@ ServerConnection::~ServerConnection() in_error = true; socket->Close(); delete socket; - delete thread; for (auto it = plugin_services.begin(); it != plugin_services.end(); ++it) delete it->second; @@ -216,13 +235,14 @@ void ServerConnection::connection_ostream::flush_proxy() } } -void ServerConnection::threadFn(void *arg) +void ServerConnection::Accepted(CActiveSocket* socket) { - ServerConnection *me = (ServerConnection*)arg; - - me->threadFn(); - - delete me; + std::thread{[](CActiveSocket* socket) { + try { + ServerConnection(socket).threadFn(); + } catch (BlockedException e) { + } + }, socket}.detach(); } void ServerConnection::threadFn() @@ -292,6 +312,7 @@ void ServerConnection::threadFn() // Find and call the function int in_size = header.size; + BlockGuard lock; ServerFunctionBase *fn = vector_get(functions, header.id); MessageLite *reply = NULL; @@ -378,25 +399,21 @@ void ServerConnection::threadFn() std::cerr << "Shutting down client connection." << endl; } -ServerMain::ServerMain() -{ - socket = new CPassiveSocket(); - thread = NULL; -} +namespace { + + struct ServerMainImpl : public ServerMain { + CPassiveSocket socket; + static void threadFn(std::promise promise, int port); + ServerMainImpl(std::promise promise, int port); + ~ServerMainImpl(); + }; -ServerMain::~ServerMain() -{ - socket->Close(); - delete socket; - delete thread; } -bool ServerMain::listen(int port) +ServerMainImpl::ServerMainImpl(std::promise promise, int port) : + socket{} { - if (thread) - return true; - - socket->Initialize(); + socket.Initialize(); std::string filename("dfhack-config/remote-server.json"); @@ -427,29 +444,49 @@ bool ServerMain::listen(int port) } std::cerr << "Listening on port " << port << (allow_remote ? " (remote enabled)" : "") << std::endl; - if (allow_remote) - { - if (!socket->Listen(NULL, port)) - return false; - } - else - { - if (!socket->Listen("127.0.0.1", port)) - return false; + const char* addr = allow_remote ? NULL : "127.0.0.1"; + if (!socket.Listen(addr, port)) { + promise.set_value(false); + return; } + promise.set_value(true); +} + +ServerMainImpl::~ServerMainImpl() +{ + socket.Close(); +} - thread = new tthread::thread(threadFn, this); - thread->detach(); - return true; +std::future ServerMain::listen(int port) +{ + std::promise promise; + auto rv = promise.get_future(); + std::thread{&ServerMainImpl::threadFn, std::move(promise), port}.detach(); + return rv; } -void ServerMain::threadFn(void *arg) +void ServerMainImpl::threadFn(std::promise promise, int port) { - ServerMain *me = (ServerMain*)arg; - CActiveSocket *client; + ServerMainImpl server{std::move(promise), port}; - while ((client = me->socket->Accept()) != NULL) - { - new ServerConnection(client); + CActiveSocket *client = nullptr; + + try { + while ((client = server.socket.Accept()) != NULL) + { + BlockGuard lock; + ServerConnection::Accepted(client); + client = nullptr; + } + } catch(BlockedException e) { + if (client) + client->Close(); + delete client; } } + +void ServerMain::block() +{ + std::lock_guard lock{access_}; + blocked_ = true; +} diff --git a/library/include/Core.h b/library/include/Core.h index 7c3bc5578..85bfdbd3e 100644 --- a/library/include/Core.h +++ b/library/include/Core.h @@ -308,7 +308,6 @@ namespace DFHack friend class CoreSuspenderBase; friend struct CoreSuspendClaimMain; friend struct CoreSuspendReleaseMain; - ServerMain *server; }; class CoreSuspenderBase : protected std::unique_lock { diff --git a/library/include/RemoteServer.h b/library/include/RemoteServer.h index 85ac463fb..a7e0ad8d5 100644 --- a/library/include/RemoteServer.h +++ b/library/include/RemoteServer.h @@ -28,6 +28,8 @@ distribution. #include "RemoteClient.h" #include "Core.h" +#include + class CPassiveSocket; class CActiveSocket; class CSimpleSocket; @@ -233,26 +235,25 @@ namespace DFHack CoreService *core_service; std::map plugin_services; - tthread::thread *thread; - static void threadFn(void *); void threadFn(); + ServerConnection(CActiveSocket* socket); + ~ServerConnection(); public: - ServerConnection(CActiveSocket *socket); - ~ServerConnection(); + + static void Accepted(CActiveSocket* socket); ServerFunctionBase *findFunction(color_ostream &out, const std::string &plugin, const std::string &name); }; class ServerMain { - CPassiveSocket *socket; + static std::mutex access_; + static bool blocked_; + friend struct BlockGuard; - tthread::thread *thread; - static void threadFn(void *); public: - ServerMain(); - ~ServerMain(); - bool listen(int port); + static std::future listen(int port); + static void block(); }; } From ea0105fa66ba53113756b5f193fbf2613eb8ee31 Mon Sep 17 00:00:00 2001 From: lethosor Date: Sat, 20 Jul 2019 11:21:44 -0400 Subject: [PATCH 106/109] Add CMake option to provide custom libstdc++ on macOS (#1344) --- CMakeLists.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 575f40288..9a9a03caf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -296,6 +296,7 @@ if(WIN32) endif() endif() +option(EXTERNAL_LIBSTDCXX "macOS only: Avoid installing the DFHack-provided libstdc++." OFF) if(APPLE) # libstdc++ (GCC 4.8.5 for OS X 10.6) # fixes crash-on-unwind bug in DF's libstdc++ @@ -346,9 +347,10 @@ if(APPLE) endif() endif() - install(PROGRAMS ${LIBSTDCXX_DOWNLOAD_DIR}/libstdc++.6.dylib - DESTINATION ./hack/) - + if(NOT EXTERNAL_LIBSTDCXX) + install(PROGRAMS ${LIBSTDCXX_DOWNLOAD_DIR}/libstdc++.6.dylib + DESTINATION ./hack/) + endif() endif() #### expose depends #### From b6678d72aec7fa7d5d39d3c21083c6b05b2673ee Mon Sep 17 00:00:00 2001 From: lethosor Date: Sat, 20 Jul 2019 14:26:30 -0400 Subject: [PATCH 107/109] Move custom lualimit.h to lua dir and rename to dfhack_llimits.h --- depends/lua/CMakeLists.txt | 5 ++--- depends/{lualimit.h => lua/include/dfhack_llimits.h} | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) rename depends/{lualimit.h => lua/include/dfhack_llimits.h} (98%) diff --git a/depends/lua/CMakeLists.txt b/depends/lua/CMakeLists.txt index 97b62dca6..fd3a59c08 100644 --- a/depends/lua/CMakeLists.txt +++ b/depends/lua/CMakeLists.txt @@ -95,11 +95,10 @@ LIST(APPEND SRC_LIBLUA ${HDR_LIBLUA}) ADD_LIBRARY ( lua SHARED ${SRC_LIBLUA} ) TARGET_LINK_LIBRARIES ( lua ${LIBS}) -target_include_directories(lua PRIVATE ../) if (MSVC) - target_compile_options(lua PRIVATE /FI lualimit.h) + target_compile_options(lua PRIVATE /FI dfhack_llimits.h) else () - target_compile_options(lua PRIVATE -include lualimit.h) + target_compile_options(lua PRIVATE -include dfhack_llimits.h) endif () install(TARGETS lua diff --git a/depends/lualimit.h b/depends/lua/include/dfhack_llimits.h similarity index 98% rename from depends/lualimit.h rename to depends/lua/include/dfhack_llimits.h index 009501cce..f8ca51819 100644 --- a/depends/lualimit.h +++ b/depends/lua/include/dfhack_llimits.h @@ -31,7 +31,7 @@ redistribute it freely, subject to the following restrictions: #include -/*! \file lualimit.h +/*! \file dfhack_llimits.h * dfhack specific lua porting header that overrides lua defaults for thread * safety. */ From aee7b6b24d375c8dbd7dfc23e34de8f96eb2596f Mon Sep 17 00:00:00 2001 From: lethosor Date: Sat, 20 Jul 2019 17:11:11 -0400 Subject: [PATCH 108/109] Note about pthread/cmake <3.8 issue (from ragundo) --- docs/Compile.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/Compile.rst b/docs/Compile.rst index fd8079861..f30775a03 100644 --- a/docs/Compile.rst +++ b/docs/Compile.rst @@ -152,6 +152,12 @@ Before you can build anything, you'll also need ``cmake``. It is advisable to also get ``ccmake`` on distributions that split the cmake package into multiple parts. +You will need pthread; most systems should have this already. Note that older +CMake versions may have trouble detecting pthread, so if you run into +pthread-related errors and pthread is installed, you may need to upgrade CMake, +either by downloading it from `cmake.org `_ or +through your package manager, if possible. + You also need zlib, libsdl (1.2, not sdl2, like DF), perl, and the XML::LibXML and XML::LibXSLT perl packages (for the code generation parts). You should be able to find them in your distro repositories. From b19a04fa88cc03aee6be97b96b19b4c35e90455d Mon Sep 17 00:00:00 2001 From: Alan Date: Thu, 22 Aug 2019 21:24:48 -0400 Subject: [PATCH 109/109] Revert newline change --- build/win64/install-debug.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/win64/install-debug.bat b/build/win64/install-debug.bat index d149a5d86..34668945c 100644 --- a/build/win64/install-debug.bat +++ b/build/win64/install-debug.bat @@ -1,4 +1,4 @@ call "%ProgramFiles(x86)%\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64 cd VC2015 msbuild /m /p:Platform=x64 /p:Configuration=RelWithDebInfo INSTALL.vcxproj -cd .. \ No newline at end of file +cd ..