|
|
@ -47,12 +47,18 @@ using df::global::ui_build_selector;
|
|
|
|
|
|
|
|
|
|
|
|
DFHACK_PLUGIN("steam-engine");
|
|
|
|
DFHACK_PLUGIN("steam-engine");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* List of known steam engine workshop raws.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
struct steam_engine_workshop {
|
|
|
|
struct steam_engine_workshop {
|
|
|
|
int id;
|
|
|
|
int id;
|
|
|
|
df::building_def_workshopst *def;
|
|
|
|
df::building_def_workshopst *def;
|
|
|
|
|
|
|
|
// Cached properties
|
|
|
|
bool is_magma;
|
|
|
|
bool is_magma;
|
|
|
|
int max_power, max_capacity;
|
|
|
|
int max_power, max_capacity;
|
|
|
|
int wear_temp;
|
|
|
|
int wear_temp;
|
|
|
|
|
|
|
|
// Special tiles (relative position)
|
|
|
|
std::vector<df::coord2d> gear_tiles;
|
|
|
|
std::vector<df::coord2d> gear_tiles;
|
|
|
|
df::coord2d hearth_tile;
|
|
|
|
df::coord2d hearth_tile;
|
|
|
|
df::coord2d water_tile;
|
|
|
|
df::coord2d water_tile;
|
|
|
@ -70,6 +76,10 @@ steam_engine_workshop *find_steam_engine(int id)
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Misc utilities.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
static const int hearth_colors[6][2] = {
|
|
|
|
static const int hearth_colors[6][2] = {
|
|
|
|
{ COLOR_BLACK, 1 },
|
|
|
|
{ COLOR_BLACK, 1 },
|
|
|
|
{ COLOR_BROWN, 0 },
|
|
|
|
{ COLOR_BROWN, 0 },
|
|
|
@ -102,26 +112,57 @@ void decrement_flow(df::coord pos, int amount)
|
|
|
|
enable_updates_at(pos, true, false);
|
|
|
|
enable_updates_at(pos, true, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool make_explosion(df::coord pos, int mat_type, int mat_index, int density)
|
|
|
|
void make_explosion(df::coord center, int power)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
using df::global::flows;
|
|
|
|
static const int bias[9] = {
|
|
|
|
|
|
|
|
60, 30, 60,
|
|
|
|
|
|
|
|
30, 0, 30,
|
|
|
|
|
|
|
|
60, 30, 60
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
auto block = Maps::getTileBlock(pos);
|
|
|
|
int mat_type = builtin_mats::WATER, mat_index = -1;
|
|
|
|
if (!flows || !block)
|
|
|
|
int i = 0;
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
for (int dx = -1; dx <= 1; dx++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
for (int dy = -1; dy <= 1; dy++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int size = power - bias[i++];
|
|
|
|
|
|
|
|
auto pos = center + df::coord(dx,dy,0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (size > 0)
|
|
|
|
|
|
|
|
Maps::spawnFlow(pos, flow_type::MaterialDust, mat_type, mat_index, size);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Gui::showAutoAnnouncement(
|
|
|
|
|
|
|
|
announcement_type::CAVE_COLLAPSE, center,
|
|
|
|
|
|
|
|
"A boiler has exploded!", COLOR_RED, true
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const int WEAR_TICKS = 806400;
|
|
|
|
|
|
|
|
|
|
|
|
auto flow = new df::flow_info();
|
|
|
|
bool add_wear_nodestroy(df::item_actual *item, int rate)
|
|
|
|
flow->type = flow_type::MaterialDust;
|
|
|
|
{
|
|
|
|
flow->mat_type = mat_type;
|
|
|
|
if (item->incWearTimer(rate))
|
|
|
|
flow->mat_index = mat_index;
|
|
|
|
{
|
|
|
|
flow->density = std::min(100, density);
|
|
|
|
while (item->wear_timer >= WEAR_TICKS)
|
|
|
|
flow->pos = pos;
|
|
|
|
{
|
|
|
|
|
|
|
|
item->wear_timer -= WEAR_TICKS;
|
|
|
|
|
|
|
|
item->wear++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
block->flows.push_back(flow);
|
|
|
|
return item->wear > 3;
|
|
|
|
flows->push_back(flow);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Hook for the liquid item. Implements a special 'boiling'
|
|
|
|
|
|
|
|
* matter state with a modified description and temperature
|
|
|
|
|
|
|
|
* locked at boiling-1.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
struct liquid_hook : df::item_liquid_miscst {
|
|
|
|
struct liquid_hook : df::item_liquid_miscst {
|
|
|
|
typedef df::item_liquid_miscst interpose_base;
|
|
|
|
typedef df::item_liquid_miscst interpose_base;
|
|
|
|
|
|
|
|
|
|
|
@ -156,9 +197,15 @@ IMPLEMENT_VMETHOD_INTERPOSE(liquid_hook, getItemDescription);
|
|
|
|
IMPLEMENT_VMETHOD_INTERPOSE(liquid_hook, adjustTemperature);
|
|
|
|
IMPLEMENT_VMETHOD_INTERPOSE(liquid_hook, adjustTemperature);
|
|
|
|
IMPLEMENT_VMETHOD_INTERPOSE(liquid_hook, checkTemperatureDamage);
|
|
|
|
IMPLEMENT_VMETHOD_INTERPOSE(liquid_hook, checkTemperatureDamage);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Hook for the workshop itself. Implements core logic.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
struct workshop_hook : df::building_workshopst {
|
|
|
|
struct workshop_hook : df::building_workshopst {
|
|
|
|
typedef df::building_workshopst interpose_base;
|
|
|
|
typedef df::building_workshopst interpose_base;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Engine detection
|
|
|
|
|
|
|
|
|
|
|
|
steam_engine_workshop *get_steam_engine()
|
|
|
|
steam_engine_workshop *get_steam_engine()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (type == workshop_type::Custom)
|
|
|
|
if (type == workshop_type::Custom)
|
|
|
@ -167,6 +214,11 @@ struct workshop_hook : df::building_workshopst {
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline bool is_fully_built()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return getBuildStage() >= getMaxBuildStage();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Use high bits of flags to store current steam amount.
|
|
|
|
// Use high bits of flags to store current steam amount.
|
|
|
|
// This is necessary for consistency if items disappear unexpectedly.
|
|
|
|
// This is necessary for consistency if items disappear unexpectedly.
|
|
|
|
|
|
|
|
|
|
|
@ -180,6 +232,8 @@ struct workshop_hook : df::building_workshopst {
|
|
|
|
flags.whole = (flags.whole & 0x0FFFFFFFU) | uint32_t((count & 15) << 28);
|
|
|
|
flags.whole = (flags.whole & 0x0FFFFFFFU) | uint32_t((count & 15) << 28);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Find liquids to consume below the engine.
|
|
|
|
|
|
|
|
|
|
|
|
bool find_liquids(df::coord *pwater, df::coord *pmagma, bool is_magma, bool any_level)
|
|
|
|
bool find_liquids(df::coord *pwater, df::coord *pmagma, bool is_magma, bool any_level)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (!is_magma)
|
|
|
|
if (!is_magma)
|
|
|
@ -225,13 +279,17 @@ struct workshop_hook : df::building_workshopst {
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Absorbs a water item produced by stoke reaction into the engine.
|
|
|
|
|
|
|
|
|
|
|
|
bool absorb_unit(steam_engine_workshop *engine, df::item_liquid_miscst *liquid)
|
|
|
|
bool absorb_unit(steam_engine_workshop *engine, df::item_liquid_miscst *liquid)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
// Consume liquid inputs
|
|
|
|
df::coord water, magma;
|
|
|
|
df::coord water, magma;
|
|
|
|
|
|
|
|
|
|
|
|
if (!find_liquids(&water, &magma, engine->is_magma, true))
|
|
|
|
if (!find_liquids(&water, &magma, engine->is_magma, true))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
liquid->addWear(WEAR_TICKS*4+1, true, false);
|
|
|
|
// Destroy the item with enormous wear amount.
|
|
|
|
|
|
|
|
liquid->addWear(WEAR_TICKS*5, true, false);
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -239,6 +297,7 @@ struct workshop_hook : df::building_workshopst {
|
|
|
|
if (engine->is_magma)
|
|
|
|
if (engine->is_magma)
|
|
|
|
decrement_flow(magma, 1);
|
|
|
|
decrement_flow(magma, 1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Update flags
|
|
|
|
liquid->flags.bits.in_building = true;
|
|
|
|
liquid->flags.bits.in_building = true;
|
|
|
|
liquid->mat_state.whole |= liquid_hook::BOILING_FLAG;
|
|
|
|
liquid->mat_state.whole |= liquid_hook::BOILING_FLAG;
|
|
|
|
liquid->temperature = liquid->getBoilingPoint()-1;
|
|
|
|
liquid->temperature = liquid->getBoilingPoint()-1;
|
|
|
@ -248,6 +307,7 @@ struct workshop_hook : df::building_workshopst {
|
|
|
|
if (engine->hearth_tile.isValid())
|
|
|
|
if (engine->hearth_tile.isValid())
|
|
|
|
liquid->pos = df::coord(x1+engine->hearth_tile.x, y1+engine->hearth_tile.y, z);
|
|
|
|
liquid->pos = df::coord(x1+engine->hearth_tile.x, y1+engine->hearth_tile.y, z);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Enable block temperature updates
|
|
|
|
enable_updates_at(liquid->pos, false, true);
|
|
|
|
enable_updates_at(liquid->pos, false, true);
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -268,6 +328,8 @@ struct workshop_hook : df::building_workshopst {
|
|
|
|
jobs[i]->flags.bits.suspend = suspend;
|
|
|
|
jobs[i]->flags.bits.suspend = suspend;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Scan contained items for boiled steam to absorb.
|
|
|
|
|
|
|
|
|
|
|
|
df::item_liquid_miscst *collect_steam(steam_engine_workshop *engine, int *count)
|
|
|
|
df::item_liquid_miscst *collect_steam(steam_engine_workshop *engine, int *count)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
df::item_liquid_miscst *first = NULL;
|
|
|
|
df::item_liquid_miscst *first = NULL;
|
|
|
@ -290,6 +352,7 @@ struct workshop_hook : df::building_workshopst {
|
|
|
|
liquid->wear != 0)
|
|
|
|
liquid->wear != 0)
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// This may destroy the item
|
|
|
|
if (!absorb_unit(engine, liquid))
|
|
|
|
if (!absorb_unit(engine, liquid))
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -303,6 +366,7 @@ struct workshop_hook : df::building_workshopst {
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// Overpressure valve
|
|
|
|
// Overpressure valve
|
|
|
|
boil_unit(liquid);
|
|
|
|
boil_unit(liquid);
|
|
|
|
|
|
|
|
suspend_jobs(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -331,62 +395,47 @@ struct workshop_hook : df::building_workshopst {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void explode()
|
|
|
|
int classify_component(df::building_actual::T_contained_items *item)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int mat_type = builtin_mats::ASH, mat_index = -1;
|
|
|
|
if (item->use_mode != 2 || item->item->isBuildMat())
|
|
|
|
int cx = (x1+x2)/2, cy = (y1+y2)/2;
|
|
|
|
return -1;
|
|
|
|
int power = std::min(240, get_steam_amount()*80);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
make_explosion(df::coord(cx, cy, z), mat_type, mat_index, power);
|
|
|
|
switch (item->item->getType())
|
|
|
|
make_explosion(df::coord(cx-1, cy, z), mat_type, mat_index, power/3);
|
|
|
|
{
|
|
|
|
make_explosion(df::coord(cx, cy-1, z), mat_type, mat_index, power/3);
|
|
|
|
case item_type::TRAPPARTS:
|
|
|
|
make_explosion(df::coord(cx+1, cy, z), mat_type, mat_index, power/3);
|
|
|
|
case item_type::CHAIN:
|
|
|
|
make_explosion(df::coord(cx, cy+1, z), mat_type, mat_index, power/3);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
case item_type::BARREL:
|
|
|
|
*df::global::pause_state = true;
|
|
|
|
return 2;
|
|
|
|
|
|
|
|
default:
|
|
|
|
Gui::showAnnouncement("A boiler has exploded!", COLOR_RED, true);
|
|
|
|
return 1;
|
|
|
|
auto ann = world->status.announcements.back();
|
|
|
|
}
|
|
|
|
ann->type = announcement_type::CAVE_COLLAPSE;
|
|
|
|
|
|
|
|
ann->pos = df::coord(cx, cy, z);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool check_component_wear(steam_engine_workshop *engine, int count, int power)
|
|
|
|
bool check_component_wear(steam_engine_workshop *engine, int count, int power)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
int coeffs[3] = { 0, power, count };
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = contained_items.size()-1; i >= 0; i--)
|
|
|
|
for (int i = contained_items.size()-1; i >= 0; i--)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto item = contained_items[i];
|
|
|
|
int type = classify_component(contained_items[i]);
|
|
|
|
if (item->use_mode != 2)
|
|
|
|
if (type < 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int melt_temp = item->item->getMeltingPoint();
|
|
|
|
|
|
|
|
if (melt_temp >= engine->wear_temp)
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (item->item->isBuildMat())
|
|
|
|
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
auto type = item->item->getType();
|
|
|
|
df::item *item = contained_items[i]->item;
|
|
|
|
if (type == item_type::TRAPPARTS || item_type::CHAIN)
|
|
|
|
int melt_temp = item->getMeltingPoint();
|
|
|
|
|
|
|
|
if (coeffs[type] == 0 || melt_temp >= engine->wear_temp)
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
int coeff = power;
|
|
|
|
// let 500 degree delta at 4 pressure work 1 season
|
|
|
|
if (type == item_type::BARREL)
|
|
|
|
float ticks = coeffs[type]*(engine->wear_temp - melt_temp)*3.0f/500.0f/4.0f;
|
|
|
|
coeff = count;
|
|
|
|
if (item->addWear(int(8*(1 + ticks)), true, true))
|
|
|
|
|
|
|
|
|
|
|
|
int ticks = coeff*(engine->wear_temp - melt_temp);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (item->item->addWear(ticks, true, true))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
explode();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const int WEAR_TICKS = 806400;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int get_steam_use_rate(steam_engine_workshop *engine, int dimension, int power_level)
|
|
|
|
int get_steam_use_rate(steam_engine_workshop *engine, int dimension, int power_level)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// total ticks to wear off completely
|
|
|
|
// total ticks to wear off completely
|
|
|
@ -409,6 +458,61 @@ struct workshop_hook : df::building_workshopst {
|
|
|
|
return std::max(1, int(ticks));
|
|
|
|
return std::max(1, int(ticks));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void update_under_construction(steam_engine_workshop *engine)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (machine.machine_id != -1)
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int cur_count = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (auto first = collect_steam(engine, &cur_count))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (add_wear_nodestroy(first, WEAR_TICKS*4/10))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
boil_unit(first);
|
|
|
|
|
|
|
|
cur_count--;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set_steam_amount(cur_count);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void update_working(steam_engine_workshop *engine)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int old_count = get_steam_amount();
|
|
|
|
|
|
|
|
int old_power = std::min(engine->max_power, old_count);
|
|
|
|
|
|
|
|
int cur_count = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (auto first = collect_steam(engine, &cur_count))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int rate = get_steam_use_rate(engine, first->dimension, old_power);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (add_wear_nodestroy(first, rate))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
boil_unit(first);
|
|
|
|
|
|
|
|
cur_count--;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (check_component_wear(engine, old_count, old_power))
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (old_count < engine->max_capacity && cur_count == engine->max_capacity)
|
|
|
|
|
|
|
|
suspend_jobs(true);
|
|
|
|
|
|
|
|
else if (cur_count <= engine->max_power+1 && old_count > engine->max_power+1)
|
|
|
|
|
|
|
|
suspend_jobs(false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set_steam_amount(cur_count);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int cur_power = std::min(engine->max_power, cur_count);
|
|
|
|
|
|
|
|
if (cur_power != old_power)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
auto mptr = df::machine::find(machine.machine_id);
|
|
|
|
|
|
|
|
if (mptr)
|
|
|
|
|
|
|
|
mptr->cur_power += (cur_power - old_power)*100;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Furnaces need architecture, and this is a workshop
|
|
|
|
// Furnaces need architecture, and this is a workshop
|
|
|
|
// only because furnaces cannot connect to machines.
|
|
|
|
// only because furnaces cannot connect to machines.
|
|
|
|
DEFINE_VMETHOD_INTERPOSE(bool, needsDesign, ())
|
|
|
|
DEFINE_VMETHOD_INTERPOSE(bool, needsDesign, ())
|
|
|
@ -513,47 +617,13 @@ struct workshop_hook : df::building_workshopst {
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (auto engine = get_steam_engine())
|
|
|
|
if (auto engine = get_steam_engine())
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int old_count = get_steam_amount();
|
|
|
|
if (is_fully_built())
|
|
|
|
int old_power = std::min(engine->max_power, old_count);
|
|
|
|
update_working(engine);
|
|
|
|
int cur_count = 0;
|
|
|
|
else
|
|
|
|
|
|
|
|
update_under_construction(engine);
|
|
|
|
if (auto first = collect_steam(engine, &cur_count))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int rate = get_steam_use_rate(engine, first->dimension, old_power);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (first->incWearTimer(rate))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
while (first->wear_timer >= WEAR_TICKS)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
first->wear_timer -= WEAR_TICKS;
|
|
|
|
|
|
|
|
first->wear++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (first->wear > 3)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
boil_unit(first);
|
|
|
|
|
|
|
|
cur_count--;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (check_component_wear(engine, old_count, old_power))
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (old_count < engine->max_capacity && cur_count == engine->max_capacity)
|
|
|
|
|
|
|
|
suspend_jobs(true);
|
|
|
|
|
|
|
|
else if (cur_count <= engine->max_power+1 && old_count > engine->max_power+1)
|
|
|
|
|
|
|
|
suspend_jobs(false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set_steam_amount(cur_count);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int cur_power = std::min(engine->max_power, cur_count);
|
|
|
|
if (flags.bits.almost_deleted)
|
|
|
|
if (cur_power != old_power)
|
|
|
|
return;
|
|
|
|
{
|
|
|
|
|
|
|
|
auto mptr = df::machine::find(machine.machine_id);
|
|
|
|
|
|
|
|
if (mptr)
|
|
|
|
|
|
|
|
mptr->cur_power += (cur_power - old_power)*100;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
INTERPOSE_NEXT(updateAction)();
|
|
|
|
INTERPOSE_NEXT(updateAction)();
|
|
|
@ -565,6 +635,9 @@ struct workshop_hook : df::building_workshopst {
|
|
|
|
|
|
|
|
|
|
|
|
if (auto engine = get_steam_engine())
|
|
|
|
if (auto engine = get_steam_engine())
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!is_fully_built())
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
// If machine is running, tweak gear assemblies
|
|
|
|
// If machine is running, tweak gear assemblies
|
|
|
|
auto mptr = df::machine::find(machine.machine_id);
|
|
|
|
auto mptr = df::machine::find(machine.machine_id);
|
|
|
|
if (mptr && (mptr->visual_phase & 1) != 0)
|
|
|
|
if (mptr && (mptr->visual_phase & 1) != 0)
|
|
|
@ -602,10 +675,18 @@ struct workshop_hook : df::building_workshopst {
|
|
|
|
DEFINE_VMETHOD_INTERPOSE(void, deconstructItems, (bool noscatter, bool lost))
|
|
|
|
DEFINE_VMETHOD_INTERPOSE(void, deconstructItems, (bool noscatter, bool lost))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (get_steam_engine())
|
|
|
|
if (get_steam_engine())
|
|
|
|
random_boil();
|
|
|
|
{
|
|
|
|
|
|
|
|
// Explode if any steam left
|
|
|
|
|
|
|
|
if (int amount = get_steam_amount())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
make_explosion(
|
|
|
|
|
|
|
|
df::coord((x1+x2)/2, (y1+y2)/2, z),
|
|
|
|
|
|
|
|
40 + amount * 20
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (lost)
|
|
|
|
random_boil();
|
|
|
|
explode();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
INTERPOSE_NEXT(deconstructItems)(noscatter, lost);
|
|
|
|
INTERPOSE_NEXT(deconstructItems)(noscatter, lost);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -623,6 +704,11 @@ IMPLEMENT_VMETHOD_INTERPOSE(workshop_hook, updateAction);
|
|
|
|
IMPLEMENT_VMETHOD_INTERPOSE(workshop_hook, drawBuilding);
|
|
|
|
IMPLEMENT_VMETHOD_INTERPOSE(workshop_hook, drawBuilding);
|
|
|
|
IMPLEMENT_VMETHOD_INTERPOSE(workshop_hook, deconstructItems);
|
|
|
|
IMPLEMENT_VMETHOD_INTERPOSE(workshop_hook, deconstructItems);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Hook for the dwarfmode screen. Tweaks the build menu
|
|
|
|
|
|
|
|
* behavior to suit the steam engine building more.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
struct dwarfmode_hook : df::viewscreen_dwarfmodest
|
|
|
|
struct dwarfmode_hook : df::viewscreen_dwarfmodest
|
|
|
|
{
|
|
|
|
{
|
|
|
|
typedef df::viewscreen_dwarfmodest interpose_base;
|
|
|
|
typedef df::viewscreen_dwarfmodest interpose_base;
|
|
|
@ -669,7 +755,7 @@ struct dwarfmode_hook : df::viewscreen_dwarfmodest
|
|
|
|
|
|
|
|
|
|
|
|
if (error)
|
|
|
|
if (error)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const char *msg = "Hanging - use down stair.";
|
|
|
|
const char *msg = "Hanging - cover channels with down stairs.";
|
|
|
|
ui_build_selector->errors.push_back(new std::string(msg));
|
|
|
|
ui_build_selector->errors.push_back(new std::string(msg));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -689,13 +775,18 @@ struct dwarfmode_hook : df::viewscreen_dwarfmodest
|
|
|
|
if (engine)
|
|
|
|
if (engine)
|
|
|
|
engine->def->needs_magma = engine->is_magma;
|
|
|
|
engine->def->needs_magma = engine->is_magma;
|
|
|
|
|
|
|
|
|
|
|
|
// And now, check for open space
|
|
|
|
// And now, check for open space. Since these workshops
|
|
|
|
|
|
|
|
// are machines, they will collapse over true open space.
|
|
|
|
check_hanging_tiles(get_steam_engine());
|
|
|
|
check_hanging_tiles(get_steam_engine());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
IMPLEMENT_VMETHOD_INTERPOSE(dwarfmode_hook, feed);
|
|
|
|
IMPLEMENT_VMETHOD_INTERPOSE(dwarfmode_hook, feed);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Scan raws for matching workshop buildings.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
static bool find_engines()
|
|
|
|
static bool find_engines()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
engines.clear();
|
|
|
|
engines.clear();
|
|
|
|