|
55 | 55 | #include "df/strain_type.h" |
56 | 56 | #include "df/material.h" |
57 | 57 | #include "df/flow_type.h" |
| 58 | +#include "df/invasion_info.h" |
58 | 59 |
|
59 | 60 | #include "MiscUtils.h" |
60 | 61 |
|
@@ -1459,6 +1460,55 @@ static int computeNearbyWeight(lua_State *L) |
1459 | 1460 | return 0; |
1460 | 1461 | } |
1461 | 1462 |
|
| 1463 | +static bool isTired(df::unit *worker) |
| 1464 | +{ |
| 1465 | + return worker->counters2.exhaustion >= 1000 || |
| 1466 | + worker->counters2.thirst_timer >= 25000 || |
| 1467 | + worker->counters2.hunger_timer >= 50000 || |
| 1468 | + worker->counters2.sleepiness_timer >= 57600; |
| 1469 | +} |
| 1470 | + |
| 1471 | +static void releaseTiredWorker(EngineInfo *engine, df::job *job, df::unit *worker) |
| 1472 | +{ |
| 1473 | + // If not in siege |
| 1474 | + auto &sieges = ui->invasions.list; |
| 1475 | + |
| 1476 | + for (size_t i = 0; i < sieges.size(); i++) |
| 1477 | + if (sieges[i]->flags.bits.active) |
| 1478 | + return; |
| 1479 | + |
| 1480 | + // And there is a free replacement |
| 1481 | + auto &others = world->units.active; |
| 1482 | + |
| 1483 | + for (size_t i = 0; i < others.size(); i++) |
| 1484 | + { |
| 1485 | + auto unit = others[i]; |
| 1486 | + |
| 1487 | + if (unit == worker || |
| 1488 | + unit->job.current_job || !unit->status.labors[unit_labor::SIEGEOPERATE] || |
| 1489 | + !Units::isCitizen(unit) || Units::getMiscTrait(unit, misc_trait_type::OnBreak) || |
| 1490 | + isTired(unit) || !Maps::canWalkBetween(job->pos, unit->pos)) |
| 1491 | + continue; |
| 1492 | + |
| 1493 | + int skill2 = Units::getEffectiveSkill(unit, job_skill::SIEGEOPERATE); |
| 1494 | + |
| 1495 | + if (skill2 >= engine->profile.min_level && skill2 <= engine->profile.max_level) |
| 1496 | + { |
| 1497 | + // Remove the worker and request a recheck |
| 1498 | + if (Job::removeWorker(job)) |
| 1499 | + { |
| 1500 | + color_ostream_proxy out(Core::getInstance().getConsole()); |
| 1501 | + out.print("Released tired operator %d from siege engine.\n", worker->id); |
| 1502 | + |
| 1503 | + if (df::global::process_jobs) |
| 1504 | + *df::global::process_jobs = true; |
| 1505 | + } |
| 1506 | + |
| 1507 | + return; |
| 1508 | + } |
| 1509 | + } |
| 1510 | +} |
| 1511 | + |
1462 | 1512 | /* |
1463 | 1513 | * Projectile hook |
1464 | 1514 | */ |
@@ -1796,6 +1846,7 @@ struct building_hook : df::building_siegeenginest { |
1796 | 1846 | { |
1797 | 1847 | auto job = jobs[0]; |
1798 | 1848 | bool save_op = false; |
| 1849 | + bool load_op = false; |
1799 | 1850 |
|
1800 | 1851 | switch (job->job_type) |
1801 | 1852 | { |
@@ -1830,12 +1881,18 @@ struct building_hook : df::building_siegeenginest { |
1830 | 1881 | // fallthrough |
1831 | 1882 |
|
1832 | 1883 | case job_type::LoadBallista: |
| 1884 | + load_op = true; |
| 1885 | + |
1833 | 1886 | case job_type::FireCatapult: |
1834 | 1887 | case job_type::FireBallista: |
1835 | 1888 | if (auto worker = Job::getWorker(job)) |
1836 | 1889 | { |
1837 | 1890 | engine->operator_id = worker->id; |
1838 | 1891 | engine->operator_frame = world->frame_counter; |
| 1892 | + |
| 1893 | + if (action == PrepareToFire && !load_op && |
| 1894 | + (world->frame_counter%100) == 0 && isTired(worker)) |
| 1895 | + releaseTiredWorker(engine, job, worker); |
1839 | 1896 | } |
1840 | 1897 | break; |
1841 | 1898 |
|
|
0 commit comments