local gui = require 'gui' local dlg = require 'gui.dialogs' local cursor=xyz2pos(df.global.cursor.x,df.global.cursor.y,df.global.cursor.z) local permited_equips={} permited_equips[df.item_backpackst]="UPPERBODY" permited_equips[df.item_flaskst]="UPPERBODY" permited_equips[df.item_armorst]="UPPERBODY" permited_equips[df.item_shoesst]="STANCE" permited_equips[df.item_glovesst]="GRASP" permited_equips[df.item_helmst]="HEAD" permited_equips[df.item_pantsst]="LOWERBODY" function DoesHaveSubtype(item) if df.item_backpackst:is_instance(item) or df.item_flaskst:is_instance(item) then return false end return true end function CheckCursor(p) if p.x==-30000 then dlg.showMessage( 'Companion orders', 'You must have a cursor on some tile!', COLOR_LIGHTRED ) return false end return true end function GetCaste(race_id,caste_id) local race=df.creature_raw.find(race_id) return race.caste[caste_id] end function EnumBodyEquipable(race_id,caste_id) local caste=GetCaste(race_id,caste_id) local bps=caste.body_info.body_parts local ret={} for k,v in pairs(bps) do ret[k]={bp=v,layers={[0]={size=0,permit=0},[1]={size=0,permit=0},[2]={size=0,permit=0},[3]={size=0,permit=0} } } end return ret end function ReadCurrentEquiped(body_equip,unit) for k,v in pairs(unit.inventory) do if v.mode==2 then local bpid=v.body_part_id if DoesHaveSubtype(v.item) then local sb=v.item.subtype.props local trg=body_equip[bpid] local trg_layer=trg.layers[sb.layer] if trg_layer.permit==0 then trg_layer.permit=sb.layer_permit else if trg_layer.permit>sb.layer_permit then trg_layer.permit=sb.layer_permit end end trg_layer.size=trg_layer.size+sb.layer_size end end end end function LayeringPermits(body_part,item) if not DoesHaveSubtype(item) then return true end local sb=item.subtype.props local trg_layer=body_part.layers[sb.layer] if math.min(trg_layer.permit ,sb.layer_permit)0 and #items>0 do if(dfhack.items.moveToInventory(items[#items],v,1,grasps[#grasps])) then table.remove(grasps) end table.remove(items) end local backpack=GetBackpack(v) if backpack then while #items>0 do dfhack.items.moveToContainer(items[#items],backpack) table.remove(items) end end end return true end}, {name="unequip",f=function (unit_list) --remove and drop all the stuff (todo maybe a gui too?) for k,v in pairs(unit_list) do while #v.inventory ~=0 do dfhack.items.moveToGround(v.inventory[0].item,v.pos) end end return true end}, --[=[ {name="roam not working :<",f=function (unit_list,pos,dist) --does not work if not CheckCursor(pos) then return false end dist=dist or 5 for k,v in pairs(unit_list) do v.idle_area:assign(pos) v.idle_area_threshold=dist end return true end}, --]=] {name="wait",f=function (unit_list) for k,v in pairs(unit_list) do v.relations.group_leader_id=-1 end return true end}, {name="follow",f=function (unit_list) local adv=df.global.world.units.active[0] for k,v in pairs(unit_list) do v.relations.group_leader_id=adv.id end return true end}, {name="leave",f=function (unit_list) local adv=df.global.world.units.active[0] local t_nem=dfhack.units.getNemesis(adv) for k,v in pairs(unit_list) do v.relations.group_leader_id=-1 local u_nem=dfhack.units.getNemesis(v) if u_nem then u_nem.group_leader_id=-1 end if t_nem and u_nem then for k,v in pairs(t_nem.companions) do if v==u_nem.id then t_nem.companions:erase(k) break end end end end return true end}, } local cheats={} --[[ todo: add cheats...]]-- function getCompanions(unit) unit=unit or df.global.world.units.active[0] local t_nem=dfhack.units.getNemesis(unit) if t_nem==nil then qerror("Invalid unit! No nemesis record") end local ret={} for k,v in pairs(t_nem.companions) do local u=df.nemesis_record.find(v) if u.unit then table.insert(ret,u.unit) end end return ret end CompanionUi=defclass(CompanionUi,gui.FramedScreen) CompanionUi.ATTRS{ frame_title = "Companions", } function CompanionUi:init(args) self.unit_list=args.unit_list self.selected={} for i=0,26 do self.selected[i]=true end end function CompanionUi:GetSelectedUnits() local ret={} for k,v in pairs(self.unit_list) do if self.selected[k] then table.insert(ret,v) end end return ret end function CompanionUi:onInput(keys) if keys.LEAVESCREEN then self:dismiss() elseif keys._STRING then local s=keys._STRING if s==string.byte('*') then local v=self.selected[1] or false for i=0,26 do self.selected[i]=not v end end if s>=string.byte('a') and s<=string.byte('z') then local idx=s-string.byte('a')+1 if self.selected[idx] then self.selected[idx]=false else self.selected[idx]=true end end if s>=string.byte('A') and s<=string.byte('Z') then local idx=s-string.byte('A')+1 if orders[idx] and orders[idx].f then if orders[idx].f(self:GetSelectedUnits(),cursor) then self:dismiss() end end --do order end end end function CompanionUi:onRenderBody( dc) --list widget goes here... local char_a=string.byte('a')-1 dc:newline(1):string("*. All") for k,v in ipairs(self.unit_list) do if self.selected[k] then dc:pen(COLOR_GREEN) else dc:pen(COLOR_GREY) end dc:newline(1):string(string.char(k+char_a)..". "):string(dfhack.TranslateName(v.name)); end dc:pen(COLOR_GREY) local w,h=self:getWindowSize() local char_A=string.byte('A')-1 for k,v in ipairs(orders) do dc:seek(w/2,k):string(string.char(k+char_A)..". "):string(v.name); end end local screen=CompanionUi{unit_list=getCompanions()} screen:show()