From 9d460d506e898a040b6f647d35163308dc34ef72 Mon Sep 17 00:00:00 2001 From: Warmist Date: Sat, 9 Aug 2014 22:14:55 +0300 Subject: [PATCH 01/35] Probably a fix to rendermax for 0.40.xx --- plugins/rendermax/renderer_light.cpp | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/plugins/rendermax/renderer_light.cpp b/plugins/rendermax/renderer_light.cpp index 395e12c14..8a213a6e3 100644 --- a/plugins/rendermax/renderer_light.cpp +++ b/plugins/rendermax/renderer_light.cpp @@ -673,6 +673,8 @@ void lightingEngineViewscreen::doOcupancyAndLights() } //df::tile_occupancy o = b->OccupancyAt(gpos); df::tiletype_shape shape = ENUM_ATTR(tiletype,shape,type); + bool is_wall=!ENUM_ATTR(tiletype_shape,passable_high,shape); + bool is_floor=!ENUM_ATTR(tiletype_shape,passable_low,shape); df::tiletype_shape_basic basic_shape = ENUM_ATTR(tiletype_shape, basic_shape, shape); df::tiletype_material tileMat= ENUM_ATTR(tiletype,material,type); @@ -685,7 +687,7 @@ void lightingEngineViewscreen::doOcupancyAndLights() { curCell=rgbf(0,0,0); } - else if(shape==df::tiletype_shape::WALL) + else if(is_wall) { if(tileMat==df::tiletype_material::FROZEN_LIQUID) applyMaterial(tile,matIce); @@ -700,8 +702,7 @@ void lightingEngineViewscreen::doOcupancyAndLights() { applyMaterial(tile,matLava,(float)d.bits.flow_size/7.0f,(float)d.bits.flow_size/7.0f); } - else if(shape==df::tiletype_shape::EMPTY || shape==df::tiletype_shape::RAMP_TOP - || shape==df::tiletype_shape::STAIR_DOWN || shape==df::tiletype_shape::STAIR_UPDOWN) + else if(!is_floor) { if(bDown) { @@ -749,20 +750,6 @@ void lightingEngineViewscreen::doOcupancyAndLights() } } - //plants - for(int i=0;iplants.size();i++) - { - df::plant* cPlant=block->plants[i]; - if (cPlant->grow_counter <180000) //todo maybe smaller light/oclusion? - continue; - df::coord2d pos=cPlant->pos; - pos=worldToViewportCoord(pos,vp,window2d); - int tile=getIndex(pos.x,pos.y); - if(isInRect(pos,vp)) - { - applyMaterial(tile,419,cPlant->material); - } - } //blood and other goo for(int i=0;iblock_events.size();i++) { From ce13eda930ae358e6858b59e087e3bbf5f771cf1 Mon Sep 17 00:00:00 2001 From: PeridexisErrant Date: Mon, 22 Sep 2014 10:49:42 +1000 Subject: [PATCH 02/35] properly documented the seedwatch plugin Because telling users to try the help function *isn't actually documentation*. Info pulled from source code without verification. --- Readme.rst | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/Readme.rst b/Readme.rst index b143b0c54..2804d4a8b 100644 --- a/Readme.rst +++ b/Readme.rst @@ -1626,10 +1626,31 @@ Fortress activity management seedwatch --------- -Tool for turning cooking of seeds and plants on/off depending on how much you -have of them. +Watches the numbers of seeds available and enables/disables seed and plant cooking. -See 'seedwatch help' for detailed description. +Each plant type can be assigned a limit. If their number falls below that limit, +the plants and seeds of that type will be excluded from cookery. +If the number rises above the limit + 20, then cooking will be allowed. + +The plugin needs a fortress to be loaded and will deactivate automatically otherwise. +You have to reactivate with 'seedwatch start' after you load the game. + +Options: + +:all: Adds all plants from the abbreviation list to the watch list. +:start: Start watching. +:stop: Stop watching. +:info: Display whether seedwatch is watching, and the watch list. +:clear: Clears the watch list. + +Examples: + +``seedwatch MUSHROOM_HELMET_PLUMP 30`` + add ``MUSHROOM_HELMET_PLUMP`` to the watch list, limit = 30 +``seedwatch MUSHROOM_HELMET_PLUMP`` + removes ``MUSHROOM_HELMET_PLUMP`` from the watch list. +``seedwatch all 30`` + adds all plants from the abbreviation list to the watch list, the limit being 30. zone ---- From 6046d686393244bd1cdeecaabf60da9816d66c5c Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Wed, 24 Sep 2014 22:47:04 +0400 Subject: [PATCH 03/35] Support std::fstream in data structures and add file_compressorst to xml. One tricky thing is that fstream does not have operator=, so the new file_compressorst requires a manually implemented one that skips it. --- library/DataDefs.cpp | 5 +---- library/DataStaticsFields.cpp | 8 ++++++++ library/LuaTypes.cpp | 7 +++++-- library/include/DataDefs.h | 11 ++++++----- library/include/DataIdentity.h | 17 +++++++++++++++++ .../df/custom/file_compressorst.methods.inc | 12 ++++++++++++ library/xml | 2 +- 7 files changed, 50 insertions(+), 12 deletions(-) create mode 100644 library/include/df/custom/file_compressorst.methods.inc diff --git a/library/DataDefs.cpp b/library/DataDefs.cpp index 93e75e280..f9187ff09 100644 --- a/library/DataDefs.cpp +++ b/library/DataDefs.cpp @@ -67,10 +67,7 @@ void *type_identity::allocate() { bool type_identity::copy(void *tgt, const void *src) { if (can_allocate() && tgt && src) - { - do_copy(tgt, src); - return true; - } + return do_copy(tgt, src); else return false; } diff --git a/library/DataStaticsFields.cpp b/library/DataStaticsFields.cpp index 79aa3bcf1..4d8decbed 100644 --- a/library/DataStaticsFields.cpp +++ b/library/DataStaticsFields.cpp @@ -39,6 +39,14 @@ namespace df { stl_bit_vector_identity identity_traits >::identity; bit_array_identity identity_traits >::identity; + static void *fstream_allocator_fn(void *out, const void *in) { + if (out) { /* *(T*)out = *(const T*)in;*/ return NULL; } + else if (in) { delete (std::fstream*)in; return (std::fstream*)in; } + else return new std::fstream(); + } + opaque_identity identity_traits::identity( + sizeof(std::fstream), fstream_allocator_fn, "fstream"); + buffer_container_identity buffer_container_identity::base_instance; #undef NUMBER_IDENTITY_TRAITS diff --git a/library/LuaTypes.cpp b/library/LuaTypes.cpp index 877609e56..410c25f88 100644 --- a/library/LuaTypes.cpp +++ b/library/LuaTypes.cpp @@ -1256,8 +1256,11 @@ static void MakePrimitiveMetatable(lua_State *state, type_identity *type) // Index the fields lua_newtable(state); - EnableMetaField(state, base+2, "value", type); - AssociateId(state, base+3, 1, "value"); + if (type->type() != IDTYPE_OPAQUE) + { + EnableMetaField(state, base+2, "value", type); + AssociateId(state, base+3, 1, "value"); + } // Add the iteration metamethods PushStructMethod(state, base+1, base+3, meta_struct_next); diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h index 3591be045..3bb62a2c1 100644 --- a/library/include/DataDefs.h +++ b/library/include/DataDefs.h @@ -61,7 +61,8 @@ namespace DFHack IDTYPE_STRUCT, IDTYPE_CLASS, IDTYPE_BUFFER, - IDTYPE_STL_PTR_VECTOR + IDTYPE_STL_PTR_VECTOR, + IDTYPE_OPAQUE }; typedef void *(*TAllocateFn)(void*,const void*); @@ -78,7 +79,7 @@ namespace DFHack virtual bool can_allocate() { return true; } virtual void *do_allocate() { return do_allocate_pod(); } - virtual void do_copy(void *tgt, const void *src) { do_copy_pod(tgt, src); } + virtual bool do_copy(void *tgt, const void *src) { do_copy_pod(tgt, src); return true; } virtual bool do_destroy(void *obj) { return do_destroy_pod(obj); } public: @@ -116,7 +117,7 @@ namespace DFHack virtual bool can_allocate() { return (allocator != NULL); } virtual void *do_allocate() { return allocator(NULL,NULL); } - virtual void do_copy(void *tgt, const void *src) { allocator(tgt,src); } + virtual bool do_copy(void *tgt, const void *src) { return allocator(tgt,src) == tgt; } virtual bool do_destroy(void *obj) { return allocator(NULL,obj) == obj; } public: virtual bool isPrimitive() { return false; } @@ -166,7 +167,7 @@ namespace DFHack protected: virtual bool can_allocate() { return true; } virtual void *do_allocate() { return do_allocate_pod(); } - virtual void do_copy(void *tgt, const void *src) { do_copy_pod(tgt, src); } + virtual bool do_copy(void *tgt, const void *src) { do_copy_pod(tgt, src); return true; } virtual bool do_destroy(void *obj) { return do_destroy_pod(obj); } public: @@ -199,7 +200,7 @@ namespace DFHack protected: virtual bool can_allocate() { return true; } virtual void *do_allocate(); - virtual void do_copy(void *tgt, const void *src) { do_copy_pod(tgt, src); } + virtual bool do_copy(void *tgt, const void *src) { do_copy_pod(tgt, src); return true; } virtual bool do_destroy(void *obj) { return do_destroy_pod(obj); } public: diff --git a/library/include/DataIdentity.h b/library/include/DataIdentity.h index e684c6abd..e6dfc6a18 100644 --- a/library/include/DataIdentity.h +++ b/library/include/DataIdentity.h @@ -65,6 +65,17 @@ namespace DFHack virtual identity_type type() { return IDTYPE_PRIMITIVE; } }; + class DFHACK_EXPORT opaque_identity : public constructed_identity { + std::string name; + + public: + opaque_identity(size_t size, TAllocateFn alloc, const std::string &name) + : constructed_identity(size, alloc), name(name) {}; + + virtual std::string getFullName() { return name; } + virtual identity_type type() { return IDTYPE_OPAQUE; } + }; + class DFHACK_EXPORT pointer_identity : public primitive_identity { type_identity *target; @@ -170,6 +181,7 @@ namespace df { using DFHack::function_identity_base; using DFHack::primitive_identity; + using DFHack::opaque_identity; using DFHack::pointer_identity; using DFHack::container_identity; using DFHack::ptr_container_identity; @@ -488,6 +500,11 @@ namespace df static stl_string_identity *get() { return &identity; } }; + template<> struct DFHACK_EXPORT identity_traits { + static opaque_identity identity; + static opaque_identity *get() { return &identity; } + }; + template<> struct DFHACK_EXPORT identity_traits { static ptr_string_identity identity; static ptr_string_identity *get() { return &identity; } diff --git a/library/include/df/custom/file_compressorst.methods.inc b/library/include/df/custom/file_compressorst.methods.inc new file mode 100644 index 000000000..ad61c7bc7 --- /dev/null +++ b/library/include/df/custom/file_compressorst.methods.inc @@ -0,0 +1,12 @@ +file_compressorst& operator=(const file_compressorst &in) { + compressed = in.compressed; + /* fstream cannot be assigned */ + in_buffer = in.in_buffer; + in_buffersize = in.in_buffersize; + in_buffer_amount_loaded = in.in_buffer_amount_loaded; + in_buffer_position = in.in_buffer_position; + out_buffer = in.out_buffer; + out_buffersize = in.out_buffersize; + out_buffer_amount_written = in.out_buffer_amount_written; + return *this; +} diff --git a/library/xml b/library/xml index 93606b34b..5541b66ce 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 93606b34b78a94b201704adb5c9ae28af304cdb1 +Subproject commit 5541b66cef283e57c32551f69cc3fd87cff966d2 From 1a38c727630539a3df09b04ecf4b1ce8f1e25014 Mon Sep 17 00:00:00 2001 From: jj Date: Wed, 24 Sep 2014 23:37:25 +0200 Subject: [PATCH 04/35] ruby: add stl-fstream to codegen --- plugins/ruby/codegen.pl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/plugins/ruby/codegen.pl b/plugins/ruby/codegen.pl index f04731e3b..8a670718e 100755 --- a/plugins/ruby/codegen.pl +++ b/plugins/ruby/codegen.pl @@ -595,6 +595,9 @@ sub get_field_align { $al = get_field_align($tg); } elsif ($meta eq 'bytes') { $al = $field->getAttribute('alignment') || 1; + } elsif ($meta eq 'primitive') { + my $subtype = $field->getAttribute('ld:subtype'); + if ($subtype eq 'stl-fstream' and $os eq 'windows') { $al = 8; } } return $al; @@ -735,6 +738,14 @@ sub sizeof { print "sizeof stl-string on $os\n"; } print "sizeof stl-string\n"; + } elsif ($subtype eq 'stl-fstream') { if ($os eq 'linux') { + return 284; + } elsif ($os eq 'windows') { + return 184; + } else { + print "sizeof stl-fstream on $os\n"; + } + print "sizeof stl-fstream\n"; } else { print "sizeof primitive $subtype\n"; } @@ -1011,6 +1022,7 @@ sub render_item_primitive { my $subtype = $item->getAttribute('ld:subtype'); if ($subtype eq 'stl-string') { push @lines_rb, "stl_string"; + } elsif ($subtype eq 'stl-fstream') { } else { print "no render primitive $subtype\n"; } From 0766538ecde984a5dafb317bd20191195d0c4623 Mon Sep 17 00:00:00 2001 From: jj Date: Thu, 25 Sep 2014 15:53:03 +0200 Subject: [PATCH 05/35] ruby: add df.print_color(col, string) --- NEWS | 1 + plugins/ruby/ruby.cpp | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/NEWS b/NEWS index bf4f7adf2..342aa1bbd 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,7 @@ DFHack future DFHack 0.40.13-r1 Internals: - unified spatter structs + - added ruby df.print_color(color, string) method for dfhack console Fixes: - no more -e after terminating diff --git a/plugins/ruby/ruby.cpp b/plugins/ruby/ruby.cpp index ea4becd6a..93d6501f0 100644 --- a/plugins/ruby/ruby.cpp +++ b/plugins/ruby/ruby.cpp @@ -543,6 +543,18 @@ static VALUE rb_dfprint_str(VALUE self, VALUE s) return Qnil; } +static VALUE rb_dfprint_color(VALUE self, VALUE c, VALUE s) +{ + if (r_console) { + color_value old_col = r_console->color(); + r_console->color(color_value(rb_num2ulong(c))); + r_console->print("%s", rb_string_value_ptr(&s)); + r_console->color(old_col); + } else + console_proxy->print("%s", rb_string_value_ptr(&s)); + return Qnil; +} + static VALUE rb_dfprint_err(VALUE self, VALUE s) { printerr("%s", rb_string_value_ptr(&s)); @@ -1072,6 +1084,7 @@ static void ruby_bind_dfhack(void) { rb_define_singleton_method(rb_cDFHack, "get_vtable_ptr", RUBY_METHOD_FUNC(rb_dfget_vtable_ptr), 1); rb_define_singleton_method(rb_cDFHack, "dfhack_run", RUBY_METHOD_FUNC(rb_dfhack_run), 1); rb_define_singleton_method(rb_cDFHack, "print_str", RUBY_METHOD_FUNC(rb_dfprint_str), 1); + rb_define_singleton_method(rb_cDFHack, "print_color", RUBY_METHOD_FUNC(rb_dfprint_color), 2); rb_define_singleton_method(rb_cDFHack, "print_err", RUBY_METHOD_FUNC(rb_dfprint_err), 1); rb_define_singleton_method(rb_cDFHack, "malloc", RUBY_METHOD_FUNC(rb_dfmalloc), 1); rb_define_singleton_method(rb_cDFHack, "free", RUBY_METHOD_FUNC(rb_dffree), 1); From eed684a8dfba80c04964a5b5ada1621fde3caaa5 Mon Sep 17 00:00:00 2001 From: jj Date: Thu, 25 Sep 2014 22:02:31 +0200 Subject: [PATCH 06/35] fix superdwarf --- NEWS | 1 + plugins/ruby/ruby.rb | 2 +- scripts/superdwarf.rb | 9 ++++++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 342aa1bbd..331575211 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,7 @@ DFHack 0.40.13-r1 - added ruby df.print_color(color, string) method for dfhack console Fixes: - no more -e after terminating + - fixed superdwarf DFHack 0.40.12-r1 Fixes: diff --git a/plugins/ruby/ruby.rb b/plugins/ruby/ruby.rb index edce8ac84..af957c76b 100644 --- a/plugins/ruby/ruby.rb +++ b/plugins/ruby/ruby.rb @@ -179,7 +179,7 @@ module DFHack if not onlylastpart out << name.first_name if name.first_name != '' if name.nickname != '' - case respond_to?(:d_init) && d_init.nickname_dwarf + case respond_to?(:d_init) && d_init.nickname[gametype] when :REPLACE_ALL; return "`#{name.nickname}'" when :REPLACE_FIRST; out.pop end diff --git a/scripts/superdwarf.rb b/scripts/superdwarf.rb index 93e299362..4aaa08231 100644 --- a/scripts/superdwarf.rb +++ b/scripts/superdwarf.rb @@ -16,9 +16,12 @@ when 'add' $superdwarf_ids.each { |id| if u = df.unit_find(id) and not u.flags1.dead # faster walk/work - if u.counters.job_counter > 0 - u.counters.job_counter = 0 - end + u.actions.each { |a| + case a.type + when :Move, :Climb, :Job, :Job2 + a.data.send(a.type.to_s.downcase).timer = 0 + end + } # no sleep if u.counters2.sleepiness_timer > 10000 From e46a27c8a4669c08c3dc7e6196bb2d7c81bad5a7 Mon Sep 17 00:00:00 2001 From: Eric Wald Date: Sat, 27 Sep 2014 11:07:26 -0600 Subject: [PATCH 07/35] Switching automelt to the stockpile iterator. --- plugins/automelt.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/plugins/automelt.cpp b/plugins/automelt.cpp index 58cbdd20c..394bd9406 100644 --- a/plugins/automelt.cpp +++ b/plugins/automelt.cpp @@ -7,6 +7,7 @@ #include "df/building_def.h" #include "df/viewscreen_dwarfmodest.h" #include "df/building_stockpilest.h" +#include "modules/Buildings.h" #include "modules/Items.h" #include "df/ui.h" #include "modules/Maps.h" @@ -25,8 +26,6 @@ static const string PERSISTENCE_KEY = "automelt/stockpiles"; static void mark_all_in_stockpiles(vector &stockpiles) { - std::vector &items = world->items.other[items_other_id::IN_PLAY]; - // Precompute a bitmask with the bad flags df::item_flags bad_flags; bad_flags.whole = 0; @@ -39,22 +38,23 @@ static void mark_all_in_stockpiles(vector &stockpiles) #undef F size_t marked_count = 0; - for (size_t i = 0; i < items.size(); i++) + auto &melting_items = world->items.other[items_other_id::ANY_MELT_DESIGNATED]; + for (auto it = stockpiles.begin(); it != stockpiles.end(); it++) { - df::item *item = items[i]; - if (item->flags.whole & bad_flags.whole) + if (!it->isValid()) continue; - if (!can_melt(item)) - continue; + Buildings::StockpileIterator stored; + for (stored.begin(it->getStockpile()); !stored.done(); ++stored) + { + df::item *item = *stored; + if (item->flags.whole & bad_flags.whole) + continue; - if (is_set_to_melt(item)) - continue; + if (!can_melt(item)) + continue; - auto &melting_items = world->items.other[items_other_id::ANY_MELT_DESIGNATED]; - for (auto it = stockpiles.begin(); it != stockpiles.end(); it++) - { - if (!it->inStockpile(item)) + if (is_set_to_melt(item)) continue; ++marked_count; From da72848b0b18ca29b5a7f6f4186b325f9b3a8ea9 Mon Sep 17 00:00:00 2001 From: hobotron-df Date: Sat, 27 Sep 2014 19:47:27 -0500 Subject: [PATCH 08/35] Fixes for fastdwarf combat speed and attack retargeting. --- plugins/fastdwarf.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/plugins/fastdwarf.cpp b/plugins/fastdwarf.cpp index b03fda561..0bd9d9698 100644 --- a/plugins/fastdwarf.cpp +++ b/plugins/fastdwarf.cpp @@ -113,8 +113,15 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out ) action->data.move.timer = 1; break; case unit_action_type::Attack: + // Attacks are executed when timer1 reaches zero, which will be + // on the following tick. action->data.attack.timer1 = 1; - action->data.attack.timer2 = 1; + // Attack actions are completed, and new ones generated, when + // timer2 reaches zero. If set to 1 this never seems to occur. + // Setting to zero makes next tick generate a new attack action + // every time, thereby allowing target enemy/body part re-selection + // take place. + action->data.attack.timer2 = 0; break; case unit_action_type::Hold: action->data.hold.timer = 1; From 0fad63bba79997db5f7fbb23a6ca8c62549a83c7 Mon Sep 17 00:00:00 2001 From: Eric Wald Date: Sun, 28 Sep 2014 18:24:07 -0600 Subject: [PATCH 09/35] New trackstop plugin. Simply adds a menu to track stops, showing and changing friction and dump direction. --- plugins/CMakeLists.txt | 1 + plugins/trackstop.cpp | 195 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 196 insertions(+) create mode 100644 plugins/trackstop.cpp diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 6ebe3ad6d..35b7ca52d 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -156,6 +156,7 @@ if (BUILD_SUPPORTED) DFHACK_PLUGIN(stocks stocks.cpp) DFHACK_PLUGIN(strangemood strangemood.cpp) DFHACK_PLUGIN(tiletypes tiletypes.cpp Brushes.h) + DFHACK_PLUGIN(trackstop trackstop.cpp) # DFHACK_PLUGIN(treefarm treefarm.cpp) DFHACK_PLUGIN(tubefill tubefill.cpp) DFHACK_PLUGIN(tweak tweak.cpp) diff --git a/plugins/trackstop.cpp b/plugins/trackstop.cpp new file mode 100644 index 000000000..54e0b56d4 --- /dev/null +++ b/plugins/trackstop.cpp @@ -0,0 +1,195 @@ +/* + * Trackstop plugin. + * Shows track stop friction and direction in its 'q' menu. + */ + +#include "uicommon.h" +#include "LuaTools.h" + +#include "df/building_trapst.h" +#include "df/viewscreen_dwarfmodest.h" + +#include "modules/Gui.h" + +using namespace DFHack; +using namespace std; + +using df::global::world; +using df::global::ui; +using df::building_trapst; +using df::enums::trap_type::trap_type; + +DFHACK_PLUGIN("trackstop"); + +#define AUTOENABLE false +DFHACK_PLUGIN_IS_ENABLED(enabled); + + +/* + * Interface hooks + */ +struct trackstop_hook : public df::viewscreen_dwarfmodest { + typedef df::viewscreen_dwarfmodest interpose_base; + + enum Friction { + Lowest = 10, + Low = 50, + Medium = 500, + High = 10000, + Highest = 50000 + }; + + building_trapst *get_selected_trackstop() { + if (!Gui::dwarfmode_hotkey(Core::getTopViewscreen()) || ui->main.mode != ui_sidebar_mode::QueryBuilding) { + return nullptr; + } + + building_trapst *ts = virtual_cast(world->selected_building); + if (ts && ts->trap_type == trap_type::TrackStop && ts->construction_stage) { + return ts; + } + + return nullptr; + } + + bool handleInput(set *input) { + building_trapst *ts = get_selected_trackstop(); + if (!ts) { + return false; + } + + if (input->count(interface_key::BUILDING_TRACK_STOP_DUMP)) { + // Change track stop dump direction. + // There might be a more elegant way to do this. + + if (!ts->use_dump) { + // No -> North + ts->use_dump = 1; + ts->dump_x_shift = 0; + ts->dump_y_shift = -1; + } else if (ts->dump_x_shift == 0 && ts->dump_y_shift == -1) { + // North -> South + ts->dump_x_shift = 0; + ts->dump_y_shift = 1; + } else if (ts->dump_x_shift == 0 && ts->dump_y_shift == 1) { + // South -> East + ts->dump_x_shift = 1; + ts->dump_y_shift = 0; + } else if (ts->dump_x_shift == 1 && ts->dump_y_shift == 0) { + // East -> West + ts->dump_x_shift = -1; + ts->dump_y_shift = 0; + } else { + // West (or Elsewhere) -> No + ts->use_dump = 0; + ts->dump_x_shift = 0; + ts->dump_y_shift = 0; + } + + return true; + } else if (input->count(interface_key::BUILDING_TRACK_STOP_FRICTION_UP)) { + ts->friction = ( + (ts->friction < Friction::Lowest)? Friction::Lowest: + (ts->friction < Friction::Low)? Friction::Low: + (ts->friction < Friction::Medium)? Friction::Medium: + (ts->friction < Friction::High)? Friction::High: + (ts->friction < Friction::Highest)? Friction::Highest: + ts->friction + ); + + return true; + } else if (input->count(interface_key::BUILDING_TRACK_STOP_FRICTION_DOWN)) { + ts->friction = ( + (ts->friction > Friction::Highest)? Friction::Highest: + (ts->friction > Friction::High)? Friction::High: + (ts->friction > Friction::Medium)? Friction::Medium: + (ts->friction > Friction::Low)? Friction::Low: + (ts->friction > Friction::Lowest)? Friction::Lowest: + ts->friction + ); + + return true; + } + + return false; + } + + DEFINE_VMETHOD_INTERPOSE(void, feed, (set *input)) { + if (!handleInput(input)) { + INTERPOSE_NEXT(feed)(input); + } + } + + DEFINE_VMETHOD_INTERPOSE(void, render, ()) { + INTERPOSE_NEXT(render)(); + + building_trapst *ts = get_selected_trackstop(); + if (ts) { + auto dims = Gui::getDwarfmodeViewDims(); + int left_margin = dims.menu_x1 + 1; + int x = left_margin; + int y = dims.y1 + 1; + + OutputString(COLOR_WHITE, x, y, "Track Stop", true, left_margin); + + y += 3; + OutputString(COLOR_WHITE, x, y, "Friction: ", false); + OutputString(COLOR_WHITE, x, y, ( + (ts->friction <= Friction::Lowest)? "Lowest": + (ts->friction <= Friction::Low)? "Low": + (ts->friction <= Friction::Medium)? "Medium": + (ts->friction <= Friction::High)? "High": + "Highest" + ), true, left_margin); + OutputString(COLOR_LIGHTRED, x, y, Screen::getKeyDisplay(interface_key::BUILDING_TRACK_STOP_FRICTION_DOWN)); + OutputString(COLOR_LIGHTRED, x, y, Screen::getKeyDisplay(interface_key::BUILDING_TRACK_STOP_FRICTION_UP)); + OutputString(COLOR_WHITE, x, y, ": Change Friction", true, left_margin); + + y += 1; + + OutputString(COLOR_WHITE, x, y, "Dump on arrival: ", false); + OutputString(COLOR_WHITE, x, y, ( + (!ts->use_dump)? "No": + (ts->dump_x_shift == 0 && ts->dump_y_shift == -1)? "North": + (ts->dump_x_shift == 0 && ts->dump_y_shift == 1)? "South": + (ts->dump_x_shift == 1 && ts->dump_y_shift == 0)? "East": + (ts->dump_x_shift == -1 && ts->dump_y_shift == 0)? "West": + "Elsewhere" + ), true, left_margin); + OutputString(COLOR_LIGHTRED, x, y, Screen::getKeyDisplay(interface_key::BUILDING_TRACK_STOP_DUMP)); + OutputString(COLOR_WHITE, x, y, ": Activate/change direction", true, left_margin); + } + } +}; + +IMPLEMENT_VMETHOD_INTERPOSE(trackstop_hook, feed); +IMPLEMENT_VMETHOD_INTERPOSE(trackstop_hook, render); + + +DFhackCExport command_result plugin_enable(color_ostream& out, bool enable) { + // Accept the "enable trackstop" / "disable trackstop" commands. + if (enable != enabled) { + if (enable && !gps) { + out.printerr("The trackstop module needs graphics.\n"); + return CR_FAILURE; + } + + if (!INTERPOSE_HOOK(trackstop_hook, feed).apply(enable) || + !INTERPOSE_HOOK(trackstop_hook, render).apply(enable)) { + out.printerr("Could not %s trackstop hooks!\n", enable? "insert": "remove"); + return CR_FAILURE; + } + + enabled = enable; + } + + return CR_OK; +} + +DFhackCExport command_result plugin_init(color_ostream &out, std::vector &commands) { + return plugin_enable(out, AUTOENABLE); +} + +DFhackCExport command_result plugin_shutdown(color_ostream &out) { + return plugin_enable(out, false); +} From c9cdc041778bbcb4037ff0502b0c47da0af194bb Mon Sep 17 00:00:00 2001 From: Eric Wald Date: Sun, 28 Sep 2014 18:43:19 -0600 Subject: [PATCH 10/35] Trackstop plugin documentation. --- NEWS | 3 +++ Readme.html | 15 +++++++++++++++ Readme.rst | 13 +++++++++++++ 3 files changed, 31 insertions(+) diff --git a/NEWS b/NEWS index bf4f7adf2..8fe274019 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,8 @@ DFHack future + New plugins: + - trackstop: Shows track stop friction and dump direction in its 'q' menu + DFHack 0.40.13-r1 Internals: - unified spatter structs diff --git a/Readme.html b/Readme.html index 10bc3b6c1..e1c693522 100644 --- a/Readme.html +++ b/Readme.html @@ -529,6 +529,7 @@ access DF memory and allow for easier development of new tools.

  • Search
  • AutoMaterial
  • Stockpile Automation
  • +
  • Track Stop Menu
  • gui/advfort
  • gui/assign-rack
  • gui/choose-weapons
  • @@ -3275,6 +3276,20 @@ enable automelt

    When querying a stockpile an option will appear to toggle automelt for this stockpile. Any items placed in this stockpile will be designated to be melted.

    +
    +

    Track Stop Menu

    +

    The q menu of track stops is completely blank by default. To enable one:

    +
    +enable trackstop
    +
    +

    This allows you to view and/or change the track stop's friction and dump direction settings. +It re-uses the keybindings from the track stop building interface:

    +
      +
    • BUILDING_TRACK_STOP_FRICTION_UP
    • +
    • BUILDING_TRACK_STOP_FRICTION_DOWN
    • +
    • BUILDING_TRACK_STOP_DUMP
    • +
    +

    gui/advfort

    This script allows to perform jobs in adventure mode. For more complete help diff --git a/Readme.rst b/Readme.rst index b143b0c54..dc92b577b 100644 --- a/Readme.rst +++ b/Readme.rst @@ -2655,6 +2655,19 @@ Enable the automelt plugin in your dfhack.init with:: When querying a stockpile an option will appear to toggle automelt for this stockpile. Any items placed in this stockpile will be designated to be melted. +Track Stop Menu +=============== + +The `q` menu of track stops is completely blank by default. To enable one:: + + enable trackstop + +This allows you to view and/or change the track stop's friction and dump direction settings. +It re-uses the keybindings from the track stop building interface: + +* BUILDING_TRACK_STOP_FRICTION_UP +* BUILDING_TRACK_STOP_FRICTION_DOWN +* BUILDING_TRACK_STOP_DUMP gui/advfort =========== From 11d08518d6e1c7f857efb99cc953676f317bf755 Mon Sep 17 00:00:00 2001 From: Eric Wald Date: Sun, 28 Sep 2014 18:45:47 -0600 Subject: [PATCH 11/35] Adding trackstop to the example init file. --- dfhack.init-example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dfhack.init-example b/dfhack.init-example index f0f380095..5338f9448 100644 --- a/dfhack.init-example +++ b/dfhack.init-example @@ -183,7 +183,7 @@ enable search enable automaterial # Other interface improvement tools -enable dwarfmonitor mousequery automelt autotrade buildingplan resume zone +enable dwarfmonitor mousequery automelt autotrade buildingplan resume trackstop zone # allow the fortress bookkeeper to queue jobs through the manager stockflow enable From 4af9b7a0546f30583d979011d13f7c969bfdf108 Mon Sep 17 00:00:00 2001 From: Eric Wald Date: Sun, 28 Sep 2014 21:34:42 -0600 Subject: [PATCH 12/35] Checking for more required variables. Trying to use trackstop without ui or world results in a hard crash. --- plugins/trackstop.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/trackstop.cpp b/plugins/trackstop.cpp index 54e0b56d4..455b53774 100644 --- a/plugins/trackstop.cpp +++ b/plugins/trackstop.cpp @@ -169,8 +169,11 @@ IMPLEMENT_VMETHOD_INTERPOSE(trackstop_hook, render); DFhackCExport command_result plugin_enable(color_ostream& out, bool enable) { // Accept the "enable trackstop" / "disable trackstop" commands. if (enable != enabled) { - if (enable && !gps) { - out.printerr("The trackstop module needs graphics.\n"); + // Check for global variables that, if missing, result in total failure. + // Missing enabler and ui_menu_width also produce visible effects, but not nearly as severe. + // This could be moved to the plugin_init step, but that's louder for no real benefit. + if (!(gps && ui && world)) { + out.printerr("trackstop: Missing required global variables.\n"); return CR_FAILURE; } From 2e80c6053c7cab318a89815e8fc5df184709cdc9 Mon Sep 17 00:00:00 2001 From: Eric Wald Date: Mon, 29 Sep 2014 21:37:05 -0600 Subject: [PATCH 13/35] Autotrade bugfix: Mark All now unmarks bin contents. This prevents a form of cheating, because they already get traded with the bin itself, so their value had been counted twice. However, the search plugin still enables this kind of cheating... --- NEWS | 3 +++ plugins/autotrade.cpp | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index bf4f7adf2..62468c478 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,8 @@ DFHack future + Fixes: + - autotrade: "Mark all" no longer double-marks bin contents + DFHack 0.40.13-r1 Internals: - unified spatter structs diff --git a/plugins/autotrade.cpp b/plugins/autotrade.cpp index ac733c1c2..eff1b5d64 100644 --- a/plugins/autotrade.cpp +++ b/plugins/autotrade.cpp @@ -455,7 +455,9 @@ struct tradeview_hook : public df::viewscreen_tradegoodsst { for (int i = 0; i < trader_selected.size(); i++) { - trader_selected[i] = 1; + // Only mark containers, not their contents. + // Granted, this behaves poorly with the search plugin... + trader_selected[i] = !trader_items[i]->flags.bits.in_inventory; } } else if (input->count(interface_key::CUSTOM_U)) @@ -469,7 +471,8 @@ struct tradeview_hook : public df::viewscreen_tradegoodsst { for (int i = 0; i < broker_selected.size(); i++) { - broker_selected[i] = 1; + // Only mark containers, not their contents. + broker_selected[i] = !broker_items[i]->flags.bits.in_inventory; } } else if (input->count(interface_key::CUSTOM_SHIFT_U)) From 6c9b94bcef458d68fab5dab3f60b993695b7315a Mon Sep 17 00:00:00 2001 From: Eric Wald Date: Tue, 30 Sep 2014 23:02:35 -0600 Subject: [PATCH 14/35] Removing duplicate world and map loading events. Saving a game in progress now goes through an extra viewscreen before reaching the condition that had been used to indicate whether the world was still valid, causing the core to emit bogus WORLD_LOADED, MAP_LOADED, MAP_UNLOADED, and WORLD_UNLOADED events. Adding that viewscreen to the list of loading/saving screens prevents those duplicate events from firing. Granted, if the game_cleaner viewscreen ever gets hit in play, this fix will cause more bogus events... --- library/Core.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/Core.cpp b/library/Core.cpp index b6ae13ae1..27adf8393 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -61,6 +61,7 @@ using namespace DFHack; #include "df/world_data.h" #include "df/interfacest.h" #include "df/viewscreen_dwarfmodest.h" +#include "df/viewscreen_game_cleanerst.h" #include "df/viewscreen_loadgamest.h" #include "df/viewscreen_savegamest.h" #include @@ -1280,6 +1281,7 @@ void Core::doUpdate(color_ostream &out, bool first_update) } bool is_load_save = + strict_virtual_cast(screen) || strict_virtual_cast(screen) || strict_virtual_cast(screen); From aafa3a5f91b2a0516c64ace071b74d965a42c9ab Mon Sep 17 00:00:00 2001 From: Eric Wald Date: Thu, 2 Oct 2014 22:00:40 -0600 Subject: [PATCH 15/35] Expanding on the rollers menu. As requested by fricy. --- plugins/trackstop.cpp | 105 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-) diff --git a/plugins/trackstop.cpp b/plugins/trackstop.cpp index 455b53774..4676a1b52 100644 --- a/plugins/trackstop.cpp +++ b/plugins/trackstop.cpp @@ -6,6 +6,7 @@ #include "uicommon.h" #include "LuaTools.h" +#include "df/building_rollersst.h" #include "df/building_trapst.h" #include "df/viewscreen_dwarfmodest.h" @@ -16,8 +17,10 @@ using namespace std; using df::global::world; using df::global::ui; +using df::building_rollersst; using df::building_trapst; using df::enums::trap_type::trap_type; +using df::enums::screw_pump_direction::screw_pump_direction; DFHACK_PLUGIN("trackstop"); @@ -162,8 +165,106 @@ struct trackstop_hook : public df::viewscreen_dwarfmodest { } }; +struct roller_hook : public df::viewscreen_dwarfmodest { + typedef df::viewscreen_dwarfmodest interpose_base; + + enum Speed { + Lowest = 10000, + Low = 20000, + Medium = 30000, + High = 40000, + Highest = 50000 + }; + + building_rollersst *get_selected_roller() { + if (!Gui::dwarfmode_hotkey(Core::getTopViewscreen()) || ui->main.mode != ui_sidebar_mode::QueryBuilding) { + return nullptr; + } + + building_rollersst *roller = virtual_cast(world->selected_building); + if (roller && roller->construction_stage) { + return roller; + } + + return nullptr; + } + + bool handleInput(set *input) { + building_rollersst *roller = get_selected_roller(); + if (!roller) { + return false; + } + + if (input->count(interface_key::BUILDING_ORIENT_NONE)) { + // Flip roller orientation. + // Long rollers can only be oriented along their length. + // Todo: Only add 1 to 1x1 rollers: x ^= ((x&1)<<1)|1 + // Todo: This could have been elegant without all the casting, + // but as an enum it might be better off listing each case. + roller->direction = (df::enums::screw_pump_direction::screw_pump_direction)(((int8_t)roller->direction) ^ 2); + return true; + } else if (input->count(interface_key::BUILDING_ROLLERS_SPEED_UP)) { + if (roller->speed < Speed::Highest) { + roller->speed += Speed::Lowest; + } + + return true; + } else if (input->count(interface_key::BUILDING_ROLLERS_SPEED_DOWN)) { + if (roller->speed > Speed::Lowest) { + roller->speed -= Speed::Lowest; + } + + return true; + } + + return false; + } + + DEFINE_VMETHOD_INTERPOSE(void, feed, (set *input)) { + if (!handleInput(input)) { + INTERPOSE_NEXT(feed)(input); + } + } + + DEFINE_VMETHOD_INTERPOSE(void, render, ()) { + INTERPOSE_NEXT(render)(); + + building_rollersst *roller = get_selected_roller(); + if (roller) { + auto dims = Gui::getDwarfmodeViewDims(); + int left_margin = dims.menu_x1 + 1; + int x = left_margin; + int y = dims.y1 + 6; + + OutputString(COLOR_LIGHTRED, x, y, Screen::getKeyDisplay(interface_key::BUILDING_ORIENT_NONE)); + OutputString(COLOR_WHITE, x, y, ": Rolls ", false); + OutputString(COLOR_WHITE, x, y, ( + (roller->direction == screw_pump_direction::FromNorth)? "Southward": + (roller->direction == screw_pump_direction::FromEast)? "Westward": + (roller->direction == screw_pump_direction::FromSouth)? "Northward": + (roller->direction == screw_pump_direction::FromWest)? "Eastward": + "" + ), true, left_margin); + + OutputString(COLOR_LIGHTRED, x, y, Screen::getKeyDisplay(interface_key::BUILDING_ROLLERS_SPEED_DOWN)); + OutputString(COLOR_LIGHTRED, x, y, Screen::getKeyDisplay(interface_key::BUILDING_ROLLERS_SPEED_UP)); + OutputString(COLOR_WHITE, x, y, ": "); + OutputString(COLOR_WHITE, x, y, ( + (roller->speed <= Speed::Lowest)? "Lowest": + (roller->speed <= Speed::Low)? "Low": + (roller->speed <= Speed::Medium)? "Medium": + (roller->speed <= Speed::High)? "High": + "Highest" + )); + OutputString(COLOR_WHITE, x, y, " Speed", true, left_margin); + } + } +}; + IMPLEMENT_VMETHOD_INTERPOSE(trackstop_hook, feed); IMPLEMENT_VMETHOD_INTERPOSE(trackstop_hook, render); +IMPLEMENT_VMETHOD_INTERPOSE(roller_hook, feed); +IMPLEMENT_VMETHOD_INTERPOSE(roller_hook, render); DFhackCExport command_result plugin_enable(color_ostream& out, bool enable) { @@ -178,7 +279,9 @@ DFhackCExport command_result plugin_enable(color_ostream& out, bool enable) { } if (!INTERPOSE_HOOK(trackstop_hook, feed).apply(enable) || - !INTERPOSE_HOOK(trackstop_hook, render).apply(enable)) { + !INTERPOSE_HOOK(trackstop_hook, render).apply(enable) || + !INTERPOSE_HOOK(roller_hook, feed).apply(enable) || + !INTERPOSE_HOOK(roller_hook, render).apply(enable)) { out.printerr("Could not %s trackstop hooks!\n", enable? "insert": "remove"); return CR_FAILURE; } From 0df2d71506b78d367dc31da8867fbd33d9fd6b9a Mon Sep 17 00:00:00 2001 From: expwnent Date: Sat, 4 Oct 2014 21:52:28 -0400 Subject: [PATCH 16/35] Fix repeat.lua documentation. --- scripts/repeat.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/repeat.lua b/scripts/repeat.lua index fe9afb026..0c08d8fa8 100644 --- a/scripts/repeat.lua +++ b/scripts/repeat.lua @@ -24,13 +24,13 @@ if args.help then print this help message repeat -cancel bob cancels the repetition with the name bob - repeat -name jim -time delay -timeUnits units -printResult true -command printArgs 3 1 2 + repeat -name jim -time delay -timeUnits units -printResult true -command [ printArgs 3 1 2 ] -name sets the name for the purposes of cancelling and making sure you don't schedule the same repeating event twice if not specified, it's set to the first argument after -command -time delay -timeUnits units delay is some positive integer units is some valid time unit for dfhack.timeout(delay,timeUnits,function) - -command ... + -command [ ... ] specify the command to be run ]]) return From 0471294b1e053139212fa4202956b8d7c7a6940a Mon Sep 17 00:00:00 2001 From: expwnent Date: Sat, 4 Oct 2014 21:54:07 -0400 Subject: [PATCH 17/35] Fix syndrome-util. --- library/lua/syndrome-util.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/lua/syndrome-util.lua b/library/lua/syndrome-util.lua index 90e699de7..083c90371 100644 --- a/library/lua/syndrome-util.lua +++ b/library/lua/syndrome-util.lua @@ -119,7 +119,7 @@ function isValidTarget(unit,syndrome) end for caste,creature in ipairs(syndrome.syn_affected_creature) do local affectedCreature = creature.value - local affectedCaste = syndrome.syn_affectedCaste[caste].value + local affectedCaste = syndrome.syn_affected_caste[caste].value if affectedCreature == unitRaceName and (affectedCaste == unitCasteName or affectedCaste == "ALL") then affected = true end From 95dd009a15bfb4d7a611fd71f24a8ef5bc9cb1c7 Mon Sep 17 00:00:00 2001 From: Eric Wald Date: Sun, 5 Oct 2014 17:57:57 -0600 Subject: [PATCH 18/35] Restoring automelt for items in bins. The stockpile iterator yields bins, but not their contents. Should other containers be checked, too? --- plugins/automelt.cpp | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/plugins/automelt.cpp b/plugins/automelt.cpp index 394bd9406..cfd348455 100644 --- a/plugins/automelt.cpp +++ b/plugins/automelt.cpp @@ -24,6 +24,34 @@ DFHACK_PLUGIN("automelt"); static const string PERSISTENCE_KEY = "automelt/stockpiles"; +static int mark_item(df::item *item, df::item_flags bad_flags, int32_t stockpile_id) +{ + if (item->flags.whole & bad_flags.whole) + return 0; + + if (item->isAssignedToThisStockpile(stockpile_id)) { + size_t marked_count = 0; + std::vector contents; + Items::getContainedItems(item, &contents); + for (auto child = contents.begin(); child != contents.end(); child++) + { + marked_count += mark_item(*child, bad_flags, stockpile_id); + } + + return marked_count; + } + + if (!can_melt(item)) + return 0; + + if (is_set_to_melt(item)) + return 0; + + insert_into_vector(world->items.other[items_other_id::ANY_MELT_DESIGNATED], &df::item::id, item); + item->flags.bits.melt = true; + return 1; +} + static void mark_all_in_stockpiles(vector &stockpiles) { // Precompute a bitmask with the bad flags @@ -38,28 +66,16 @@ static void mark_all_in_stockpiles(vector &stockpiles) #undef F size_t marked_count = 0; - auto &melting_items = world->items.other[items_other_id::ANY_MELT_DESIGNATED]; for (auto it = stockpiles.begin(); it != stockpiles.end(); it++) { if (!it->isValid()) continue; + auto spid = it->getId(); Buildings::StockpileIterator stored; for (stored.begin(it->getStockpile()); !stored.done(); ++stored) { - df::item *item = *stored; - if (item->flags.whole & bad_flags.whole) - continue; - - if (!can_melt(item)) - continue; - - if (is_set_to_melt(item)) - continue; - - ++marked_count; - insert_into_vector(melting_items, &df::item::id, item); - item->flags.bits.melt = true; + marked_count += mark_item(*stored, bad_flags, spid); } } From 0fd3f3dbf4aa3dba7e9cfe3e351538355b64a2ec Mon Sep 17 00:00:00 2001 From: Lethosor Date: Sun, 5 Oct 2014 23:14:25 -0400 Subject: [PATCH 19/35] Update digFlood documentation to mention onLoad(World).init Per http://www.bay12forums.com/smf/index.php?topic=139553.msg5712785#msg5712785 --- plugins/digFlood.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/digFlood.cpp b/plugins/digFlood.cpp index abe144a63..1646f4deb 100644 --- a/plugins/digFlood.cpp +++ b/plugins/digFlood.cpp @@ -72,7 +72,7 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector Date: Mon, 6 Oct 2014 16:46:43 -0400 Subject: [PATCH 20/35] Allow console to be disabled by setting an environment variable --- library/Core.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/library/Core.cpp b/library/Core.cpp index b6ae13ae1..48fe48531 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -1027,12 +1027,15 @@ bool Core::Init() cerr << "Initializing Console.\n"; // init the console. - bool is_text_mode = false; - if(init && init->display.flag.is_set(init_display_flags::TEXT)) + bool is_text_mode = (init && init->display.flag.is_set(init_display_flags::TEXT)); + if (is_text_mode || getenv("DFHACK_DISABLE_CONSOLE")) { - is_text_mode = true; con.init(true); cerr << "Console is not available. Use dfhack-run to send commands.\n"; + if (!is_text_mode) + { + cout << "Console disabled.\n"; + } } else if(con.init(false)) cerr << "Console is running.\n"; From f3626c100451e6d83bc04d9a95d95482976ee1c5 Mon Sep 17 00:00:00 2001 From: lethosor Date: Mon, 25 Aug 2014 21:24:23 -0400 Subject: [PATCH 21/35] embark-tools cleanup Fix #358: Disable "s" keybinding for settings on notes screen --- plugins/embark-tools.cpp | 656 ++++++++++++++++++++++----------------- 1 file changed, 366 insertions(+), 290 deletions(-) diff --git a/plugins/embark-tools.cpp b/plugins/embark-tools.cpp index 148e6787f..44a79f2be 100644 --- a/plugins/embark-tools.cpp +++ b/plugins/embark-tools.cpp @@ -11,98 +11,13 @@ #include #include "ColorText.h" +#include "uicommon.h" #include "df/viewscreen_choose_start_sitest.h" #include "df/interface_key.h" using namespace DFHack; -struct EmbarkTool -{ - std::string id; - std::string name; - std::string desc; - bool enabled; - df::interface_key toggle_key; -}; - -EmbarkTool embark_tools[] = { - {"anywhere", "Embark anywhere", "Allows embarking anywhere on the world map", - false, df::interface_key::CUSTOM_A}, - {"nano", "Nano embark", "Allows the embark size to be decreased below 2x2", - false, df::interface_key::CUSTOM_N}, - {"sand", "Sand indicator", "Displays an indicator when sand is present on the given embark site", - false, df::interface_key::CUSTOM_S}, - {"sticky", "Stable position", "Maintains the selected local area while navigating the world map", - false, df::interface_key::CUSTOM_P}, -}; -#define NUM_TOOLS int(sizeof(embark_tools) / sizeof(EmbarkTool)) - -command_result embark_tools_cmd (color_ostream &out, std::vector & parameters); - -void OutputString (int8_t color, int &x, int y, const std::string &text); - -bool tool_exists (std::string tool_name); -bool tool_enabled (std::string tool_name); -bool tool_enable (std::string tool_name, bool enable_state); -void tool_update (std::string tool_name); - -class embark_tools_settings : public dfhack_viewscreen -{ -public: - embark_tools_settings () { }; - ~embark_tools_settings () { }; - void help () { }; - std::string getFocusString () { return "embark-tools/options"; }; - void render () - { - parent->render(); - int x; - auto dim = Screen::getWindowSize(); - int width = 50, - height = 4 + 1 + NUM_TOOLS, // Padding + lower row - min_x = (dim.x - width) / 2, - max_x = (dim.x + width) / 2, - min_y = (dim.y - height) / 2, - max_y = min_y + height; - Screen::fillRect(Screen::Pen(' ', COLOR_BLACK, COLOR_DARKGREY), min_x, min_y, max_x, max_y); - Screen::fillRect(Screen::Pen(' ', COLOR_BLACK, COLOR_BLACK), min_x + 1, min_y + 1, max_x - 1, max_y - 1); - x = min_x + 2; - OutputString(COLOR_LIGHTRED, x, max_y - 2, Screen::getKeyDisplay(df::interface_key::SELECT)); - OutputString(COLOR_WHITE, x, max_y - 2, "/"); - OutputString(COLOR_LIGHTRED, x, max_y - 2, Screen::getKeyDisplay(df::interface_key::LEAVESCREEN)); - OutputString(COLOR_WHITE, x, max_y - 2, ": Done"); - for (int i = 0, y = min_y + 2; i < NUM_TOOLS; i++, y++) - { - EmbarkTool t = embark_tools[i]; - x = min_x + 2; - OutputString(COLOR_LIGHTRED, x, y, Screen::getKeyDisplay(t.toggle_key)); - OutputString(COLOR_WHITE, x, y, ": " + t.name + (t.enabled ? ": Enabled" : ": Disabled")); - } - }; - void feed (std::set * input) - { - if (input->count(df::interface_key::SELECT) || input->count(df::interface_key::LEAVESCREEN)) - { - Screen::dismiss(this); - return; - } - for (auto iter = input->begin(); iter != input->end(); iter++) - { - df::interface_key key = *iter; - for (int i = 0; i < NUM_TOOLS; i++) - { - if (embark_tools[i].toggle_key == key) - { - embark_tools[i].enabled = !embark_tools[i].enabled; - } - } - } - }; -}; - -/* - * Logic - */ +#define FOR_ITER_TOOLS(iter) for(auto iter = tools.begin(); iter != tools.end(); iter++) void update_embark_sidebar (df::viewscreen_choose_start_sitest * screen) { @@ -159,238 +74,317 @@ void resize_embark (df::viewscreen_choose_start_sitest * screen, int dx, int dy) update_embark_sidebar(screen); } -std::string sand_indicator = ""; -bool sand_dirty = true; // Flag set when update is needed -void sand_update (df::viewscreen_choose_start_sitest * screen) -{ - CoreSuspendClaimer suspend; - buffered_color_ostream out; - Core::getInstance().runCommand(out, "prospect"); - auto fragments = out.fragments(); - sand_indicator = ""; - for (auto iter = fragments.begin(); iter != fragments.end(); iter++) - { - std::string fragment = iter->second; - if (fragment.find("SAND_") != std::string::npos) - { - sand_indicator = "Sand"; - break; - } - } - sand_dirty = false; -} +typedef df::viewscreen_choose_start_sitest start_sitest; +typedef std::set ikey_set; -int sticky_pos[] = {0, 0, 3, 3}; -bool sticky_moved = false; -void sticky_save (df::viewscreen_choose_start_sitest * screen) +class EmbarkTool { - sticky_pos[0] = screen->location.embark_pos_min.x; - sticky_pos[1] = screen->location.embark_pos_max.x; - sticky_pos[2] = screen->location.embark_pos_min.y; - sticky_pos[3] = screen->location.embark_pos_max.y; -} - -void sticky_apply (df::viewscreen_choose_start_sitest * screen) -{ - if (screen->finder.finder_state != -1) - { - // Site finder is active - don't override default local position - return; - } - screen->location.embark_pos_min.x = sticky_pos[0]; - screen->location.embark_pos_max.x = sticky_pos[1]; - screen->location.embark_pos_min.y = sticky_pos[2]; - screen->location.embark_pos_max.y = sticky_pos[3]; - update_embark_sidebar(screen); -} +protected: + bool enabled; +public: + EmbarkTool() + :enabled(false) + { } + virtual bool getEnabled() { return enabled; } + virtual void setEnabled(bool state) { enabled = state; } + virtual void toggleEnabled() { setEnabled(!enabled); } + virtual std::string getId() = 0; + virtual std::string getName() = 0; + virtual std::string getDesc() = 0; + virtual df::interface_key getToggleKey() = 0; + virtual void before_render(start_sitest* screen) { }; + virtual void after_render(start_sitest* screen) { }; + virtual void before_feed(start_sitest* screen, ikey_set* input, bool &cancel) { }; + virtual void after_feed(start_sitest* screen, ikey_set* input) { }; +}; +std::vector tools; /* - * Viewscreen hooks - */ -void OutputString (int8_t color, int &x, int y, const std::string &text) +class SampleTool : public EmbarkTool { - Screen::paintString(Screen::Pen(' ', color, 0), x, y, text); - x += text.length(); -} + virtual std::string getId() { return "id"; } + virtual std::string getName() { return "Name"; } + virtual std::string getDesc() { return "Description"; } + virtual df::interface_key getToggleKey() { return df::interface_key::KEY; } + virtual void before_render(start_sitest* screen) { } + virtual void after_render(start_sitest* screen) { } + virtual void before_feed(start_sitest* screen, ikey_set* input, bool &cancel) { }; + virtual void after_feed(start_sitest* screen, ikey_set* input) { }; +}; -struct choose_start_site_hook : df::viewscreen_choose_start_sitest -{ - typedef df::viewscreen_choose_start_sitest interpose_base; +*/ - DEFINE_VMETHOD_INTERPOSE(void, feed, (std::set *input)) +class EmbarkAnywhere : public EmbarkTool +{ +public: + virtual std::string getId() { return "anywhere"; } + virtual std::string getName() { return "Embark anywhere"; } + virtual std::string getDesc() { return "Allows embarking anywhere on the world map"; } + virtual df::interface_key getToggleKey() { return df::interface_key::CUSTOM_A; } + virtual void after_render(start_sitest* screen) { - bool prevent_default = false; - if (tool_enabled("anywhere")) + auto dim = Screen::getWindowSize(); + int x = 20, y = dim.y - 2; + if (screen->page >= 0 && screen->page <= 4) { - for (auto iter = input->begin(); iter != input->end(); iter++) - { - df::interface_key key = *iter; - if (key == df::interface_key::SETUP_EMBARK) - { - prevent_default = true; - this->in_embark_normal = 1; - } - } + OutputString(COLOR_WHITE, x, y, ": Embark!"); } - - if (input->count(df::interface_key::CUSTOM_S)) + } + virtual void before_feed(start_sitest* screen, ikey_set *input, bool &cancel) + { + if (input->count(df::interface_key::SETUP_EMBARK)) { - Screen::show(new embark_tools_settings); - return; + cancel = true; + screen->in_embark_normal = 1; } + }; +}; - if (tool_enabled("nano")) +class NanoEmbark : public EmbarkTool +{ +public: + virtual std::string getId() { return "nano"; } + virtual std::string getName() { return "Nano embark"; } + virtual std::string getDesc() { return "Allows the embark size to be decreased below 2x2"; } + virtual df::interface_key getToggleKey() { return df::interface_key::CUSTOM_N; } + virtual void before_feed(start_sitest* screen, ikey_set* input, bool &cancel) + { + for (auto iter = input->begin(); iter != input->end(); iter++) { - for (auto iter = input->begin(); iter != input->end(); iter++) + df::interface_key key = *iter; + bool is_resize = true; + int dx = 0, dy = 0; + switch (key) { - df::interface_key key = *iter; - bool is_resize = true; - int dx = 0, dy = 0; - switch (key) - { - case df::interface_key::SETUP_LOCAL_Y_UP: - dy = 1; - break; - case df::interface_key::SETUP_LOCAL_Y_DOWN: - dy = -1; - break; - case df::interface_key::SETUP_LOCAL_X_UP: - dx = 1; - break; - case df::interface_key::SETUP_LOCAL_X_DOWN: - dx = -1; - break; - default: - is_resize = false; - } - if (is_resize) - { - prevent_default = true; - resize_embark(this, dx, dy); - } + case df::interface_key::SETUP_LOCAL_Y_UP: + dy = 1; + break; + case df::interface_key::SETUP_LOCAL_Y_DOWN: + dy = -1; + break; + case df::interface_key::SETUP_LOCAL_X_UP: + dx = 1; + break; + case df::interface_key::SETUP_LOCAL_X_DOWN: + dx = -1; + break; + default: + is_resize = false; + } + if (is_resize) + { + cancel = true; + resize_embark(screen, dx, dy); + return; } } + }; +}; - if (tool_enabled("sticky")) +class SandIndicator : public EmbarkTool +{ +protected: + bool dirty; + std::string indicator; + void update_indicator() + { + CoreSuspendClaimer suspend; + buffered_color_ostream out; + Core::getInstance().runCommand(out, "prospect"); + auto fragments = out.fragments(); + indicator = ""; + for (auto iter = fragments.begin(); iter != fragments.end(); iter++) { - for (auto iter = input->begin(); iter != input->end(); iter++) + std::string fragment = iter->second; + if (fragment.find("SAND_") != std::string::npos) { - df::interface_key key = *iter; - bool is_motion = false; - int dx = 0, dy = 0; - switch (key) - { - case df::interface_key::CURSOR_UP: - case df::interface_key::CURSOR_DOWN: - case df::interface_key::CURSOR_LEFT: - case df::interface_key::CURSOR_RIGHT: - case df::interface_key::CURSOR_UPLEFT: - case df::interface_key::CURSOR_UPRIGHT: - case df::interface_key::CURSOR_DOWNLEFT: - case df::interface_key::CURSOR_DOWNRIGHT: - case df::interface_key::CURSOR_UP_FAST: - case df::interface_key::CURSOR_DOWN_FAST: - case df::interface_key::CURSOR_LEFT_FAST: - case df::interface_key::CURSOR_RIGHT_FAST: - case df::interface_key::CURSOR_UPLEFT_FAST: - case df::interface_key::CURSOR_UPRIGHT_FAST: - case df::interface_key::CURSOR_DOWNLEFT_FAST: - case df::interface_key::CURSOR_DOWNRIGHT_FAST: - is_motion = true; - break; - default: - is_motion = false; - } - if (is_motion && !sticky_moved) - { - sticky_save(this); - sticky_moved = true; - } + indicator = "Sand"; + break; } } - - if (tool_enabled("sand")) + dirty = false; + } +public: + SandIndicator() + :EmbarkTool(), + dirty(true), + indicator("") + { } + virtual void setEnabled(bool state) + { + EmbarkTool::setEnabled(state); + dirty = true; + } + virtual std::string getId() { return "sand"; } + virtual std::string getName() { return "Sand indicator"; } + virtual std::string getDesc() { return "Displays an indicator when sand is present on the given embark site"; } + virtual df::interface_key getToggleKey() { return df::interface_key::CUSTOM_S; } + virtual void after_render(start_sitest* screen) + { + if (dirty) + update_indicator(); + auto dim = Screen::getWindowSize(); + int x = dim.x - 28, + y = 13; + if (screen->page == 0) { - sand_dirty = true; + OutputString(COLOR_YELLOW, x, y, indicator); } - if (!prevent_default) - INTERPOSE_NEXT(feed)(input); } + virtual void after_feed(start_sitest* screen, ikey_set* input) + { + dirty = true; + }; +}; - DEFINE_VMETHOD_INTERPOSE(void, render, ()) +class StablePosition : public EmbarkTool +{ +protected: + int prev_position[4]; + bool moved_position; + void save_position(start_sitest* screen) + { + prev_position[0] = screen->location.embark_pos_min.x; + prev_position[1] = screen->location.embark_pos_max.x; + prev_position[2] = screen->location.embark_pos_min.y; + prev_position[3] = screen->location.embark_pos_max.y; + } + void restore_position(start_sitest* screen) { - if (tool_enabled("sticky") && sticky_moved) + if (screen->finder.finder_state != -1) { - sticky_apply(this); - sticky_moved = false; + // Site finder is active - don't override default local position + return; } - - INTERPOSE_NEXT(render)(); - - auto dim = Screen::getWindowSize(); - int x = 1, - y = dim.y - 5; - OutputString(COLOR_LIGHTRED, x, y, Screen::getKeyDisplay(df::interface_key::CUSTOM_S)); - OutputString(COLOR_WHITE, x, y, ": Enabled: "); - std::list parts; - for (int i = 0; i < NUM_TOOLS; i++) + screen->location.embark_pos_min.x = prev_position[0]; + screen->location.embark_pos_max.x = prev_position[1]; + screen->location.embark_pos_min.y = prev_position[2]; + screen->location.embark_pos_max.y = prev_position[3]; + update_embark_sidebar(screen); + } +public: + StablePosition() + :EmbarkTool(), + moved_position(false) + { + prev_position[0] = 0; + prev_position[1] = 0; + prev_position[2] = 3; + prev_position[3] = 3; + } + virtual std::string getId() { return "sticky"; } + virtual std::string getName() { return "Stable position"; } + virtual std::string getDesc() { return "Maintains the selected local area while navigating the world map"; } + virtual df::interface_key getToggleKey() { return df::interface_key::CUSTOM_P; } + virtual void before_render(start_sitest* screen) { + if (moved_position) { - if (embark_tools[i].enabled) - { - parts.push_back(embark_tools[i].name); - parts.push_back(", "); - } + restore_position(screen); + moved_position = false; } - if (parts.size()) + } + virtual void before_feed(start_sitest* screen, ikey_set* input, bool &cancel) { + for (auto iter = input->begin(); iter != input->end(); iter++) { - parts.pop_back(); // Remove trailing comma - for (auto iter = parts.begin(); iter != parts.end(); iter++) + df::interface_key key = *iter; + bool is_motion = false; + int dx = 0, dy = 0; + switch (key) { - OutputString(COLOR_LIGHTMAGENTA, x, y, *iter); + case df::interface_key::CURSOR_UP: + case df::interface_key::CURSOR_DOWN: + case df::interface_key::CURSOR_LEFT: + case df::interface_key::CURSOR_RIGHT: + case df::interface_key::CURSOR_UPLEFT: + case df::interface_key::CURSOR_UPRIGHT: + case df::interface_key::CURSOR_DOWNLEFT: + case df::interface_key::CURSOR_DOWNRIGHT: + case df::interface_key::CURSOR_UP_FAST: + case df::interface_key::CURSOR_DOWN_FAST: + case df::interface_key::CURSOR_LEFT_FAST: + case df::interface_key::CURSOR_RIGHT_FAST: + case df::interface_key::CURSOR_UPLEFT_FAST: + case df::interface_key::CURSOR_UPRIGHT_FAST: + case df::interface_key::CURSOR_DOWNLEFT_FAST: + case df::interface_key::CURSOR_DOWNRIGHT_FAST: + is_motion = true; + break; + } + if (is_motion && !moved_position) + { + save_position(screen); + moved_position = true; } } - else + }; +}; + +class embark_tools_settings : public dfhack_viewscreen +{ +public: + embark_tools_settings () { }; + ~embark_tools_settings () { }; + void help () { }; + std::string getFocusString () { return "embark-tools/options"; }; + void render () + { + parent->render(); + int x, y; + auto dim = Screen::getWindowSize(); + int width = 50, + height = 4 + 1 + tools.size(), // Padding + lower row + min_x = (dim.x - width) / 2, + max_x = (dim.x + width) / 2, + min_y = (dim.y - height) / 2, + max_y = min_y + height; + Screen::fillRect(Screen::Pen(' ', COLOR_BLACK, COLOR_DARKGREY), min_x, min_y, max_x, max_y); + Screen::fillRect(Screen::Pen(' ', COLOR_BLACK, COLOR_BLACK), min_x + 1, min_y + 1, max_x - 1, max_y - 1); + x = min_x + 2; + y = max_y - 2; + OutputString(COLOR_LIGHTRED, x, y, Screen::getKeyDisplay(df::interface_key::SELECT)); + OutputString(COLOR_WHITE, x, y, "/"); + OutputString(COLOR_LIGHTRED, x, y, Screen::getKeyDisplay(df::interface_key::LEAVESCREEN)); + OutputString(COLOR_WHITE, x, y, ": Done"); + y = min_y + 2; + FOR_ITER_TOOLS(iter) { - OutputString(COLOR_LIGHTMAGENTA, x, y, "(none)"); + EmbarkTool* t = *iter; + x = min_x + 2; + OutputString(COLOR_LIGHTRED, x, y, Screen::getKeyDisplay(t->getToggleKey())); + OutputString(COLOR_WHITE, x, y, ": " + t->getName() + + (t->getEnabled() ? ": Enabled" : ": Disabled")); + y++; } - - if (tool_enabled("anywhere")) + }; + void feed (std::set * input) + { + if (input->count(df::interface_key::SELECT) || input->count(df::interface_key::LEAVESCREEN)) { - x = 20; y = dim.y - 2; - if (this->page >= 0 && this->page <= 4) - { - // Only display on five map pages, not on site finder or notes - OutputString(COLOR_WHITE, x, y, ": Embark!"); - } + Screen::dismiss(this); + return; } - if (tool_enabled("sand")) + for (auto iter = input->begin(); iter != input->end(); iter++) { - if (sand_dirty) - { - sand_update(this); - } - x = dim.x - 28; y = 13; - if (this->page == 0) + df::interface_key key = *iter; + FOR_ITER_TOOLS(iter) { - OutputString(COLOR_YELLOW, x, y, sand_indicator); + EmbarkTool* t = *iter; + if (t->getToggleKey() == key) + { + t->toggleEnabled(); + } } } - } + }; }; -IMPLEMENT_VMETHOD_INTERPOSE(choose_start_site_hook, feed); -IMPLEMENT_VMETHOD_INTERPOSE(choose_start_site_hook, render); - -/* - * Tool management - */ - bool tool_exists (std::string tool_name) { - for (int i = 0; i < NUM_TOOLS; i++) + FOR_ITER_TOOLS(iter) { - if (embark_tools[i].id == tool_name) + EmbarkTool* tool = *iter; + if (tool->getId() == tool_name) return true; } return false; @@ -398,10 +392,11 @@ bool tool_exists (std::string tool_name) bool tool_enabled (std::string tool_name) { - for (int i = 0; i < NUM_TOOLS; i++) + FOR_ITER_TOOLS(iter) { - if (embark_tools[i].id == tool_name) - return embark_tools[i].enabled; + EmbarkTool* tool = *iter; + if (tool->getId() == tool_name) + return tool->getEnabled(); } return false; } @@ -409,42 +404,122 @@ bool tool_enabled (std::string tool_name) bool tool_enable (std::string tool_name, bool enable_state) { int n = 0; - for (int i = 0; i < NUM_TOOLS; i++) + FOR_ITER_TOOLS(iter) { - if (embark_tools[i].id == tool_name || tool_name == "all") + EmbarkTool* tool = *iter; + if (tool->getId() == tool_name || tool_name == "all") { - embark_tools[i].enabled = enable_state; - tool_update(tool_name); + tool->setEnabled(enable_state); n++; } } return (bool)n; } -void tool_update (std::string tool_name) +struct choose_start_site_hook : df::viewscreen_choose_start_sitest { - // Called whenever a tool is enabled/disabled - if (tool_name == "sand") + typedef df::viewscreen_choose_start_sitest interpose_base; + + void display_tool_status() + { + auto dim = Screen::getWindowSize(); + int x = 1, + y = dim.y - 5; + OutputString(COLOR_LIGHTRED, x, y, Screen::getKeyDisplay(df::interface_key::CUSTOM_S)); + OutputString(COLOR_WHITE, x, y, ": Enabled: "); + std::list parts; + FOR_ITER_TOOLS(iter) + { + EmbarkTool* tool = *iter; + if (tool->getEnabled()) + { + parts.push_back(tool->getName()); + parts.push_back(", "); + } + } + if (parts.size()) + { + parts.pop_back(); // Remove trailing comma + for (auto iter = parts.begin(); iter != parts.end(); iter++) + { + OutputString(COLOR_LIGHTMAGENTA, x, y, *iter); + } + } + else + { + OutputString(COLOR_LIGHTMAGENTA, x, y, "(none)"); + } + } + + void display_settings() { - sand_dirty = true; + Screen::show(new embark_tools_settings); } -} -/* - * Plugin management - */ + inline bool is_valid_page() + { + return (page >= 0 && page <= 4); + } + + DEFINE_VMETHOD_INTERPOSE(void, feed, (std::set *input)) + { + bool cancel = false; + FOR_ITER_TOOLS(iter) + { + EmbarkTool* tool = *iter; + if (tool->getEnabled()) + tool->before_feed(this, input, cancel); + } + if (cancel) + return; + INTERPOSE_NEXT(feed)(input); + if (input->count(df::interface_key::CUSTOM_S) && is_valid_page()) + display_settings(); + FOR_ITER_TOOLS(iter) + { + EmbarkTool* tool = *iter; + if (tool->getEnabled()) + tool->after_feed(this, input); + } + } + DEFINE_VMETHOD_INTERPOSE(void, render, ()) + { + FOR_ITER_TOOLS(iter) + { + EmbarkTool* tool = *iter; + if (tool->getEnabled()) + tool->before_render(this); + } + INTERPOSE_NEXT(render)(); + display_tool_status(); + FOR_ITER_TOOLS(iter) + { + EmbarkTool* tool = *iter; + if (tool->getEnabled()) + tool->after_render(this); + } + } +}; +IMPLEMENT_VMETHOD_INTERPOSE(choose_start_site_hook, feed); +IMPLEMENT_VMETHOD_INTERPOSE(choose_start_site_hook, render); DFHACK_PLUGIN("embark-tools"); DFHACK_PLUGIN_IS_ENABLED(is_enabled); +command_result embark_tools_cmd (color_ostream &out, std::vector & parameters); + DFhackCExport command_result plugin_init (color_ostream &out, std::vector &commands) { + tools.push_back(new EmbarkAnywhere); + tools.push_back(new NanoEmbark); + tools.push_back(new SandIndicator); + tools.push_back(new StablePosition); std::string help = ""; help += "embark-tools (enable/disable) tool [tool...]\n" "Tools:\n"; - for (int i = 0; i < NUM_TOOLS; i++) + FOR_ITER_TOOLS(iter) { - help += (" " + embark_tools[i].id + ": " + embark_tools[i].desc + "\n"); + help += (" " + (*iter)->getId() + ": " + (*iter)->getDesc() + "\n"); } commands.push_back(PluginCommand( "embark-tools", @@ -504,10 +579,11 @@ command_result embark_tools_cmd (color_ostream &out, std::vector & if (is_enabled) { out << "Tool status:" << std::endl; - for (int i = 0; i < NUM_TOOLS; i++) + FOR_ITER_TOOLS(iter) { - EmbarkTool t = embark_tools[i]; - out << t.name << " (" << t.id << "): " << (t.enabled ? "Enabled" : "Disabled") << std::endl; + EmbarkTool* t = *iter; + out << t->getName() << " (" << t->getId() << "): " + << (t->getEnabled() ? "Enabled" : "Disabled") << std::endl; } } else From b0b1dd62d13720224da49c1d3effd78c8ccabbce Mon Sep 17 00:00:00 2001 From: Eric Wald Date: Sun, 12 Oct 2014 21:54:55 -0600 Subject: [PATCH 22/35] Rewriting the drainaquifer script The original drainaquifer script could occasionally fail to notice aquifer layers if they happen to skip each of the special tiles that it checks, two per block. It also left the block-level aquifer flags set, which seems like a minor waste of FPS. The new script uses the block-level flags to determine which blocks to check, which seems to be both more correct and faster. It's also written in Lua instead of Ruby, for clarity and ease of debugging. The name has changed slightly to prevent problems if both scripts are installed for some reason. --- NEWS | 2 ++ Readme.html | 6 +++--- Readme.rst | 4 ++-- scripts/drain-aquifer.lua | 33 +++++++++++++++++++++++++++++++++ scripts/drainaquifer.rb | 13 ------------- 5 files changed, 40 insertions(+), 18 deletions(-) create mode 100644 scripts/drain-aquifer.lua delete mode 100644 scripts/drainaquifer.rb diff --git a/NEWS b/NEWS index bf4f7adf2..4ce9edc5d 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,6 @@ DFHack future + Fixes: + - replaced drainaquifer.rb with a faster less buggy drain-aquifer.lua DFHack 0.40.13-r1 Internals: diff --git a/Readme.html b/Readme.html index 10bc3b6c1..bd9ea6aa5 100644 --- a/Readme.html +++ b/Readme.html @@ -501,7 +501,7 @@ access DF memory and allow for easier development of new tools.

  • binpatch
  • create-items
  • digfort
  • -
  • drainaquifer
  • +
  • drain-aquifer
  • deathcause
  • dfstatus
  • embark
  • @@ -2873,8 +2873,8 @@ as an offset for the pattern: instead of starting at the cursor, it will start

    The script takes the plan filename, starting from the root df folder (where Dwarf Fortress.exe is found).

    -
    -

    drainaquifer

    +
    +

    drain-aquifer

    Remove all 'aquifer' tag from the map blocks. Irreversible.

    diff --git a/Readme.rst b/Readme.rst index b143b0c54..2eb75b6b1 100644 --- a/Readme.rst +++ b/Readme.rst @@ -2149,8 +2149,8 @@ as an offset for the pattern: instead of starting at the cursor, it will start The script takes the plan filename, starting from the root df folder (where Dwarf Fortress.exe is found). -drainaquifer -============ +drain-aquifer +============= Remove all 'aquifer' tag from the map blocks. Irreversible. deathcause diff --git a/scripts/drain-aquifer.lua b/scripts/drain-aquifer.lua new file mode 100644 index 000000000..79c169b77 --- /dev/null +++ b/scripts/drain-aquifer.lua @@ -0,0 +1,33 @@ +-- Remove all aquifers from the map + +local function drain() + local last_layer = nil + local layer_count = 0 + local tile_count = 0 + + for k, block in ipairs(df.global.world.map.map_blocks) do + if block.flags.has_aquifer then + block.flags.has_aquifer = false + block.flags.check_aquifer = false + + for x, row in ipairs(block.designation) do + for y, tile in ipairs(row) do + if tile.water_table then + tile.water_table = false + tile_count = tile_count + 1 + end + end + end + + if block.map_pos.z ~= last_layer then + last_layer = block.map_pos.z + layer_count = layer_count + 1 + end + end + end + + print("Cleared "..tile_count.." aquifer tile"..((tile_count ~= 1) and "s" or "").. + " in "..layer_count.." layer"..((layer_count ~= 1) and "s" or "")..".") +end + +drain(...) diff --git a/scripts/drainaquifer.rb b/scripts/drainaquifer.rb deleted file mode 100644 index 169ea94fe..000000000 --- a/scripts/drainaquifer.rb +++ /dev/null @@ -1,13 +0,0 @@ -# remove all aquifers from the map - -count = 0 -df.each_map_block { |b| - if b.designation[0][0].water_table or b.designation[8][8].water_table - count += 1 - df.each_map_block_z(b.map_pos.z) { |bz| - bz.designation.each { |dx| dx.each { |dy| dy.water_table = false } } - } - end -} - -puts "cleared #{count} aquifer#{'s' if count > 1}" From 5d53163e16908382b8f7c2b44aad03b6c8add69b Mon Sep 17 00:00:00 2001 From: Eric Wald Date: Sun, 12 Oct 2014 22:28:23 -0600 Subject: [PATCH 23/35] Repairing drain-aquifer layer counting. --- scripts/drain-aquifer.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/drain-aquifer.lua b/scripts/drain-aquifer.lua index 79c169b77..0c153acaf 100644 --- a/scripts/drain-aquifer.lua +++ b/scripts/drain-aquifer.lua @@ -1,7 +1,7 @@ -- Remove all aquifers from the map local function drain() - local last_layer = nil + local layers = {} local layer_count = 0 local tile_count = 0 @@ -19,8 +19,8 @@ local function drain() end end - if block.map_pos.z ~= last_layer then - last_layer = block.map_pos.z + if not layers[block.map_pos.z] then + layers[block.map_pos.z] = true layer_count = layer_count + 1 end end From 169da1342d3eaffc8252d614bdebeff120e85f14 Mon Sep 17 00:00:00 2001 From: Eric Wald Date: Tue, 21 Oct 2014 22:43:56 -0600 Subject: [PATCH 24/35] Switching Dwarf Manipulator to a stable sort. This means, for example, that when you sort by one skill, then by a second, dwarves with the first skill but not the second will still be grouped together. --- plugins/manipulator.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/manipulator.cpp b/plugins/manipulator.cpp index ebd23a9d7..c1f585c3f 100644 --- a/plugins/manipulator.cpp +++ b/plugins/manipulator.cpp @@ -917,7 +917,7 @@ void viewscreen_unitlaborsst::feed(set *events) descending = events->count(interface_key::SECONDSCROLL_UP); sort_skill = columns[input_column].skill; sort_labor = columns[input_column].labor; - std::sort(units.begin(), units.end(), sortBySkill); + std::stable_sort(units.begin(), units.end(), sortBySkill); } if (events->count(interface_key::SECONDSCROLL_PAGEUP) || events->count(interface_key::SECONDSCROLL_PAGEDOWN)) @@ -926,16 +926,16 @@ void viewscreen_unitlaborsst::feed(set *events) switch (input_sort) { case ALTSORT_NAME: - std::sort(units.begin(), units.end(), sortByName); + std::stable_sort(units.begin(), units.end(), sortByName); break; case ALTSORT_PROFESSION_OR_SQUAD: - std::sort(units.begin(), units.end(), show_squad ? sortBySquad : sortByProfession); + std::stable_sort(units.begin(), units.end(), show_squad ? sortBySquad : sortByProfession); break; case ALTSORT_HAPPINESS: - std::sort(units.begin(), units.end(), sortByHappiness); + std::stable_sort(units.begin(), units.end(), sortByHappiness); break; case ALTSORT_ARRIVAL: - std::sort(units.begin(), units.end(), sortByArrival); + std::stable_sort(units.begin(), units.end(), sortByArrival); break; } } From ac73c0eeba2a3d1b67e00d7a94c7c20e90b760dc Mon Sep 17 00:00:00 2001 From: Eric Wald Date: Tue, 21 Oct 2014 22:49:50 -0600 Subject: [PATCH 25/35] Allowing non-labor skills to sort stably. --- plugins/manipulator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/manipulator.cpp b/plugins/manipulator.cpp index c1f585c3f..296048fb5 100644 --- a/plugins/manipulator.cpp +++ b/plugins/manipulator.cpp @@ -363,7 +363,7 @@ bool sortBySkill (const UnitInfo *d1, const UnitInfo *d2) else return d1->unit->status.labors[sort_labor] < d2->unit->status.labors[sort_labor]; } - return sortByName(d1, d2); + return false; } enum display_columns { From beebd624e7039ba1cfdedc6c5f8e0eb61fca42c9 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sun, 26 Oct 2014 13:20:45 +0300 Subject: [PATCH 26/35] Last xml update for v0.40.13 --- library/xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/xml b/library/xml index 5541b66ce..aed9a7644 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 5541b66cef283e57c32551f69cc3fd87cff966d2 +Subproject commit aed9a7644cd1d4a599c10d5f579fc742ced6bc3f From 04ec2c99324817828295d22f1e1dce00d5750438 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sun, 26 Oct 2014 16:40:39 +0300 Subject: [PATCH 27/35] Update version to v0.40.14 and hack things so they compile. Also make the find-offsets script less likely to crash if the unit structure is misaligned and add more integrity checks. --- CMakeLists.txt | 4 +-- library/modules/Units.cpp | 2 +- library/xml | 2 +- plugins/CMakeLists.txt | 4 +-- plugins/autolabor.cpp | 2 +- plugins/manipulator.cpp | 7 +++--- plugins/strangemood.cpp | 4 +-- scripts/devel/find-offsets.lua | 46 +++++++++++++++++++++++----------- 8 files changed, 45 insertions(+), 26 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a353495b8..c1862d122 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,8 +58,8 @@ if (NOT EXISTS ${dfhack_SOURCE_DIR}/library/xml/codegen.pl OR NOT EXISTS ${dfhac endif() # set up versioning. -set(DF_VERSION "0.40.13") -SET(DFHACK_RELEASE "r1" CACHE STRING "Current release revision.") +set(DF_VERSION "0.40.14") +SET(DFHACK_RELEASE "r0" CACHE STRING "Current release revision.") set(DFHACK_VERSION "${DF_VERSION}-${DFHACK_RELEASE}") add_definitions(-DDFHACK_VERSION="${DFHACK_VERSION}") diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index 9d2ebf2dd..463cea227 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -154,7 +154,7 @@ void Units::CopyCreature(df::unit * source, t_unit & furball) // profession furball.profession = source->profession; // happiness - furball.happiness = source->status.happiness; + furball.happiness = 100;//source->status.happiness; // physical attributes memcpy(&furball.strength, source->body.physical_attrs, sizeof(source->body.physical_attrs)); diff --git a/library/xml b/library/xml index aed9a7644..62dcffa67 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit aed9a7644cd1d4a599c10d5f579fc742ced6bc3f +Subproject commit 62dcffa67998643966267763526b82bd7674b583 diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 6ebe3ad6d..2aea9542c 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -110,7 +110,7 @@ if (BUILD_SUPPORTED) DFHACK_PLUGIN(digFlood digFlood.cpp) add_subdirectory(diggingInvaders) DFHACK_PLUGIN(drybuckets drybuckets.cpp) - DFHACK_PLUGIN(dwarfmonitor dwarfmonitor.cpp) + #DFHACK_PLUGIN(dwarfmonitor dwarfmonitor.cpp) DFHACK_PLUGIN(embark-tools embark-tools.cpp) DFHACK_PLUGIN(eventful eventful.cpp LINK_LIBRARIES lua) DFHACK_PLUGIN(fastdwarf fastdwarf.cpp) @@ -132,7 +132,7 @@ if (BUILD_SUPPORTED) DFHACK_PLUGIN(liquids liquids.cpp Brushes.h LINK_LIBRARIES lua) DFHACK_PLUGIN(manipulator manipulator.cpp) DFHACK_PLUGIN(mode mode.cpp) - DFHACK_PLUGIN(misery misery.cpp) + #DFHACK_PLUGIN(misery misery.cpp) DFHACK_PLUGIN(mousequery mousequery.cpp) DFHACK_PLUGIN(petcapRemover petcapRemover.cpp) DFHACK_PLUGIN(plants plants.cpp) diff --git a/plugins/autolabor.cpp b/plugins/autolabor.cpp index 05855a749..23ae71969 100644 --- a/plugins/autolabor.cpp +++ b/plugins/autolabor.cpp @@ -819,7 +819,7 @@ static void assign_labor(unit_labor::unit_labor labor, // bias by happiness - value += dwarfs[dwarf]->status.happiness; + //value += dwarfs[dwarf]->status.happiness; values[dwarf] = value; diff --git a/plugins/manipulator.cpp b/plugins/manipulator.cpp index ebd23a9d7..8deddec11 100644 --- a/plugins/manipulator.cpp +++ b/plugins/manipulator.cpp @@ -313,10 +313,11 @@ bool sortBySquad (const UnitInfo *d1, const UnitInfo *d2) bool sortByHappiness (const UnitInfo *d1, const UnitInfo *d2) { - if (descending) + return sortByName(d1, d2); + /*if (descending) return (d1->unit->status.happiness > d2->unit->status.happiness); else - return (d1->unit->status.happiness < d2->unit->status.happiness); + return (d1->unit->status.happiness < d2->unit->status.happiness);*/ } bool sortByArrival (const UnitInfo *d1, const UnitInfo *d2) @@ -1043,7 +1044,7 @@ void viewscreen_unitlaborsst::render() df::unit *unit = cur->unit; int8_t fg = 15, bg = 0; - int happy = cur->unit->status.happiness; + int happy = 100;//cur->unit->status.happiness; string happiness = stl_sprintf("%4i", happy); if (happy == 0) // miserable fg = 13; // 5:1 diff --git a/plugins/strangemood.cpp b/plugins/strangemood.cpp index e1cedbfe3..41b25a9bc 100644 --- a/plugins/strangemood.cpp +++ b/plugins/strangemood.cpp @@ -631,7 +631,7 @@ command_result df_strangemood (color_ostream &out, vector & parameters) // If no mood type was specified, pick one randomly if (type == mood_type::None) { - if (rng.df_trandom(100) > unit->status.happiness) + if (rng.df_trandom(100) > 90)//rng.df_trandom(100) > unit->status.happiness) { switch (rng.df_trandom(2)) { @@ -691,7 +691,7 @@ command_result df_strangemood (color_ostream &out, vector & parameters) unit->relations.mood_copy = unit->mood; Gui::showAutoAnnouncement(announcement_type::STRANGE_MOOD, unit->pos, msg, color, bright); - unit->status.happiness = 100; + //unit->status.happiness = 100; // TODO: make sure unit drops any wrestle items unit->job.mood_timeout = 50000; unit->flags1.bits.has_mood = true; diff --git a/scripts/devel/find-offsets.lua b/scripts/devel/find-offsets.lua index d8b3406f9..ae99adbca 100644 --- a/scripts/devel/find-offsets.lua +++ b/scripts/devel/find-offsets.lua @@ -131,15 +131,24 @@ local function zoomed_searcher(startn, end_or_sz) end local finder_searches = {} -local function exec_finder(finder, names) +local function exec_finder(finder, names, validators) if type(names) ~= 'table' then names = { names } end + if type(validators) ~= 'table' then + validators = { validators } + end local search = force_scan['all'] - for _,v in ipairs(names) do + for k,v in ipairs(names) do if force_scan[v] or not is_known(v) then table.insert(finder_searches, v) search = true + elseif validators[k] then + if not validators[k](df.global[v]) then + dfhack.printerr('Validation failed for '..v..', will try to find again') + table.insert(finder_searches, v) + search = true + end end end if search then @@ -505,6 +514,7 @@ end local function is_valid_world(world) if not ms.is_valid_vector(world.units.all, 4) + or not ms.is_valid_vector(world.units.active, 4) or not ms.is_valid_vector(world.units.bad, 4) or not ms.is_valid_vector(world.history.figures, 4) or not ms.is_valid_vector(world.features.map_features, 4) @@ -776,11 +786,6 @@ end -- local function find_current_weather() - print('\nPlease load the save previously processed with prepare-save.') - if not utils.prompt_yes_no('Proceed?', true) then - return - end - local zone if os_type == 'windows' then zone = zoomed_searcher('crime_next_id', 512) @@ -839,7 +844,14 @@ local function find_ui_selected_unit() end for i,unit in ipairs(df.global.world.units.active) do - dfhack.units.setNickname(unit, i) + -- This function does a lot of things and accesses histfigs, souls and so on: + --dfhack.units.setNickname(unit, i) + + -- Instead use just a simple bit of code that only requires the start of the + -- unit to be valid. It may not work properly with vampires or reset later + -- if unpaused, but is sufficient for this script and won't crash: + unit.name.nickname = tostring(i) + unit.name.has_name = true end local addr = searcher:find_menu_cursor([[ @@ -1506,17 +1518,23 @@ print('\nInitial globals (need title screen):\n') exec_finder(find_gview, 'gview') exec_finder(find_cursor, { 'cursor', 'selection_rect', 'gamemode', 'gametype' }) exec_finder(find_announcements, 'announcements') -exec_finder(find_d_init, 'd_init') -exec_finder(find_enabler, 'enabler') -exec_finder(find_gps, 'gps') +exec_finder(find_d_init, 'd_init', is_valid_d_init) +exec_finder(find_enabler, 'enabler', is_valid_enabler) +exec_finder(find_gps, 'gps', is_valid_gps) print('\nCompound globals (need loaded world):\n') -exec_finder(find_world, 'world') -exec_finder(find_ui, 'ui') +print('\nPlease load the save previously processed with prepare-save.') +if not utils.prompt_yes_no('Proceed?', true) then + searcher:reset() + return +end + +exec_finder(find_world, 'world', is_valid_world) +exec_finder(find_ui, 'ui', is_valid_ui) exec_finder(find_ui_sidebar_menus, 'ui_sidebar_menus') exec_finder(find_ui_build_selector, 'ui_build_selector') -exec_finder(find_init, 'init') +exec_finder(find_init, 'init', is_valid_init) print('\nPrimitive globals:\n') From f683395caea03a6f3e732434a565870f20907c89 Mon Sep 17 00:00:00 2001 From: Quietust Date: Fri, 31 Oct 2014 13:33:04 -0500 Subject: [PATCH 28/35] Comment out more of military-training tweak, which no longer compiles --- plugins/tweak.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/tweak.cpp b/plugins/tweak.cpp index 1e114fc43..0420d61ca 100644 --- a/plugins/tweak.cpp +++ b/plugins/tweak.cpp @@ -765,6 +765,7 @@ struct military_assign_hook : df::viewscreen_layer_militaryst { IMPLEMENT_VMETHOD_INTERPOSE(military_assign_hook, feed); IMPLEMENT_VMETHOD_INTERPOSE(military_assign_hook, render); +/* // Unit updates are executed based on an action divisor variable, // which is computed from the alive unit count and has range 10-100. static int adjust_unit_divisor(int value) { @@ -943,6 +944,7 @@ struct military_training_ct_hook : df::activity_event_combat_trainingst { } } }; +*/ /* IMPLEMENT_VMETHOD_INTERPOSE(military_training_ct_hook, process); From ed225de3651b44153b421c56c46c646b1ae447f2 Mon Sep 17 00:00:00 2001 From: Quietust Date: Fri, 31 Oct 2014 13:33:18 -0500 Subject: [PATCH 29/35] Update strangemood to check stress level for fell/macabre moods --- plugins/strangemood.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/strangemood.cpp b/plugins/strangemood.cpp index 41b25a9bc..b91b1ff94 100644 --- a/plugins/strangemood.cpp +++ b/plugins/strangemood.cpp @@ -631,7 +631,11 @@ command_result df_strangemood (color_ostream &out, vector & parameters) // If no mood type was specified, pick one randomly if (type == mood_type::None) { - if (rng.df_trandom(100) > 90)//rng.df_trandom(100) > unit->status.happiness) + if (soul && ( + (soul->personality.stress_level >= 500000) || + (soul->personality.stress_level >= 250000 && !rng.df_trandom(2)) || + (soul->personality.stress_level >= 100000 && !rng.df_trandom(10)) + )) { switch (rng.df_trandom(2)) { From f08a32f4e2fd2da676b459a08319170ddeddcbb3 Mon Sep 17 00:00:00 2001 From: Quietust Date: Fri, 31 Oct 2014 13:33:35 -0500 Subject: [PATCH 30/35] Update Manipulator to display stress level instead of happiness --- plugins/manipulator.cpp | 65 +++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/plugins/manipulator.cpp b/plugins/manipulator.cpp index 8deddec11..8e379f98a 100644 --- a/plugins/manipulator.cpp +++ b/plugins/manipulator.cpp @@ -270,7 +270,7 @@ struct UnitInfo enum altsort_mode { ALTSORT_NAME, ALTSORT_PROFESSION_OR_SQUAD, - ALTSORT_HAPPINESS, + ALTSORT_STRESS, ALTSORT_ARRIVAL, ALTSORT_MAX }; @@ -311,13 +311,17 @@ bool sortBySquad (const UnitInfo *d1, const UnitInfo *d2) return descending ? gt : !gt; } -bool sortByHappiness (const UnitInfo *d1, const UnitInfo *d2) +bool sortByStress (const UnitInfo *d1, const UnitInfo *d2) { - return sortByName(d1, d2); - /*if (descending) - return (d1->unit->status.happiness > d2->unit->status.happiness); + if (!d1->unit->status.current_soul) + return !descending; + if (!d2->unit->status.current_soul) + return descending; + + if (descending) + return (d1->unit->status.current_soul->personality.stress_level > d2->unit->status.current_soul->personality.stress_level); else - return (d1->unit->status.happiness < d2->unit->status.happiness);*/ + return (d1->unit->status.current_soul->personality.stress_level < d2->unit->status.current_soul->personality.stress_level); } bool sortByArrival (const UnitInfo *d1, const UnitInfo *d2) @@ -368,7 +372,7 @@ bool sortBySkill (const UnitInfo *d1, const UnitInfo *d2) } enum display_columns { - DISP_COLUMN_HAPPINESS, + DISP_COLUMN_STRESS, DISP_COLUMN_NAME, DISP_COLUMN_PROFESSION_OR_SQUAD, DISP_COLUMN_LABORS, @@ -510,8 +514,8 @@ void viewscreen_unitlaborsst::calcSize() // min/max width of columns int col_minwidth[DISP_COLUMN_MAX]; int col_maxwidth[DISP_COLUMN_MAX]; - col_minwidth[DISP_COLUMN_HAPPINESS] = 4; - col_maxwidth[DISP_COLUMN_HAPPINESS] = 4; + col_minwidth[DISP_COLUMN_STRESS] = 6; + col_maxwidth[DISP_COLUMN_STRESS] = 6; col_minwidth[DISP_COLUMN_NAME] = 16; col_maxwidth[DISP_COLUMN_NAME] = 16; // adjusted in the loop below col_minwidth[DISP_COLUMN_PROFESSION_OR_SQUAD] = 10; @@ -779,10 +783,10 @@ void viewscreen_unitlaborsst::feed(set *events) switch (click_header) { - case DISP_COLUMN_HAPPINESS: + case DISP_COLUMN_STRESS: if (enabler->mouse_lbut || enabler->mouse_rbut) { - input_sort = ALTSORT_HAPPINESS; + input_sort = ALTSORT_STRESS; if (enabler->mouse_lbut) events->insert(interface_key::SECONDSCROLL_PAGEUP); if (enabler->mouse_rbut) @@ -826,7 +830,7 @@ void viewscreen_unitlaborsst::feed(set *events) switch (click_body) { - case DISP_COLUMN_HAPPINESS: + case DISP_COLUMN_STRESS: // do nothing break; @@ -932,8 +936,8 @@ void viewscreen_unitlaborsst::feed(set *events) case ALTSORT_PROFESSION_OR_SQUAD: std::sort(units.begin(), units.end(), show_squad ? sortBySquad : sortByProfession); break; - case ALTSORT_HAPPINESS: - std::sort(units.begin(), units.end(), sortByHappiness); + case ALTSORT_STRESS: + std::sort(units.begin(), units.end(), sortByStress); break; case ALTSORT_ARRIVAL: std::sort(units.begin(), units.end(), sortByArrival); @@ -948,9 +952,9 @@ void viewscreen_unitlaborsst::feed(set *events) altsort = ALTSORT_PROFESSION_OR_SQUAD; break; case ALTSORT_PROFESSION_OR_SQUAD: - altsort = ALTSORT_HAPPINESS; + altsort = ALTSORT_STRESS; break; - case ALTSORT_HAPPINESS: + case ALTSORT_STRESS: altsort = ALTSORT_ARRIVAL; break; case ALTSORT_ARRIVAL: @@ -1001,7 +1005,7 @@ void viewscreen_unitlaborsst::render() Screen::clear(); Screen::drawBorder(" Dwarf Manipulator - Manage Labors "); - Screen::paintString(Screen::Pen(' ', 7, 0), col_offsets[DISP_COLUMN_HAPPINESS], 2, "Hap."); + Screen::paintString(Screen::Pen(' ', 7, 0), col_offsets[DISP_COLUMN_STRESS], 2, "Stress"); Screen::paintString(Screen::Pen(' ', 7, 0), col_offsets[DISP_COLUMN_NAME], 2, "Name"); Screen::paintString(Screen::Pen(' ', 7, 0), col_offsets[DISP_COLUMN_PROFESSION_OR_SQUAD], 2, show_squad ? "Squad" : "Profession"); @@ -1044,23 +1048,22 @@ void viewscreen_unitlaborsst::render() df::unit *unit = cur->unit; int8_t fg = 15, bg = 0; - int happy = 100;//cur->unit->status.happiness; - string happiness = stl_sprintf("%4i", happy); - if (happy == 0) // miserable + int stress_lvl = unit->status.current_soul ? unit->status.current_soul->personality.stress_level : 0; + // cap at 6 digits + if (stress_lvl < -99999) stress_lvl = -99999; + if (stress_lvl > 999999) stress_lvl = 999999; + string stress = stl_sprintf("%6i", stress_lvl); + if (stress_lvl >= 500000) fg = 13; // 5:1 - else if (happy <= 25) // very unhappy + else if (stress_lvl >= 250000) fg = 12; // 4:1 - else if (happy <= 50) // unhappy - fg = 4; // 4:0 - else if (happy < 75) // fine + else if (stress_lvl >= 100000) fg = 14; // 6:1 - else if (happy < 125) // quite content - fg = 6; // 6:0 - else if (happy < 150) // happy + else if (stress_lvl >= 0) fg = 2; // 2:0 - else // ecstatic + else fg = 10; // 2:1 - Screen::paintString(Screen::Pen(' ', fg, bg), col_offsets[DISP_COLUMN_HAPPINESS], 4 + row, happiness); + Screen::paintString(Screen::Pen(' ', fg, bg), col_offsets[DISP_COLUMN_STRESS], 4 + row, stress); fg = 15; if (row_offset == sel_row) @@ -1233,8 +1236,8 @@ void viewscreen_unitlaborsst::render() case ALTSORT_PROFESSION_OR_SQUAD: OutputString(15, x, y, show_squad ? "Squad" : "Profession"); break; - case ALTSORT_HAPPINESS: - OutputString(15, x, y, "Happiness"); + case ALTSORT_STRESS: + OutputString(15, x, y, "Stress Level"); break; case ALTSORT_ARRIVAL: OutputString(15, x, y, "Arrival"); From 7c92f4abaac5ca88b0a2677924f8065e219300b6 Mon Sep 17 00:00:00 2001 From: Quietust Date: Fri, 31 Oct 2014 13:47:04 -0500 Subject: [PATCH 31/35] Seems I misread the code from 0.34.11 - it switches against rand(2), not rand(3) --- plugins/strangemood.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/plugins/strangemood.cpp b/plugins/strangemood.cpp index b91b1ff94..74c717816 100644 --- a/plugins/strangemood.cpp +++ b/plugins/strangemood.cpp @@ -695,7 +695,6 @@ command_result df_strangemood (color_ostream &out, vector & parameters) unit->relations.mood_copy = unit->mood; Gui::showAutoAnnouncement(announcement_type::STRANGE_MOOD, unit->pos, msg, color, bright); - //unit->status.happiness = 100; // TODO: make sure unit drops any wrestle items unit->job.mood_timeout = 50000; unit->flags1.bits.has_mood = true; @@ -1148,7 +1147,7 @@ command_result df_strangemood (color_ostream &out, vector & parameters) { if ((job->job_type == job_type::StrangeMoodBrooding) && (rng.df_trandom(2))) { - switch (rng.df_trandom(3)) + switch (rng.df_trandom(2)) { case 0: job->job_items.push_back(item = new df::job_item()); @@ -1163,10 +1162,6 @@ command_result df_strangemood (color_ostream &out, vector & parameters) item->flags2.bits.body_part = true; item->quantity = 1; break; - case 2: - // in older versions, they would request additional skulls - // in 0.34.11, the request becomes "nothing" - break; } } else From bad923130c5454885cd76940ec5ab79d8d59f590 Mon Sep 17 00:00:00 2001 From: Quietust Date: Sat, 1 Nov 2014 11:24:05 -0500 Subject: [PATCH 32/35] Manipulator - remove minimum width for Labors column, since it triggered the "should never happen" case upon extending the first column from 4 to 6 --- plugins/manipulator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/manipulator.cpp b/plugins/manipulator.cpp index 8e379f98a..16cef345f 100644 --- a/plugins/manipulator.cpp +++ b/plugins/manipulator.cpp @@ -520,7 +520,7 @@ void viewscreen_unitlaborsst::calcSize() col_maxwidth[DISP_COLUMN_NAME] = 16; // adjusted in the loop below col_minwidth[DISP_COLUMN_PROFESSION_OR_SQUAD] = 10; col_maxwidth[DISP_COLUMN_PROFESSION_OR_SQUAD] = 10; // adjusted in the loop below - col_minwidth[DISP_COLUMN_LABORS] = num_columns*3/5; // 60% + col_minwidth[DISP_COLUMN_LABORS] = 1; col_maxwidth[DISP_COLUMN_LABORS] = NUM_COLUMNS; // get max_name/max_prof from strings length From c60e06aed3dec12ece21b9338d58767728e51987 Mon Sep 17 00:00:00 2001 From: Lethosor Date: Sat, 1 Nov 2014 17:28:08 -0400 Subject: [PATCH 33/35] Fix forum-dwarves.lua formatted_text -> src_text --- scripts/forum-dwarves.lua | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/scripts/forum-dwarves.lua b/scripts/forum-dwarves.lua index 0b8828dfc..21f8d1abc 100644 --- a/scripts/forum-dwarves.lua +++ b/scripts/forum-dwarves.lua @@ -31,7 +31,7 @@ target file: will be displayed if the script is successful. character encoding: The text will likely be using system-default encoding, and as such - will likely NOT display special characters (eg:,,) correctly. To + will likely NOT display special characters (eg:È,ı,Á) correctly. To fix this, you need to modify the character set that you are reading the document with. 'Notepad++' is a freely available program which can do this using the following steps: @@ -99,23 +99,16 @@ local function format_for_forum(strin) end if flerb == 'textviewer' then - print(scrn) - printall(scrn) - local lines = scrn.formatted_text + local lines = scrn.src_text local line = "" if lines ~= nil then local log = io.open('forumdwarves.txt', 'a') log:write("[color=silver]") for n,x in ipairs(lines) do - print(x) - printall(x) - print(x.text) - printall(x.text) - if (x ~= nil) and (x.text ~= nil) then - log:write(format_for_forum(x.text), ' ') - --log:write(x[0],'\n') - end + if x ~= nil and x.value ~= nil then + log:write(format_for_forum(x.value), ' ') + end end log:write("[/color]\n") log:close() From 4e0ad256a5d0059223884588193badb13b148438 Mon Sep 17 00:00:00 2001 From: expwnent Date: Sun, 2 Nov 2014 04:06:51 -0500 Subject: [PATCH 34/35] Update XML. --- library/xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/xml b/library/xml index 62dcffa67..af94d10e9 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 62dcffa67998643966267763526b82bd7674b583 +Subproject commit af94d10e9a3b17ea36b7e896bb950c6fc5369e31 From 21a75465561b280dd1d7c9453e9bcd3c18a465f2 Mon Sep 17 00:00:00 2001 From: expwnent Date: Sun, 2 Nov 2014 04:09:46 -0500 Subject: [PATCH 35/35] Add stocks, autochop to dfhack.init-example enable (PeridexisErrant) --- dfhack.init-example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dfhack.init-example b/dfhack.init-example index 5338f9448..8cb1cce2b 100644 --- a/dfhack.init-example +++ b/dfhack.init-example @@ -183,7 +183,7 @@ enable search enable automaterial # Other interface improvement tools -enable dwarfmonitor mousequery automelt autotrade buildingplan resume trackstop zone +enable dwarfmonitor mousequery automelt autotrade buildingplan resume trackstop zone stocks autochop # allow the fortress bookkeeper to queue jobs through the manager stockflow enable