Skip to content

Commit 06b3677

Browse files
authored
Merge pull request #5467 from quietust/animaltrap
Add "animaltrap-reuse" tweak
2 parents 4bf1b13 + 4457a8c commit 06b3677

File tree

4 files changed

+91
-0
lines changed

4 files changed

+91
-0
lines changed

docs/changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ Template for new versions:
5454
## New Tools
5555

5656
## New Features
57+
- `tweak`: ``animaltrap-reuse``: make it so built animal traps automatically unload the vermin they catch into stockpiled animal traps, so that they can be automatically re-baited and reused
5758

5859
## Fixes
5960

docs/plugins/tweak.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ Commands
3838
``adamantine-cloth-wear``
3939
Prevents adamantine clothing from wearing out while being worn
4040
(:bug:`6481`).
41+
``animaltrap-reuse``
42+
Makes built animal traps unload caught vermin into stockpiled animal traps
43+
so that they can be automatically re-baited and reused.
4144
``craft-age-wear``
4245
Fixes crafted items not wearing out over time (:bug:`6003`). With this
4346
tweak, items made from cloth and leather will gain a level of wear every 20

plugins/tweak/tweak.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ using std::string;
1414
using namespace DFHack;
1515

1616
#include "tweaks/adamantine-cloth-wear.h"
17+
#include "tweaks/animaltrap-reuse.h"
1718
#include "tweaks/craft-age-wear.h"
1819
#include "tweaks/eggs-fertile.h"
1920
#include "tweaks/fast-heat.h"
@@ -53,6 +54,8 @@ DFhackCExport command_result plugin_init(color_ostream &out, vector<PluginComman
5354
TWEAK_HOOK("adamantine-cloth-wear", adamantine_cloth_wear_shoes_hook, incWearTimer);
5455
TWEAK_HOOK("adamantine-cloth-wear", adamantine_cloth_wear_pants_hook, incWearTimer);
5556

57+
TWEAK_HOOK("animaltrap-reuse", animaltrap_reuse_hook, updateAction);
58+
5659
TWEAK_HOOK("craft-age-wear", craft_age_wear_hook, ageItem);
5760

5861
TWEAK_HOOK("eggs-fertile", eggs_fertile_hook, getItemDescription);
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#include "modules/Job.h"
2+
#include "modules/Items.h"
3+
4+
#include "df/building_animaltrapst.h"
5+
#include "df/buildingitemst.h"
6+
#include "df/general_ref_building_holderst.h"
7+
#include "df/general_ref_contained_in_itemst.h"
8+
#include "df/general_ref_contains_itemst.h"
9+
#include "df/job.h"
10+
11+
using namespace df::enums;
12+
13+
struct animaltrap_reuse_hook : df::building_animaltrapst {
14+
typedef df::building_animaltrapst interpose_base;
15+
DEFINE_VMETHOD_INTERPOSE(void, updateAction, ())
16+
{
17+
// Skip processing if the trap isn't fully built
18+
if (getBuildStage() != getMaxBuildStage()) return;
19+
20+
// The first item is always the trap itself, and the second item (if any) is always either the Bait or the caught Vermin
21+
if ((contained_items.size() > 1) && (contained_items[1]->item->getType() == df::item_type::VERMIN))
22+
{
23+
auto trap = contained_items[0]->item;
24+
auto vermin = contained_items[1]->item;
25+
26+
// Make sure we don't already have a "Release Small Creature" job
27+
for (size_t j = 0; j < jobs.size(); j++)
28+
{
29+
if (jobs[j]->job_type == df::job_type::ReleaseSmallCreature)
30+
return;
31+
// Also bail out if the player marked the building for destruction
32+
if (jobs[j]->job_type == df::job_type::DestroyBuilding)
33+
return;
34+
}
35+
36+
// Create the job
37+
auto job = new df::job();
38+
Job::linkIntoWorld(job, true);
39+
40+
job->job_type = df::job_type::ReleaseSmallCreature;
41+
job->pos.x = centerx;
42+
job->pos.y = centery;
43+
job->pos.z = z;
44+
45+
// Attach the vermin to the job
46+
Job::attachJobItem(job, vermin, df::job_role_type::Hauled, -1, -1);
47+
48+
// Link the job to the building
49+
df::general_ref *ref = df::allocate<df::general_ref_building_holderst>();
50+
ref->setID(id);
51+
job->general_refs.push_back(ref);
52+
53+
jobs.push_back(job);
54+
55+
// Hack: put the vermin inside the trap ITEM right away, otherwise the job will cancel.
56+
// Normally, this doesn't happen until after the trap is deconstructed, but the game still
57+
// seems to handle everything correctly and doesn't leave any bad references afterwards.
58+
if (!Items::getContainer(vermin))
59+
{
60+
// We can't use Items::moveToContainer, because that would remove it from the Building
61+
// (and cause the game to no longer recognize the trap as being "full").
62+
// Instead, manually add the references and set the necessary bits.
63+
64+
ref = df::allocate<df::general_ref_contained_in_itemst>();
65+
ref->setID(trap->id);
66+
vermin->general_refs.push_back(ref);
67+
68+
ref = df::allocate<df::general_ref_contains_itemst>();
69+
ref->setID(vermin->id);
70+
trap->general_refs.push_back(ref);
71+
72+
vermin->flags.bits.in_inventory = true;
73+
trap->flags.bits.weight_computed = false;
74+
// Don't set this flag here (even though it would normally get set),
75+
// since the game doesn't clear it after the vermin gets taken out
76+
// trap->flags.bits.container = true;
77+
}
78+
return;
79+
}
80+
INTERPOSE_NEXT(updateAction)();
81+
}
82+
};
83+
84+
IMPLEMENT_VMETHOD_INTERPOSE(animaltrap_reuse_hook, updateAction);

0 commit comments

Comments
 (0)