diff --git a/NEWS.rst b/NEWS.rst index 7ccab0c54..714ae7e50 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -139,6 +139,10 @@ Removed ------- - DFusion: legacy script system, obsolete or replaced by better alternatives +New Scripts +----------- +- `modtools/extra-gamelog`: replaces ``log-region``, ``soundsense-season``, and ``soundsense`` + DFHack 0.40.24-r4 ================= diff --git a/dfhack.init-example b/dfhack.init-example index f2cf6b156..a367d3441 100644 --- a/dfhack.init-example +++ b/dfhack.init-example @@ -234,11 +234,8 @@ embark-tools enable sand mouse # Scripts # ########### -# write the correct season to gamelog on world load -soundsense-season - -# write identifying information about the fort to gamelog on world load -log-region +# write extra information to the gamelog +modtools/extra-gamelog enable # add information to item viewscreens view-item-info enable diff --git a/scripts/log-region.lua b/scripts/log-region.lua deleted file mode 100644 index 733b2aea6..000000000 --- a/scripts/log-region.lua +++ /dev/null @@ -1,50 +0,0 @@ --- On map load writes information about the loaded region to gamelog.txt --- By Kurik Amudnil and Warmist (http://www.bay12forums.com/smf/index.php?topic=91166.msg4467072#msg4467072) ---[[=begin - -log-region -========== -When enabled in :file:`dfhack.init`, each time a fort is loaded identifying information -will be written to the gamelog. Assists in parsing the file if you switch -between forts, and adds information for story-building. - -=end]] - -local function write_gamelog(msg) - local log = io.open('gamelog.txt', 'a') - log:write(msg.."\n") - log:close() -end - -local function fullname(item) - return dfhack.TranslateName(item.name)..' ('..dfhack.TranslateName(item.name ,true)..')' -end - -local args = {...} -if args[1] == 'disable' then - dfhack.onStateChange[_ENV] = nil -else - dfhack.onStateChange[_ENV] = function(op) - if op == SC_WORLD_LOADED then - if df.world_site.find(df.global.ui.site_id) ~= nil then -- added this check, now only attempts write in fort mode - local site = df.world_site.find(df.global.ui.site_id) - local fort_ent = df.global.ui.main.fortress_entity - local civ_ent = df.historical_entity.find(df.global.ui.civ_id) - local world = df.global.world - -- site positions - -- site .pos.x .pos.y - -- site .rgn_min_x .rgn_min_y .rgn_max_x .rgn_max.y - -- site .global_min_x .global_min_y .global_max_x .global_max_y - --site.name - --fort_ent.name - --civ_ent.name - - write_gamelog('Loaded '..world.cur_savegame.save_dir..', '..fullname(world.world_data).. - ' at coordinates ('..site.pos.x..','..site.pos.y..')'..NEWLINE.. - 'Loaded the fortress '..fullname(site).. - (fort_ent and ', colonized by the group '..fullname(fort_ent) or '').. - (civ_ent and ' of the civilization '..fullname(civ_ent) or '')..'.'..NEWLINE) - end - end - end -end diff --git a/scripts/modtools/extra-gamelog.lua b/scripts/modtools/extra-gamelog.lua new file mode 100644 index 000000000..47f39b574 --- /dev/null +++ b/scripts/modtools/extra-gamelog.lua @@ -0,0 +1,192 @@ +-- Regularly writes extra info to gamelog.txt +local help = [[=begin + +modtools/extra-gamelog +====================== +This script writes extra information to the gamelog. +This is useful for tools like :forums:`Soundsense <106497>`. + +=end]] + +msg = dfhack.gui.writeToGamelog + +function log_on_load(op) + if op ~= SC_WORLD_LOADED then return end + + -- Seasons fix for Soundsense + local seasons = { + [-1] = 'Nothing', -- worldgen + 'Spring', + 'Summer', + 'Autumn', + 'Winter'} + msg(seasons[df.global.cur_season]..' has arrived on the calendar.') + + -- Weather fix for Soundsense + local raining = false + local snowing = false + for _, row in ipairs(df.global.current_weather) do + for _, weather in ipairs(row) do + raining = raining or weather == 1 + snowing = snowing or weather == 2 + end + end + if (not snowing and not raining) then msg("The weather has cleared.") + elseif raining then msg("It has started raining.") + elseif snowing then msg("A snow storm has come.") + end + + -- Log site information for forts + if df.world_site.find(df.global.ui.site_id) == nil then return end + local site = df.world_site.find(df.global.ui.site_id) + local fort_ent = df.global.ui.main.fortress_entity + local civ_ent = df.historical_entity.find(df.global.ui.civ_id) + local function fullname(item) + return dfhack.TranslateName(item.name)..' ('..dfhack.TranslateName(item.name ,true)..')' + end + msg('Loaded '..df.global.world.cur_savegame.save_dir..', '..fullname(df.global.world.world_data).. + ' at coordinates ('..site.pos.x..','..site.pos.y..')') + msg('Loaded the fortress '..fullname(site).. + (fort_ent and ', colonized by the group '..fullname(fort_ent) or '').. + (civ_ent and ' of the civilization '..fullname(civ_ent)..'.' or '.')) +end + + +old_expedition_leader = nil +old_mayor = nil +function log_nobles() + local expedition_leader = nil + local mayor = nil + local function check(unit) + if not dfhack.units.isCitizen(unit) then return end + for _, pos in ipairs(dfhack.units.getNoblePositions(unit) or {}) do + if pos.position.name[0] == "expedition leader" then + expedition_leader = unit + elseif pos.position.name[0] == "mayor" then + mayor = unit + end + end + end + for _, unit in ipairs(df.global.world.units.active) do + check(unit) + end + + if old_mayor == nil and expedition_leader == nil and mayor ~= nil and old_expedition_leader ~= nil then + msg("Expedition leader was replaced by mayor.") + end + + if expedition_leader ~= old_expedition_leader then + if expedition_leader == nil then + msg("Expedition leader position is now vacant.") + else + msg(dfhack.TranslateName(dfhack.units.getVisibleName(expedition_leader)).." became expedition leader.") + end + end + + if mayor ~= old_mayor then + if mayor == nil then + msg("Mayor position is now vacant.") + else + msg(dfhack.TranslateName(dfhack.units.getVisibleName(mayor)).." became mayor.") + end + end + old_mayor = mayor + old_expedition_leader = expedition_leader +end + +siege = false +function log_siege() + local function cur_siege() + for _, unit in ipairs(df.global.world.units.active) do + if unit.flags1.active_invader then return true end + end + return false + end + local old_siege = siege + siege = cur_siege() + if siege ~= old_siege and siege then + msg("A vile force of darkness has arrived!") + elseif siege ~= old_siege and not siege then + msg("Siege was broken.") + end +end + + +local workshopTypes = { + [0]="Carpenters Workshop", + "Farmers Workshop", + "Masons Workshop", + "Craftsdwarfs Workshop", + "Jewelers Workshop", + "Metalsmiths Forge", + "Magma Forge", + "Bowyers Workshop", + "Mechanics Workshop", + "Siege Workshop", + "Butchers Workshop", + "Leatherworks Workshop", + "Tanners Workshop", + "Clothiers Workshop", + "Fishery", + "Still", + "Loom", + "Quern", + "Kennels", + "Kitchen", + "Ashery", + "Dyers Workshop", + "Millstone", + "Custom", + "Tool", + } + +local furnaceTypes = { + [0]="Wood Furnace", + "Smelter", + "Glass Furnace", + "Kiln", + "Magma Smelter", + "Magma Glass Furnace", + "Magma Kiln", + "Custom Furnace", + } + +buildStates = {} + +function log_buildings() + for _, building in ipairs(df.global.world.buildings.all) do + if getmetatable(building) == "building_workshopst" or getmetatable(building) == "building_furnacest" then + buildStates[building.id] = buildStates[building.id] or building.flags.exists + if buildStates[building.id] ~= building.flags.exists then + buildStates[building.id] = building.flags.exists + if building.flags.exists then + if getmetatable(building) == "building_workshopst" then + msg(workshopTypes[building.type].." was built.") + elseif getmetatable(building) == "building_furnacest" then + msg(furnaceTypes[building.type].." was built.") + end + end + end + end + end +end + +local function event_loop() + log_nobles() + log_siege() + log_buildings() + if extra_gamelog_enabled then dfhack.timeout(50, 'ticks', event_loop) end +end + +extra_gamelog_enabled = false +local args = {...} +if args[1] == 'disable' then + dfhack.onStateChange[_ENV] = nil + extra_gamelog_enabled = false +elseif args[1] == 'enable' then + dfhack.onStateChange[_ENV] = log_on_load + extra_gamelog_enabled = true + event_loop() +else + print(help) +end diff --git a/scripts/soundsense-season.lua b/scripts/soundsense-season.lua deleted file mode 100644 index da5920588..000000000 --- a/scripts/soundsense-season.lua +++ /dev/null @@ -1,34 +0,0 @@ --- On map load writes the current season to gamelog.txt ---[[=begin - -soundsense-season -================= -It is a well known issue that Soundsense cannot detect the correct -current season when a savegame is loaded and has to play random -season music until a season switch occurs. - -This script registers a hook that prints the appropriate string -to :file:`gamelog.txt` on every map load to fix this. For best results -call the script from :file:`dfhack.init`. - -=end]] - -local seasons = { - [-1] = 'Nothing', -- worldgen - [0] = 'Spring', - [1] = 'Summer', - [2] = 'Autumn', - [3] = 'Winter', -} - -local args = {...} - -if args[1] == 'disable' then - dfhack.onStateChange[_ENV] = nil -else - dfhack.onStateChange[_ENV] = function(op) - if op == SC_WORLD_LOADED then - dfhack.gui.writeToGamelog(seasons[df.global.cur_season]..' has arrived on the calendar.') - end - end -end