Well, here goes my first DFHack script(s).
A week or two ago searched through this thread and didn't find anything that let me add units to my fort's population. So, I spent my spare time the last two weeks writing two scripts that let me do just that.
Known problems:
* When I took some guards for my civ's caravan, all of them except just sat around gathering bad thoughts until they went insane. In another fort, the dwarven caravan was ambushed and everybody except one caravan guard was killed. After he felled the last goblin, I took control of him and he became a normal worker in my fort.
* I haven't yet found a unit that I took that I can add to my military. So all those caravan guards are not that useful...unless you need more peasants. Which, personally, I do.
* All non-dwarven creatures (or, I assume, creatures not of your race -- haven't tried this script with other races as my race) are classified as "tame." So even though sentients usually show up in your "civilians" tab and they have professions and you can set their labors with v -> p -> l, all those goblins you captured aren't actually going to do anything other than walk around. I'd assume this can be fixed with something like companion (which, unfortunately, I don't have in Linux).
* It doesn't seem you can assign captured units positions in your nobles and administrators screen.
If anybody has any idea how to fix those, please let me know.
Warning: These bug your save or crash your game. I'm not responsible for anything that goes wrong. You are using these scripts at your own risk.
I've had no crashes or save-breaking problems yet, but don't come crying to me if something does go wrong in any way, shape, or form (though a bug report of sorts is appreciated).
I advise you to always save & additionally back up your save when playing with these (though this applies to DFHack in general) so that you can revert anything that goes wrong.
This first script adds the currently selected unit to your fort. Sentients should show up in your civilians tab and animals should show up in your pets/livestock tab.
local theunit=dfhack.gui.getSelectedUnit() --TODO: Argument to pass a unit. Probably would be useful in conjunction with autosyndrome or something to make a mind control ray, I don't know.
if not theunit then qerror("No unit selected") end
function takeUnit(unit)
if (unit.flags1.dead) then qerror("Unit is dead") end
print(unit)
print("Name: " .. unit.name.first_name .. " & nickname: " .. unit.name.nickname)
print("\nunit.civ_id = "..unit.civ_id)
if (unit.civ_id ~= df.global.ui.civ_id) then
print("Setting unit.civ_id to df.global.ui.race_id ("..tostring(df.global.ui.civ_id)..").")
unit.civ_id = df.global.ui.civ_id
end
print("unit.flags1.marauder", "= ", unit.flags1.marauder)
if (unit.flags1.marauder) then
print("Setting unit.flags1.marauder to false.")
unit.flags1.marauder = false
end
print("unit.flags1.invader_origin", "=", unit.flags1.invader_origin)
if(unit.flags1.invader_origin) then
print("Setting unit.flags1.invader_origin to false.")
unit.flags1.invader_origin = false
end
print("unit.invasion_id", "=", unit.invasion_id)
if (unit.invasion_id ~= -1) then
print("Setting unit.invasion_id to -1.")
unit.invasion_id = -1
end
print("unit.flags1.merchant", "= ",unit.flags1.merchant)
if (unit.flags1.merchant) then
print("Setting unit.flags1.merchant to false.")
unit.flags1.merchant = false
end
print("unit.flags1.forest", "= ",unit.flags1.forest)
if (unit.flags1.forest) then
print("Setting unit.flags1.forest to false")
unit.flags1.forest = false
end
print("unit.flags1.diplomat", "= ",unit.flags1.diplomat)
if (unit.flags1.diplomat) then
print("Setting unit.flags1.diplomat to false")
unit.flags1.diplomat = false
end
print("unit.flags1.active_invader", "= ",unit.flags1.active_invader)
if (unit.flags1.active_invader) then
print("Setting unit.flags1.active_invader")
unit.flags1.active_invader = false
end
if (unit.flags1.important_historical_figure ~= true or unit.flags2.important_historical_figure) then
print("Warning: Unit is not an important historical figure. You cannot use it in the military or assign it a position in your nobles screen, and who knows what else. I think.")
end
print("unit.flags2.resident", "= ",unit.flags2.resident)
if (unit.flags2.resident) then
print("Setting unit.flags2.resident to false")
unit.flags2.resident = false
end
print("unit.flags2.visitor", "= ",unit.flags2.visitor)
if (unit.flags2.visitor) then
print("Setting unit.flags2.visitor to false")
unit.flags2.visitor = false
end
end
takeUnit(theunit)
This one loops through all of the units on the map and adds the ones with the specified ID to your fort.
The script will prompt you for the ID (though I should probably make it look at arguments passed to it).
print("Please enter ID of civ you want to steal units from:")
local target_civ_id = io.read() --TODO: Pass this as an argument.
print("\n")
function takeUnit(unit)
if (unit.flags1.dead) then return("Aborting unit"..tostring(unit).."; it is dead") end
if (unit.civ_id ~= df.global.ui.civ_id) then unit.civ_id = df.global.ui.civ_id end
if (unit.flags1.marauder) then unit.flags1.marauder = false end
if(unit.flags1.invader_origin) then unit.flags1.invader_origin = false end
if (unit.invasion_id ~= -1) then unit.invasion_id = -1 end
if (unit.flags1.merchant) then unit.flags1.merchant = false end
if (unit.flags1.forest) then unit.flags1.forest = false end
if (unit.flags1.diplomat) then unit.flags1.diplomat = false end
if (unit.flags1.active_invader) then unit.flags1.active_invader = false end
if (unit.flags2.resident) then unit.flags2.resident = false end
if (unit.flags2.visitor) then unit.flags2.visitor = false end
end
local count = 0
for fnUnitCount,fnUnit in ipairs(df.global.world.units.all) do
if (fnUnit.civ_id == tonumber(target_civ_id)) then -- Append the following clause to the if statement: "and fnUnit.civ_id ~= df.global.ui.civ_id) then" if you want to skip units of the same civ. Note that this check is neccessary in some cases such as traders or if you spawn a siege from your own civ.
local answer = takeUnit(fnUnit)
if (answer ~= nil) then
print(answer)
else
count = count + 1
end
end
end
print("Did "..count..".")
I'm pretty sure there are other flags that could/should be set to make this work better, but I'm no expert
I appreciate any feedback, constructive criticism, and improvements you guys can offer.