Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added ability to request gems by their value #1079

Merged
merged 5 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
5 changes: 3 additions & 2 deletions docs/caravan.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,9 @@ selected, then the range of items will be selected.
Trade agreement
```````````````

A small panel is shown with a hotkey (``Ctrl-A``) for selecting all/none in the
currently shown category.
A small panel is shown with a hotkeys:
(``Ctrl-A``) for selecting all/none in the currently shown category.
(``Ctrl-M``) for selecting items with specific base material price.

Display furniture
`````````````````
Expand Down
152 changes: 135 additions & 17 deletions internal/caravan/tradeagreement.lua
Original file line number Diff line number Diff line change
@@ -1,23 +1,83 @@
--@ module = true

local dlg = require('gui.dialogs')
local gui = require('gui')
local overlay = require('plugins.overlay')
local widgets = require('gui.widgets')

TradeAgreementOverlay = defclass(TradeAgreementOverlay, overlay.OverlayWidget)
TradeAgreementOverlay.ATTRS{
desc='Adds select all/none functionality when requesting trade agreement items.',
default_pos={x=45, y=-6},
default_enabled=true,
viewscreens='dwarfmode/Diplomacy/Requests',
frame={w=25, h=3},
frame_style=gui.MEDIUM_FRAME,
frame_background=gui.CLEAR_PEN,
TradeAgreementOverlay.ATTRS {
desc = 'Adds select all/none functionality when requesting trade agreement items.',
default_pos = { x = 45, y = -6 },
default_enabled = true,
viewscreens = 'dwarfmode/Diplomacy/Requests',
frame = { w = 40, h = 4 },
frame_style = gui.MEDIUM_FRAME,
frame_background = gui.CLEAR_PEN,
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inside of tables, the convention (at least inside of DFHack code) is to have no spaces around the =


local diplomacy = df.global.game.main_interface.diplomacy
local lasttab, lastresult = -1, nil

local function tabsdef(pages, labelSingular, labelPlural, getCivResourceList, funcGetValue)
return {
pages = pages,
labelSingular = labelSingular,
labelPlural = labelPlural,
getCivResourceList = getCivResourceList,
funcGetValue = funcGetValue,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the convention for this type of variable is to name it like get_value_fn

}
end

local Tabs = {}

local function SquashMatIndexType(matList)
local list = {}
for key, value in pairs(matList.mat_index) do
list[key] = { type = matList.mat_type[key], index = value }
end
return list
end
local function DecodeMatInfoFromSquash(mat)
return dfhack.matinfo.decode(mat.type, mat.index).material.material_value
end

table.insert(Tabs, tabsdef({ 6, 7 }, "gem", "gems",
function(resources) return resources.gems end,
function(id) return dfhack.matinfo.decode(0, id).material.material_value end)
)
table.insert(Tabs, tabsdef({ 0 }, "leather", "leathers",
function(resources) return SquashMatIndexType(resources.organic.leather) end,
DecodeMatInfoFromSquash)
)
table.insert(Tabs, tabsdef({ 29 }, "meat", "meats",
function(resources) return SquashMatIndexType(resources.misc_mat.meat) end,
DecodeMatInfoFromSquash)
)
table.insert(Tabs, tabsdef({ 62 }, "parchment", "parchments",
function(resources) return SquashMatIndexType(resources.organic.parchment) end,
DecodeMatInfoFromSquash)
)

local function GetCurrentTabId()
return diplomacy.taking_requests_tablist[diplomacy.taking_requests_selected_tab];
end

local function GetTab()
local curtab = GetCurrentTabId()
if (curtab == lasttab) then return lastresult end
lasttab = curtab
for _, tab in ipairs(Tabs) do
for _, page in ipairs(tab.pages) do
if page == curtab then
lastresult = tab
return tab
end
end
end
lastresult = nil
end

local function diplomacy_toggle_cat()
local priority_idx = diplomacy.taking_requests_tablist[diplomacy.taking_requests_selected_tab]
local priority_idx = GetCurrentTabId()
local priority = diplomacy.environment.dipev.sell_requests.priority[priority_idx]
if #priority == 0 then return end
local target_val = priority[0] == 0 and 4 or 0
Expand All @@ -26,13 +86,71 @@ local function diplomacy_toggle_cat()
end
end

local function OrderGemWithMinValue(matPrices, val)
local priority_idx = GetCurrentTabId()

local priority = diplomacy.environment.dipev.sell_requests.priority[priority_idx]
for i in ipairs(priority) do
if matPrices[i] == val then
priority[i] = 4
end
end
end

local function GetCivMatPrices(tabSelected)
local resource = tabSelected.getCivResourceList(df.historical_entity.find(diplomacy.actor.civ_id).resources)
local matPrices = {}
local matValuesUnique = {}
local filter = {}
for civid, matid in pairs(resource) do
local matPrice = tabSelected.funcGetValue(matid)
matPrices[civid] = matPrice
if not filter[matPrice] then
local val = { value = matPrice, count = 1 }
filter[matPrice] = val
table.insert(matValuesUnique, val)
else
filter[matPrice].count = filter[matPrice].count + 1
end
end
table.sort(matValuesUnique, function(a, b) return a.value < b.value end)
return matPrices, matValuesUnique
end

local function ValueSelector()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

convention for local functions is snake_case, not PascalCase (which is generally used for class names)

local currTab = GetTab()
local matPrices, matValuesUnique = GetCivMatPrices(currTab)
local list = {}
for index, value in ipairs(matValuesUnique) do
list[index] = tostring(value.value) ..
" - " .. tostring(value.count) .. " " .. (value.count == 1 and currTab.labelSingular or currTab.labelPlural)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for multi-part strings like this, it is usually cleaner to use a format string:

('%d - %d %s'):format(value.value, value.count,
    value.count == 1 and currTab.labelSingular or currTab.labelPlural)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd also suggest adding the "gear" symbol after the value to indicate price. the number-heavy string label also feels a bit user-unfriendly. we might want to post some more screenshots to the #feature-discuss Discord channel to get feedback on that.

end
dlg.showListPrompt(
"Select materials with base value", "",
COLOR_WHITE,
list,
function(id, choice)
OrderGemWithMinValue(matPrices, matValuesUnique[id].value)
end
)
end

function TradeAgreementOverlay:init()
self:addviews{
widgets.HotkeyLabel{
frame={t=0, l=0},
label='Select all/none',
key='CUSTOM_CTRL_A',
on_activate=diplomacy_toggle_cat,
self:addviews {
widgets.HotkeyLabel {
frame = { t = 0, l = 0 },
label = 'Select all/none',
key = 'CUSTOM_CTRL_A',
on_activate = diplomacy_toggle_cat,
},
}
self:addviews {
widgets.HotkeyLabel {
frame = { t = 1, l = 0 },
label = 'Select materials with value',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
label = 'Select materials with value',
label = 'Select by value',

key = 'CUSTOM_CTRL_M',
on_activate = ValueSelector,
visible = function() return GetTab() ~= nil end,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since GetTab (or get_tab, once renamed) is a function, this can just be visible=get_tab

},
}
end