Merge branch 'develop' of github.com:DFHack/dfhack into develop

develop
Quietust 2014-08-20 10:32:59 -05:00
commit ae80ca9ec9
8 changed files with 185 additions and 145 deletions

@ -965,6 +965,12 @@ Job module
Compares important fields in the job item structures. Compares important fields in the job item structures.
* ``dfhack.job.linkIntoWorld(job,new_id)``
Adds job into ``df.global.job_list``, and if new_id
is true, then also sets it's id and increases
``df.global.job_next_id``
* ``dfhack.job.listNewlyCreated(first_id)`` * ``dfhack.job.listNewlyCreated(first_id)``
Returns the current value of ``df.global.job_next_id``, and Returns the current value of ``df.global.job_next_id``, and
@ -3209,7 +3215,8 @@ Functions
5. ``registerSidebar(shop_name,callback)`` 5. ``registerSidebar(shop_name,callback)``
Enable callback when sidebar for ``shop_name`` is drawn. Usefull for custom workshop views e.g. using gui.dwarfmode lib. Enable callback when sidebar for ``shop_name`` is drawn. Usefull for custom workshop views e.g. using gui.dwarfmode lib. Also accepts a ``class`` instead of function
as callback. Best used with ``gui.dwarfmode`` class ``WorkshopOverlay``.
Examples Examples
-------- --------
@ -3266,6 +3273,7 @@ Functions
a. tables of 4 numbers ``{tile,fore,back,bright}`` OR a. tables of 4 numbers ``{tile,fore,back,bright}`` OR
b. empty table (tile not modified) OR b. empty table (tile not modified) OR
c. ``{x=<number> y=<number> + 4 numbers like in first case}``, this generates full frame useful for animations that change little (1-2 tiles) c. ``{x=<number> y=<number> + 4 numbers like in first case}``, this generates full frame useful for animations that change little (1-2 tiles)
8. canBeRoomSubset -- a flag if this building can be counted in room. 1 means it can, 0 means it can't and -1 default building behaviour
Animate table also might contain: Animate table also might contain:
1. frameLenght -- how many ticks does one frame take OR 1. frameLenght -- how many ticks does one frame take OR

