Skip to content

Commit 067d182

Browse files
Merge remote-tracking branch 'upstream/master' into sci-gym-script
2 parents 595a760 + 6c24dc1 commit 067d182

16 files changed

+371
-158
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ repos:
2020
args: ['--fix=lf']
2121
- id: trailing-whitespace
2222
- repo: https://github.com/python-jsonschema/check-jsonschema
23-
rev: 0.31.2
23+
rev: 0.32.1
2424
hooks:
2525
- id: check-github-workflows
2626
- repo: https://github.com/Lucas-C/pre-commit-hooks

changelog.txt

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,28 @@ Template for new versions:
2929
## New Tools
3030

3131
## New Features
32+
- `gui/mod-manager`: when run in a loaded world, shows a list of active mods -- click to export the list to the clipboard for easy sharing or posting
33+
34+
## Fixes
35+
- `starvingdead`: properly restore to correct enabled state when loading a new game that is different from the first game loaded in this session
36+
- `starvingdead`: ensure undead decay does not happen faster than the declared decay rate when saving and loading the game
37+
38+
## Misc Improvements
39+
40+
## Removed
41+
42+
# 51.11-r1
3243

3344
## Fixes
3445
- `list-agreements`: fix date math when determining petition age
3546
- `gui/petitions`: fix date math when determining petition age
47+
- `gui/rename`: fix commandline processing when manually specifying target ids
48+
- `gui/sandbox`: restore metal equipment options when spawning units
3649

3750
## Misc Improvements
3851
- `fix/loyaltycascade`: now also breaks up brawls and other intra-fort conflicts that *look* like loyalty cascades
3952
- `makeown`: remove selected unit from any current conflicts so they don't just start attacking other citizens when you make them a citizen of your fort
4053

41-
## Removed
42-
4354
# 51.09-r1
4455

4556
## New Features

docs/gui/mod-manager.rst

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,33 @@ gui/mod-manager
22
===============
33

44
.. dfhack-tool::
5-
:summary: Save and restore lists of active mods.
5+
:summary: Manange your active mods.
66
:tags: dfhack interface
77

8-
Adds an optional overlay to the mod list screen that allows you to save and
9-
load mod list presets, as well as set a default mod list preset for new worlds.
8+
When run with a world loaded, shows a list of active mods. You can copy the
9+
list to the system clipboard for easy sharing or posting.
1010

1111
Usage
1212
-----
1313

1414
::
1515

1616
gui/mod-manager
17+
18+
Overlay
19+
-------
20+
21+
This tool also provides two overlays that are managed by the `overlay`
22+
framework.
23+
24+
gui/mod-manager.button
25+
~~~~~~~~~~~~~~~~~~~~~~
26+
27+
Adds a widget to the mod list screen that allows you to save and load mod list
28+
presets. You can also set a default mod list preset for new worlds so you don't
29+
have to manualy re-select the same mods every time you generate a world.
30+
31+
gui/mod-manager.notification
32+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
33+
34+
Displays a message when a mod preset has been auto-applied.

docs/starvingdead.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ gradually decay, losing strength, speed, and toughness. After six months,
1010
they collapse upon themselves, never to be reanimated.
1111

1212
Strength lost is proportional to the time until death, all units will have
13-
roughly 10% of each of their attributes' values when close to being removed.
13+
roughly 10% of each of their attributes' values when they succumb to decay.
1414

1515
In any game, this can be a welcome gameplay feature, but it is especially
16-
useful in preventing undead cascades in the caverns in reanimating biomes,
17-
where constant combat can lead to hundreds of undead roaming the caverns and
16+
useful in preventing undead cascades in the caverns in reanimating biomes.
17+
Constant combat can lead to hundreds of undead roaming the caverns and
1818
destroying your FPS.
1919

2020
Usage

emigration.lua

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ local unit_link_utils = reqscript('internal/emigration/unit-link-utils')
99
local GLOBAL_KEY = 'emigration' -- used for state change hooks and persistence
1010

1111
local function get_default_state()
12-
return {enabled=false, last_cycle_tick=0}
12+
return {
13+
enabled=false,
14+
last_cycle_tick=0
15+
}
1316
end
1417

1518
state = state or get_default_state()
@@ -127,15 +130,15 @@ function checkmigrationnow()
127130
end
128131

129132
local function event_loop()
130-
if state.enabled then
131-
local current_tick = dfhack.world.ReadCurrentTick() + TICKS_PER_YEAR * dfhack.world.ReadCurrentYear()
132-
if current_tick - state.last_cycle_tick < TICKS_PER_MONTH then
133-
local timeout_ticks = state.last_cycle_tick - current_tick + TICKS_PER_MONTH
134-
dfhack.timeout(timeout_ticks, 'ticks', event_loop)
135-
else
136-
checkmigrationnow()
137-
dfhack.timeout(1, 'months', event_loop)
138-
end
133+
if not state.enabled then return end
134+
135+
local current_tick = dfhack.world.ReadCurrentTick() + TICKS_PER_YEAR * dfhack.world.ReadCurrentYear()
136+
if current_tick - state.last_cycle_tick < TICKS_PER_MONTH then
137+
local timeout_ticks = state.last_cycle_tick - current_tick + TICKS_PER_MONTH
138+
dfhack.timeout(timeout_ticks, 'ticks', event_loop)
139+
else
140+
checkmigrationnow()
141+
dfhack.timeout(1, 'months', event_loop)
139142
end
140143
end
141144

