Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
112 commits
Select commit Hold shift + click to select a range
9da6925
New Feature: `gym`
realSquidCoder Mar 1, 2025
81127f2
Fix whitespace
realSquidCoder Mar 1, 2025
5c08fb6
missed some
realSquidCoder Mar 1, 2025
edb3e83
MORE whitespace (and some other cleanup)
realSquidCoder Mar 1, 2025
0c4f5b5
Update gym.lua
realSquidCoder Mar 1, 2025
50d6a96
Create gym.rst
realSquidCoder Mar 2, 2025
deca155
Fix EOF
realSquidCoder Mar 2, 2025
74784f8
Update gym.rst
realSquidCoder Mar 2, 2025
f4cf0a0
fix key error
realSquidCoder Mar 2, 2025
39f2c9c
more key errors
realSquidCoder Mar 2, 2025
a5d6c0a
Update the documentation
realSquidCoder Mar 3, 2025
105b0cc
Merge remote-tracking branch 'upstream/master' into sci-gym-script
realSquidCoder Mar 5, 2025
6c53215
Use the enable/disable stuff not args to start or stop
realSquidCoder Mar 6, 2025
f701f9f
Merge branch 'master' into sci-gym-script
realSquidCoder Mar 6, 2025
f149d5c
Merge remote-tracking branch 'upstream/master' into sci-gym-script
realSquidCoder Mar 8, 2025
4492f3e
Merge remote-tracking branch 'upstream/master' into sci-gym-script
realSquidCoder Mar 12, 2025
a6761bd
Do the documentation in one place
realSquidCoder Mar 12, 2025
0acd601
Various fixes
realSquidCoder Mar 12, 2025
9463d79
More cleanup
realSquidCoder Mar 12, 2025
7dba7e4
rename the script itself
realSquidCoder Mar 12, 2025
86967d7
fix docs
realSquidCoder Mar 12, 2025
eaa1d86
Add credit where credit is due
realSquidCoder Mar 12, 2025
1892f62
add to control panel
realSquidCoder Mar 12, 2025
e69aba5
Check the squad's entity_id to make sure we get *our* Gym
realSquidCoder Mar 13, 2025
0d0ef1e
Update autotraining.lua
realSquidCoder Mar 13, 2025
c7c73ad
Fix the ignore count never being reset
realSquidCoder Mar 14, 2025
bceb905
Fix units that need training but are already doing so being reported …
realSquidCoder Mar 14, 2025
8803e82
fix the ignore count (it should be global)
realSquidCoder Mar 14, 2025
82d3acd
Apply suggestions from code review
realSquidCoder Mar 15, 2025
00e883f
fix typo
realSquidCoder Mar 16, 2025
6634120
fix to actually check the unit's squad
realSquidCoder Mar 16, 2025
ed76a08
Update for gui usage
realSquidCoder Mar 16, 2025
92076ba
clean up
realSquidCoder Mar 16, 2025
fc832a3
initial gui and update from code review
realSquidCoder Mar 16, 2025
55ddbfe
show alias in gui too
realSquidCoder Mar 16, 2025
f1edec2
clean up
realSquidCoder Mar 16, 2025
3906eb0
Create gui docs
realSquidCoder Mar 19, 2025
59d53f5
update the docs
realSquidCoder Mar 19, 2025
612936b
remove non-existant name args in docs
realSquidCoder Mar 19, 2025
f59f6de
fix typo in message
realSquidCoder Mar 19, 2025
1c427c6
fix trainees being labeled as queued
realSquidCoder Mar 19, 2025
648ae90
add ignore nobles
realSquidCoder Mar 21, 2025
3612593
Remove more debug code
realSquidCoder Mar 21, 2025
a9bf6e6
Gui cleanup
realSquidCoder Mar 21, 2025
218a41f
Merge remote-tracking branch 'upstream/master' into sci-gym-script
realSquidCoder Mar 23, 2025
3b151be
Merge remote-tracking branch 'upstream/master' into sci-gym-script
realSquidCoder Mar 23, 2025
236c54e
Add toolbar button for `gui/design`
realSquidCoder Mar 28, 2025
a1e8500
Update changelog.txt
realSquidCoder Mar 28, 2025
00a1324
Fix the positioning
realSquidCoder Mar 28, 2025
d17b1ca
fix up a non-bug
realSquidCoder Mar 28, 2025
d4e8993
Merge branch 'sci-gym-script' into conglomerate
realSquidCoder Mar 29, 2025
9600a57
data-driven position info for DF toolbars
ChrisJohnsen Mar 29, 2025
237143b
gui/mass-remove.toolbar: use toolbar positioning info
ChrisJohnsen Mar 30, 2025
43cc86d
gui/mass-remove.toolbar: handle right- and top-anchored overlay posit…
ChrisJohnsen Mar 30, 2025
a659d13
toolbars: remove fort.right:rect
ChrisJohnsen Mar 31, 2025
456b6c9
toolbars: (demo) directly use designation and bottom values
ChrisJohnsen Mar 31, 2025
9c54dac
toolbars: (demo) fix type flaw
ChrisJohnsen Mar 31, 2025
b1a4b5e
Merge branch 'pr/1426' into glom
realSquidCoder Mar 31, 2025
143c473
Clean up all
realSquidCoder Mar 31, 2025
3d5f180
gui/mass-remove.toolbar: fix toolbars library use
ChrisJohnsen Apr 1, 2025
70262e0
gui/mass-remove.toolbar: extra panel to support changes in anchor sides
ChrisJohnsen Apr 1, 2025
3c325cc
gui/mass-remove.toolbar: position is constrained to minimum-size inte…
ChrisJohnsen Apr 1, 2025
0eb3df5
toolbars: type fix and internal function rename
ChrisJohnsen Apr 1, 2025
f832e5d
toolbars: (demo) show computed button positions
ChrisJohnsen Apr 1, 2025
834c082
toolbars: expose button widths
ChrisJohnsen Apr 1, 2025
767ebaa
toolbars: (demo) show proper button widths
ChrisJohnsen Apr 1, 2025
a6a6046
toolbars: (demo) make update_demonstrations local
ChrisJohnsen Apr 1, 2025
9b36299
toolbars: some documentation
ChrisJohnsen Apr 1, 2025
62ce0bf
Merge
realSquidCoder Apr 1, 2025
fe0028d
merge
realSquidCoder Apr 1, 2025
7f0a8d2
Merge branch 'master' into squid-design-toolbar
realSquidCoder Apr 1, 2025
e1b0a32
Merge remote-tracking branch 'upstream/master' into glom
realSquidCoder Apr 2, 2025
1a101c2
Fix the overlays being overwritten
realSquidCoder Apr 2, 2025
d7d2d84
Merge branch 'squid-design-toolbar' into glom
realSquidCoder Apr 2, 2025
f44a37a
Update to use the Military Module
realSquidCoder Apr 4, 2025
7c186d3
use the squad position
realSquidCoder Apr 4, 2025
b77d6c7
Merge remote-tracking branch 'upstream/master' into glom
realSquidCoder Apr 4, 2025
8ac8b50
Merge branch 'sci-gym-script' into glom
realSquidCoder Apr 4, 2025
f670df7
Remove all training dwarves when you disable
realSquidCoder Apr 6, 2025
996a5f8
Merge branch 'master' into sci-gym-script
realSquidCoder Apr 6, 2025
edfa126
Merge remote-tracking branch 'upstream/master' into glom
realSquidCoder Apr 6, 2025
d581e56
Merge branch 'sci-gym-script' into glom
realSquidCoder Apr 6, 2025
13e50cc
add prefer nicknamed
realSquidCoder Apr 7, 2025
5f68243
Update changelog.txt
realSquidCoder Apr 7, 2025
3fb5645
make it look better
realSquidCoder Apr 7, 2025
4065d76
Merge branch 'squid-gui/spectate(nicknames)' into glom
realSquidCoder Apr 7, 2025
ddae413
Add a window showing the active mods in a world
realSquidCoder Apr 7, 2025
6c71d7f
Merge branch 'squid-active-modlist' into glom
realSquidCoder Apr 7, 2025
595a760
disable autotraining on map unload
realSquidCoder Apr 10, 2025
145c3dc
Merge branch 'sci-gym-script' into glom
realSquidCoder Apr 10, 2025
22c579a
Merge branch 'master' into squid-active-modlist
realSquidCoder Apr 11, 2025
eaa3fc9
Update docs
realSquidCoder Apr 11, 2025
e364299
Update changelog.txt
realSquidCoder Apr 11, 2025
af5ee3d
Merge branch 'squid-active-modlist' of https://github.com/SquidCoderI…
realSquidCoder Apr 11, 2025
1c8a8bb
Merge branch 'squid-active-modlist' into glom
realSquidCoder Apr 11, 2025
765d1c8
Update mod-manager.rst
realSquidCoder Apr 11, 2025
d587cff
Merge branch 'squid-active-modlist' into glom
realSquidCoder Apr 11, 2025
f2970b1
Apply suggestions from code review
realSquidCoder Apr 12, 2025
13beea8
Update mod-manager.rst
realSquidCoder Apr 12, 2025
89c7d13
Update mod-manager.lua
realSquidCoder Apr 12, 2025
f76c0d2
Update docs/gui/mod-manager.rst
realSquidCoder Apr 12, 2025
02801ab
Update mod-manager.lua
realSquidCoder Apr 12, 2025
54e955e
Merge branch 'squid-active-modlist' of https://github.com/SquidCoderI…
realSquidCoder Apr 12, 2025
4e6998c
Update mod-manager.lua
realSquidCoder Apr 12, 2025
52a3558
Update mod-manager.lua
realSquidCoder Apr 12, 2025
00fd97b
Update mod-manager.lua
realSquidCoder Apr 12, 2025
11cb1de
Update mod-manager.lua
realSquidCoder Apr 12, 2025
119b6b2
Update mod-manager.lua
realSquidCoder Apr 13, 2025
a6f80ba
Update mod-manager.lua
realSquidCoder Apr 13, 2025
fca0788
Update mod-manager.lua
realSquidCoder Apr 13, 2025
5f13a42
Merge branch 'squid-active-modlist' into glom
realSquidCoder Apr 13, 2025
03bcb0c
Merge remote-tracking branch 'upstream/master' into glom
realSquidCoder Apr 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
309 changes: 309 additions & 0 deletions autotraining.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,309 @@
-- Based on the original code by RNGStrategist (who also got some help from Uncle Danny)
--@ enable = true
--@ module = true

