@ -12,11 +12,13 @@
# include "modules/Items.h"
# include "modules/Job.h"
# include "modules/Materials.h"
# include "modules/MapCache.h"
# include "MiscUtils.h"
# include "DataDefs.h"
# include <VTableInterpose.h>
# include "../uicommon.h"
# include "df/ui.h"
# include "df/world.h"
# include "df/squad.h"
@ -68,6 +70,20 @@
//#include "df/building_hivest.h"
# include <stdlib.h>
# include <unordered_map>
# include "tweaks/adamantine-cloth-wear.h"
# include "tweaks/advmode-contained.h"
# include "tweaks/civ-agreement-ui.h"
# include "tweaks/craft-age-wear.h"
# include "tweaks/farm-plot-select.h"
# include "tweaks/fast-heat.h"
# include "tweaks/fast-trade.h"
# include "tweaks/import-priority-category.h"
# include "tweaks/manager-quantity.h"
# include "tweaks/military-assign.h"
# include "tweaks/nestbox-color.h"
# include "tweaks/stable-cursor.h"
using std : : set ;
using std : : vector ;
@ -83,12 +99,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,42 +134,81 @@ 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 "
" when updating from the environment temperature. Use 0 to disable. \n "
/*" tweak fix-dimensions [disable]\n"
" Fixes subtracting small amount of thread/cloth/liquid from a stack \n "
" by splitting the stack and subtracting from the remaining single item. \n " */
" tweak adamantine-cloth-wear [disable] \n "
" Stops adamantine clothing from wearing out while being worn (bug 6481). \n "
" tweak advmode-contained [disable] \n "
" Fixes custom reactions with container inputs in advmode. The issue is \n "
" that the screen tries to force you to select the contents separately \n "
" from the container. This forcefully skips child reagents. \n "
" tweak civ-view-agreement \n "
" Fixes overlapping text on the \" view agreement \" screen \n "
" tweak craft-age-wear [disable] \n "
" Makes cloth and leather items wear out at the correct rate (bug 6003). \n "
" tweak farm-plot-select [disable] \n "
" Adds \" Select all \" and \" Deselect all \" options to farm plot menus \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 "
" when updating from the environment temperature. Use 0 to disable. \n "
" tweak fast-trade [disable] \n "
" Makes Shift-Enter in the Move Goods to Depot and Trade screens select \n "
" the current item (fully, in case of a stack), and scroll down one line. \n "
" tweak import-priority-category [disable] \n "
" When meeting with a liaison, makes Shift+Left/Right arrow adjust \n "
" the priority of an entire category of imports. \n "
" tweak manager-quantity [disable] \n "
" Removes the limit of 30 jobs per manager order \n "
" tweak nestbox-color [disable] \n "
" Makes built nestboxes use the color of their material \n "
" tweak military-color-assigned [disable] \n "
" Color squad candidates already assigned to other squads in brown/green \n "
" to make them stand out more in the list. \n "
" tweak military-stable-assign [disable] \n "
" Preserve list order and cursor position when assigning to squad, \n "
" i.e. stop the rightmost list of the Positions page of the military \n "
" screen from constantly jumping to the top. \n "
" tweak military-color-assigned [disable] \n "
" Color squad candidates already assigned to other squads in brown/green \n "
" 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 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 ( " civ-view-agreement " , civ_agreement_view_hook , render ) ;
TWEAK_HOOK ( " craft-age-wear " , craft_age_wear_hook , ageItem ) ;
TWEAK_HOOK ( " farm-plot-select " , farm_select_hook , feed ) ;
TWEAK_HOOK ( " farm-plot-select " , farm_select_hook , render ) ;
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 ( " import-priority-category " , takerequest_hook , feed ) ;
TWEAK_HOOK ( " import-priority-category " , takerequest_hook , render ) ;
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 ( " nestbox-color " , nestbox_color_hook , drawBuilding ) ;
TWEAK_HOOK ( " stable-cursor " , stable_cursor_hook , feed ) ;
return CR_OK ;
}
@ -216,271 +274,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 +363,7 @@ 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 ) {
@ -943,6 +542,7 @@ struct military_training_ct_hook : df::activity_event_combat_trainingst {
}
}
} ;
*/
/*
IMPLEMENT_VMETHOD_INTERPOSE ( military_training_ct_hook , process ) ;
@ -1007,104 +607,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 > & parameters )
{
if ( vector_get ( parameters , 1 ) = = " disable " )
@ -1121,6 +623,26 @@ static void enable_hook(color_ostream &out, VMethodInterposeLinkBase &hook, vect
}
}
static command_result enable_tweak ( string tweak , color_ostream & out , vector < string > & parameters )
{
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 > & parameters )
{
CoreSuspender suspend ;
@ -1219,25 +741,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 +748,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 +759,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 +767,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 ;
}