fix/ownership.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ local zone_vecs = {
3333
local function relink_zones()
3434
for _,zones in ipairs(zone_vecs) do
3535
for _,zone in ipairs(zones) do
36-
local unit = zone.assigned_unit
36+
local unit = dfhack.buildings.getOwner(zone)
3737
if not unit then goto continue end
3838
if not utils.linear_index(unit.owned_buildings, zone.id, 'id') then
3939
print(('fix/ownership: Restoring %s ownership link for %s'):format(

gui/family-affairs.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,7 @@ end
777777
FamilyAffairs = defclass(FamilyAffairs, widgets.Window)
778778
FamilyAffairs.ATTRS {
779779
frame_title='Family manager',
780-
frame={w=50, h=30, r=2, t=18},
780+
frame={w=65, h=30, r=2, t=18},
781781
frame_inset={t=1, l=1, r=1},
782782
resizable=true,
783783
initial_tab=DEFAULT_NIL,

gui/manipulator.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -709,11 +709,11 @@ function Spreadsheet:init()
709709
},
710710
DataColumn{
711711
view_id='name',
712-
frame={w=30},
712+
frame={w=45},
713713
label='Name',
714714
label_inset=8,
715715
data_fn=dfhack.units.getReadableName,
716-
data_width=30,
716+
data_width=45,
717717
shared=self.shared,
718718
},
719719
cols,

gui/mod-manager.lua

Lines changed: 173 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
-- Save and restore lists of active mods.
1+
-- Show, save, and restore lists of active mods.
22
--@ module = true
33

4-
local overlay = require('plugins.overlay')
5-
local gui = require('gui')
6-
local widgets = require('gui.widgets')
74
local dialogs = require('gui.dialogs')
5+
local gui = require('gui')
86
local json = require('json')
7+
local overlay = require('plugins.overlay')
8+
local scriptmanager = require('script-manager')
99
local utils = require('utils')
10+
local widgets = require('gui.widgets')
1011

1112
local presets_file = json.open("dfhack-config/mod-manager.json")
1213
local GLOBAL_KEY = 'mod-manager'
@@ -119,6 +120,9 @@ local function swap_modlist(viewscreen, modlist)
119120
return failures
120121
end
121122

123+
--------------------
124+
-- ModmanageMenu
125+
122126
ModmanageMenu = defclass(ModmanageMenu, widgets.Window)
123127
ModmanageMenu.ATTRS {
124128
view_id = "modman_menu",
@@ -389,6 +393,9 @@ function ModmanageMenu:init()
389393
}
390394
end
391395

396+
--------------------
397+
-- ModmanageScreen
398+
392399
ModmanageScreen = defclass(ModmanageScreen, gui.ZScreen)
393400
ModmanageScreen.ATTRS {
394401
focus_path = "mod-manager",
@@ -401,6 +408,163 @@ function ModmanageScreen:init()
401408
}
402409
end
403410

411+
--------------------
412+
-- ModlistWindow
413+
414+
ModlistWindow = defclass(ModlistWindow, widgets.Window)
415+
ModlistWindow.ATTRS{
416+
frame_title="Active Mods",
417+
frame={w=55, h=20},
418+
resizable=true,
419+
}
420+
421+
local function get_num_vanilla_mods()
422+
local count = 0
423+
for _,mod in ipairs(scriptmanager.get_active_mods()) do
424+
if mod.vanilla then
425+
count = count + 1
426+
end
427+
end
428+
return count
429+
end
430+
431+
local function get_num_non_vanilla_mods()
432+
local count = 0
433+
for _,mod in ipairs(scriptmanager.get_active_mods()) do
434+
if not mod.vanilla then
435+
count = count + 1
436+
end
437+
end
438+
return count
439+
end
440+
441+
function ModlistWindow:init()
442+
self:addviews{
443+
widgets.CycleHotkeyLabel{
444+
view_id='vanilla',
445+
frame={l=0, t=0, w=24},
446+
key='CUSTOM_V',
447+
label='Vanilla mods:',
448+
options={
449+
{label='Include', value=true, pen=COLOR_LIGHTBLUE},
450+
{label='Exclude', value=false, pen=COLOR_LIGHTRED},
451+
},
452+
initial_option=false,
453+
on_change=function() self:refresh_list() end,
454+
},
455+
widgets.Divider{
456+
frame={t=2, h=1},
457+
frame_style=gui.FRAME_THIN,
458+
frame_style_l=false,
459+
frame_style_r=false,
460+
},
461+
widgets.HotkeyLabel{
462+
frame={t=4, r=0},
463+
label='Export to clipboard (single line)',
464+
text_pen=COLOR_YELLOW,
465+
auto_width=true,
466+
on_activate=function()
467+
local text = {}
468+
for _,choice in ipairs(self.subviews.list:getChoices()) do
469+
table.insert(text, ('%s %s'):format(choice.data.name, choice.data.version))
470+
end
471+
dfhack.internal.setClipboardTextCp437Multiline(table.concat(text, ', '))
472+
end,
473+
enabled=function() return #self.subviews.list:getChoices() > 0 end,
474+
},
475+
widgets.HotkeyLabel{
476+
frame={t=5, r=0},
477+
label='Export to clipboard (with links)',
478+
text_pen=COLOR_YELLOW,
479+
auto_width=true,
480+
on_activate=function()
481+
local text = {}
482+
for _,choice in ipairs(self.subviews.list:getChoices()) do
483+
table.insert(text, choice.export_text)
484+
end
485+
dfhack.internal.setClipboardTextCp437Multiline(table.concat(text, NEWLINE))
486+
end,
487+
enabled=function() return #self.subviews.list:getChoices() > 0 end,
488+
},
489+
widgets.Label{
490+
frame={l=0, t=4},
491+
text={
492+
'Load',
493+
NEWLINE,
494+
'order',
495+
},
496+
},
497+
widgets.Label{
498+
frame={l=7, t=5},
499+
text='Mod',
500+
},
501+
widgets.List{
502+
view_id='list',
503+
frame={t=7, b=2},
504+
},
505+
widgets.Label{
506+
frame={l=0, b=0},
507+
text={
508+
{text=('%d'):format(get_num_vanilla_mods()), pen=COLOR_LIGHTBLUE},
509+
' vanilla mods',
510+
{text=function() return self.subviews.vanilla:getOptionValue() and '' or ' (hidden)' end},
511+
', ',
512+
{text=('%d'):format(get_num_non_vanilla_mods()), pen=COLOR_BROWN},
513+
' non-vanilla mods',
514+
},
515+
},
516+
}
517+
518+
self:refresh_list()
519+
end
520+
521+
function ModlistWindow:refresh_list()
522+
local include_vanilla = self.subviews.vanilla:getOptionValue()
523+
524+
local choices = {}
525+
for idx,mod in ipairs(scriptmanager.get_active_mods()) do
526+
if not include_vanilla and mod.vanilla then goto continue end
527+
local steam_id = scriptmanager.get_mod_info_metadata(mod.path, 'STEAM_FILE_ID').STEAM_FILE_ID
528+
local url = steam_id and (': https://steamcommunity.com/sharedfiles/filedetails/?id=%s'):format(steam_id) or ''
529+
table.insert(choices, {
530+
text={
531+
{text=idx, width=2, rjustify=true},
532+
') ',
533+
{text=mod.name, gap=3},
534+
' (',
535+
{text=mod.version, pen=COLOR_LIGHTGREEN},
536+
')',
537+
},
538+
data=mod,
539+
export_text=('- %s (%s)%s'):format(mod.name, mod.version, url),
540+
})
541+
::continue::
542+
end
543+
544+
self.subviews.list:setChoices(choices)
545+
end
546+
547+
--------------------
548+
-- ModlistScreen
549+
550+
ModlistScreen = defclass(ModlistScreen, gui.ZScreen)
551+
ModlistScreen.ATTRS{
552+
focus_path="mod-manager",
553+
}
554+
555+
function ModlistScreen:init()
556+
self:addviews{
557+
ModlistWindow{}
558+
}
559+
end
560+
561+
function ModlistScreen:onDismiss()
562+
view = nil
563+
end
564+
565+
--------------------
566+
-- Overlays
567+
404568
ModmanageOverlay = defclass(ModmanageOverlay, overlay.OverlayWidget)
405569
ModmanageOverlay.ATTRS {
406570
frame = { w=16, h=3 },
@@ -494,5 +658,8 @@ if dfhack_flags.module then
494658
return
495659
end
496660

497-
-- TODO: when invoked as a command, should show information on which mods are loaded
498-
-- and give the player the option to export the list (or at least copy it to the clipboard)
661+
if not dfhack.isWorldLoaded() then
662+
qerror("Please load a game before using the mod manager to see active mods.")
663+
end
664+
665+
view = view and view:raise() or ModlistScreen{}:show()

gui/notes.lua

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,8 +361,7 @@ function main()
361361
qerror('notes requires a fortress map to be loaded')
362362
end
363363

364-
view = view and view:raise() or NotesScreen{
365-
}:show()
364+
view = view and view:raise() or NotesScreen{}:show()
366365
end
367366

368367
if not dfhack_flags.module then

0 commit comments

Comments
 (0)