@ -1339,6 +1339,7 @@ static const LuaWrapper::FunctionReg dfhack_job_module[] = {
WRAPM(Job,isSuitableItem), WRAPM(Job,isSuitableItem),
WRAPM(Job,isSuitableMaterial), WRAPM(Job,isSuitableMaterial),
WRAPM(Job,getName), WRAPM(Job,getName),
WRAPM(Job,linkIntoWorld),
WRAPN(is_equal, jobEqual), WRAPN(is_equal, jobEqual),
WRAPN(is_item_equal, jobItemEqual), WRAPN(is_item_equal, jobItemEqual),
{ NULL, NULL } { NULL, NULL }

@ -383,7 +383,7 @@ MenuOverlay = defclass(MenuOverlay, DwarfOverlay)
MenuOverlay.ATTRS { MenuOverlay.ATTRS {
frame_inset = 0, frame_inset = 0,
frame_background = CLEAR_PEN, frame_background = gui.CLEAR_PEN,
} }
function MenuOverlay:computeFrame(parent_rect) function MenuOverlay:computeFrame(parent_rect)
@ -417,5 +417,35 @@ function MenuOverlay:render(dc)
MenuOverlay.super.render(self, dc) MenuOverlay.super.render(self, dc)
end end
end end
--fakes a "real" workshop sidebar menu, but on exactly selected workshop
WorkshopOverlay = defclass(WorkshopOverlay, MenuOverlay)
WorkshopOverlay.ATTRS={
workshop=DEFAULT_NIL,
}
function WorkshopOverlay:onInput(keys)
local allowedKeys={ --TODO add options: job management, profile, etc...
"CURSOR_RIGHT","CURSOR_LEFT","CURSOR_UP","CURSOR_DOWN",
"CURSOR_UPRIGHT","CURSOR_UPLEFT","CURSOR_DOWNRIGHT","CURSOR_DOWNLEFT",
"CURSOR_UP_Z","CURSOR_DOWN_Z","DESTROYBUILDING","CHANGETAB"}
if keys.LEAVESCREEN then
self:dismiss()
self:sendInputToParent('LEAVESCREEN')
elseif keys.CHANGETAB then
self:sendInputToParent("CHANGETAB")
self:inputToSubviews(keys)
self:updateLayout()
else
for _,name in ipairs(allowedKeys) do
if keys[name] then
self:sendInputToParent(name)
break
end
end
self:inputToSubviews(keys)
end
if df.global.world.selected_building ~= self.workshop then
self:dismiss()
return
end
end
return _ENV return _ENV

@ -47,6 +47,7 @@ struct workshop_hack_data
int frame_skip; // e.g. 2 means have to ticks between frames int frame_skip; // e.g. 2 means have to ticks between frames
//updateCallback: //updateCallback:
int skip_updates; int skip_updates;
int room_subset; //0 no, 1 yes, -1 default
}; };
typedef std::map<int32_t,workshop_hack_data> workshops_data_t; typedef std::map<int32_t,workshop_hack_data> workshops_data_t;
workshops_data_t hacked_workshops; workshops_data_t hacked_workshops;
@ -174,6 +175,17 @@ struct work_hook : df::building_workshopst{
return INTERPOSE_NEXT(isUnpowered)(); return INTERPOSE_NEXT(isUnpowered)();
} }
DEFINE_VMETHOD_INTERPOSE(bool, canBeRoomSubset, ())
{
if(auto def = find_def())
{
if(def->room_subset==0)
return false;
if(def->room_subset==1)
return true;
}
return INTERPOSE_NEXT(canBeRoomSubset)();
}
DEFINE_VMETHOD_INTERPOSE(void, updateAction, ()) DEFINE_VMETHOD_INTERPOSE(void, updateAction, ())
{ {
if(auto def = find_def()) if(auto def = find_def())
@ -241,6 +253,7 @@ IMPLEMENT_VMETHOD_INTERPOSE(work_hook, categorize);
IMPLEMENT_VMETHOD_INTERPOSE(work_hook, uncategorize); IMPLEMENT_VMETHOD_INTERPOSE(work_hook, uncategorize);
IMPLEMENT_VMETHOD_INTERPOSE(work_hook, canConnectToMachine); IMPLEMENT_VMETHOD_INTERPOSE(work_hook, canConnectToMachine);
IMPLEMENT_VMETHOD_INTERPOSE(work_hook, isUnpowered); IMPLEMENT_VMETHOD_INTERPOSE(work_hook, isUnpowered);
IMPLEMENT_VMETHOD_INTERPOSE(work_hook, canBeRoomSubset);
IMPLEMENT_VMETHOD_INTERPOSE(work_hook, updateAction); IMPLEMENT_VMETHOD_INTERPOSE(work_hook, updateAction);
IMPLEMENT_VMETHOD_INTERPOSE(work_hook, drawBuilding); IMPLEMENT_VMETHOD_INTERPOSE(work_hook, drawBuilding);
void clear_mapping() void clear_mapping()
@ -336,6 +349,7 @@ static int addBuilding(lua_State* L)
else else
newDefinition.machine_timing=false; newDefinition.machine_timing=false;
} }
newDefinition.room_subset=luaL_optinteger(L,9,-1);
hacked_workshops[newDefinition.myType]=newDefinition; hacked_workshops[newDefinition.myType]=newDefinition;
return 0; return 0;
} }
@ -354,6 +368,7 @@ static void enable_hooks(bool enable)
INTERPOSE_HOOK(work_hook,uncategorize).apply(enable); INTERPOSE_HOOK(work_hook,uncategorize).apply(enable);
INTERPOSE_HOOK(work_hook,canConnectToMachine).apply(enable); INTERPOSE_HOOK(work_hook,canConnectToMachine).apply(enable);
INTERPOSE_HOOK(work_hook,isUnpowered).apply(enable); INTERPOSE_HOOK(work_hook,isUnpowered).apply(enable);
INTERPOSE_HOOK(work_hook,canBeRoomSubset).apply(enable);
//update n render //update n render
INTERPOSE_HOOK(work_hook,updateAction).apply(enable); INTERPOSE_HOOK(work_hook,updateAction).apply(enable);
INTERPOSE_HOOK(work_hook,drawBuilding).apply(enable); INTERPOSE_HOOK(work_hook,drawBuilding).apply(enable);

