Add a couple of useful scripts and fix two missing NULL checks.
- A script to unstick jobs trying to build walls from the same tile. - A devel script for viewing the path a unit is currently following.develop
							parent
							
								
									4b8760815d
								
							
						
					
					
						commit
						6bef167f83
					
				| @ -0,0 +1,210 @@ | ||||
| -- Show the internal path a unit is currently following. | ||||
| 
 | ||||
| local utils = require 'utils' | ||||
| local gui = require 'gui' | ||||
| local guidm = require 'gui.dwarfmode' | ||||
| local dlg = require 'gui.dialogs' | ||||
| 
 | ||||
| local tile_attrs = df.tiletype.attrs | ||||
| 
 | ||||
| UnitPathUI = defclass(UnitPathUI, guidm.MenuOverlay) | ||||
| 
 | ||||
| UnitPathUI.focus_path = 'unit-path' | ||||
| 
 | ||||
| UnitPathUI.ATTRS { | ||||
|     unit = DEFAULT_NIL, | ||||
| } | ||||
| 
 | ||||
| function UnitPathUI:init() | ||||
|     self.saved_mode = df.global.ui.main.mode | ||||
| 
 | ||||
| end | ||||
| 
 | ||||
| function UnitPathUI:onShow() | ||||
|     -- with cursor, but without those ugly lines from native hauling mode | ||||
|     df.global.ui.main.mode = df.ui_sidebar_mode.Stockpiles | ||||
| end | ||||
| 
 | ||||
| function UnitPathUI:onDestroy() | ||||
|     self:moveCursorTo(copyall(self.unit.pos)) | ||||
|     df.global.ui.main.mode = self.saved_mode | ||||
| end | ||||
| 
 | ||||
| local function getTileType(cursor) | ||||
|     local block = dfhack.maps.getTileBlock(cursor) | ||||
|     if block then | ||||
|         return block.tiletype[cursor.x%16][cursor.y%16] | ||||
|     else | ||||
|         return 0 | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| local function getTileWalkable(cursor) | ||||
|     local block = dfhack.maps.getTileBlock(cursor) | ||||
|     if block then | ||||
|         return block.walkable[cursor.x%16][cursor.y%16] | ||||
|     else | ||||
|         return 0 | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| local function paintMapTile(dc, vp, cursor, pos, ...) | ||||
|     if not same_xyz(cursor, pos) then | ||||
|         local stile = vp:tileToScreen(pos) | ||||
|         if stile.z == 0 then | ||||
|             dc:seek(stile.x,stile.y):char(...) | ||||
|         end | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| local function get_path_point(gpath,i) | ||||
|     return xyz2pos(gpath.x[i], gpath.y[i], gpath.z[i]) | ||||
| end | ||||
| 
 | ||||
| function UnitPathUI:renderPath(dc,vp,cursor) | ||||
|     local gpath = self.unit.path.path | ||||
|     local startp = self.unit.pos | ||||
|     local endp = self.unit.path.dest | ||||
|     local visible = gui.blink_visible(500) | ||||
| 
 | ||||
|     if visible then | ||||
|         paintMapTile(dc, vp, cursor, endp, '+', COLOR_LIGHTGREEN) | ||||
|     end | ||||
| 
 | ||||
|     local ok = nil | ||||
|     local pcnt = #gpath.x | ||||
|     if pcnt > 0 then | ||||
|         ok = true | ||||
| 
 | ||||
