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