165 lines
3.5 KiB
Lua
165 lines
3.5 KiB
Lua
--scripts/modtools/transform-unit.lua
|
|
--author expwnent
|
|
--based on shapechange by Putnam
|
|
--[[=begin
|
|
|
|
modtools/transform-unit
|
|
=======================
|
|
Transforms a unit into another unit type, possibly permanently.
|
|
Warning: this will crash arena mode if you view the unit on the
|
|
same tick that it transforms. If you wait until later, it will be fine.
|
|
|
|
=end]]
|
|
local utils = require 'utils'
|
|
|
|
normalRace = normalRace or {}
|
|
|
|
local function transform(unit,race,caste)
|
|
unit.enemy.normal_race = race
|
|
unit.enemy.normal_caste = caste
|
|
unit.enemy.were_race = race
|
|
unit.enemy.were_caste = caste
|
|
end
|
|
|
|
validArgs = validArgs or utils.invert({
|
|
'clear',
|
|
'help',
|
|
'unit',
|
|
'duration',
|
|
'setPrevRace',
|
|
'keepInventory',
|
|
'race',
|
|
'caste',
|
|
'suppressAnnouncement',
|
|
'untransform',
|
|
})
|
|
|
|
local args = utils.processArgs({...}, validArgs)
|
|
|
|
if args.help then
|
|
print([[scripts/modtools/transform-unit.lua
|
|
arguments
|
|
-help
|
|
print this help message
|
|
-clear
|
|
clear records of normal races
|
|
-unit id
|
|
set the target unit
|
|
-duration ticks
|
|
how long it should last, or "forever"
|
|
-setPrevRace
|
|
make a record of the previous race so that you can change it back with -untransform
|
|
-keepInventory
|
|
move items back into inventory after transformation
|
|
-race raceName
|
|
-caste casteName
|
|
-suppressAnnouncement
|
|
don't show the Unit has transformed into a Blah! event
|
|
-untransform
|
|
turn the unit back into what it was before
|
|
]])
|
|
return
|
|
end
|
|
|
|
if args.clear then
|
|
normalRace = {}
|
|
end
|
|
|
|
if not args.unit then
|
|
error 'Specify a unit.'
|
|
end
|
|
|
|
if not args.duration then
|
|
args.duration = 'forever'
|
|
end
|
|
|
|
local raceIndex
|
|
local race
|
|
local caste
|
|
if args.untransform then
|
|
local unit = df.unit.find(tonumber(args.unit))
|
|
raceIndex = normalRace[args.unit].race
|
|
race = df.creature_raw.find(raceIndex)
|
|
caste = normalRace[args.unit].caste
|
|
normalRace[args.unit] = nil
|
|
else
|
|
if not args.race or not args.caste then
|
|
error 'Specficy a target form.'
|
|
end
|
|
|
|
--find race
|
|
for i,v in ipairs(df.global.world.raws.creatures.all) do
|
|
if v.creature_id == args.race then
|
|
raceIndex = i
|
|
race = v
|
|
break
|
|
end
|
|
end
|
|
|
|
if not race then
|
|
error 'Invalid race.'
|
|
end
|
|
|
|
for i,v in ipairs(race.caste) do
|
|
if v.caste_id == args.caste then
|
|
caste = i
|
|
break
|
|
end
|
|
end
|
|
|
|
if not caste then
|
|
error 'Invalid caste.'
|
|
end
|
|
end
|
|
|
|
local unit = df.unit.find(tonumber(args.unit))
|
|
local oldRace = unit.enemy.normal_race
|
|
local oldCaste = unit.enemy.normal_caste
|
|
if args.setPrevRace then
|
|
normalRace[args.unit] = {}
|
|
normalRace[args.unit].race = oldRace
|
|
normalRace[args.unit].caste = oldCaste
|
|
end
|
|
transform(unit,raceIndex,caste,args.setPrevRace)
|
|
|
|
local inventoryItems = {}
|
|
|
|
local function getInventory()
|
|
local result = {}
|
|
for _,item in ipairs(unit.inventory) do
|
|
table.insert(result, item:new());
|
|
end
|
|
return result
|
|
end
|
|
|
|
local function restoreInventory()
|
|
dfhack.timeout(1, 'ticks', function()
|
|
for _,item in ipairs(inventoryItems) do
|
|
dfhack.items.moveToInventory(item.item, unit, item.mode, item.body_part_id)
|
|
item:delete()
|
|
end
|
|
inventoryItems = {}
|
|
end)
|
|
end
|
|
|
|
if args.keepInventory then
|
|
inventoryItems = getInventory()
|
|
end
|
|
|
|
if args.keepInventory then
|
|
restoreInventory()
|
|
end
|
|
if args.duration and args.duration ~= 'forever' then
|
|
--when the timeout ticks down, transform them back
|
|
dfhack.timeout(tonumber(args.duration), 'ticks', function()
|
|
if args.keepInventory then
|
|
inventoryItems = getInventory()
|
|
end
|
|
transform(unit,oldRace,oldCaste)
|
|
if args.keepInventory then
|
|
restoreInventory()
|
|
end
|
|
end)
|
|
end
|
|
|