|         for i = 0,pcnt-1 do | ||||
|             local pt = get_path_point(gpath, i) | ||||
|             if i == 0 and not same_xyz(startp,pt) then | ||||
|                 ok = false | ||||
|             end | ||||
|             if i == pcnt-1 and not same_xyz(endp,pt) then | ||||
|                 ok = false | ||||
|             end | ||||
|             --[[local tile = getTileType(pt) | ||||
|             if not isTrackTile(tile) then | ||||
|                 ok = false | ||||
|             end]] | ||||
|             if visible then | ||||
|                 local char = '+' | ||||
|                 if i < pcnt-1 then | ||||
|                     local npt = get_path_point(gpath, i+1) | ||||
|                     if npt.z == pt.z+1 then | ||||
|                         char = 30 | ||||
|                     elseif npt.z == pt.z-1 then | ||||
|                         char = 31 | ||||
|                     elseif npt.x == pt.x+1 then | ||||
|                         char = 26 | ||||
|                     elseif npt.x == pt.x-1 then | ||||
|                         char = 27 | ||||
|                     elseif npt.y == pt.y+1 then | ||||
|                         char = 25 | ||||
|                     elseif npt.y == pt.y-1 then | ||||
|                         char = 24 | ||||
|                     end | ||||
|                 end | ||||
|                 local color = COLOR_LIGHTGREEN | ||||
|                 if getTileWalkable(pt) == 0 then color = COLOR_LIGHTRED end | ||||
|                 paintMapTile(dc, vp, cursor, pt, char, color) | ||||
|             end | ||||
|         end | ||||
|     end | ||||
| 
 | ||||
|     if gui.blink_visible(120) then | ||||
|         paintMapTile(dc, vp, cursor, startp, 240, COLOR_LIGHTGREEN, COLOR_GREEN) | ||||
|     end | ||||
| 
 | ||||
|     return ok | ||||
| end | ||||
| 
 | ||||
| function UnitPathUI:onRenderBody(dc) | ||||
|     dc:clear():seek(1,1):pen(COLOR_WHITE):string("Unit Path") | ||||
| 
 | ||||
|     local prof = dfhack.units.getProfessionName(self.unit) | ||||
|     local name = dfhack.units.getVisibleName(self.unit) | ||||
| 
 | ||||
|     dc:seek(2,3):pen(COLOR_BLUE):string(prof) | ||||
|     if name and name.has_name then | ||||
|         dc:seek(2,4):pen(COLOR_BLUE):string(dfhack.TranslateName(name)) | ||||
|     end | ||||
| 
 | ||||
|     local cursor = guidm.getCursorPos() | ||||
|     local has_path = #self.unit.path.path.x>0 | ||||
| 
 | ||||
|     local vp = self:getViewport() | ||||
|     local mdc = gui.Painter.new(self.df_layout.map) | ||||
| 
 | ||||
|     if not has_path then | ||||
|         if gui.blink_visible(120) then | ||||
|             paintMapTile(mdc, vp, cursor, self.unit.pos, 15, COLOR_LIGHTRED, COLOR_RED) | ||||
|         end | ||||
| 
 | ||||
|         dc:seek(1,6):pen(COLOR_RED):string('Not following path') | ||||
|     else | ||||
|         self:renderPath(mdc,vp,cursor) | ||||
| 
 | ||||
|         dc:seek(1,6):pen(COLOR_GREEN):string(df.unit_path_goal[self.unit.path.goal]) | ||||
|     end | ||||
| 
 | ||||
|     dc:newline():pen(COLOR_GREY) | ||||
|     dc:newline(2):string('Speed: '..dfhack.units.computeMovementSpeed(self.unit)) | ||||
|     dc:newline(2):string('Slowdown: '..dfhack.units.computeSlowdownFactor(self.unit)) | ||||
| 
 | ||||
|     dc:newline():newline(1) | ||||
| 
 | ||||
|     local has_station = self.unit.idle_area_type >= 0 | ||||
| 
 | ||||
|     if has_station then | ||||
|         if gui.blink_visible(250) then | ||||
|             paintMapTile(mdc, vp, cursor, self.unit.idle_area, 21, COLOR_LIGHTCYAN) | ||||
|         end | ||||
| 
 | ||||