local repeatUtil = require('repeat-util')
local utils=require('utils')

validArgs = utils.invert({
't'
})

local args = utils.processArgs({...}, validArgs)
local GLOBAL_KEY = "autotraining"
local need_id = df.need_type['MartialTraining']
local ignore_count = 0

local function get_default_state()
return {
enabled=false,
threshold=-5000,
ignored={},
ignored_nobles={},
training_squads = {},
}
end

state = state or get_default_state()

function isEnabled()
return state.enabled
end

-- persisting a table with numeric keys results in a json array with a huge number of null entries
-- therefore, we convert the keys to strings for persistence
local function to_persist(persistable)
local persistable_ignored = {}
for k, v in pairs(persistable) do
persistable_ignored[tostring(k)] = v
end
return persistable_ignored
end

-- loads both from the older array format and the new string table format
local function from_persist(persistable)
if not persistable then
return
end
local ret = {}
for k, v in pairs(persistable) do
ret[tonumber(k)] = v
end
return ret
end

function persist_state()
dfhack.persistent.saveSiteData(GLOBAL_KEY, {
enabled=state.enabled,
threshold=state.threshold,
ignored=to_persist(state.ignored),
ignored_nobles=state.ignored_nobles,
training_squads=to_persist(state.training_squads)
})
end

