summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorKelly Martin2012-09-22 13:07:00 -0500
committerKelly Martin2012-09-22 13:07:00 -0500
commitb0bec4c4d4daa732f3845ce1350c1e892cc4a553 (patch)
tree853c6fad7be30ea50710c7da50ca85c4dee4f510 /scripts
parentebd4b94c2d26f18bfde389fed910eb69dccd7ced (diff)
parent825d21c91a24f7f95bf05ad10b54845054a36411 (diff)
downloaddfhack-b0bec4c4d4daa732f3845ce1350c1e892cc4a553.tar.gz
dfhack-b0bec4c4d4daa732f3845ce1350c1e892cc4a553.tar.bz2
dfhack-b0bec4c4d4daa732f3845ce1350c1e892cc4a553.tar.xz
Merge remote-tracking branch 'angavrilov/master'
Diffstat (limited to 'scripts')
-rw-r--r--scripts/devel/find-offsets.lua96
-rw-r--r--scripts/devel/inject-raws.lua178
-rw-r--r--scripts/gui/rename.lua10
-rw-r--r--scripts/gui/siege-engine.lua4
-rw-r--r--scripts/siren.lua109
5 files changed, 392 insertions, 5 deletions
diff --git a/scripts/devel/find-offsets.lua b/scripts/devel/find-offsets.lua
index 6fc12735..07a05847 100644
--- a/scripts/devel/find-offsets.lua
+++ b/scripts/devel/find-offsets.lua
@@ -803,6 +803,19 @@ end
-- cur_year_tick
--
+function stop_autosave()
+ if is_known 'd_init' then
+ local f = df.global.d_init.flags4
+ if f.AUTOSAVE_SEASONAL or f.AUTOSAVE_YEARLY then
+ f.AUTOSAVE_SEASONAL = false
+ f.AUTOSAVE_YEARLY = false
+ print('Disabled seasonal and yearly autosave.')
+ end
+ else
+ dfhack.printerr('Could not disable autosave!')
+ end
+end
+
local function find_cur_year_tick()
local zone
if os_type == 'windows' then
@@ -815,6 +828,8 @@ local function find_cur_year_tick()
return
end
+ stop_autosave()
+
local addr = zone:find_counter([[
Searching for cur_year_tick. Please exit to main dwarfmode
menu, then do as instructed below:]],
@@ -825,6 +840,79 @@ menu, then do as instructed below:]],
end
--
+-- cur_season_tick
+--
+
+function step_n_frames(cnt)
+ local world = df.global.world
+ local ctick = world.frame_counter
+ local more = ''
+ while world.frame_counter-ctick < cnt do
+ print(" Please step the game "..(cnt-world.frame_counter+ctick)..more.." frames.")
+ more = ' more'
+ if not utils.prompt_yes_no(' Done?', true) then
+ return nil
+ end
+ end
+ return world.frame_counter-ctick
+end
+
+local function find_cur_season_tick()
+ if not (is_known 'cur_year_tick') then
+ dfhack.printerr('Cannot search for cur_season_tick - prerequisites missing.')
+ return
+ end
+
+ stop_autosave()
+
+ local addr = searcher:find_interactive([[
+Searching for cur_season_tick. Please exit to main dwarfmode
+menu, then do as instructed below:]],
+ 'int32_t',
+ function(ccursor)
+ if ccursor > 0 then
+ if not step_n_frames(10) then
+ return false
+ end
+ end
+ return true, math.floor(((df.global.cur_year_tick+10)%100800)/10)
+ end
+ )
+ ms.found_offset('cur_season_tick', addr)
+end
+
+--
+-- cur_season
+--
+
+local function find_cur_season()
+ if not (is_known 'cur_year_tick' and is_known 'cur_season_tick') then
+ dfhack.printerr('Cannot search for cur_season - prerequisites missing.')
+ return
+ end
+
+ stop_autosave()
+
+ local addr = searcher:find_interactive([[
+Searching for cur_season. Please exit to main dwarfmode
+menu, then do as instructed below:]],
+ 'int8_t',
+ function(ccursor)
+ if ccursor > 0 then
+ local cst = df.global.cur_season_tick
+ df.global.cur_season_tick = 10079
+ df.global.cur_year_tick = df.global.cur_year_tick + (10079-cst)*10
+ if not step_n_frames(10) then
+ return false
+ end
+ end
+ return true, math.floor((df.global.cur_year_tick+10)/100800)%4
+ end
+ )
+ ms.found_offset('cur_season', addr)
+end
+
+--
-- process_jobs
--
@@ -839,6 +927,8 @@ end
local function find_process_jobs()
local zone = get_process_zone() or searcher
+ stop_autosave()
+
local addr = zone:find_menu_cursor([[
Searching for process_jobs. Please do as instructed below:]],
'int8_t',
@@ -856,6 +946,8 @@ end
local function find_process_dig()
local zone = get_process_zone() or searcher
+ stop_autosave()
+
local addr = zone:find_menu_cursor([[
Searching for process_dig. Please do as instructed below:]],
'int8_t',
@@ -879,6 +971,8 @@ local function find_pause_state()
end
zone = zone or searcher
+ stop_autosave()
+
local addr = zone:find_menu_cursor([[
Searching for pause_state. Please do as instructed below:]],
'int8_t',
@@ -930,6 +1024,8 @@ print('\nUnpausing globals:\n')
exec_finder(find_cur_year, 'cur_year')
exec_finder(find_cur_year_tick, 'cur_year_tick')
+exec_finder(find_cur_season_tick, 'cur_season_tick')
+exec_finder(find_cur_season, 'cur_season')
exec_finder(find_process_jobs, 'process_jobs')
exec_finder(find_process_dig, 'process_dig')
exec_finder(find_pause_state, 'pause_state')
diff --git a/scripts/devel/inject-raws.lua b/scripts/devel/inject-raws.lua
new file mode 100644
index 00000000..a4ebeec1
--- /dev/null
+++ b/scripts/devel/inject-raws.lua
@@ -0,0 +1,178 @@
+-- Injects new reaction, item and building defs into the world.
+
+-- The savegame contains a list of the relevant definition tokens in
+-- the right order, but all details are read from raws every time.
+-- This allows just adding stub definitions, and simply saving and
+-- reloading the game.
+
+local utils = require 'utils'
+
+local raws = df.global.world.raws
+
+print[[
+WARNING: THIS SCRIPT CAN PERMANENLY DAMAGE YOUR SAVE.
+
+This script attempts to inject new raw objects into your
+world. If the injected references do not match the actual
+edited raws, your save will refuse to load, or load but crash.
+]]
+
+if not utils.prompt_yes_no('Did you make a backup?') then
+ qerror('Not backed up.')
+end
+
+df.global.pause_state = true
+
+local changed = false
+
+function inject_reaction(name)
+ for _,v in ipairs(raws.reactions) do
+ if v.code == name then
+ print('Reaction '..name..' already exists.')
+ return
+ end
+ end
+
+ print('Injecting reaction '..name)
+ changed = true
+
+ raws.reactions:insert('#', {
+ new = true,
+ code = name,
+ name = 'Dummy reaction '..name,
+ index = #raws.reactions,
+ })
+end
+
+local building_types = {
+ workshop = { df.building_def_workshopst, raws.buildings.workshops },
+ furnace = { df.building_def_furnacest, raws.buildings.furnaces },
+}
+
+function inject_building(btype, name)
+ for _,v in ipairs(raws.buildings.all) do
+ if v.code == name then
+ print('Building '..name..' already exists.')
+ return
+ end
+ end
+
+ print('Injecting building '..name)
+ changed = true
+
+ local typeinfo = building_types[btype]
+
+ local id = raws.buildings.next_id
+ raws.buildings.next_id = id+1
+
+ raws.buildings.all:insert('#', {
+ new = typeinfo[1],
+ code = name,
+ name = 'Dummy '..btype..' '..name,
+ id = id,
+ })
+
+ typeinfo[2]:insert('#', raws.buildings.all[#raws.buildings.all-1])
+end
+
+local itemdefs = raws.itemdefs
+local item_types = {
+ weapon = { df.itemdef_weaponst, itemdefs.weapons, 'weapon_type' },
+ trainweapon = { df.itemdef_weaponst, itemdefs.weapons, 'training_weapon_type' },
+ pick = { df.itemdef_weaponst, itemdefs.weapons, 'digger_type' },
+ trapcomp = { df.itemdef_trapcompst, itemdefs.trapcomps, 'trapcomp_type' },
+ toy = { df.itemdef_toyst, itemdefs.toys, 'toy_type' },
+ tool = { df.itemdef_toolst, itemdefs.tools, 'tool_type' },
+ instrument = { df.itemdef_instrumentst, itemdefs.instruments, 'instrument_type' },
+ armor = { df.itemdef_armorst, itemdefs.armor, 'armor_type' },
+ ammo = { df.itemdef_ammost, itemdefs.ammo, 'ammo_type' },
+ siegeammo = { df.itemdef_siegeammost, itemdefs.siege_ammo, 'siegeammo_type' },
+ gloves = { df.itemdef_glovest, itemdefs.gloves, 'gloves_type' },
+ shoes = { df.itemdef_shoest, itemdefs.shoes, 'shoes_type' },
+ shield = { df.itemdef_shieldst, itemdefs.shields, 'shield_type' },
+ helm = { df.itemdef_helmst, itemdefs.helms, 'helm_type' },
+ pants = { df.itemdef_pantsst, itemdefs.pants, 'pants_type' },
+ food = { df.itemdef_foodst, itemdefs.food },
+}
+
+function add_to_civ(entity, bvec, id)
+ for _,v in ipairs(entity.resources[bvec]) do
+ if v == id then
+ return
+ end
+ end
+
+ entity.resources[bvec]:insert('#', id)
+end
+
+function add_to_dwarf_civs(btype, id)
+ local typeinfo = item_types[btype]
+ if not typeinfo[3] then
+ print('Not adding to civs.')
+ end
+
+ for _,entity in ipairs(df.global.world.entities.all) do
+ if entity.race == df.global.ui.race_id then
+ add_to_civ(entity, typeinfo[3], id)
+ end
+ end
+end
+
+function inject_item(btype, name)
+ for _,v in ipairs(itemdefs.all) do
+ if v.id == name then
+ print('Itemdef '..name..' already exists.')
+ return
+ end
+ end
+
+ print('Injecting item '..name)
+ changed = true
+
+ local typeinfo = item_types[btype]
+ local vec = typeinfo[2]
+ local id = #vec
+
+ vec:insert('#', {
+ new = typeinfo[1],
+ id = name,
+ subtype = id,
+ name = name,
+ name_plural = name,
+ })
+
+ itemdefs.all:insert('#', vec[id])
+
+ add_to_dwarf_civs(btype, id)
+end
+
+local args = {...}
+local mode = nil
+local ops = {}
+
+for _,kv in ipairs(args) do
+ if mode and string.match(kv, '^[%u_]+$') then
+ table.insert(ops, curry(mode, kv))
+ elseif kv == 'reaction' then
+ mode = inject_reaction
+ elseif building_types[kv] then
+ mode = curry(inject_building, kv)
+ elseif item_types[kv] then
+ mode = curry(inject_item, kv)
+ else
+ qerror('Invalid option: '..kv)
+ end
+end
+
+if #ops > 0 then
+ print('')
+ for _,v in ipairs(ops) do
+ v()
+ end
+end
+
+if changed then
+ print('\nNow without unpausing save and reload the game to re-read raws.')
+else
+ print('\nNo changes made.')
+end
diff --git a/scripts/gui/rename.lua b/scripts/gui/rename.lua
index a457a0bf..70a09b2f 100644
--- a/scripts/gui/rename.lua
+++ b/scripts/gui/rename.lua
@@ -13,10 +13,12 @@ local function verify_mode(expected)
end
end
-if string.match(focus, '^dwarfmode/QueryBuilding/Some') then
+local unit = dfhack.gui.getSelectedUnit(true)
+local building = dfhack.gui.getSelectedBuilding(true)
+
+if building and (not unit or mode == 'building') then
verify_mode('building')
- local building = df.global.world.selected_building
if plugin.canRenameBuilding(building) then
dlg.showInputPrompt(
'Rename Building',
@@ -30,9 +32,7 @@ if string.match(focus, '^dwarfmode/QueryBuilding/Some') then
'Cannot rename this type of building.', COLOR_LIGHTRED
)
end
-elseif dfhack.gui.getSelectedUnit(true) then
- local unit = dfhack.gui.getSelectedUnit(true)
-
+elseif unit then
if mode == 'unit-profession' then
dlg.showInputPrompt(
'Rename Unit',
diff --git a/scripts/gui/siege-engine.lua b/scripts/gui/siege-engine.lua
index c98cb167..f460bb21 100644
--- a/scripts/gui/siege-engine.lua
+++ b/scripts/gui/siege-engine.lua
@@ -74,6 +74,10 @@ function SiegeEngine:onDestroy()
end
end
+function SiegeEngine:onGetSelectedBuilding()
+ return df.global.world.selected_building
+end
+
function SiegeEngine:showCursor(enable)
local cursor = guidm.getCursorPos()
if cursor and not enable then
diff --git a/scripts/siren.lua b/scripts/siren.lua
new file mode 100644
index 00000000..5371e3d7
--- /dev/null
+++ b/scripts/siren.lua
@@ -0,0 +1,109 @@
+-- Wakes up the sleeping, breaks up parties and stops breaks.
+
+local utils = require 'utils'
+
+local args = {...}
+local burrows = {}
+local bnames = {}
+
+if not dfhack.isMapLoaded() then
+ qerror('Map is not loaded.')
+end
+
+for _,v in ipairs(args) do
+ local b = dfhack.burrows.findByName(v)
+ if not b then
+ qerror('Unknown burrow: '..v)
+ end
+ table.insert(bnames, v)
+ table.insert(burrows, b)
+end
+
+function is_in_burrows(pos)
+ if #burrows == 0 then
+ return true
+ end
+ for _,v in ipairs(burrows) do
+ if dfhack.burrows.isAssignedTile(v, pos) then
+ return true
+ end
+ end
+end
+
+function add_thought(unit, code)
+ for _,v in ipairs(unit.status.recent_events) do
+ if v.type == code then
+ v.age = 0
+ return
+ end
+ end
+
+ unit.status.recent_events:insert('#', { new = true, type = code })
+end
+
+function wake_unit(unit)
+ local job = unit.job.current_job
+ if not job or job.job_type ~= df.job_type.Sleep then
+ return
+ end
+
+ if job.completion_timer > 0 then
+ unit.counters.unconscious = 0
+ add_thought(unit, df.unit_thought_type.SleepNoiseWake)
+ elseif job.completion_timer < 0 then
+ add_thought(unit, df.unit_thought_type.Tired)
+ end
+
+ job.pos:assign(unit.pos)
+
+ job.completion_timer = 0
+
+ unit.path.dest:assign(unit.pos)
+ unit.path.path.x:resize(0)
+ unit.path.path.y:resize(0)
+ unit.path.path.z:resize(0)
+
+ unit.counters.job_counter = 0
+end
+
+function stop_break(unit)
+ local counter = dfhack.units.getMiscTrait(unit, df.misc_trait_type.OnBreak)
+ if counter then
+ counter.id = df.misc_trait_type.TimeSinceBreak
+ counter.value = 100800 - 30*1200
+ add_thought(unit, df.unit_thought_type.Tired)
+ end
+end
+
+-- Stop rest
+for _,v in ipairs(df.global.world.units.active) do
+ local x,y,z = dfhack.units.getPosition(v)
+ if x and not dfhack.units.isDead(v) and is_in_burrows(xyz2pos(x,y,z)) then
+ wake_unit(v)
+ stop_break(v)
+ end
+end
+
+-- Stop parties
+for _,v in ipairs(df.global.ui.parties) do
+ local pos = utils.getBuildingCenter(v.location)
+ if is_in_burrows(pos) then
+ v.timer = 0
+ for _, u in ipairs(v.units) do
+ add_thought(unit, df.unit_thought_type.Tired)
+ end
+ end
+end
+
+local place = 'the halls and tunnels'
+if #bnames > 0 then
+ if #bnames == 1 then
+ place = bnames[1]
+ else
+ place = table.concat(bnames,', ',1,#bnames-1)..' and '..bnames[#bnames]
+ end
+end
+dfhack.gui.showAnnouncement(
+ 'A loud siren sounds throughout '..place..', waking the sleeping and startling the awake.',
+ COLOR_BROWN, true
+)