|  |  |  | @ -68,6 +68,16 @@ | 
		
	
		
			
				|  |  |  |  | //#include "df/building_hivest.h"
 | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | #include <stdlib.h> | 
		
	
		
			
				|  |  |  |  | #include <unordered_map> | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | #include "tweaks/adamantine-cloth-wear.h" | 
		
	
		
			
				|  |  |  |  | #include "tweaks/advmode-contained.h" | 
		
	
		
			
				|  |  |  |  | #include "tweaks/craft-age-wear.h" | 
		
	
		
			
				|  |  |  |  | #include "tweaks/fast-heat.h" | 
		
	
		
			
				|  |  |  |  | #include "tweaks/fast-trade.h" | 
		
	
		
			
				|  |  |  |  | #include "tweaks/manager-quantity.h" | 
		
	
		
			
				|  |  |  |  | #include "tweaks/military-assign.h" | 
		
	
		
			
				|  |  |  |  | #include "tweaks/stable-cursor.h" | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | using std::set; | 
		
	
		
			
				|  |  |  |  | using std::vector; | 
		
	
	
		
			
				
					|  |  |  | @ -83,12 +93,15 @@ using df::global::ui_menu_width; | 
		
	
		
			
				|  |  |  |  | using df::global::ui_area_map_width; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | using namespace DFHack::Gui; | 
		
	
		
			
				|  |  |  |  | using Screen::Pen; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static command_result tweak(color_ostream &out, vector <string> & parameters); | 
		
	
		
			
				|  |  |  |  | static std::multimap<std::string, VMethodInterposeLinkBase> tweak_hooks; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | DFHACK_PLUGIN("tweak"); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | #define TWEAK_HOOK(tweak, cls, func) tweak_hooks.insert(std::pair<std::string, VMethodInterposeLinkBase>\ | 
		
	
		
			
				|  |  |  |  |     (tweak, INTERPOSE_HOOK(cls, func))) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     commands.push_back(PluginCommand( | 
		
	
	
		
			
				
					|  |  |  | @ -115,14 +128,6 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector <Plugi | 
		
	
		
			
				|  |  |  |  |         "  tweak stable-cursor [disable]\n" | 
		
	
		
			
				|  |  |  |  |         "    Keeps exact position of dwarfmode cursor during exits to main menu.\n" | 
		
	
		
			
				|  |  |  |  |         "    E.g. allows switching between t/q/k/d without losing position.\n" | 
		
	
		
			
				|  |  |  |  |         "  tweak patrol-duty [disable]\n" | 
		
	
		
			
				|  |  |  |  |         "    Causes 'Train' orders to no longer be considered 'patrol duty' so\n" | 
		
	
		
			
				|  |  |  |  |         "    soldiers will stop getting unhappy thoughts. Does NOT fix the problem\n" | 
		
	
		
			
				|  |  |  |  |         "    when soldiers go off-duty (i.e. civilian).\n" | 
		
	
		
			
				|  |  |  |  |         "  tweak confirm-embark [disable]\n" | 
		
	
		
			
				|  |  |  |  |         "    Asks for confirmation on the embark setup screen before embarking\n" | 
		
	
		
			
				|  |  |  |  |         "  tweak stable-temp [disable]\n" | 
		
	
		
			
				|  |  |  |  |         "    Fixes performance bug 6012 by squashing jitter in temperature updates.\n" | 
		
	
		
			
				|  |  |  |  |         "  tweak fast-heat <max-ticks>\n" | 
		
	
		
			
				|  |  |  |  |         "    Further improves temperature updates by ensuring that 1 degree of\n" | 
		
	
		
			
				|  |  |  |  |         "    item temperature is crossed in no more than specified number of frames\n" | 
		
	
	
		
			
				
					|  |  |  | @ -146,11 +151,39 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector <Plugi | 
		
	
		
			
				|  |  |  |  |         "    to make them stand out more in the list.\n" | 
		
	
		
			
				|  |  |  |  | //        "  tweak military-training [disable]\n"
 | 
		
	
		
			
				|  |  |  |  | //        "    Speed up melee squad training, removing inverse dependency on unit count.\n"
 | 
		
	
		
			
				|  |  |  |  |         "  tweak manager-quantity [disable]\n" | 
		
	
		
			
				|  |  |  |  |         "    Removes the limit of 30 jobs per manager order\n" | 
		
	
		
			
				|  |  |  |  |         "  tweak craft-age-wear [disable]\n" | 
		
	
		
			
				|  |  |  |  |         "    Makes cloth and leather items wear out at the correct rate (bug 6003).\n" | 
		
	
		
			
				|  |  |  |  |         "  tweak adamantine-cloth-wear [disable]\n" | 
		
	
		
			
				|  |  |  |  |         "    Stops adamantine clothing from wearing out while being worn (bug 6481).\n" | 
		
	
		
			
				|  |  |  |  |     )); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     TWEAK_HOOK("adamantine-cloth-wear", adamantine_cloth_wear_armor_hook, incWearTimer); | 
		
	
		
			
				|  |  |  |  |     TWEAK_HOOK("adamantine-cloth-wear", adamantine_cloth_wear_helm_hook, incWearTimer); | 
		
	
		
			
				|  |  |  |  |     TWEAK_HOOK("adamantine-cloth-wear", adamantine_cloth_wear_gloves_hook, incWearTimer); | 
		
	
		
			
				|  |  |  |  |     TWEAK_HOOK("adamantine-cloth-wear", adamantine_cloth_wear_shoes_hook, incWearTimer); | 
		
	
		
			
				|  |  |  |  |     TWEAK_HOOK("adamantine-cloth-wear", adamantine_cloth_wear_pants_hook, incWearTimer); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     TWEAK_HOOK("advmode-contained", advmode_contained_hook, feed); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     TWEAK_HOOK("craft-age-wear", craft_age_wear_hook, ageItem); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     TWEAK_HOOK("fast-heat", fast_heat_hook, updateTempFromMap); | 
		
	
		
			
				|  |  |  |  |     TWEAK_HOOK("fast-heat", fast_heat_hook, updateTemperature); | 
		
	
		
			
				|  |  |  |  |     TWEAK_HOOK("fast-heat", fast_heat_hook, adjustTemperature); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     TWEAK_HOOK("fast-trade", fast_trade_assign_hook, feed); | 
		
	
		
			
				|  |  |  |  |     TWEAK_HOOK("fast-trade", fast_trade_select_hook, feed); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     TWEAK_HOOK("manager-quantity", manager_quantity_hook, feed); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     TWEAK_HOOK("military-color-assigned", military_assign_hook, render); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     TWEAK_HOOK("military-stable-assign", military_assign_hook, feed); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     TWEAK_HOOK("stable-cursor", stable_cursor_hook, feed); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     return CR_OK; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -216,271 +249,6 @@ command_result fix_clothing_ownership(color_ostream &out, df::unit* unit) | 
		
	
		
			
				|  |  |  |  |     return CR_OK; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | /*
 | 
		
	
		
			
				|  |  |  |  |  * Save or restore cursor position on change to/from main dwarfmode menu. | 
		
	
		
			
				|  |  |  |  |  */ | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static df::coord last_view, last_cursor; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | struct stable_cursor_hook : df::viewscreen_dwarfmodest | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     typedef df::viewscreen_dwarfmodest interpose_base; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     bool check_default() | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         switch (ui->main.mode) { | 
		
	
		
			
				|  |  |  |  |             case ui_sidebar_mode::Default: | 
		
	
		
			
				|  |  |  |  |                 return true; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |             case ui_sidebar_mode::Build: | 
		
	
		
			
				|  |  |  |  |                 return ui_build_selector && | 
		
	
		
			
				|  |  |  |  |                        (ui_build_selector->building_type < 0 || | 
		
	
		
			
				|  |  |  |  |                         ui_build_selector->stage < 1); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |             default: | 
		
	
		
			
				|  |  |  |  |                 return false; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     DEFINE_VMETHOD_INTERPOSE(void, feed, (set<df::interface_key> *input)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         bool was_default = check_default(); | 
		
	
		
			
				|  |  |  |  |         df::coord view = Gui::getViewportPos(); | 
		
	
		
			
				|  |  |  |  |         df::coord cursor = Gui::getCursorPos(); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         INTERPOSE_NEXT(feed)(input); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         bool is_default = check_default(); | 
		
	
		
			
				|  |  |  |  |         df::coord cur_cursor = Gui::getCursorPos(); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         if (is_default && !was_default) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             last_view = view; last_cursor = cursor; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         else if (!is_default && was_default && | 
		
	
		
			
				|  |  |  |  |                  Gui::getViewportPos() == last_view && | 
		
	
		
			
				|  |  |  |  |                  last_cursor.isValid() && cur_cursor.isValid()) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             Gui::setCursorCoords(last_cursor.x, last_cursor.y, last_cursor.z); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |             // Force update of ui state
 | 
		
	
		
			
				|  |  |  |  |             set<df::interface_key> tmp; | 
		
	
		
			
				|  |  |  |  |             if (last_cursor.z < 2) | 
		
	
		
			
				|  |  |  |  |                 tmp.insert(interface_key::CURSOR_UP_Z); | 
		
	
		
			
				|  |  |  |  |             else | 
		
	
		
			
				|  |  |  |  |                 tmp.insert(interface_key::CURSOR_DOWN_Z); | 
		
	
		
			
				|  |  |  |  |             INTERPOSE_NEXT(feed)(&tmp); | 
		
	
		
			
				|  |  |  |  |             tmp.clear(); | 
		
	
		
			
				|  |  |  |  |             if (last_cursor.z < 2) | 
		
	
		
			
				|  |  |  |  |                 tmp.insert(interface_key::CURSOR_DOWN_Z); | 
		
	
		
			
				|  |  |  |  |             else | 
		
	
		
			
				|  |  |  |  |                 tmp.insert(interface_key::CURSOR_UP_Z); | 
		
	
		
			
				|  |  |  |  |             INTERPOSE_NEXT(feed)(&tmp); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         else if (!is_default && cur_cursor.isValid()) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             last_cursor = df::coord(); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | IMPLEMENT_VMETHOD_INTERPOSE(stable_cursor_hook, feed); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | struct patrol_duty_hook : df::squad_order_trainst | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     typedef df::squad_order_trainst interpose_base; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     DEFINE_VMETHOD_INTERPOSE(bool, isPatrol, ()) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         return false; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | IMPLEMENT_VMETHOD_INTERPOSE(patrol_duty_hook, isPatrol); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | enum confirm_embark_states | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     ECS_INACTIVE = 0, | 
		
	
		
			
				|  |  |  |  |     ECS_CONFIRM, | 
		
	
		
			
				|  |  |  |  |     ECS_ACCEPTED | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  | static confirm_embark_states confirm_embark_state = ECS_INACTIVE; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | struct confirm_embark_hook : df::viewscreen_setupdwarfgamest | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     typedef df::viewscreen_setupdwarfgamest interpose_base; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     void OutputString(int8_t fg, int &x, int y, std::string text) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         Screen::paintString(Screen::Pen(' ', fg, COLOR_BLACK), x, y, text); | 
		
	
		
			
				|  |  |  |  |         x += text.length(); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     DEFINE_VMETHOD_INTERPOSE(void, feed, (set<df::interface_key> *input)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         bool intercept = false; | 
		
	
		
			
				|  |  |  |  |         if (this->show_play_now == 0) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             if (confirm_embark_state == ECS_INACTIVE) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 if (input->count(df::interface_key::SETUP_EMBARK)) | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     confirm_embark_state = ECS_CONFIRM; | 
		
	
		
			
				|  |  |  |  |                     intercept = true; | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |             else if (confirm_embark_state == ECS_CONFIRM) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 intercept = true; | 
		
	
		
			
				|  |  |  |  |                 if (input->count(df::interface_key::MENU_CONFIRM)) | 
		
	
		
			
				|  |  |  |  |                     confirm_embark_state = ECS_ACCEPTED; | 
		
	
		
			
				|  |  |  |  |                 else if (input->size()) | 
		
	
		
			
				|  |  |  |  |                     confirm_embark_state = ECS_INACTIVE; | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         if (!intercept) | 
		
	
		
			
				|  |  |  |  |             INTERPOSE_NEXT(feed)(input); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     DEFINE_VMETHOD_INTERPOSE(bool, key_conflict, (df::interface_key key)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         if (confirm_embark_state == ECS_CONFIRM) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             if (key == df::interface_key::OPTIONS) | 
		
	
		
			
				|  |  |  |  |                 return true; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         return INTERPOSE_NEXT(key_conflict)(key); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     DEFINE_VMETHOD_INTERPOSE(void, render, ()) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         INTERPOSE_NEXT(render)(); | 
		
	
		
			
				|  |  |  |  |         auto dim = Screen::getWindowSize(); | 
		
	
		
			
				|  |  |  |  |         int x = 0, y = 0; | 
		
	
		
			
				|  |  |  |  |         if (confirm_embark_state != ECS_INACTIVE) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             Screen::fillRect(Screen::Pen(' ', COLOR_BLACK, COLOR_BLACK), 0, 0, dim.x - 1, dim.y - 1); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         if (confirm_embark_state == ECS_CONFIRM) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             x = 2, y = 2; | 
		
	
		
			
				|  |  |  |  |             OutputString(COLOR_WHITE, x, y, "Really embark? ("); | 
		
	
		
			
				|  |  |  |  |             OutputString(COLOR_LIGHTGREEN, x, y, Screen::getKeyDisplay(df::interface_key::MENU_CONFIRM)); | 
		
	
		
			
				|  |  |  |  |             OutputString(COLOR_WHITE, x, y, " = yes, other = no)"); | 
		
	
		
			
				|  |  |  |  |             x = 2, y = 4; | 
		
	
		
			
				|  |  |  |  |             int32_t points = this->points_remaining; | 
		
	
		
			
				|  |  |  |  |             OutputString(COLOR_WHITE, x, y, "Points left: "); | 
		
	
		
			
				|  |  |  |  |             OutputString((points ? COLOR_YELLOW : COLOR_LIGHTGREEN), x, y, std::to_string((unsigned long long/*won't compile on windows otherwise*/)points)); | 
		
	
		
			
				|  |  |  |  |             x = dim.x - 10, y = dim.y - 1; | 
		
	
		
			
				|  |  |  |  |             OutputString(COLOR_WHITE, x, y, "DFHack"); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         else if (confirm_embark_state == ECS_ACCEPTED) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             std::set<df::interface_key> input; | 
		
	
		
			
				|  |  |  |  |             input.insert(df::interface_key::SETUP_EMBARK); | 
		
	
		
			
				|  |  |  |  |             this->feed(&input); | 
		
	
		
			
				|  |  |  |  |             confirm_embark_state = ECS_INACTIVE; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | IMPLEMENT_VMETHOD_INTERPOSE(confirm_embark_hook, feed); | 
		
	
		
			
				|  |  |  |  | IMPLEMENT_VMETHOD_INTERPOSE(confirm_embark_hook, key_conflict); | 
		
	
		
			
				|  |  |  |  | IMPLEMENT_VMETHOD_INTERPOSE(confirm_embark_hook, render); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | struct stable_temp_hook : df::item_actual { | 
		
	
		
			
				|  |  |  |  |     typedef df::item_actual interpose_base; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     DEFINE_VMETHOD_INTERPOSE(bool, adjustTemperature, (uint16_t temp, int32_t rate_mult)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         if (temperature.whole != temp) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             // Bug 6012 is caused by fixed-point precision mismatch jitter
 | 
		
	
		
			
				|  |  |  |  |             // when an item is being pushed by two sources at N and N+1.
 | 
		
	
		
			
				|  |  |  |  |             // This check suppresses it altogether.
 | 
		
	
		
			
				|  |  |  |  |             if (temp == temperature.whole+1 || | 
		
	
		
			
				|  |  |  |  |                 (temp == temperature.whole-1 && temperature.fraction == 0)) | 
		
	
		
			
				|  |  |  |  |                 temp = temperature.whole; | 
		
	
		
			
				|  |  |  |  |             // When SPEC_HEAT is NONE, the original function seems to not
 | 
		
	
		
			
				|  |  |  |  |             // change the temperature, yet return true, which is silly.
 | 
		
	
		
			
				|  |  |  |  |             else if (getSpecHeat() == 60001) | 
		
	
		
			
				|  |  |  |  |                 temp = temperature.whole; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         return INTERPOSE_NEXT(adjustTemperature)(temp, rate_mult); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     DEFINE_VMETHOD_INTERPOSE(bool, updateContaminants, ()) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         if (contaminants) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             // Force 1-degree difference in contaminant temperature to 0
 | 
		
	
		
			
				|  |  |  |  |             for (size_t i = 0; i < contaminants->size(); i++) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 auto obj = (*contaminants)[i]; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                 if (abs(obj->temperature.whole - temperature.whole) == 1) | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     obj->temperature.whole = temperature.whole; | 
		
	
		
			
				|  |  |  |  |                     obj->temperature.fraction = temperature.fraction; | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         return INTERPOSE_NEXT(updateContaminants)(); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | IMPLEMENT_VMETHOD_INTERPOSE(stable_temp_hook, adjustTemperature); | 
		
	
		
			
				|  |  |  |  | IMPLEMENT_VMETHOD_INTERPOSE(stable_temp_hook, updateContaminants); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static int map_temp_mult = -1; | 
		
	
		
			
				|  |  |  |  | static int max_heat_ticks = 0; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | struct fast_heat_hook : df::item_actual { | 
		
	
		
			
				|  |  |  |  |     typedef df::item_actual interpose_base; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     DEFINE_VMETHOD_INTERPOSE( | 
		
	
		
			
				|  |  |  |  |         bool, updateTempFromMap, | 
		
	
		
			
				|  |  |  |  |         (bool local, bool contained, bool adjust, int32_t rate_mult) | 
		
	
		
			
				|  |  |  |  |     ) { | 
		
	
		
			
				|  |  |  |  |         int cmult = map_temp_mult; | 
		
	
		
			
				|  |  |  |  |         map_temp_mult = rate_mult; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         bool rv = INTERPOSE_NEXT(updateTempFromMap)(local, contained, adjust, rate_mult); | 
		
	
		
			
				|  |  |  |  |         map_temp_mult = cmult; | 
		
	
		
			
				|  |  |  |  |         return rv; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     DEFINE_VMETHOD_INTERPOSE( | 
		
	
		
			
				|  |  |  |  |         bool, updateTemperature, | 
		
	
		
			
				|  |  |  |  |         (uint16_t temp, bool local, bool contained, bool adjust, int32_t rate_mult) | 
		
	
		
			
				|  |  |  |  |     ) { | 
		
	
		
			
				|  |  |  |  |         // Some items take ages to cross the last degree, so speed them up
 | 
		
	
		
			
				|  |  |  |  |         if (map_temp_mult > 0 && temp != temperature.whole && max_heat_ticks > 0) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             int spec = getSpecHeat(); | 
		
	
		
			
				|  |  |  |  |             if (spec != 60001) | 
		
	
		
			
				|  |  |  |  |                 rate_mult = std::max(map_temp_mult, spec/max_heat_ticks/abs(temp - temperature.whole)); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         return INTERPOSE_NEXT(updateTemperature)(temp, local, contained, adjust, rate_mult); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     DEFINE_VMETHOD_INTERPOSE(bool, adjustTemperature, (uint16_t temp, int32_t rate_mult)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         if (map_temp_mult > 0) | 
		
	
		
			
				|  |  |  |  |             rate_mult = map_temp_mult; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         return INTERPOSE_NEXT(adjustTemperature)(temp, rate_mult); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | IMPLEMENT_VMETHOD_INTERPOSE(fast_heat_hook, updateTempFromMap); | 
		
	
		
			
				|  |  |  |  | IMPLEMENT_VMETHOD_INTERPOSE(fast_heat_hook, updateTemperature); | 
		
	
		
			
				|  |  |  |  | IMPLEMENT_VMETHOD_INTERPOSE(fast_heat_hook, adjustTemperature); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static void correct_dimension(df::item_actual *self, int32_t &delta, int32_t dim) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     // Zero dimension or remainder?
 | 
		
	
	
		
			
				
					|  |  |  | @ -570,201 +338,6 @@ struct dimension_cloth_hook : df::item_clothst { | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | IMPLEMENT_VMETHOD_INTERPOSE(dimension_cloth_hook, subtractDimension); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | struct advmode_contained_hook : df::viewscreen_layer_unit_actionst { | 
		
	
		
			
				|  |  |  |  |     typedef df::viewscreen_layer_unit_actionst interpose_base; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     DEFINE_VMETHOD_INTERPOSE(void, feed, (set<df::interface_key> *input)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         auto old_reaction = cur_reaction; | 
		
	
		
			
				|  |  |  |  |         auto old_reagent = reagent; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         INTERPOSE_NEXT(feed)(input); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         if (cur_reaction && (cur_reaction != old_reaction || reagent != old_reagent)) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             old_reagent = reagent; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |             // Skip reagents already contained by others
 | 
		
	
		
			
				|  |  |  |  |             while (reagent < (int)cur_reaction->reagents.size()-1) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 if (!cur_reaction->reagents[reagent]->flags.bits.IN_CONTAINER) | 
		
	
		
			
				|  |  |  |  |                     break; | 
		
	
		
			
				|  |  |  |  |                 reagent++; | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |             if (old_reagent != reagent) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 // Reproduces a tiny part of the orginal screen code
 | 
		
	
		
			
				|  |  |  |  |                 choice_items.clear(); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                 auto preagent = cur_reaction->reagents[reagent]; | 
		
	
		
			
				|  |  |  |  |                 reagent_amnt_left = preagent->quantity; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                 for (int i = held_items.size()-1; i >= 0; i--) | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     if (!preagent->matchesRoot(held_items[i], cur_reaction->index)) | 
		
	
		
			
				|  |  |  |  |                         continue; | 
		
	
		
			
				|  |  |  |  |                     if (linear_index(sel_items, held_items[i]) >= 0) | 
		
	
		
			
				|  |  |  |  |                         continue; | 
		
	
		
			
				|  |  |  |  |                     choice_items.push_back(held_items[i]); | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                 layer_objects[6]->setListLength(choice_items.size()); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                 if (!choice_items.empty()) | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     layer_objects[4]->active = layer_objects[5]->active = false; | 
		
	
		
			
				|  |  |  |  |                     layer_objects[6]->active = true; | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |                 else if (layer_objects[6]->active) | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     layer_objects[6]->active = false; | 
		
	
		
			
				|  |  |  |  |                     layer_objects[5]->active = true; | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | IMPLEMENT_VMETHOD_INTERPOSE(advmode_contained_hook, feed); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | struct fast_trade_assign_hook : df::viewscreen_layer_assigntradest { | 
		
	
		
			
				|  |  |  |  |     typedef df::viewscreen_layer_assigntradest interpose_base; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     DEFINE_VMETHOD_INTERPOSE(void, feed, (set<df::interface_key> *input)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         if (layer_objects[1]->active && input->count(interface_key::SELECT_ALL)) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             set<df::interface_key> tmp; tmp.insert(interface_key::SELECT); | 
		
	
		
			
				|  |  |  |  |             INTERPOSE_NEXT(feed)(&tmp); | 
		
	
		
			
				|  |  |  |  |             tmp.clear(); tmp.insert(interface_key::STANDARDSCROLL_DOWN); | 
		
	
		
			
				|  |  |  |  |             INTERPOSE_NEXT(feed)(&tmp); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         else | 
		
	
		
			
				|  |  |  |  |             INTERPOSE_NEXT(feed)(input); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | IMPLEMENT_VMETHOD_INTERPOSE(fast_trade_assign_hook, feed); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | struct fast_trade_select_hook : df::viewscreen_tradegoodsst { | 
		
	
		
			
				|  |  |  |  |     typedef df::viewscreen_tradegoodsst interpose_base; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     DEFINE_VMETHOD_INTERPOSE(void, feed, (set<df::interface_key> *input)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         if (!(is_unloading || !has_traders || in_edit_count) | 
		
	
		
			
				|  |  |  |  |             && input->count(interface_key::SELECT_ALL)) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             set<df::interface_key> tmp; tmp.insert(interface_key::SELECT); | 
		
	
		
			
				|  |  |  |  |             INTERPOSE_NEXT(feed)(&tmp); | 
		
	
		
			
				|  |  |  |  |             if (in_edit_count) | 
		
	
		
			
				|  |  |  |  |                 INTERPOSE_NEXT(feed)(&tmp); | 
		
	
		
			
				|  |  |  |  |             tmp.clear(); tmp.insert(interface_key::STANDARDSCROLL_DOWN); | 
		
	
		
			
				|  |  |  |  |             INTERPOSE_NEXT(feed)(&tmp); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         else | 
		
	
		
			
				|  |  |  |  |             INTERPOSE_NEXT(feed)(input); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | IMPLEMENT_VMETHOD_INTERPOSE(fast_trade_select_hook, feed); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | struct military_assign_hook : df::viewscreen_layer_militaryst { | 
		
	
		
			
				|  |  |  |  |     typedef df::viewscreen_layer_militaryst interpose_base; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     inline bool inPositionsMode() { | 
		
	
		
			
				|  |  |  |  |         return page == Positions && !(in_create_squad || in_new_squad); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     DEFINE_VMETHOD_INTERPOSE(void, feed, (set<df::interface_key> *input)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         if (inPositionsMode() && !layer_objects[0]->active) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             auto pos_list = layer_objects[1]; | 
		
	
		
			
				|  |  |  |  |             auto plist = layer_objects[2]; | 
		
	
		
			
				|  |  |  |  |             auto &cand = positions.candidates; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |             // Save the candidate list and cursors
 | 
		
	
		
			
				|  |  |  |  |             std::vector<df::unit*> copy = cand; | 
		
	
		
			
				|  |  |  |  |             int cursor = plist->getListCursor(); | 
		
	
		
			
				|  |  |  |  |             int pos_cursor = pos_list->getListCursor(); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |             INTERPOSE_NEXT(feed)(input); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |             if (inPositionsMode() && !layer_objects[0]->active) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 bool is_select = input->count(interface_key::SELECT); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                 // Resort the candidate list and restore cursor
 | 
		
	
		
			
				|  |  |  |  |                 // on add to squad OR scroll in the position list.
 | 
		
	
		
			
				|  |  |  |  |                 if (!plist->active || is_select) | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     // Since we don't know the actual sorting order, preserve
 | 
		
	
		
			
				|  |  |  |  |                     // the ordering of the items in the list before keypress.
 | 
		
	
		
			
				|  |  |  |  |                     // This does the right thing even if the list was sorted
 | 
		
	
		
			
				|  |  |  |  |                     // with sort-units.
 | 
		
	
		
			
				|  |  |  |  |                     std::set<df::unit*> prev, next; | 
		
	
		
			
				|  |  |  |  |                     prev.insert(copy.begin(), copy.end()); | 
		
	
		
			
				|  |  |  |  |                     next.insert(cand.begin(), cand.end()); | 
		
	
		
			
				|  |  |  |  |                     std::vector<df::unit*> out; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                     // (old-before-cursor) (new) |cursor| (old-after-cursor)
 | 
		
	
		
			
				|  |  |  |  |                     for (int i = 0; i < cursor && i < (int)copy.size(); i++) | 
		
	
		
			
				|  |  |  |  |                         if (next.count(copy[i])) out.push_back(copy[i]); | 
		
	
		
			
				|  |  |  |  |                     for (size_t i = 0; i < cand.size(); i++) | 
		
	
		
			
				|  |  |  |  |                         if (!prev.count(cand[i])) out.push_back(cand[i]); | 
		
	
		
			
				|  |  |  |  |                     int new_cursor = out.size(); | 
		
	
		
			
				|  |  |  |  |                     for (int i = cursor; i < (int)copy.size(); i++) | 
		
	
		
			
				|  |  |  |  |                         if (next.count(copy[i])) out.push_back(copy[i]); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                     cand.swap(out); | 
		
	
		
			
				|  |  |  |  |                     plist->setListLength(cand.size()); | 
		
	
		
			
				|  |  |  |  |                     if (new_cursor < (int)cand.size()) | 
		
	
		
			
				|  |  |  |  |                         plist->setListCursor(new_cursor); | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                 // Preserve the position list index on remove from squad
 | 
		
	
		
			
				|  |  |  |  |                 if (pos_list->active && is_select) | 
		
	
		
			
				|  |  |  |  |                     pos_list->setListCursor(pos_cursor); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         else | 
		
	
		
			
				|  |  |  |  |             INTERPOSE_NEXT(feed)(input); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     DEFINE_VMETHOD_INTERPOSE(void, render, ()) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         INTERPOSE_NEXT(render)(); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         if (inPositionsMode()) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             auto plist = layer_objects[2]; | 
		
	
		
			
				|  |  |  |  |             int x1 = plist->getX1(), y1 = plist->getY1(); | 
		
	
		
			
				|  |  |  |  |             int x2 = plist->getX2(), y2 = plist->getY2(); | 
		
	
		
			
				|  |  |  |  |             int i1 = plist->getFirstVisible(), i2 = plist->getLastVisible(); | 
		
	
		
			
				|  |  |  |  |             int si = plist->getListCursor(); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |             for (int y = y1, i = i1; i <= i2; i++, y++) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 auto unit = vector_get(positions.candidates, i); | 
		
	
		
			
				|  |  |  |  |                 if (!unit || unit->military.squad_id < 0) | 
		
	
		
			
				|  |  |  |  |                     continue; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                 for (int x = x1; x <= x2; x++) | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     Pen cur_tile = Screen::readTile(x, y); | 
		
	
		
			
				|  |  |  |  |                     if (!cur_tile.valid()) continue; | 
		
	
		
			
				|  |  |  |  |                     cur_tile.fg = (i == si) ? COLOR_BROWN : COLOR_GREEN; | 
		
	
		
			
				|  |  |  |  |                     Screen::paintTile(cur_tile, x, y); | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 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) { | 
		
	
	
		
			
				
					|  |  |  | @ -1007,104 +580,6 @@ struct military_training_id_hook : df::activity_event_individual_skill_drillst { | 
		
	
		
			
				|  |  |  |  | IMPLEMENT_VMETHOD_INTERPOSE(military_training_id_hook, process); | 
		
	
		
			
				|  |  |  |  | */ | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | struct craft_age_wear_hook : df::item_crafted { | 
		
	
		
			
				|  |  |  |  |     typedef df::item_crafted interpose_base; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     DEFINE_VMETHOD_INTERPOSE(bool, ageItem, (int amount)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         int orig_age = age; | 
		
	
		
			
				|  |  |  |  |         age += amount; | 
		
	
		
			
				|  |  |  |  |         if (age > 200000000) | 
		
	
		
			
				|  |  |  |  |             age = 200000000; | 
		
	
		
			
				|  |  |  |  |         if (age == orig_age) | 
		
	
		
			
				|  |  |  |  |             return false; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         MaterialInfo mat(mat_type, mat_index); | 
		
	
		
			
				|  |  |  |  |         if (!mat.isValid()) | 
		
	
		
			
				|  |  |  |  |             return false; | 
		
	
		
			
				|  |  |  |  |         int wear = 0; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         if (mat.material->flags.is_set(material_flags::WOOD)) | 
		
	
		
			
				|  |  |  |  |             wear = 5; | 
		
	
		
			
				|  |  |  |  |         else if (mat.material->flags.is_set(material_flags::LEATHER) || | 
		
	
		
			
				|  |  |  |  |             mat.material->flags.is_set(material_flags::THREAD_PLANT) || | 
		
	
		
			
				|  |  |  |  |             mat.material->flags.is_set(material_flags::SILK) || | 
		
	
		
			
				|  |  |  |  |             mat.material->flags.is_set(material_flags::YARN)) | 
		
	
		
			
				|  |  |  |  |             wear = 1; | 
		
	
		
			
				|  |  |  |  |         else | 
		
	
		
			
				|  |  |  |  |             return false; | 
		
	
		
			
				|  |  |  |  |         wear = ((orig_age % wear) + (age - orig_age)) / wear; | 
		
	
		
			
				|  |  |  |  |         if (wear > 0) | 
		
	
		
			
				|  |  |  |  |             return incWearTimer(wear); | 
		
	
		
			
				|  |  |  |  |         else | 
		
	
		
			
				|  |  |  |  |             return false; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  | IMPLEMENT_VMETHOD_INTERPOSE(craft_age_wear_hook, ageItem); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static bool inc_wear_timer (df::item_constructed *item, int amount) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     if (item->flags.bits.artifact) | 
		
	
		
			
				|  |  |  |  |         return false; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     MaterialInfo mat(item->mat_type, item->mat_index); | 
		
	
		
			
				|  |  |  |  |     if (mat.isInorganic() && mat.inorganic->flags.is_set(inorganic_flags::DEEP_SPECIAL)) | 
		
	
		
			
				|  |  |  |  |         return false; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     item->wear_timer += amount; | 
		
	
		
			
				|  |  |  |  |     return (item->wear_timer > 806400); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | struct adamantine_cloth_wear_armor_hook : df::item_armorst { | 
		
	
		
			
				|  |  |  |  |     typedef df::item_armorst interpose_base; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     DEFINE_VMETHOD_INTERPOSE(bool, incWearTimer, (int amount)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         return inc_wear_timer(this, amount); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  | IMPLEMENT_VMETHOD_INTERPOSE(adamantine_cloth_wear_armor_hook, incWearTimer); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | struct adamantine_cloth_wear_helm_hook : df::item_helmst { | 
		
	
		
			
				|  |  |  |  |     typedef df::item_helmst interpose_base; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     DEFINE_VMETHOD_INTERPOSE(bool, incWearTimer, (int amount)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         return inc_wear_timer(this, amount); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  | IMPLEMENT_VMETHOD_INTERPOSE(adamantine_cloth_wear_helm_hook, incWearTimer); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | struct adamantine_cloth_wear_gloves_hook : df::item_glovesst { | 
		
	
		
			
				|  |  |  |  |     typedef df::item_glovesst interpose_base; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     DEFINE_VMETHOD_INTERPOSE(bool, incWearTimer, (int amount)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         return inc_wear_timer(this, amount); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  | IMPLEMENT_VMETHOD_INTERPOSE(adamantine_cloth_wear_gloves_hook, incWearTimer); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | struct adamantine_cloth_wear_shoes_hook : df::item_shoesst { | 
		
	
		
			
				|  |  |  |  |     typedef df::item_shoesst interpose_base; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     DEFINE_VMETHOD_INTERPOSE(bool, incWearTimer, (int amount)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         return inc_wear_timer(this, amount); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  | IMPLEMENT_VMETHOD_INTERPOSE(adamantine_cloth_wear_shoes_hook, incWearTimer); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | struct adamantine_cloth_wear_pants_hook : df::item_pantsst { | 
		
	
		
			
				|  |  |  |  |     typedef df::item_pantsst interpose_base; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     DEFINE_VMETHOD_INTERPOSE(bool, incWearTimer, (int amount)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         return inc_wear_timer(this, amount); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  | IMPLEMENT_VMETHOD_INTERPOSE(adamantine_cloth_wear_pants_hook, incWearTimer); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static void enable_hook(color_ostream &out, VMethodInterposeLinkBase &hook, vector <string> ¶meters) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     if (vector_get(parameters, 1) == "disable") | 
		
	
	
		
			
				
					|  |  |  | @ -1121,6 +596,26 @@ static void enable_hook(color_ostream &out, VMethodInterposeLinkBase &hook, vect | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static command_result enable_tweak(string tweak, color_ostream &out, vector <string> ¶meters) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     bool recognized = false; | 
		
	
		
			
				|  |  |  |  |     string cmd = parameters[0]; | 
		
	
		
			
				|  |  |  |  |     for (auto it = tweak_hooks.begin(); it != tweak_hooks.end(); ++it) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         if (it->first == cmd) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             recognized = true; | 
		
	
		
			
				|  |  |  |  |             enable_hook(out, it->second, parameters); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     if (!recognized) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         out.printerr("Unrecognized tweak: %s\n", cmd.c_str()); | 
		
	
		
			
				|  |  |  |  |         return CR_WRONG_USAGE; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     return CR_OK; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static command_result tweak(color_ostream &out, vector <string> ¶meters) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     CoreSuspender suspend; | 
		
	
	
		
			
				
					|  |  |  | @ -1219,25 +714,6 @@ static command_result tweak(color_ostream &out, vector <string> ¶meters) | 
		
	
		
			
				|  |  |  |  |             unit->profession2 = df::profession::TRADER; | 
		
	
		
			
				|  |  |  |  |         return fix_clothing_ownership(out, unit); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     else if (cmd == "stable-cursor") | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(stable_cursor_hook, feed), parameters); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     else if (cmd == "patrol-duty") | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(patrol_duty_hook, isPatrol), parameters); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     else if (cmd == "confirm-embark") | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(confirm_embark_hook, feed), parameters); | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(confirm_embark_hook, key_conflict), parameters); | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(confirm_embark_hook, render), parameters); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     else if (cmd == "stable-temp") | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(stable_temp_hook, adjustTemperature), parameters); | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(stable_temp_hook, updateContaminants), parameters); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     else if (cmd == "fast-heat") | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         if (parameters.size() < 2) | 
		
	
	
		
			
				
					|  |  |  | @ -1245,9 +721,8 @@ static command_result tweak(color_ostream &out, vector <string> ¶meters) | 
		
	
		
			
				|  |  |  |  |         max_heat_ticks = atoi(parameters[1].c_str()); | 
		
	
		
			
				|  |  |  |  |         if (max_heat_ticks <= 0) | 
		
	
		
			
				|  |  |  |  |             parameters[1] = "disable"; | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(fast_heat_hook, updateTempFromMap), parameters); | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(fast_heat_hook, updateTemperature), parameters); | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(fast_heat_hook, adjustTemperature), parameters); | 
		
	
		
			
				|  |  |  |  |         enable_tweak(cmd, out, parameters); | 
		
	
		
			
				|  |  |  |  |         return CR_OK; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     /*else if (cmd == "fix-dimensions")
 | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
	
		
			
				
					|  |  |  | @ -1257,23 +732,6 @@ static command_result tweak(color_ostream &out, vector <string> ¶meters) | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(dimension_thread_hook, subtractDimension), parameters); | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(dimension_cloth_hook, subtractDimension), parameters); | 
		
	
		
			
				|  |  |  |  |     }*/ | 
		
	
		
			
				|  |  |  |  |     else if (cmd == "advmode-contained") | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(advmode_contained_hook, feed), parameters); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     else if (cmd == "fast-trade") | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(fast_trade_assign_hook, feed), parameters); | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(fast_trade_select_hook, feed), parameters); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     else if (cmd == "military-stable-assign") | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(military_assign_hook, feed), parameters); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     else if (cmd == "military-color-assigned") | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(military_assign_hook, render), parameters); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | /*
 | 
		
	
		
			
				|  |  |  |  |     else if (cmd == "military-training") | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
	
		
			
				
					|  |  |  | @ -1282,20 +740,10 @@ static command_result tweak(color_ostream &out, vector <string> ¶meters) | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(military_training_sp_hook, process), parameters); | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(military_training_id_hook, process), parameters); | 
		
	
		
			
				|  |  |  |  |     }*/ | 
		
	
		
			
				|  |  |  |  |     else if (cmd == "craft-age-wear") | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(craft_age_wear_hook, ageItem), parameters); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     else if (cmd == "adamantine-cloth-wear") | 
		
	
		
			
				|  |  |  |  |     else | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(adamantine_cloth_wear_armor_hook, incWearTimer), parameters); | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(adamantine_cloth_wear_helm_hook, incWearTimer), parameters); | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(adamantine_cloth_wear_gloves_hook, incWearTimer), parameters); | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(adamantine_cloth_wear_shoes_hook, incWearTimer), parameters); | 
		
	
		
			
				|  |  |  |  |         enable_hook(out, INTERPOSE_HOOK(adamantine_cloth_wear_pants_hook, incWearTimer), parameters); | 
		
	
		
			
				|  |  |  |  |         return enable_tweak(cmd, out, parameters); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     else | 
		
	
		
			
				|  |  |  |  |         return CR_WRONG_USAGE; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     return CR_OK; | 
		
	
		
			
				|  |  |  |  | } |