|
| 1 | +local function for_pray_need(needs, fn) |
| 2 | + for idx, need in ipairs(needs) do |
| 3 | + if need.id == df.need_type.PrayOrMeditate then |
| 4 | + fn(idx, need) |
| 5 | + end |
| 6 | + end |
| 7 | +end |
| 8 | + |
| 9 | +local function shuffle_prayer_needs(needs, prayer_targets) |
| 10 | + local idx_of_prayer_target, max_focus_level |
| 11 | + local idx_of_min_focus_level, min_focus_level |
| 12 | + for_pray_need(needs, function(idx, need) |
| 13 | + -- only shuffle if the need for one of the current prayer targets |
| 14 | + -- is already met |
| 15 | + if prayer_targets[need.deity_id] and need.focus_level > -1000 and |
| 16 | + (not max_focus_level or need.focus_level > max_focus_level) |
| 17 | + then |
| 18 | + idx_of_prayer_target = idx |
| 19 | + max_focus_level = need.focus_level |
| 20 | + |
| 21 | + -- find a need that hasn't been met outside of the current prayer targets |
| 22 | + elseif not prayer_targets[need.deity_id] and |
| 23 | + need.focus_level <= -1000 and |
| 24 | + (not min_focus_level or need.focus_level < min_focus_level) |
| 25 | + then |
| 26 | + idx_of_min_focus_level = idx |
| 27 | + min_focus_level = need.focus_level |
| 28 | + end |
| 29 | + end) |
| 30 | + |
| 31 | + -- if a need inside the prayer group is met and a need outside of the |
| 32 | + -- prayer group is not met, transfer the credit outside of the prayer group |
| 33 | + if idx_of_prayer_target and idx_of_min_focus_level then |
| 34 | + needs[idx_of_min_focus_level].focus_level = needs[idx_of_prayer_target].focus_level |
| 35 | + needs[idx_of_prayer_target].focus_level = min_focus_level |
| 36 | + return true |
| 37 | + end |
| 38 | + |
| 39 | + if not idx_of_prayer_target then return end |
| 40 | + |
| 41 | + -- otherwise, if the only unmet needs are inside the prayer group, |
| 42 | + -- set the credit inside the prayer group to the level of the met need |
| 43 | + -- we found earlier |
| 44 | + local modified = false |
| 45 | + for_pray_need(needs, function(_, need) |
| 46 | + if prayer_targets[need.deity_id] and need.focus_level <= -1000 then |
| 47 | + need.focus_level = needs[idx_of_prayer_target].focus_level |
| 48 | + modified = true |
| 49 | + end |
| 50 | + end) |
| 51 | + return modified |
| 52 | +end |
| 53 | + |
| 54 | +local function get_prayer_targets(unit) |
| 55 | + for _, sa in ipairs(unit.social_activities) do |
| 56 | + local ae = df.activity_entry.find(sa) |
| 57 | + if not ae or ae.type ~= df.activity_entry_type.Prayer then |
| 58 | + goto next_activity |
| 59 | + end |
| 60 | + for _, ev in ipairs(ae.events) do |
| 61 | + if not df.activity_event_worshipst:is_instance(ev) then |
| 62 | + goto next_event |
| 63 | + end |
| 64 | + for _, hfid in ipairs(ev.participants.histfigs) do |
| 65 | + local hf = df.historical_figure.find(hfid) |
| 66 | + if not hf then goto next_hf end |
| 67 | + local deity_set = {} |
| 68 | + for _, hf_link in ipairs(hf.histfig_links) do |
| 69 | + if df.histfig_hf_link_deityst:is_instance(hf_link) then |
| 70 | + deity_set[hf_link.target_hf] = true |
| 71 | + end |
| 72 | + end |
| 73 | + if next(deity_set) then return deity_set end |
| 74 | + ::next_hf:: |
| 75 | + end |
| 76 | + ::next_event:: |
| 77 | + end |
| 78 | + ::next_activity:: |
| 79 | + end |
| 80 | +end |
| 81 | + |
| 82 | +for _,unit in ipairs(dfhack.units.getCitizens(true)) do |
| 83 | + local prayer_targets = get_prayer_targets(unit) |
| 84 | + if not unit.status.current_soul or not prayer_targets then |
| 85 | + goto next_unit |
| 86 | + end |
| 87 | + local needs = unit.status.current_soul.personality.needs |
| 88 | + if shuffle_prayer_needs(needs, prayer_targets) then |
| 89 | + print('rebalanced prayer needs for ' .. |
| 90 | + dfhack.df2console(dfhack.TranslateName(dfhack.units.getVisibleName(unit)))) |
| 91 | + end |
| 92 | + ::next_unit:: |
| 93 | +end |
0 commit comments