Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 142 additions & 0 deletions bodyswap.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
-- Shifts player control over to another unit in adventure mode.
-- author: Atomic Chicken
-- based on "assumecontrol.lua" by maxthyme, as well as the defunct advtools plugin "adv-bodyswap"
-- calls "modtools/create-unit" for nemesis and histfig creation

--@ module = true

local utils = require 'utils'
validArgs = validArgs or utils.invert({
'unit',
'help'
})
local args = utils.processArgs({...}, validArgs)

local usage = [====[
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think two versions of the documentation is ideal. Sphinx should pick up anything between [====[ and ]====], even if it's a string instead of a comment (see repeat, spawnunit, and lots of modtools scripts for examples).

Copy link
Copy Markdown
Member Author

@AtomicChicken AtomicChicken May 17, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't recall carrying out any major alterations on the create-unit functions, so using reqscript and supplementing where necessary is indeed a better idea.

I was not aware of the documentation issue; thank you for clarifying it. Is either of the two versions preferred? If not, I'll remove the first one.

Edit: submitted PR #56 to allow calling of reqscript('modtools/create-unit').createNemesis() .


bodyswap
========
This script allows the player to gain control over a new unit in adventurer mode
whilst simultaneously loosing control over their current character.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

losing


To specify the target unit, simply select it in the user interface,
such as by opening the unit's status screen or viewing its description
and enter "bodyswap" in the DFHack console.

Alternatively, the target unit can be specified by its unit id as shown below.

Arguments::

-unit id
replace "id" with the unit id of your target
example:
bodyswap -unit 42

]====]

if args.help then
print(usage)
return
end

if not dfhack.world.isAdventureMode() then
qerror("This script can only be used in adventure mode!")
end

function setNewAdvNemFlags(nem)
nem.flags.ACTIVE_ADVENTURER = true
nem.flags.RETIRED_ADVENTURER = false
nem.flags.ADVENTURER = true
end
function setOldAdvNemFlags(nem)
nem.flags.ACTIVE_ADVENTURER = false
nem.flags.RETIRED_ADVENTURER = true
nem.unit.idle_area.x = nem.unit.pos.x
nem.unit.idle_area.y = nem.unit.pos.y
nem.unit.idle_area.z = nem.unit.pos.z
end

function clearNemesisFromLinkedSites(nem)
-- this is a workaround for a bug which tends to cause duplication of the unit entry in df.global.world.units.active when the site to which a historical figure is linked is reloaded with the unit present
-- appears to fix the problem without causing any noticeable issues
if not nem.figure then
return
end
for _,link in ipairs(nem.figure.site_links) do
local site = df.world_site.find(link.site)
for i = #site.unk_1.nemesis-1,0,-1 do
if site.unk_1.nemesis[i] == nem.id then
site.unk_1.nemesis:erase(i)
end
end
end
end

function createNemesis(unit)
local nemesis = reqscript('modtools/create-unit').createNemesis(unit,unit.civ_id)
nemesis.figure.flags.never_cull = true
return nemesis
end

function swapAdvUnit(newUnit)

if not newUnit then
qerror('Target unit not specified!')
end

local oldUnit = df.nemesis_record.find(df.global.ui_advmode.player_id).unit
if newUnit == oldUnit then
return
end

local activeUnits = df.global.world.units.active
local oldUnitIndex
if activeUnits[0] == oldUnit then
oldUnitIndex = 0
else -- unlikely; this is just in case
for i,u in pairs(activeUnits) do
if u == oldUnit then
oldUnitIndex = i
break
end
end
end
local newUnitIndex
for i,u in pairs(activeUnits) do
if u == newUnit then
newUnitIndex = i
break
end
end

if not newUnitIndex then
qerror("Target unit index not found!")
end

activeUnits[newUnitIndex] = oldUnit
activeUnits[oldUnitIndex] = newUnit

local newNem = dfhack.units.getNemesis(newUnit) or createNemesis(newUnit)
if newNem then
local oldNem = dfhack.units.getNemesis(oldUnit)
if oldNem then
setOldAdvNemFlags(oldNem)
end
setNewAdvNemFlags(newNem)
clearNemesisFromLinkedSites(newNem)
df.global.ui_advmode.player_id = newNem.id
end
end

if not dfhack_flags.module then
local unit = args.unit and df.unit.find(tonumber(args.unit)) or dfhack.gui.getSelectedUnit()
if not unit then
print("Enter the following if you require assistance: bodyswap -help")
if args.unit then
qerror("Invalid unit id: "..args.unit)
else
qerror("Target unit not specified!")
end
end
swapAdvUnit(unit)
end