diff options
| author | Kelly Martin | 2012-09-22 13:07:00 -0500 |
|---|---|---|
| committer | Kelly Martin | 2012-09-22 13:07:00 -0500 |
| commit | b0bec4c4d4daa732f3845ce1350c1e892cc4a553 (patch) | |
| tree | 853c6fad7be30ea50710c7da50ca85c4dee4f510 /scripts | |
| parent | ebd4b94c2d26f18bfde389fed910eb69dccd7ced (diff) | |
| parent | 825d21c91a24f7f95bf05ad10b54845054a36411 (diff) | |
| download | dfhack-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.lua | 96 | ||||
| -rw-r--r-- | scripts/devel/inject-raws.lua | 178 | ||||
| -rw-r--r-- | scripts/gui/rename.lua | 10 | ||||
| -rw-r--r-- | scripts/gui/siege-engine.lua | 4 | ||||
| -rw-r--r-- | scripts/siren.lua | 109 |
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 +) |
