252 lines
7.8 KiB
Lua
252 lines
7.8 KiB
Lua
|
-- hackWish.lua
|
||
|
-- Allows for script-based wishing.
|
||
|
-- author Putnam
|
||
|
-- edited by expwnent
|
||
|
|
||
|
function getGenderString(gender)
|
||
|
local genderStr
|
||
|
if gender==0 then
|
||
|
genderStr=string.char(12)
|
||
|
elseif gender==1 then
|
||
|
genderStr=string.char(11)
|
||
|
else
|
||
|
return ""
|
||
|
end
|
||
|
return string.char(40)..genderStr..string.char(41)
|
||
|
end
|
||
|
|
||
|
function getCreatureList()
|
||
|
local crList={}
|
||
|
for k,cr in ipairs(df.global.world.raws.creatures.alphabetic) do
|
||
|
for kk,ca in ipairs(cr.caste) do
|
||
|
local str=ca.caste_name[0]
|
||
|
str=str..' '..getGenderString(ca.gender)
|
||
|
table.insert(crList,{str,nil,ca})
|
||
|
end
|
||
|
end
|
||
|
return crList
|
||
|
end
|
||
|
|
||
|
function getMatFilter(itemtype)
|
||
|
local itemTypes={
|
||
|
SEEDS=function(mat,parent,typ,idx)
|
||
|
return mat.flags.SEED_MAT
|
||
|
end,
|
||
|
PLANT=function(mat,parent,typ,idx)
|
||
|
return mat.flags.STRUCTURAL_PLANT_MAT
|
||
|
end,
|
||
|
LEAVES=function(mat,parent,typ,idx)
|
||
|
return mat.flags.LEAF_MAT
|
||
|
end,
|
||
|
MEAT=function(mat,parent,typ,idx)
|
||
|
return mat.flags.MEAT
|
||
|
end,
|
||
|
CHEESE=function(mat,parent,typ,idx)
|
||
|
return (mat.flags.CHEESE_PLANT or mat.flags.CHEESE_CREATURE)
|
||
|
end,
|
||
|
LIQUID_MISC=function(mat,parent,typ,idx)
|
||
|
return (mat.flags.LIQUID_MISC_PLANT or mat.flags.LIQUID_MISC_CREATURE or mat.flags.LIQUID_MISC_OTHER)
|
||
|
end,
|
||
|
POWDER_MISC=function(mat,parent,typ,idx)
|
||
|
return (mat.flags.POWDER_MISC_PLANT or mat.flags.POWDER_MISC_CREATURE)
|
||
|
end,
|
||
|
DRINK=function(mat,parent,typ,idx)
|
||
|
return (mat.flags.ALCOHOL_PLANT or mat.flags.ALCOHOL_CREATURE)
|
||
|
end,
|
||
|
GLOB=function(mat,parent,typ,idx)
|
||
|
return (mat.flags.STOCKPILE_GLOB)
|
||
|
end,
|
||
|
WOOD=function(mat,parent,typ,idx)
|
||
|
return (mat.flags.WOOD)
|
||
|
end,
|
||
|
THREAD=function(mat,parent,typ,idx)
|
||
|
return (mat.flags.THREAD_PLANT)
|
||
|
end,
|
||
|
LEATHER=function(mat,parent,typ,idx)
|
||
|
return (mat.flags.LEATHER)
|
||
|
end
|
||
|
}
|
||
|
return itemTypes[df.item_type[itemtype]] or getRestrictiveMatFilter(itemtype)
|
||
|
end
|
||
|
|
||
|
function getRestrictiveMatFilter(itemType)
|
||
|
if not args.veryRestrictive then return nil else
|
||
|
local itemTypes={
|
||
|
WEAPON=function(mat,parent,typ,idx)
|
||
|
return (mat.flags.ITEMS_WEAPON or mat.flags.ITEMS_WEAPON_RANGED)
|
||
|
end,
|
||
|
AMMO=function(mat,parent,typ,idx)
|
||
|
return (mat.flags.ITEMS_AMMO)
|
||
|
end,
|
||
|
ARMOR=function(mat,parent,typ,idx)
|
||
|
return (mat.flags.ITEMS_ARMOR)
|
||
|
end,
|
||
|
SHOES,SHIELD,HELM,GLOVES=ARMOR,ARMOR,ARMOR,ARMOR,
|
||
|
INSTRUMENT=function(mat,parent,typ,idx)
|
||
|
return (mat.flags.ITEMS_HARD)
|
||
|
end,
|
||
|
GOBLET,FLASK,TOY,RING,CROWN,SCEPTER,FIGURINE,TOOL=INSTRUMENT,INSTRUMENT,INSTRUMENT,INSTRUMENT,INSTRUMENT,INSTRUMENT,INSTRUMENT,
|
||
|
AMULET=function(mat,parent,typ,idx)
|
||
|
return (mat.flags.ITEMS_SOFT or mat.flags.ITEMS_HARD)
|
||
|
end,
|
||
|
EARRING,BRACELET=AMULET,AMULET,
|
||
|
ROCK=function(mat,parent,typ,idx)
|
||
|
return (mat.flags.IS_STONE)
|
||
|
end,
|
||
|
BOULDER=ROCK,
|
||
|
BAR=function(mat,parent,typ,idx)
|
||
|
return (mat.flags.IS_METAL or mat.flags.SOAP or mat.id==COAL)
|
||
|
end
|
||
|
}
|
||
|
return itemTypes[df.item_type[itemType]]
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function createItem(mat,itemType,quality,pos,description)
|
||
|
local item=df[df.item_type.attrs[itemType[1]].classname]:new()
|
||
|
item.id=df.global.item_next_id
|
||
|
df.global.world.items.all:insert('#',item)
|
||
|
df.global.item_next_id=df.global.item_next_id+1
|
||
|
item:setSubtype(itemType[2])
|
||
|
item:setMaterial(mat[1])
|
||
|
item:setMaterialIndex(mat[2])
|
||
|
if df.item_type[itemType[1]]=='EGG' then
|
||
|
local creature=df.creature_raw.find(mat[1])
|
||
|
local eggMat={}
|
||
|
eggMat[1]=dfhack.matinfo.find(creature.creature_id..':EGGSHELL')
|
||
|
if eggMat[1] then
|
||
|
eggMat[2]=dfhack.matinfo.find(creature.creature_id..':EGG_WHITE')
|
||
|
eggMat[3]=dfhack.matinfo.find(creature.creature_id..'EGG_YOLK')
|
||
|
for k,v in ipairs(eggMat) do
|
||
|
item.egg_materials.mat_type:insert('#',v.type)
|
||
|
item.egg_materials.mat_index:insert('#',v.index)
|
||
|
end
|
||
|
else
|
||
|
eggMat=dfhack.matinfo.find(creature.creature_id..':MUSCLE')
|
||
|
item.egg_materials.mat_type:insert('#',eggMat.type)
|
||
|
item.egg_materials.mat_index:insert('#',eggMat.index)
|
||
|
end
|
||
|
end
|
||
|
item:categorize(true)
|
||
|
item.flags.removed=true
|
||
|
item:setSharpness(1,0)
|
||
|
item:setQuality(quality-1)
|
||
|
if df.item_type[itemType[1]]=='SLAB' then
|
||
|
item.description=description
|
||
|
end
|
||
|
dfhack.items.moveToGround(item,{x=pos.x,y=pos.y,z=pos.z})
|
||
|
end
|
||
|
|
||
|
--TODO: should this be a function?
|
||
|
function qualityTable()
|
||
|
return {{'None'},
|
||
|
{'-Well-crafted-'},
|
||
|
{'+Finely-crafted+'},
|
||
|
{'*Superior*'},
|
||
|
{string.char(240)..'Exceptional'..string.char(240)},
|
||
|
{string.char(15)..'Masterwork'..string.char(15)}
|
||
|
}
|
||
|
end
|
||
|
|
||
|
local script=require('gui/script')
|
||
|
local guimaterials=require('gui.materials')
|
||
|
|
||
|
function showItemPrompt(text,item_filter,hide_none)
|
||
|
guimaterials.ItemTypeDialog{
|
||
|
prompt=text,
|
||
|
item_filter=item_filter,
|
||
|
hide_none=hide_none,
|
||
|
on_select=script.mkresume(true),
|
||
|
on_cancel=script.mkresume(false),
|
||
|
on_close=script.qresume(nil)
|
||
|
}:show()
|
||
|
|
||
|
return script.wait()
|
||
|
end
|
||
|
|
||
|
function showMaterialPrompt(title, prompt, filter, inorganic, creature, plant) --the one included with DFHack doesn't have a filter or the inorganic, creature, plant things available
|
||
|
guimaterials.MaterialDialog{
|
||
|
frame_title = title,
|
||
|
prompt = prompt,
|
||
|
mat_filter = filter,
|
||
|
use_inorganic = inorganic,
|
||
|
use_creature = creature,
|
||
|
use_plant = plant,
|
||
|
on_select = script.mkresume(true),
|
||
|
on_cancel = script.mkresume(false),
|
||
|
on_close = script.qresume(nil)
|
||
|
}:show()
|
||
|
|
||
|
return script.wait()
|
||
|
end
|
||
|
|
||
|
function usesCreature(itemtype)
|
||
|
typesThatUseCreatures={REMAINS=true,FISH=true,FISH_RAW=true,VERMIN=true,PET=true,EGG=true,CORPSE=true,CORPSEPIECE=true}
|
||
|
return typesThatUseCreatures[df.item_type[itemtype]]
|
||
|
end
|
||
|
|
||
|
function getCreatureRaceAndCaste(caste)
|
||
|
return df.global.world.raws.creatures.list_creature[caste.index],df.global.world.raws.creatures.list_caste[caste.index]
|
||
|
end
|
||
|
|
||
|
function hackWish(posOrUnit)
|
||
|
local pos = df.unit:is_instance(posOrUnit) and posOrUnit.pos or posOrUnit
|
||
|
script.start(function()
|
||
|
--local amountok, amount
|
||
|
local matok,mattype,matindex,matFilter
|
||
|
local itemok,itemtype,itemsubtype=showItemPrompt('What item do you want?',function(itype) return df.item_type[itype]~='CORPSE' and df.item_type[itype]~='FOOD' end ,true)
|
||
|
if not args.notRestrictive then
|
||
|
matFilter=getMatFilter(itemtype)
|
||
|
end
|
||
|
if not usesCreature(itemtype) then
|
||
|
matok,mattype,matindex=showMaterialPrompt('Wish','And what material should it be made of?',matFilter)
|
||
|
else
|
||
|
local creatureok,useless,creatureTable=script.showListPrompt('Wish','What creature should it be?',COLOR_LIGHTGREEN,getCreatureList())
|
||
|
mattype,matindex=getCreatureRaceAndCaste(creatureTable[3])
|
||
|
end
|
||
|
local qualityok,quality=script.showListPrompt('Wish','What quality should it be?',COLOR_LIGHTGREEN,qualityTable())
|
||
|
local description
|
||
|
if df.item_type[itemtype]=='SLAB' then
|
||
|
local descriptionok
|
||
|
descriptionok,description=script.showInputPrompt('Slab','What should the slab say?',COLOR_WHITE)
|
||
|
end
|
||
|
--repeat amountok,amount=script.showInputPrompt('Wish','How many do you want? (numbers only!)',COLOR_LIGHTGREEN) until tonumber(amount)
|
||
|
if mattype and itemtype then
|
||
|
--for i=1,tonumber(amount) do
|
||
|
createItem({mattype,matindex},{itemtype,itemsubtype},quality,pos,description)
|
||
|
--end
|
||
|
end
|
||
|
end)
|
||
|
end
|
||
|
|
||
|
scriptArgs={...}
|
||
|
|
||
|
args={}
|
||
|
|
||
|
for k,v in ipairs(scriptArgs) do
|
||
|
v=v:lower()
|
||
|
if v=='startup' then args.startup=true end
|
||
|
if v=='all' then args.notRestrictive=true end
|
||
|
if v=='restrictive' then args.veryRestrictive=true end
|
||
|
if v=='unit' then args.unitNum=args[k+1] end
|
||
|
if v=='x' then args.x=args[k+1] end
|
||
|
if v=='y' then args.y=args[k+1] end
|
||
|
if v=='z' then args.z=args[k+1] end
|
||
|
end
|
||
|
|
||
|
eventful=require('plugins.eventful')
|
||
|
|
||
|
function posIsValid(pos)
|
||
|
return pos.x~=-30000 and pos or false
|
||
|
end
|
||
|
|
||
|
if not args.startup then
|
||
|
local posOrUnit=args.x and {x=args.x,y=args.y,z=args.z} or args.unitNum and df.unit.find(args.unitNum) or posIsValid(df.global.cursor) or dfhack.gui.getSelectedUnit(true)
|
||
|
hackWish(posOrUnit)
|
||
|
else
|
||
|
eventful.onReactionComplete.hackWishP=function(reaction,unit,input_items,input_reagents,output_items, call_native)
|
||
|
if not reaction.code:find('DFHACK_WISH') then return nil end
|
||
|
hackWish(unit)
|
||
|
end
|
||
|
end
|