|         dc:pen(COLOR_GREEN):string(df.unit_station_type[self.unit.idle_area_type]) | ||||
|         dc:newline():newline(2):pen(COLOR_GREY):string('Threshold: '..self.unit.idle_area_threshold) | ||||
|     else | ||||
|         dc:pen(COLOR_RED):string('No station'):newline():newline(2) | ||||
|     end | ||||
| 
 | ||||
|     dc:newline():newline(1):string('At cursor:') | ||||
|     dc:newline():newline(2) | ||||
| 
 | ||||
|     local tile = getTileType(cursor) | ||||
|     dc:string(df.tiletype[tile],COLOR_CYAN) | ||||
| 
 | ||||
|     dc:newline():newline(1):pen(COLOR_WHITE) | ||||
|     dc:key('CUSTOM_Z'):string(": Zoom unit, ") | ||||
|     dc:key('CUSTOM_G'):string(": Zoom goal",COLOR_GREY,nil,has_path) | ||||
|     dc:newline(1) | ||||
|     dc:key('CUSTOM_N'):string(": Zoom station",COLOR_GREY,nil,has_station) | ||||
|     dc:newline():newline(1) | ||||
|     dc:key('LEAVESCREEN'):string(": Back") | ||||
| end | ||||
| 
 | ||||
| function UnitPathUI:onInput(keys) | ||||
|     if keys.CUSTOM_Z then | ||||
|         self:moveCursorTo(copyall(self.unit.pos)) | ||||
|     elseif keys.CUSTOM_G then | ||||
|         if #self.unit.path.path.x > 0 then | ||||
|             self:moveCursorTo(copyall(self.unit.path.dest)) | ||||
|         end | ||||
|     elseif keys.CUSTOM_N then | ||||
|         if self.unit.idle_area_type > 0 then | ||||
|             self:moveCursorTo(copyall(self.unit.idle_area)) | ||||
|         end | ||||
|     elseif keys.LEAVESCREEN then | ||||
|         self:dismiss() | ||||
|     elseif self:propagateMoveKeys(keys) then | ||||
|         return | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| local unit = dfhack.gui.getSelectedUnit(true) | ||||
| 
 | ||||
| if not unit or not string.match(dfhack.gui.getCurFocus(), '^dwarfmode/ViewUnits/Some/') then | ||||
|     qerror("This script requires the main dwarfmode view in 'v' mode with a unit selected") | ||||
| end | ||||
| 
 | ||||
| UnitPathUI{ unit = unit }:show() | ||||
| @ -0,0 +1,37 @@ | ||||
| -- Lets constructions reconsider the build location. | ||||
| 
 | ||||
| -- Partial work-around for http://www.bay12games.com/dwarves/mantisbt/view.php?id=5991 | ||||
| 
 | ||||
| local utils = require('utils') | ||||
| 
 | ||||
| local count = 0 | ||||
| 
 | ||||
| for link,job in utils.listpairs(df.global.world.job_list) do | ||||
|     local job = link.item | ||||
|     local place = dfhack.job.getHolder(job) | ||||
| 
 | ||||
|     if job.job_type == df.job_type.ConstructBuilding | ||||
|     and place and place:isImpassableAtCreation() | ||||
|     and job.item_category[0] | ||||
|     then | ||||
|         local cpos = utils.getBuildingCenter(place) | ||||
| 
 | ||||
|         if same_xyz(cpos, job.pos) then | ||||
|             -- Reset the flag | ||||
|             job.item_category[0] = false | ||||
|             job.flags.suspend = false | ||||
| 
 | ||||
|             -- Mark the tile restricted traffic | ||||
|             local dsgn,occ = dfhack.maps.getTileFlags(cpos) | ||||
|             dsgn.traffic = df.tile_traffic.Restricted | ||||
| 
 | ||||
|             count = count + 1 | ||||
|         end | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| print('Found and unstuck '..count..' construct building jobs.') | ||||
| 
 | ||||
| if count > 0 then | ||||
|     df.global.process_jobs = true | ||||
| end | ||||
		Loading…
	
		Reference in New Issue