--- Load the saved state of the script
local function load_state()
-- load persistent data
local persisted_data = dfhack.persistent.getSiteData(GLOBAL_KEY, {})
state.enabled = persisted_data.enabled or state.enabled
state.threshold = persisted_data.threshold or state.threshold
state.ignored = from_persist(persisted_data.ignored) or state.ignored
state.ignored_nobles = persisted_data.ignored_nobles or state.ignored_nobles
state.training_squads = from_persist(persisted_data.training_squads) or state.training_squads
return state
end

dfhack.onStateChange[GLOBAL_KEY] = function(sc)
if sc == SC_MAP_UNLOADED then
state.enabled = false
return
end
-- the state changed, is a map loaded and is that map in fort mode?
if sc ~= SC_MAP_LOADED or df.global.gamemode ~= df.game_mode.DWARF then
-- no its isnt, so bail
return
end
-- yes it was, so:

-- retrieve state saved in game. merge with default state so config
-- saved from previous versions can pick up newer defaults.
load_state()
if ( state.enabled ) then
start()
else
stop()
end
-- start can change the enabled state if the squad cant be found
if state.enabled then
dfhack.print(GLOBAL_KEY .." was persisted with the following data:\nThreshold: ".. state.threshold .. '\n')
end
persist_state()
end


