--script using warmist spellbook code to make a cheap gui for expanding and contracting a player fort.
-- this script is pretty dangerous in that it reveals the expanded map chunk, and when contracting it culls anyone in that map chunk.
-- so far probably best to use this with the void fort scripts as it allows one to expand and explore the world while keeping your site.
--oh warning if you're about to collapse a map chunk make sure to clear any stockpiles and civ zones you made in that map chunk.
--oh and don't retire unless you're back to the original fort embark size or the game will corrupt that fort and or crash.
--also it will take a while for any results to happen. I have no idea on speeding up the process.
--:edit 7/7/2023 this version of nomad script speeds up the process instantly due to messing with cur_season_ticks
--if you use this for some nomad playstyle best learn how to haul goods across map and burrowing folks.
--as you might lose folks while traveling.
local dlg=require("gui.dialogs")
function GoN()
local Site=df.global.plotinfo.main.fortress_site
local Nor=Site.global_min_y-1
Site.global_min_y=Nor
df.global.cur_season_tick=3999
end
function NoN()
local Site=df.global.plotinfo.main.fortress_site
local Nor=Site.global_min_y+1
Site.global_min_y=Nor
df.global.cur_season_tick=3999
end
function GoS()
local Site=df.global.plotinfo.main.fortress_site
local Sor=Site.global_max_y+1
Site.global_max_y=Sor
df.global.cur_season_tick=3999
end
function NoS()
local Site=df.global.plotinfo.main.fortress_site
local Sor=Site.global_max_y-1
Site.global_max_y=Sor
df.global.cur_season_tick=3999
end
function GoE()
local Site=df.global.plotinfo.main.fortress_site
local Eor=Site.global_max_x+1
Site.global_max_x=Eor
df.global.cur_season_tick=3999
end
function NoE()
local Site=df.global.plotinfo.main.fortress_site
local Eor=Site.global_max_x-1
Site.global_max_x=Eor
df.global.cur_season_tick=3999
end
function GoW()
local Site=df.global.plotinfo.main.fortress_site
local Wor=Site.global_min_x-1
Site.global_min_x=Wor
df.global.cur_season_tick=3999
end
function NoW()
local Site=df.global.plotinfo.main.fortress_site
local Wor=Site.global_min_x+1
Site.global_min_x=Wor
df.global.cur_season_tick=3999
end
function Go()
for k,v in pairs(df.global.world.armies.all) do
if v.flags[0]== true then
local Nor=v.pos.y-1
v.pos.y=Nor
df.global.cur_season_tick=3999
end
end
end
function doNothing()
print("doing nothing real good but here have a site")
--require("plugins.dfusion.adv_tools").addSite(nil,nil,nil,nil,nil,nil,df.global.world.units.active[0].civ_id)
end
function doNothing2()
dlg.showMessage("Travel-Hack","Bypassing Message to access FastTravel")
df.global.ui_advmode.message=""
--require("plugins.dfusion.adv_tools").addSite(nil,nil,nil,nil,nil,nil,df.global.world.units.active[0].civ_id)
end
function greetAndStuff()
dlg.showMessage("Greetings", "Seasons greatings and lols")
end
MOVEMENT_KEYS = {
A_CARE_MOVE_N = { 0, -1, 0 }, A_CARE_MOVE_S = { 0, 1, 0 },
A_CARE_MOVE_W = { -1, 0, 0 }, A_CARE_MOVE_E = { 1, 0, 0 },
A_CARE_MOVE_NW = { -1, -1, 0 }, A_CARE_MOVE_NE = { 1, -1, 0 },
A_CARE_MOVE_SW = { -1, 1, 0 }, A_CARE_MOVE_SE = { 1, 1, 0 },
--[[A_MOVE_N = { 0, -1, 0 }, A_MOVE_S = { 0, 1, 0 },
A_MOVE_W = { -1, 0, 0 }, A_MOVE_E = { 1, 0, 0 },
A_MOVE_NW = { -1, -1, 0 }, A_MOVE_NE = { 1, -1, 0 },
A_MOVE_SW = { -1, 1, 0 }, A_MOVE_SE = { 1, 1, 0 },--]]
A_CUSTOM_CTRL_D = { 0, 0, -1 },
A_CUSTOM_CTRL_E = { 0, 0, 1 },
CURSOR_UP_Z_AUX = { 0, 0, 1 }, CURSOR_DOWN_Z_AUX = { 0, 0, -1 },
A_MOVE_SAME_SQUARE={0,0,0},
SELECT={0,0,0},
}
ALLOWED_KEYS={
A_MOVE_N=true,A_MOVE_S=true,A_MOVE_W=true,A_MOVE_E=true,A_MOVE_NW=true,
A_MOVE_NE=true,A_MOVE_SW=true,A_MOVE_SE=true,A_STANCE=true,SELECT=true,A_MOVE_DOWN_AUX=true,
A_MOVE_UP_AUX=true,A_LOOK=true,CURSOR_DOWN=true,CURSOR_UP=true,CURSOR_LEFT=true,CURSOR_RIGHT=true,
CURSOR_UPLEFT=true,CURSOR_UPRIGHT=true,CURSOR_DOWNLEFT=true,CURSOR_DOWNRIGHT=true,A_CLEAR_ANNOUNCEMENTS=true,
CURSOR_UP_Z=true,CURSOR_DOWN_Z=true,
}
listofspells={
{text="nothing", spell=doNothing,icon='*'},
{text="expand: North+", spell=GoN,key="CUSTOM_W"},
{text="expand: South+", spell=GoS,key="CUSTOM_S"},
{text="expand: East+", spell=GoE,key="CUSTOM_D"},
{text="expand: West+", spell=GoW,key="CUSTOM_A"},
{text="Contract: North-", spell=NoN,key="CUSTOM_T"},
{text="Contract: South-", spell=NoS,key="CUSTOM_G"},
{text="Contract: East-", spell=NoE,key="CUSTOM_H"},
{text="Contract: West-", spell=NoW,key="CUSTOM_F"},
}
dlg.showListPrompt("Directions","Choze Direct",nil, listofspells,function(index,choice) choice.spell() end)
ok so here's an updated version of nomad now with less waiting all thanks to cur_season_tick being set to 3999 and letting time progress to 4000
this does mean going through nomad fast might require seeing what happens if you mess with seasonal timers.
also here's an liquids gui edit for future proofing scripts with
the personal keyboard cursor gui script
--keyboard cursor that uses the widget of gui/liquids as I don't know how to write widgets
--proof of concept for adding an extra keyboard cursor to df50 that doesn't rely on mining tools.
local gui = require('gui')
local guidm = require('gui.dwarfmode')
local widgets = require('gui.widgets')
local SpawnLiquidCursor = {
[df.tile_liquid.Water] = dfhack.screen.findGraphicsTile('MINING_INDICATORS', 0, 0),
[df.tile_liquid.Magma] = dfhack.screen.findGraphicsTile('MINING_INDICATORS', 1, 0),
[df.tiletype.RiverSource] = dfhack.screen.findGraphicsTile('LIQUIDS', 0, 0),
}
SpawnLiquid = defclass(SpawnLiquid, widgets.Window)
SpawnLiquid.ATTRS {
frame_title='Cursor Keyboard menu',
frame={b = 4, r = 4, w = 50, h = 12},
}
function SpawnLiquid:init()
self.type = df.tile_liquid.Water
self.tile = SpawnLiquidCursor[self.type]
self:addviews{
widgets.Label{
frame = {l = 0, t = 0},
text = {{ text = self:callback('getLabel') }}
},
widgets.HotkeyLabel{
frame = {l = 0, b = 1},
label = 'does nothing',
auto_width = true,
key = 'KEYBOARD_CURSOR_LEFT',
on_activate = self:callback('moveleft'),
disabled = function() return self.level == 1 end
},
widgets.HotkeyLabel{
frame = { l = 19, b = 1},
label = 'also Does nothing',
auto_width = true,
key = 'KEYBOARD_CURSOR_RIGHT',
on_activate = self:callback('moveright'),
disabled = function() return self.level == 7 end
},
widgets.HotkeyLabel{
frame = { l = 19, b = 1},
label = 'also Does nothing',
auto_width = true,
key = 'KEYBOARD_CURSOR_UP',
on_activate = self:callback('moveup'),
disabled = function() return self.level == 7 end
},
widgets.HotkeyLabel{
frame = { l = 19, b = 1},
label = 'also Does nothing',
auto_width = true,
key = 'KEYBOARD_CURSOR_DOWN',
on_activate = self:callback('movedown'),
disabled = function() return self.level == 7 end
},
widgets.CycleHotkeyLabel{
frame = {l = 0, b = 2},
label = 'cursor color:',
auto_width = true,
key = 'CUSTOM_Q',
options = {
{ label = "Water", value = df.tile_liquid.Water, pen = COLOR_CYAN },
{ label = "Magma", value = df.tile_liquid.Magma, pen = COLOR_RED },
{ label = "River", value = df.tiletype.RiverSource, pen = COLOR_BLUE },
},
initial_option = 0,
on_change = function(new, _)
self.type = new
self.tile = SpawnLiquidCursor[new]
end,
},
}
end
-- TODO: More reactive label dependant on options selected.
function SpawnLiquid:getLabel()
return ([[Click on a tile to spawn a %s/7 level of %s]]):format(
self.level,
self.type == 0 and "Water" or self.type == 1 and "Magma" or "River"
)
end
function SpawnLiquid:getLiquidLevel(position)
local tile = dfhack.maps.getTileFlags(position)
if self.mode == SpawnLiquidMode.ADD then
return math.max(0, math.min(tile.flow_size + self.level, 7))
elseif self.mode == SpawnLiquidMode.REMOVE then
return math.max(0, math.min(tile.flow_size - self.level, 7))
end
return self.level
end
function SpawnLiquid:increaseLiquidLevel()
self.level = math.min(self.level + 1, 7)
end
function SpawnLiquid:decreaseLiquidLevel()
self.level = math.max(self.level - 1, 1)
end
function SpawnLiquid:moveleft()
local move=df.global.cursor
move.x=move.x-1
end
function SpawnLiquid:moveright()
local move=df.global.cursor
move.x=move.x+1
end
function SpawnLiquid:moveup()
local move=df.global.cursor
move.y=move.y-1
end
function SpawnLiquid:movedown()
local move=df.global.cursor
move.y=move.y+1
end
function SpawnLiquid:spawn(pos)
--local MapCure=df.global.gview.view.child
mouse_pos = dfhack.gui.getMousePos()
df.global.cursor.x=mouse_pos.x
df.global.cursor.y=mouse_pos.y
df.global.cursor.z=mouse_pos.z
end
function SpawnLiquid:getPen()
return self.type == df.tile_liquid.Water and COLOR_BLUE or COLOR_RED, "X", self.tile
end
function SpawnLiquid:getBounds(start_position, end_position)
return {
x1=math.min(start_position.x, end_position.x),
x2=math.max(start_position.x, end_position.x),
y1=math.min(start_position.y, end_position.y),
y2=math.max(start_position.y, end_position.y),
z1=math.min(start_position.z, end_position.z),
z2=math.max(start_position.z, end_position.z),
}
end
function SpawnLiquid:onRenderFrame(dc, rect)
SpawnLiquid.super.onRenderFrame(self, dc, rect)
local mouse_pos = dfhack.gui.getMousePos()
if self.is_dragging then
if df.global.enabler.mouse_lbut == 0 then
self.is_dragging = false
elseif mouse_pos and not self:getMouseFramePos() then
self:spawn(mouse_pos)
end
end
guidm.renderMapOverlay(self:callback('getPen'), self:getBounds(
self.area_first_pos or df.global.cursor, df.global.cursor
))
end
function SpawnLiquid:onInput(keys)
if SpawnLiquid.super.onInput(self, keys) then return true end
if keys._MOUSE_L_DOWN and not self:getMouseFramePos() then
local mouse_pos = dfhack.gui.getMousePos()
self:spawn()
end
end
SpawnLiquidScreen = defclass(SpawnLiquidScreen, gui.ZScreen)
SpawnLiquidScreen.ATTRS {
focus_path = 'spawnliquid',
pass_movement_keys = true,
pass_mouse_clicks = false,
force_pause = true,
}
function SpawnLiquidScreen:init()
self:addviews{SpawnLiquid{}}
end
function SpawnLiquidScreen:onDismiss()
view = nil
end
view = view and view:raise() or SpawnLiquidScreen{}:show()
oh and here's a script for telling where you are on the global min x and y coords of the site you're on the info shown is going off the top left corner of the map to the bottom right it probably best to not use this after changing the site's coords as the script looks at the site's current global min and max coords to get the second info from for the folks who dip into gui gm-editoring as their means to nomad around the world.
oh and this only works if the wagon is named Nomad as do most of my nomad scripts as it grabs the wagon's coords to check where it is on the game field embark space wise.
function wagon(curx,cury,curz)
for de,oe in pairs(df.global.world.buildings.other.WAGON) do
if oe.name == 'Nomad' then
local regionx=math.floor(oe.centerx/47)
local regiony=math.floor(oe.centery/47)
print("X region", regionx,
"Y region", regiony)
local site=df.global.plotinfo.main.fortress_site
print("X region + min", regionx + site.global_min_x,
"Y region + min", regiony + site.global_min_y )
end
end
end
wagon()
I think this is prime for folks to fully explore the worlds with their fort citizens... combine this with that force petition script and you could play out series of oregon trail like sessions.
usually with the nomad scripts
oh and uhh if you leave your starting location and you dig out a bunch of stuff in the process the game will undo any changes you did on a digging and construction wise, buildings are safe though. folks stored in cages that are stored in the wagon will stay in the wagon while you travel around the world.
getting mayors and nobles who like to stay in a room would make nomad playstyle a bit rough as you would be building up and tearing down their rooms while you prep to travel to a new location.
this playstyle does open up to some different challenges one could take on like the no-build run where you just strip mine the land and harvest the fields to trek to one of the dwarven fortress entrances that houses all workshops for you to use.
this also means no trading until you get to a trade depot this challenge is probably more rough if you play it with dwarves as the strange mood would mean ditching the dwarf to avoid the mood hit or dealing with staying at the dwarven fortress entrance longer for hoping to get that artifact built.
I just realize folks could build a magma pump that leads to a tunnel that pours the magma into the ocean to make an island then just settle their group on the island... and probably with a lil extra void fort set up sail the seas on their remote obsidian casts landmass and harvest all the fish from the sea.