From 77b33c81b10a687e6a8d91ec836e2f20ee4f8e50 Mon Sep 17 00:00:00 2001 From: Mmtrx Date: Mon, 4 Apr 2022 17:35:10 +0200 Subject: [PATCH] v1.2.3.0 filter contract types contracts list can now be filtered --- betterContracts.lua | 106 +++++++++++++++++++++----- gui/filterGui.xml | 43 +++++++++++ gui/guiProfiles.xml | 176 ++++++++++++++++++++++++++++---------------- l10n/l10n_de.xml | 2 + l10n/l10n_en.xml | 2 + l10n/l10n_fr.xml | 2 + l10n/l10n_it.xml | 2 + l10n/l10n_jp.xml | 2 + l10n/l10n_pl.xml | 2 + l10n/l10n_ru.xml | 2 + modDesc.xml | 14 +++- scripts/gui.lua | 107 ++++++++++++++++++++++++++- 12 files changed, 370 insertions(+), 90 deletions(-) create mode 100644 gui/filterGui.xml diff --git a/betterContracts.lua b/betterContracts.lua index 1e4e320..9d43de3 100644 --- a/betterContracts.lua +++ b/betterContracts.lua @@ -14,6 +14,7 @@ -- v1.2.1.0 09.02.2022 support for FS22_SupplyTransportContracts by GtX -- v1.2.2.0 30.03.2022 recognize conflict FS22_Contracts_Plus, adjust harvest keep formulas to FS22 1.3.1 -- details for transport missions +-- v1.2.3.0 04.04.2022 filter contracts per jobtype --======================================================================================================= InitRoyalUtility(Utils.getFilename("lib/utility/", g_currentModDirectory)) InitRoyalMod(Utils.getFilename("lib/rmod/", g_currentModDirectory)) @@ -85,7 +86,7 @@ function BetterContracts:initialize() self.SPEEDLIMS = {15, 12, 15, 15, 0, 10, 12, 20} self.WORKWIDTH = {42, 24, 6, 6, 0, 9, 4.9, 9} --[[ contract types: - 1 mow/ bale + 1 mow_bale 2 plow 3 cultivate 4 sow @@ -96,23 +97,25 @@ function BetterContracts:initialize() 9 transport 10 supplyTransport (Mod) ]] - self.typeToCat = {4, 3, 3, 2, 1, 3, 2, 2, 5, 6} -- mission.type to self category: harvest, spread, simple, mow, transport - self.harvest = {} -- harvest missions 1 - self.spread = {} -- sow, spray, fertilize 2 - self.simple = {} -- plow, cultivate, weed 3 - self.baling = {} -- mow/ bale 4 - self.transp = {} -- transport 5 - self.supply = {} -- supplyTransport mod 6 + -- mission.type to BC category: harvest, spread, simple, mow, transp, supply + self.typeToCat = {4, 3, 3, 2, 1, 3, 2, 2, 5, 6} + self.harvest = {} -- harvest missions 1 + self.spread = {} -- sow, spray, fertilize 2 + self.simple = {} -- plow, cultivate, weed 3 + self.mow_bale = {} -- mow/ bale 4 + self.transp = {} -- transport 5 + self.supply = {} -- supplyTransport mod 6 self.IdToCont = {} -- to find a contract from its mission id self.fieldToMission = {} -- to find a contract from its field number self.catHarvest = "BEETHARVESTING BEETVEHICLES CORNHEADERS COTTONVEHICLES CUTTERS POTATOHARVESTING POTATOVEHICLES SUGARCANEHARVESTING SUGARCANEVEHICLES" self.catSpread = "fertilizerspreaders seeders planters sprayers sprayervehicles slurrytanks manurespreaders" self.catSimple = "CULTIVATORS DISCHARROWS PLOWS POWERHARROWS SUBSOILERS WEEDERS" self.isOn = false - self.numCont = 0 -- # of contracts in our tables - self.my = {} -- will hold my gui element adresses - self.sort = 0 -- sorted status: 1 cat, 2 prof, 3 permin - self.lastSort = 0 -- last sorted status + self.numCont = 0 -- # of contracts in our tables + self.numHidden = 0 -- # of hidden (filtered) contracts + self.my = {} -- will hold my gui element adresses + self.sort = 0 -- sorted status: 1 cat, 2 prof, 3 permin + self.lastSort = 0 -- last sorted status self.buttons = { {"sortcat", g_i18n:getText("SC_sortCat")}, -- {button id, help text} {"sortprof", g_i18n:getText("SC_sortProf")}, @@ -145,7 +148,7 @@ function BetterContracts:initialize() InGameMenuContractsFrame.onFrameClose = Utils.appendedFunction(InGameMenuContractsFrame.onFrameClose, onFrameClose) InGameMenuContractsFrame.updateFarmersBox = Utils.appendedFunction(InGameMenuContractsFrame.updateFarmersBox, updateFarmersBox) InGameMenuContractsFrame.populateCellForItemInSection = Utils.appendedFunction(InGameMenuContractsFrame.populateCellForItemInSection, populateCell) - InGameMenuContractsFrame.updateList = Utils.prependedFunction(InGameMenuContractsFrame.updateList, updateList) + InGameMenuContractsFrame.updateList = Utils.overwrittenFunction(InGameMenuContractsFrame.updateList, updateList) InGameMenuContractsFrame.sortList = Utils.overwrittenFunction(InGameMenuContractsFrame.sortList, sortList) -- to allow multiple missions: MissionManager.hasFarmReachedMissionLimit = @@ -242,6 +245,52 @@ function BetterContracts:onPostLoadMap(mapNode, mapFile) for _, name in pairs(SC.CONTROLS) do self.my[name] = self.frCon.farmerBox:getDescendantById(name) end + + -- setup fieldjob types: + local fjobs = { + mow_bale = g_i18n:getText("fieldJob_jobType_baling"), + cultivate = g_i18n:getText("fieldJob_jobType_cultivating"), + fertilize = g_i18n:getText("fieldJob_jobType_fertilizing"), + harvest = g_i18n:getText("fieldJob_jobType_harvesting" ), + plow = g_i18n:getText("fieldJob_jobType_plowing"), + sow = g_i18n:getText("fieldJob_jobType_sowing"), + spray = g_i18n:getText("fieldJob_jobType_spraying"), + weed = g_i18n:getText("fieldJob_jobType_weeding"), + } + self.fieldjobs = {} + for i = 1, 8 do + local type = g_missionManager.missionTypes[i] + table.insert(self.fieldjobs, {type.typeId, type.name, fjobs[type.name]}) + end + table.sort(self.fieldjobs, function(a,b) + return a[3] < b[3] + end) + self.fieldjobs[9] = {9,"transport", g_i18n:getText("bc_other")} + -- initial state: show all types + self.filterState = { + mow_bale = true, + cultivate = true, + fertilize = true, + harvest = true, + plow = true, + sow = true, + spray = true, + weed = true, + transport = true, + supplyTransport = true + } + -- set controls for filterbox: + self.my.filterlayout = self.frCon.contractsContainer:getDescendantById("filterlayout") + self.my.hidden = self.frCon.contractsContainer:getDescendantById("hidden") + for i, name in ipairs({"fb1","fb2","fb3", + "fb4","fb5","fb6","fb7","fb8","fb9"}) do + self.my[name] = self.frCon.contractsContainer:getDescendantById(name) + local button = self.my[name] + button.onClickCallback = onClickFilterButton + button.pressed = true + -- set button text + button.elements[1]:setText(self.fieldjobs[i][3]) + end -- set callbacks for our 3 sort buttons for _, name in ipairs({"sortcat", "sortprof", "sortpmin"}) do self.my[name].onClickCallback = onClickSortButton @@ -250,9 +299,9 @@ function BetterContracts:onPostLoadMap(mapNode, mapFile) self.my[name].onFocusCallback = onHighSortButton self.my[name].onLeaveCallback = onRemoveSortButton end - -- set static texts: "SORT" - self.my.sort:setText(g_i18n:getText("SC_sort")) + self.my.filterlayout:setVisible(true) + self.my.hidden:setVisible(false) self.my.npcbox:setVisible(false) self.my.sortbox:setVisible(false) self.initialized = true @@ -277,13 +326,14 @@ function BetterContracts:loadGUI(canLoad, guiPath) else canLoad = false end + local xmlFile, layout -- load "SCGui.xml" fname = guiPath .. "SCGui.xml" if canLoad and fileExists(fname) then - local xmlFile = loadXMLFile("Temp", fname) + xmlFile = loadXMLFile("Temp", fname) local fbox = self.frCon.farmerBox g_gui:loadGuiRec(xmlFile, "GUI", fbox, self.frCon) - local layout = fbox:getDescendantById("layout") + layout = fbox:getDescendantById("layout") layout:invalidateLayout(true) -- adjust sort buttons fbox:applyScreenAlignment() fbox:updateAbsolutePosition() @@ -293,12 +343,28 @@ function BetterContracts:loadGUI(canLoad, guiPath) canLoad = false Logging.error("[GuiLoader %s] Required file '%s' could not be found!", self.name, fname) end + -- load "filterGui.xml" + fname = guiPath .. "filterGui.xml" + if canLoad and fileExists(fname) then + xmlFile = loadXMLFile("Temp", fname) + local cont = self.frCon.contractsContainer + g_gui:loadGuiRec(xmlFile, "GUI", cont, self.frCon) + layout = cont:getDescendantById("filterlayout") + cont:applyScreenAlignment() + cont:updateAbsolutePosition() + layout:invalidateLayout(true) -- adjust filter buttons + delete(xmlFile) + else + canLoad = false + Logging.error("[GuiLoader %s] Required file '%s' could not be found!", self.name, fname) + end end return canLoad end function BetterContracts:refresh() -- refresh our contract tables. Called by onFrameOpen/updateList, and every 15 sec by self:onUpdate - self.harvest, self.spread, self.simple, self.baling, self.transp = {}, {}, {}, {}, {} + self.harvest, self.spread, self.simple, self.mow_bale, self.transp, self.supply = + {}, {}, {}, {}, {}, {} self.IdToCont, self.fieldToMission = {}, {} local list = g_missionManager:getMissionsList(g_currentMission:getFarmId()) local res = {} @@ -409,7 +475,7 @@ function BetterContracts:addMission(m) permin = profit / dura / 3 * 60, reward = rew } - table.insert(self.baling, cont) + table.insert(self.mow_bale, cont) elseif cat == SC.SUPPLY then cont = { miss = m, @@ -469,4 +535,4 @@ function abstractMissionNew(isServer, superf, isClient, customMt ) self.mission = g_currentMission -- Fix for error in AbstractMission 'self.mission' still missing in Version 1.2.0.2 return self -end \ No newline at end of file +end diff --git a/gui/filterGui.xml b/gui/filterGui.xml new file mode 100644 index 0000000..e65fad8 --- /dev/null +++ b/gui/filterGui.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gui/guiProfiles.xml b/gui/guiProfiles.xml index 01aac62..3613222 100644 --- a/gui/guiProfiles.xml +++ b/gui/guiProfiles.xml @@ -1,73 +1,119 @@ - + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/l10n/l10n_de.xml b/l10n/l10n_de.xml index 31cae8f..dd31117 100644 --- a/l10n/l10n_de.xml +++ b/l10n/l10n_de.xml @@ -4,6 +4,8 @@ + + diff --git a/l10n/l10n_en.xml b/l10n/l10n_en.xml index 1ec0d50..825cc2d 100644 --- a/l10n/l10n_en.xml +++ b/l10n/l10n_en.xml @@ -4,6 +4,8 @@ + + diff --git a/l10n/l10n_fr.xml b/l10n/l10n_fr.xml index 1dd5282..489f8dd 100644 --- a/l10n/l10n_fr.xml +++ b/l10n/l10n_fr.xml @@ -4,6 +4,8 @@ + + diff --git a/l10n/l10n_it.xml b/l10n/l10n_it.xml index 760d3de..56227ce 100644 --- a/l10n/l10n_it.xml +++ b/l10n/l10n_it.xml @@ -4,6 +4,8 @@ + + diff --git a/l10n/l10n_jp.xml b/l10n/l10n_jp.xml index 48b36d9..c195512 100644 --- a/l10n/l10n_jp.xml +++ b/l10n/l10n_jp.xml @@ -4,6 +4,8 @@ + + diff --git a/l10n/l10n_pl.xml b/l10n/l10n_pl.xml index 44fc9fd..6e5e05e 100644 --- a/l10n/l10n_pl.xml +++ b/l10n/l10n_pl.xml @@ -4,6 +4,8 @@ + + diff --git a/l10n/l10n_ru.xml b/l10n/l10n_ru.xml index 31faf5c..79737dd 100644 --- a/l10n/l10n_ru.xml +++ b/l10n/l10n_ru.xml @@ -4,6 +4,8 @@ + + diff --git a/modDesc.xml b/modDesc.xml index b167668..b6c8eb2 100644 --- a/modDesc.xml +++ b/modDesc.xml @@ -1,7 +1,7 @@  Mmtrx - 1.2.2.0 + 1.2.3.0 <en>Better Contracts</en> @@ -24,6 +24,9 @@ Disclaimer: All values shown in details display are ESTIMATES. You should not take them absolutely, but rather as an indication of what contracts to prefer among others. +Changelog v1.2.3.0: +- Added display filter function for contracts list + Changelog v1.2.2.0: - Adjusted calculation of keep / deliver values for harvest / baling contracts - Added conflicts prevention with other mods @@ -48,6 +51,9 @@ Changelog v1.2.2.0: Warnung: Alle in der Detailanzeige angegebenen Werte sind GESCHÄTZT. Sie sollten sie also nicht als absolute Zahlen verstehen, sondern als Hinweis, welche Verträge vielleicht anderen vorzuziehen sind. +Changelog v1.2.3.0: +- Anzeigefilter für die Vertragsliste hinzugefügt + Changelog v1.2.2.0: - Berechnung der Mindestliefer- und Eigenmengen angepasst bei Ernte- und Gras-Verträgen - Konfliktvermeidung mit anderen Mods @@ -73,6 +79,9 @@ Ce mod permet d'améliorer le système de contrat, à la fois en solo et multijo Avertissement: toutes les valeurs indiquées dans l'affichage détaillé sont des ESTIMATIONS. Il ne faut donc pas les considérer comme des chiffres absolus, mais plutôt comme une indication des contrats qui pourraient être préférés à d'autres. +Changelog v1.2.3.0: +- Ajout d'une fonction de filtre d'affichage pour la liste des contrats + Changelog v1.2.2.0: - Calcul ajusté des valeurs de conservation et de livraison pour les contrats de récolte et de mise en balles - Ajout de la prévention des conflits avec d'autres mods @@ -97,6 +106,9 @@ Changelog v1.2.2.0: Внимание: Все значения, указанные на подробном дисплее, являются ИСКЛЮЧИТЕЛЬНЫМИ. Поэтому не следует воспринимать их как абсолютные цифры, а как указание на то, какие контракты могут быть предпочтительнее других. +Changelog v1.2.3.0: +- Added display filter function for contracts list + Changelog v1.2.2.0: - Adjusted calculation of keep / deliver values for harvest / baling contracts - Added conflicts prevention with other mods diff --git a/scripts/gui.lua b/scripts/gui.lua index f50c0d1..c7ea2a6 100644 --- a/scripts/gui.lua +++ b/scripts/gui.lua @@ -12,6 +12,7 @@ -- v1.2.0.0 18.01.2022 (Mmtrx) adapt for FS22 -- v1.2.2.0 30.03.2022 recognize conflict FS22_Contracts_Plus, -- details for transport missions +-- v1.2.3.0 04.04.2022 filter contracts per jobtype --======================================================================================================= -------------------- Gui enhance functions --------------------------------------------------- @@ -31,6 +32,7 @@ function onFrameOpen(superself, superFunc, ...) inGameMenu.refreshContractsElement_Button = nil inGameMenu.newContractsButton = nil inGameMenu.clearContractsButton = nil + FocusManager:unsetFocus(self.frCon.contractsList) -- to allow focus movement local parent = inGameMenu.menuButton[1].parent -- add new buttons @@ -148,13 +150,89 @@ function detailsButtonCallback(inGameMenu) frCon:updateDetailContents(s, i) end -function updateList(frCon) - -- if a new mission was created, update our tables, so that we can show the details - -- No:(if deleted or taken by another player, postpone refresh to next 15sec update tick) +function makeCon(m) + local missionInfo = m:getData() + return { + mission = m, + active = m.status == AbstractMission.STATUS_RUNNING, + finished = m.status == AbstractMission.STATUS_FINISHED, + possible = m.status == AbstractMission.STATUS_STOPPED, + jobType = missionInfo.jobType + } +end +function updateList(frCon,superFunc) + -- complete overwrite, to handle filterbutton settings + -- called from messageCenter on mission change events (start,dismiss,finish), + -- mission generated / deleted local self = BetterContracts - if #g_missionManager:getMissionsList(g_currentMission:getFarmId()) ~= self.numCont then + local list = g_missionManager:getMissionsList(g_currentMission:getFarmId()) + local numCont = #list + local hasMissions = numCont ~= 0 + if numCont ~= self.numCont then + -- update our own mission type tables, so that we can show the details self:refresh() end + frCon.contractsListBox:setVisible(hasMissions) + frCon.detailsBox:setVisible(hasMissions) + frCon.noContractsBox:setVisible(not hasMissions) + + frCon.contracts = {} + self.numHidden = 0 + for _, m in ipairs(list) do + local nofilter = m.status == AbstractMission.STATUS_RUNNING or + m.status == AbstractMission.STATUS_FINISHED + if nofilter or self.filterState[m.type.name] then + table.insert(frCon.contracts, makeCon(m)) + else + self.numHidden = self.numHidden +1 + end + end + frCon:sortList() + frCon.contractsList:reloadData() + self.my.hidden:setText(string.format(g_i18n:getText("bc_hidden"),self.numHidden)) + self.my.hidden:setVisible(self.numHidden > 0) +end +function filterList(typeId, show) + -- called when a filterbutton was clicked. Gui contractsFrame is up, i.e. + -- contracts list is already there. Needs some adjustments only + local self = BetterContracts + local frCon = self.frCon + local mycats = {"harvest", "spread", "simple","mow_bale","transp", "supply"} + local mycat = mycats[self.typeToCat[typeId]] + local type = g_missionManager:getMissionTypeById(typeId) + local nofilter, multi + debugPrint("*filterList - show: %s, mycat: %s, type.name %s", + show, mycat, type.name) + if show then + -- re-insert filtered contracts: + for _, c in ipairs(self[mycat]) do + nofilter = c.miss.status == AbstractMission.STATUS_RUNNING or + c.miss.status == AbstractMission.STATUS_FINISHED + -- harvest/mow/transp lists contain only one fieldjob type: + multi = mycat=="simple" or mycat=="spread" + if not nofilter and (not multi or c.miss.type == type) then + table.insert(frCon.contracts, makeCon(c.miss)) + self.numHidden = self.numHidden -1 + end + end + else + -- remove filtered-off contracts: + local remove = {} + for _, c in ipairs(frCon.contracts) do + nofilter = c.active or c.finished + if not nofilter and c.mission.type.typeId == typeId then + table.insert(remove, c) + end + end + for _, c in ipairs(remove) do + table.removeElement(frCon.contracts, c) + end + self.numHidden = self.numHidden + #remove + end + frCon:sortList() + frCon.contractsList:reloadData() + self.my.hidden:setText(string.format(g_i18n:getText("bc_hidden"),self.numHidden)) + self.my.hidden:setVisible(self.numHidden > 0) end function populateCell(frCon, list, sect, index, cell) local profit = cell:getAttribute("profit") @@ -434,6 +512,27 @@ function BetterContracts:radioButton(st) self.my[self.buttons[a][1]]:applyProfile(prof.std[a]) -- reset the other 2 self.my[self.buttons[b][1]]:applyProfile(prof.std[b]) end +function onClickFilterButton(frCon, button) + local self = BetterContracts + local index = tonumber(button.id:sub(-1)) + local typeId = self.fieldjobs[index][1] + local type = self.fieldjobs[index][2] + debugPrint("*** Filter button %s: state %s, type %d %s", button.id, + button.pressed, typeId, type) + button.pressed = not button.pressed + self.filterState[type] = button.pressed + + local prof = "myFilterDynamicTextInactive" + if button.pressed then prof = "myFilterDynamicText" end + button.elements[1]:applyProfile(prof) + + filterList(typeId, button.pressed) + -- if button "Other" clicked: + if self.supplyTransport and typeId == 9 then -- also handle type 10 supplyTransport: + self.filterState.supplyTransport = button.pressed + filterList(10, button.pressed) + end +end function onClickSortButton(frCon, button) local self, n = BetterContracts, 0 for i, bu in ipairs(self.buttons) do