--######
--Functions
--######
function getTrainingCandidates()
local ret = {}
local citizen = dfhack.units.getCitizens(true)
ignore_count = 0
for _, unit in ipairs(citizen) do
if dfhack.units.isAdult(unit) then
local noblePos = dfhack.units.getNoblePositions(unit)
local isIgnNoble = false
if ( not state.ignored[unit.id] ) then
if noblePos ~=nil then
for _, position in ipairs(noblePos) do
if state.ignored_nobles[position.position.code] then
isIgnNoble = true
break
end
end
end
if not isIgnNoble then
table.insert(ret, unit)
else
removeTraining(unit)
ignore_count = ignore_count +1
end
else
removeTraining(unit)
ignore_count = ignore_count +1
end
end
end
return ret
end

function getTrainingSquads()
local squads = {}
for squad_id, _ in pairs(state.training_squads) do
local squad = df.squad.find(squad_id)
if squad then
table.insert(squads, squad)
else
-- setting to nil during iteration is permitted by lua
state.training_squads[squad_id] = nil
end
end
return squads
end

function findNeed(unit)
local needs = unit.status.current_soul.personality.needs
for _, need in ipairs(needs) do
if need.id == need_id then
return need
end
end
return nil
end

--######
--Main
--######

function getByID(id)
for _, unit in ipairs(getTrainingCandidates()) do
if (unit.hist_figure_id == id) then
return unit
end
end

return nil
end

-- Find all training squads
-- Abort if no squads found
function checkSquads()
local squads = {}
for _, squad in ipairs(getTrainingSquads()) do
if squad.entity_id == df.global.plotinfo.group_id then
local leader = squad.positions[0].occupant
if ( leader ~= -1) then
table.insert(squads,squad)
end
end
end