@ -102,8 +102,8 @@ function registerBuilding(args)
end end
frames=processFrames(shop_def,animate.frames) frames=processFrames(shop_def,animate.frames)
end end
local roomSubset=args.canBeRoomSubset or -1
addBuilding(shop_id,fix_impassible,consume,produce,gears,updateSkip,frames,frameLength) addBuilding(shop_id,fix_impassible,consume,produce,gears,updateSkip,frames,frameLength,roomSubset)
end end
return _ENV return _ENV

@ -98,10 +98,25 @@ function registerReaction(reaction_name,callback)
end end
function registerSidebar(shop_name,callback) function registerSidebar(shop_name,callback)
if type(callback)=="function" then
_registeredStuff.customSidebar=_registeredStuff.customSidebar or {} _registeredStuff.customSidebar=_registeredStuff.customSidebar or {}
_registeredStuff.customSidebar[shop_name]=callback _registeredStuff.customSidebar[shop_name]=callback
onWorkshopFillSidebarMenu._library=customSidebarsCallback onWorkshopFillSidebarMenu._library=customSidebarsCallback
dfhack.onStateChange.eventful=unregall dfhack.onStateChange.eventful=unregall
else
local function drawSidebar( wshop )
local valid_focus="dwarfmode/QueryBuilding/Some"
if wshop:getMaxBuildStage()==wshop:getBuildStage() then
local sidebar=callback{workshop=wshop}
if string.sub(dfhack.gui.getCurFocus(),1,#valid_focus)==valid_focus then
sidebar:show()
else
sidebar:show(dfhack.gui.getCurViewscreen(true).parent)
end
end
end
registerSidebar(shop_name,drawSidebar)
end
end end
function removeNative(shop_name,name) function removeNative(shop_name,name)

@ -3,6 +3,7 @@
-- author Putnam -- author Putnam
-- edited by expwnent -- edited by expwnent
function getGenderString(gender) function getGenderString(gender)
local genderStr local genderStr
if gender==0 then if gender==0 then
@ -97,47 +98,19 @@ function getRestrictiveMatFilter(itemType)
BAR=function(mat,parent,typ,idx) BAR=function(mat,parent,typ,idx)
return (mat.flags.IS_METAL or mat.flags.SOAP or mat.id==COAL) return (mat.flags.IS_METAL or mat.flags.SOAP or mat.id==COAL)
end end
} }
return itemTypes[df.item_type[itemType]] return itemTypes[df.item_type[itemType]]
end end
end end
function createItem(mat,itemType,quality,pos,description) function createItem(mat,itemType,quality,creator,description)
local item=df[df.item_type.attrs[itemType[1]].classname]:new() dfhack.items.createItem(itemType[1], itemType[2], mat[1], mat[2], creator)
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 if df.item_type[itemType[1]]=='SLAB' then
item.description=description item.description=description
end end
dfhack.items.moveToGround(item,{x=pos.x,y=pos.y,z=pos.z})
end end
--TODO: should this be a function?
function qualityTable() function qualityTable()
return {{'None'}, return {{'None'},
{'-Well-crafted-'}, {'-Well-crafted-'},
@ -148,11 +121,10 @@ function qualityTable()
} }
end end
local script=require('gui/script') local script=require('gui.script')
local guimaterials=require('gui.materials')
function showItemPrompt(text,item_filter,hide_none) function showItemPrompt(text,item_filter,hide_none)
guimaterials.ItemTypeDialog{ require('gui.materials').ItemTypeDialog{
prompt=text, prompt=text,
item_filter=item_filter, item_filter=item_filter,
hide_none=hide_none, hide_none=hide_none,
@ -165,7 +137,7 @@ function showItemPrompt(text,item_filter,hide_none)
end 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 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{ require('gui.materials').MaterialDialog{
frame_title = title, frame_title = title,
prompt = prompt, prompt = prompt,
mat_filter = filter, mat_filter = filter,
@ -189,10 +161,9 @@ function getCreatureRaceAndCaste(caste)
return df.global.world.raws.creatures.list_creature[caste.index],df.global.world.raws.creatures.list_caste[caste.index] return df.global.world.raws.creatures.list_creature[caste.index],df.global.world.raws.creatures.list_caste[caste.index]
end end
function hackWish(posOrUnit) function hackWish(unit)
local pos = df.unit:is_instance(posOrUnit) and posOrUnit.pos or posOrUnit
script.start(function() script.start(function()
--local amountok, amount local amountok, amount
local matok,mattype,matindex,matFilter 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) 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 if not args.notRestrictive then
@ -210,43 +181,43 @@ function hackWish(posOrUnit)
local descriptionok local descriptionok
descriptionok,description=script.showInputPrompt('Slab','What should the slab say?',COLOR_WHITE) descriptionok,description=script.showInputPrompt('Slab','What should the slab say?',COLOR_WHITE)
end end
--repeat amountok,amount=script.showInputPrompt('Wish','How many do you want? (numbers only!)',COLOR_LIGHTGREEN) until tonumber(amount) if args.multi then
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,unit,description)
end
end
else
if mattype and itemtype then if mattype and itemtype then
--for i=1,tonumber(amount) do createItem({mattype,matindex},{itemtype,itemsubtype},quality,unit,description)
createItem({mattype,matindex},{itemtype,itemsubtype},quality,pos,description) end
--end
end end
end) end)
end end
scriptArgs={...} scriptArgs={...}
args={} validArgs = validArgs or utils.invert({
'startup',
for k,v in ipairs(scriptArgs) do 'all',
v=v:lower() 'restrictive',
if v=='startup' then args.startup=true end 'unit',
if v=='all' then args.notRestrictive=true end 'multi'
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') utils=require('utils')
function posIsValid(pos) args = utils.processArgs({...}, validArgs)
return pos.x~=-30000 and pos or false
end eventful=require('plugins.eventful')
if not args.startup then 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) local unit=args.unit and df.unit.find(args.unit) or dfhack.gui.getSelectedUnit(true)
hackWish(posOrUnit) hackWish(unit)
else else
eventful.onReactionComplete.hackWishP=function(reaction,unit,input_items,input_reagents,output_items, call_native) 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 if not reaction.code:find('DFHACK_WISH') then return nil end
hackWish(unit) hackWish(unit)
end end
end end

@ -34,7 +34,7 @@ function fileExists(filename)
end end
end end
if not fileExists(init_file) then if not fileExists(init_file) then
local initFile=io.open(initFileName,"a") local initFile=io.open(init_file,"a")
initFile:close() initFile:close()
end end
function copyFile(from,to) --oh so primitive function copyFile(from,to) --oh so primitive
@ -52,15 +52,15 @@ function patchInit(initFileName,patch_guard,code)
code,patch_guard[2])) code,patch_guard[2]))
initFile:close() initFile:close()
end end
function patchDofile( initFileName,patch_guard,dofile_list ) function patchDofile( luaFileName,patch_guard,dofile_list,mod_path )
local initFile=io.open(initFileName,"a") local luaFile=io.open(luaFileName,"a")
initFile:write(patch_guard[1].."\n") luaFile:write(patch_guard[1].."\n")
for _,v in ipairs(dofile_list) do for _,v in ipairs(dofile_list) do
local fixed_path=mod_dir:gsub("\\","/") local fixed_path=mod_path:gsub("\\","/")
initFile:write(string.format("dofile('%s/%s')\n",fixed_path,v)) luaFile:write(string.format("dofile('%s/%s')\n",fixed_path,v))
end end
initFile:write(patch_guard[2].."\n") luaFile:write(patch_guard[2].."\n")
initFile:close() luaFile:close()
end end
function patchFile(file_name,patch_guard,after_string,code) function patchFile(file_name,patch_guard,after_string,code)
local input_lines=patch_guard[1].."\n"..code.."\n"..patch_guard[2] local input_lines=patch_guard[1].."\n"..code.."\n"..patch_guard[2]
@ -294,7 +294,7 @@ function manager:install(trgMod,force)
patchInit(init_file,trgMod.guard_init,trgMod.patch_init) patchInit(init_file,trgMod.guard_init,trgMod.patch_init)
end end
if trgMod.patch_dofile then if trgMod.patch_dofile then
patchDofile(init_file,trgMod.guard_init,trgMod.patch_dofile) patchDofile(init_file,trgMod.guard_init,trgMod.patch_dofile,trgMod.path)
end end
trgMod.installed=true trgMod.installed=true