if (#squads == 0) then
return nil
end

return squads
end

function addTraining(unit)
if (unit.military.squad_id ~= -1) then
for _, squad in ipairs(getTrainingSquads()) do
if unit.military.squad_id == squad.id then
return true
end
end
return false
end
for _, squad in ipairs(getTrainingSquads()) do
for i=1,9,1 do
if ( squad.positions[i].occupant == -1 ) then
dfhack.military.addToSquad(unit.id,squad.id,i)
-- squad.positions[i].occupant = unit.hist_figure_id
-- unit.military.squad_id = squad.id
-- unit.military.squad_position = i
return true
end
end
end

return false
end

function removeTraining(unit)
for _, squad in ipairs(getTrainingSquads()) do
for i=1,9,1 do
if ( unit.hist_figure_id == squad.positions[i].occupant ) then
dfhack.military.removeFromSquad(unit.id)
-- unit.military.squad_id = -1
-- unit.military.squad_position = -1
-- squad.positions[i].occupant = -1
return true
end
end
end
return false
end

function removeAll()
if ( state.training_squads == nil) then return end
for _, squad in ipairs(getTrainingSquads()) do
for i=1,9,1 do
local dwarf = getByID(squad.positions[i].occupant)
if (dwarf ~= nil) then
removeTraining(dwarf)
end
end
end
end


function check()
local squads = checkSquads()
local intraining_count = 0
local inque_count = 0
if ( squads == nil) then return end
for _, unit in ipairs(getTrainingCandidates()) do
local need = findNeed(unit)
if ( need ~= nil ) then
if ( need.focus_level < state.threshold ) then
local bol = addTraining(unit)
if ( bol ) then
intraining_count = intraining_count +1
else
inque_count = inque_count +1
end
else
removeTraining(unit)
end
end
end

dfhack.println(GLOBAL_KEY .. " | IGN: " .. ignore_count .. " TRAIN: " .. intraining_count .. " QUE: " ..inque_count )
end

function start()
dfhack.println(GLOBAL_KEY .. " | START")

if (args.t) then
state.threshold = 0-tonumber(args.t)
end
repeatUtil.scheduleEvery(GLOBAL_KEY, 1, 'days', check) -- 997 is the closest prime to 1000
end

function stop()
removeAll()
repeatUtil.cancel(GLOBAL_KEY)
dfhack.println(GLOBAL_KEY .. " | STOP")
end

if dfhack_flags.enable then
if dfhack_flags.enable_state then
state.enabled = true
else
state.enabled = false
end
persist_state()
end

if dfhack_flags.module then
return
end

if ( state.enabled ) then
start()
dfhack.println(GLOBAL_KEY .." | Enabled")
else
stop()
dfhack.println(GLOBAL_KEY .." | Disabled")
end
persist_state()
3 changes: 3 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ Template for new versions:
## New Tools

## New Features
- `gui/spectate`: added "Prefer nicknamed" to the list of options
- `gui/mod-manager`: when run in a loaded world, opens a copyable list of active mods.

## Fixes
- `list-agreements`: fix date math when determining petition age
Expand All @@ -48,6 +50,7 @@ Template for new versions:
- `gui/mass-remove`: add a button to the bottom toolbar when eraser mode is active for launching `gui/mass-remove`
- `idle-crafting`: default to only considering happy and ecstatic units for the highest need threshold
- `gui/sitemap`: add a button to the toolbar at the bottom left corner of the screen for launching `gui/sitemap`
- `gui/design`: add a button to the toolbar at the bottom left corner of the screen for launching `gui/design`

## Fixes
- `idle-crafting`: check that units still have crafting needs before creating a job for them
Expand Down
41 changes: 41 additions & 0 deletions docs/autotraining.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
autotraining
============

.. dfhack-tool::
:summary: Assigns citizens to a military squad until they have fulfilled their need for Martial Training
:tags: fort auto bugfix units

Automation script for citizens to hit the gym when they yearn for the gains. Also passively builds military skills and physical stats.

You need to have at least one squad that is set up for training. This should be a new non-military-use squad. The uniform should be
set to "No Uniform" and the squad should be set to "Constant Training" in the military screen. Edit the squad's schedule to full time training with around 8 units training.
The squad doesn't need months off. The members leave the squad once they have gotten their gains.

Once you have made squads for training use `gui/autotraining` to select the squads and ignored units, as well as the needs threshhold.

Usage
-----

``autotraining [<options>]``

Examples
--------

``autotraining``
Current status of script

``enable autotraining``
Checks to see if you have fullfilled the creation of a training gym.
If there is no squad marked for training use, a clickable notification will appear letting you know to set one up/
Searches your fort for dwarves with a need to go to the gym, and begins assigning them to said gym.
Once they have fulfilled their need they will be removed from the gym squad to be replaced by the next dwarf in the list.

``disable autotraining``
Stops adding new units to the squad.

Options
-------
``-t``
Use integer values. (Default 5000)
The negative need threshhold to trigger for each citizen
The greater the number the longer before a dwarf is added to the waiting list.
15 changes: 15 additions & 0 deletions docs/gui/autotraining.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
gui/autotraining
================

.. dfhack-tool::
:summary: GUI interface for ``autotraining``
:tags: fort auto interface

This is an in-game configuration interface for `autotraining`. You can pick squads for training, select ignored units, and set the needs threshold.

Usage
-----

::

gui/autotraining
Loading