├── icon_VIPOM.dds
├── FS22_VIPOrderManager_update.zip
├── Screenshots
├── Complete Order.png
├── Abort current Order.png
├── Overview VIP Orders.png
└── Controls and current Order.png
├── InfoHUD.lua
├── MyTools.lua
├── gui
├── AvailableTypesDlgFrame.lua
├── AvailableTypesDlgFrame.xml
├── OrderFrame.xml
├── guiProfiles.xml
└── OrderFrame.lua
├── VIPOrderManagerDefaults.lua
├── modDesc.xml
└── VIPOrderManager.lua
/icon_VIPOM.dds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fetty42/FS22_VIPOrderManager/HEAD/icon_VIPOM.dds
--------------------------------------------------------------------------------
/FS22_VIPOrderManager_update.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fetty42/FS22_VIPOrderManager/HEAD/FS22_VIPOrderManager_update.zip
--------------------------------------------------------------------------------
/Screenshots/Complete Order.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fetty42/FS22_VIPOrderManager/HEAD/Screenshots/Complete Order.png
--------------------------------------------------------------------------------
/Screenshots/Abort current Order.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fetty42/FS22_VIPOrderManager/HEAD/Screenshots/Abort current Order.png
--------------------------------------------------------------------------------
/Screenshots/Overview VIP Orders.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fetty42/FS22_VIPOrderManager/HEAD/Screenshots/Overview VIP Orders.png
--------------------------------------------------------------------------------
/Screenshots/Controls and current Order.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fetty42/FS22_VIPOrderManager/HEAD/Screenshots/Controls and current Order.png
--------------------------------------------------------------------------------
/InfoHUD.lua:
--------------------------------------------------------------------------------
1 | -- Author: Fetty42
2 | -- Date: 20.10.2024
3 | -- Version: 1.4.0.0
4 |
5 | InfoHUD = {}
6 |
7 | local InfoHUD_mt = Class(InfoHUD, HUDElement)
8 |
9 | function InfoHUD.new()
10 | -- print("InfoHUD.new")
11 | local hudAtlasPath = g_baseHUDFilename
12 | -- print("g_baseHUDFilename=" .. tostring(g_baseHUDFilename))
13 | local backgroundOverlay = InfoHUD.createBackground(hudAtlasPath)
14 | local self = InfoHUD:superClass().new(backgroundOverlay, nil, InfoHUD_mt)
15 |
16 | self:setVisible(false)
17 |
18 | return self
19 | end
20 |
21 | function InfoHUD.createBackground(hudAtlasPath)
22 | -- print("InfoHUD.createBackground")
23 | local width, height = getNormalizedScreenValues(table.unpack(InfoHUD.SIZE.BACKGROUND))
24 | -- local backgroundOverlay = Overlay.new('dataS/menu/blank.png', 0.5, 0.5, width, height)
25 | local backgroundOverlay = Overlay.new(hudAtlasPath, 0.5, 0.5, width, height)
26 |
27 | backgroundOverlay:setAlignment(Overlay.ALIGN_VERTICAL_TOP, Overlay.ALIGN_HORIZONTAL_LEFT)
28 | backgroundOverlay:setUVs(GuiUtils.getUVs(HUDElement.UV.FILL))
29 | backgroundOverlay:setColor(table.unpack(InfoHUD.COLOR.FRAME))
30 |
31 | return backgroundOverlay
32 | end
33 |
34 | function InfoHUD:draw()
35 | -- print("InfoHUD.draw")
36 | InfoHUD:superClass().draw(self)
37 | end
38 |
39 |
40 | InfoHUD.SIZE = {
41 | BACKGROUND = {
42 | 300,
43 | 80
44 | }
45 | }
46 |
47 | InfoHUD.COLOR = {
48 | BAR_BACKGROUND = {
49 | 1,
50 | 1,
51 | 1,
52 | 0.2
53 | },
54 | FRAME = {
55 | 0,
56 | 0,
57 | 0,
58 | 0.75
59 | }
60 | }
--------------------------------------------------------------------------------
/MyTools.lua:
--------------------------------------------------------------------------------
1 | -- ************************************************************************************************
2 | -- MyTools
3 | -- ************************************************************************************************
4 |
5 | -- Author: Fetty42
6 | -- Version: 1.0.0.0
7 |
8 | local dbPrintfOn = false
9 | local dbInfoPrintfOn = false
10 |
11 | local function dbInfoPrintf(...)
12 | if dbInfoPrintfOn then
13 | print(string.format(...))
14 | end
15 | end
16 |
17 | local function dbPrintf(...)
18 | if dbPrintfOn then
19 | print(string.format(...))
20 | end
21 | end
22 |
23 |
24 | MyTools = {}; -- Class
25 |
26 |
27 | -- global variables
28 | MyTools.dir = g_currentModDirectory
29 | MyTools.modName = g_currentModName
30 |
31 | --
32 | function MyTools:tableToString(t, separator)
33 | local str = ""
34 | for _, value in pairs(t) do
35 | if str == "" then
36 | str = tostring(value)
37 | else
38 | str = str .. separator .. tostring(value)
39 | end
40 | end
41 | return str
42 | end
43 |
44 |
45 | function MyTools:getCountElements(myTable)
46 | local i = 0
47 | for _, _ in pairs(myTable) do
48 | i = i + 1
49 | end
50 | return i
51 | end
52 |
53 | function MyTools:round(num, numDecimalPlaces)
54 | local mult = 10^(numDecimalPlaces or 0)
55 | return math.floor(num * mult + 0.5) / mult
56 | end
57 |
58 | -- Save copied tables in `copies`, indexed by original table.
59 | -- http://lua-users.org/wiki/CopyTable
60 | function MyTools:deepcopy(orig, copies)
61 | copies = copies or {}
62 | local orig_type = type(orig)
63 | local copy
64 | if orig_type == 'table' then
65 | if copies[orig] then
66 | copy = copies[orig]
67 | else
68 | copy = {}
69 | copies[orig] = copy
70 | for orig_key, orig_value in next, orig, nil do
71 | copy[MyTools:deepcopy(orig_key, copies)] = MyTools:deepcopy(orig_value, copies)
72 | end
73 | setmetatable(copy, MyTools:deepcopy(getmetatable(orig), copies))
74 | end
75 | else -- number, string, boolean, etc
76 | copy = orig
77 | end
78 | return copy
79 | end
80 |
--------------------------------------------------------------------------------
/gui/AvailableTypesDlgFrame.lua:
--------------------------------------------------------------------------------
1 | -- Author: Fetty42
2 | -- Date: 20.10.2024
3 | -- Version: 1.4.0.0
4 |
5 |
6 | local dbPrintfOn = false
7 |
8 | local function dbPrintf(...)
9 | if dbPrintfOn then
10 | print(string.format(...))
11 | end
12 | end
13 |
14 |
15 |
16 | -- AvailableTypesDlgFrame = {
17 | -- CONTROLS = {
18 | -- DIALOG_TITLE = "dialogTitleElement",
19 | -- TABLE = "overviewTable",
20 | -- TABLE_TEMPLATE = "orderRowTemplate",
21 | -- }
22 | -- }
23 |
24 | AvailableTypesDlgFrame = {
25 | CONTROLS = {
26 | "dialogTitleElement",
27 | "typesTable",
28 | "orderRowTemplate",
29 | }
30 | }
31 |
32 | local AvailableTypesDlgFrame_mt = Class(AvailableTypesDlgFrame, MessageDialog)
33 |
34 | function AvailableTypesDlgFrame.new(target, custom_mt)
35 | dbPrintf("AvailableTypesDlgFrame:new()")
36 | local self = MessageDialog.new(target, custom_mt or AvailableTypesDlgFrame_mt)
37 |
38 | self:registerControls(AvailableTypesDlgFrame.CONTROLS)
39 |
40 | return self
41 | end
42 |
43 | function AvailableTypesDlgFrame:onGuiSetupFinished()
44 | dbPrintf("AvailableTypesDlgFrame:onGuiSetupFinished()")
45 | AvailableTypesDlgFrame:superClass().onGuiSetupFinished(self)
46 | self.typesTable:setDataSource(self)
47 | self.typesTable:setDelegate(self)
48 | end
49 |
50 | function AvailableTypesDlgFrame:onCreate()
51 | dbPrintf("AvailableTypesDlgFrame:onCreate()")
52 | AvailableTypesDlgFrame:superClass().onCreate(self)
53 | end
54 |
55 |
56 | function AvailableTypesDlgFrame:onOpen()
57 | dbPrintf("AvailableTypesDlgFrame:onOpen()")
58 | AvailableTypesDlgFrame:superClass().onOpen(self)
59 | end
60 |
61 |
62 | function AvailableTypesDlgFrame:InitData(data)
63 | dbPrintf("AvailableTypesDlgFrame:InitData()")
64 |
65 | -- Fill data structure
66 | self.tableData = data
67 |
68 | -- finilaze dialog
69 | self.typesTable:reloadData()
70 |
71 | self:setSoundSuppressed(true)
72 | FocusManager:setFocus(self.typesTable)
73 | self:setSoundSuppressed(false)
74 |
75 | end
76 |
77 |
78 | function AvailableTypesDlgFrame:getNumberOfSections(list)
79 | dbPrintf("AvailableTypesDlgFrame:getNumberOfSections()")
80 | return #self.tableData
81 | end
82 |
83 |
84 | function AvailableTypesDlgFrame:getNumberOfItemsInSection(list, section)
85 | dbPrintf("AvailableTypesDlgFrame:getNumberOfItemsInSection()")
86 | return #self.tableData[section].items
87 | end
88 |
89 |
90 | function AvailableTypesDlgFrame:getTitleForSectionHeader(list, section)
91 | dbPrintf("AvailableTypesDlgFrame:getTitleForSectionHeader()")
92 | return self.tableData[section].sectionTitle
93 | end
94 |
95 |
96 | function AvailableTypesDlgFrame:populateCellForItemInSection(list, section, index, cell)
97 | dbPrintf("AvailableTypesDlgFrame:populateCellForItemInSection()")
98 | local item = self.tableData[section].items[index]
99 | cell:getAttribute("ftIcon"):setImageFilename(item.hudOverlayFilename)
100 | cell:getAttribute("ftTitle"):setText(item.title)
101 | cell:getAttribute("minOrderLevel"):setText(item.minOrderLevel)
102 | cell:getAttribute("probability"):setText(string.format("%s %%", item.probability))
103 | cell:getAttribute("quantityCorrectionFactor"):setText(string.format("%.1f", item.quantityCorrectionFactor))
104 | cell:getAttribute("msg"):setText(item.msg)
105 | end
106 |
107 |
108 | function AvailableTypesDlgFrame:onClose()
109 | dbPrintf("AvailableTypesDlgFrame:onClose()")
110 | AvailableTypesDlgFrame:superClass().onClose(self)
111 | end
112 |
113 |
114 | function AvailableTypesDlgFrame:onClickClose(sender)
115 | dbPrintf("AvailableTypesDlgFrame:onClickClose()")
116 | self:close()
117 | end
118 |
119 |
--------------------------------------------------------------------------------
/gui/AvailableTypesDlgFrame.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/gui/OrderFrame.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | />
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/gui/guiProfiles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/gui/OrderFrame.lua:
--------------------------------------------------------------------------------
1 | -- Author: Fetty42
2 | -- Date: 20.10.2024
3 | -- Version: 1.4.0.0
4 |
5 |
6 | local dbPrintfOn = false
7 |
8 | local function dbPrintf(...)
9 | if dbPrintfOn then
10 | print(string.format(...))
11 | end
12 | end
13 |
14 |
15 |
16 | OrderFrame = {
17 | CONTROLS = {
18 | DIALOG_TITLE = "dialogTitleElement",
19 | TABLE = "orderTable",
20 | TABLE_TEMPLATE = "orderRowTemplate",
21 | BUTTON_ABORT = "buttonAbort",
22 | BUTTON_TAG = "buttonTag",
23 | BUTTON_SHOWTYPES = "buttonShowTypes"
24 | }
25 | }
26 |
27 | OrderFrame.availableTypesDlg = nil
28 | source(VIPOrderManager.dir .. "MyTools.lua")
29 | source(VIPOrderManager.dir .. "gui/AvailableTypesDlgFrame.lua")
30 |
31 |
32 | local OrderFrame_mt = Class(OrderFrame, MessageDialog)
33 |
34 | function OrderFrame.new(target, custom_mt)
35 | local self = MessageDialog.new(target, custom_mt or OrderFrame_mt)
36 |
37 | self:registerControls(OrderFrame.CONTROLS)
38 |
39 | return self
40 | end
41 |
42 | function OrderFrame:onGuiSetupFinished()
43 | -- dbPrintf("OrderFrame:onGuiSetupFinished()")
44 | OrderFrame:superClass().onGuiSetupFinished(self)
45 | self.orderTable:setDataSource(self)
46 | self.orderTable:setDelegate(self)
47 | end
48 |
49 | function OrderFrame:onCreate()
50 | -- dbPrintf("OrderFrame:onCreate()")
51 | OrderFrame:superClass().onCreate(self)
52 | end
53 |
54 |
55 | function OrderFrame:onOpen()
56 | -- dbPrintf("OrderFrame:onOpen()")
57 | OrderFrame:superClass().onOpen(self)
58 | FocusManager:setFocus(self.orderTable)
59 | end
60 |
61 |
62 | function OrderFrame:setVIPOrders(VIPOrders)
63 | -- dbPrintf("OrderFrame:setVIPOrders()")
64 |
65 | -- fill table data (title, quantity, fillLevel, payout, targetStationTitle, isCompleted, mapHotspot)
66 | self.VIPOrdersData = {}
67 |
68 | -- hudOverlayFilename :: dataS/menu/hud/fillTypes/hud_fill_grass.png
69 |
70 | -- current VIPOrder
71 | for _, vipOrder in pairs(VIPOrders) do
72 | local VIPOrderData = {title = "No title", orders = {}}
73 | local payoutTotal = 0
74 | for _, vipOrderEntry in pairs(vipOrder.entries) do
75 | local orderEntry = {}
76 | orderEntry.ft = g_fillTypeManager:getFillTypeByName(vipOrderEntry.fillTypeName)
77 | if vipOrderEntry.isAnimal then
78 | orderEntry.fillLevel = string.format("%d %s", math.ceil(vipOrderEntry.fillLevel), g_i18n:getText("VIPOrderManager_Piece"))
79 | orderEntry.quantity = string.format("%d %s", vipOrderEntry.quantity, g_i18n:getText("VIPOrderManager_Piece"))
80 | else
81 | orderEntry.fillLevel = g_i18n:formatVolume(math.ceil(vipOrderEntry.fillLevel), 0)
82 | orderEntry.quantity = g_i18n:formatVolume(vipOrderEntry.quantity, 0)
83 | end
84 | orderEntry.isCompleted = math.ceil(vipOrderEntry.fillLevel) >= vipOrderEntry.quantity
85 | orderEntry.title = vipOrderEntry.title
86 |
87 | orderEntry.mapHotspot = nil
88 | if vipOrderEntry.targetStation ~= nil then
89 | orderEntry.targetStationTitle = vipOrderEntry.targetStation.owningPlaceable:getName()
90 | if vipOrderEntry.targetStation.owningPlaceable.spec_hotspots ~= nil and vipOrderEntry.targetStation.owningPlaceable.spec_hotspots.mapHotspots ~= nil then
91 |
92 | for _, mapHotspot in ipairs(vipOrderEntry.targetStation.owningPlaceable.spec_hotspots.mapHotspots) do
93 | if mapHotspot.worldX ~= nil and mapHotspot.worldZ ~= nil then
94 | orderEntry.mapHotspot = mapHotspot
95 | end
96 | end
97 | end
98 | else
99 | if vipOrderEntry.isAnimal then
100 | orderEntry.targetStationTitle = g_i18n:getText("VIPOrderManager_Automatic")
101 | else
102 | orderEntry.targetStationTitle = g_i18n:getText("VIPOrderManager_FreeChoise")
103 | end
104 | end
105 |
106 | orderEntry.payout = g_i18n:formatMoney(vipOrderEntry.payout, 0, true) -- g_i18n:formatMoney(value, bool Währung ausgeben, bool Währung vor dem Betrag?)
107 | table.insert(VIPOrderData.orders, orderEntry)
108 | payoutTotal = payoutTotal + vipOrderEntry.payout
109 | end
110 | if vipOrder == VIPOrders[1] then
111 | VIPOrderData.title = string.format(g_i18n:getText("ui_orderDlg_section_active"), vipOrder.level, g_i18n:formatMoney(payoutTotal, 0, true))
112 | else
113 | VIPOrderData.title = string.format(g_i18n:getText("ui_orderDlg_section_notactive"), vipOrder.level, g_i18n:formatMoney(payoutTotal, 0, true))
114 | end
115 | table.insert(self.VIPOrdersData, VIPOrderData)
116 | end
117 |
118 | self.orderTable:reloadData()
119 | end
120 |
121 |
122 | function OrderFrame:getNumberOfSections()
123 | return #self.VIPOrdersData
124 | end
125 |
126 |
127 | function OrderFrame:getNumberOfItemsInSection(list, section)
128 | return #self.VIPOrdersData[section].orders
129 | end
130 |
131 |
132 | function OrderFrame:getTitleForSectionHeader(list, section)
133 | -- dbPrintf("OrderFrame:getTitleForSectionHeader()")
134 | return self.VIPOrdersData[section].title
135 | end
136 |
137 |
138 | function OrderFrame:populateCellForItemInSection(list, section, index, cell)
139 | local orderEntry = self.VIPOrdersData[section].orders[index]
140 | cell:getAttribute("fillTypeIcon"):setImageFilename(orderEntry.ft.hudOverlayFilename)
141 | cell:getAttribute("ftTitle"):setText(orderEntry.title)
142 | cell:getAttribute("quantity"):setText(orderEntry.quantity)
143 | cell:getAttribute("fillLevel"):setText(orderEntry.fillLevel)
144 | cell:getAttribute("payout"):setText(orderEntry.payout)
145 | cell:getAttribute("targetStationTitle"):setText(orderEntry.targetStationTitle)
146 |
147 | local bold = section == 1 -- only the active order
148 | local color = {1, 1, 1, 1}
149 | local colorSelected = {1, 1, 1, 1}
150 |
151 | dbPrintf("section=%s | index=%s | title=%s | quantity=%s | filllevel=%s", section, index, orderEntry.title, orderEntry.quantity, orderEntry.fillLevel)
152 | if orderEntry.isCompleted then
153 | dbPrintf("order entry completed")
154 | -- color completed order entrys
155 | color = {0.2122, 0.5271, 0.0307, 1}
156 | colorSelected = {0.0781, 0.2233, 0.0478, 1}
157 | end
158 |
159 | cell:getAttribute("ftTitle").textBold = bold
160 | cell:getAttribute("quantity").textBold = bold
161 | cell:getAttribute("fillLevel").textBold = bold
162 | cell:getAttribute("payout").textBold = bold
163 | cell:getAttribute("targetStationTitle").textBold = bold
164 |
165 | cell:getAttribute("ftTitle"):setTextColor(table.unpack(color))
166 | cell:getAttribute("ftTitle"):setTextSelectedColor(table.unpack(colorSelected))
167 | cell:getAttribute("quantity").textColor = color
168 | cell:getAttribute("quantity"):setTextSelectedColor(table.unpack(colorSelected))
169 | cell:getAttribute("fillLevel").textColor = color
170 | cell:getAttribute("fillLevel"):setTextSelectedColor(table.unpack(colorSelected))
171 | cell:getAttribute("payout").textColor = color
172 | cell:getAttribute("payout"):setTextSelectedColor(table.unpack(colorSelected))
173 | cell:getAttribute("targetStationTitle").textColor = color
174 | cell:getAttribute("targetStationTitle"):setTextSelectedColor(table.unpack(colorSelected))
175 |
176 | -- dbPrintf("** Start DebugUtil.printTableRecursively() ************************************************************")
177 | -- DebugUtil.printTableRecursively(cell:getAttribute("targetStationTitle"), ".", 0, 2)
178 | -- dbPrintf("** End DebugUtil.printTableRecursively() **************************************************************\n")
179 | end
180 |
181 |
182 | function OrderFrame:onClose()
183 | -- dbPrintf("OrderFrame:onClose()")
184 | OrderFrame:superClass().onClose(self)
185 | end
186 |
187 |
188 | function OrderFrame:onClickBack(sender)
189 | -- dbPrintf("OrderFrame:onClickBack()")
190 | self:close()
191 | end
192 |
193 |
194 | function OrderFrame:onClickAbort()
195 | -- dbPrintf("OrderFrame:onClickAbort()")
196 | VIPOrderManager:AbortCurrentVIPOrder()
197 | end
198 |
199 |
200 | function OrderFrame:onListSelectionChanged(list, section, index)
201 | local orderEntry = self.VIPOrdersData[section].orders[index]
202 |
203 | self.mapHotspot = orderEntry.mapHotspot
204 | if self.mapHotspot ~= nil then
205 | self.buttonTag.disabled = false
206 | if self.mapHotspot == g_currentMission.currentMapTargetHotspot then
207 | self.buttonTag.text = string.upper(g_i18n:getText("ui_orderDlg_btnUntagSellPoint"))
208 | else
209 | self.buttonTag.text = string.upper(g_i18n:getText("ui_orderDlg_btnTagSellPoint"))
210 | end
211 | else
212 | self.buttonTag.disabled = true
213 | end
214 | end
215 |
216 |
217 | function OrderFrame:onTagLocation(m)
218 | if self.mapHotspot ~= nil then
219 | if self.mapHotspot == g_currentMission.currentMapTargetHotspot then
220 | self.buttonTag.text = string.upper(g_i18n:getText("ui_orderDlg_btnTagSellPoint"))
221 | g_currentMission:setMapTargetHotspot()
222 | else
223 | self.buttonTag.text = string.upper(g_i18n:getText("ui_orderDlg_btnUntagSellPoint"))
224 | g_currentMission:setMapTargetHotspot(self.mapHotspot)
225 | end
226 | end
227 | end
228 |
229 |
230 | function OrderFrame:onShowAvailableTypes(m)
231 | dbPrintf("OrderFrame:onShowAvailableTypes()")
232 |
233 | -- fill table
234 | local data = {}
235 |
236 | local groupNameSections = {}
237 |
238 | local sectionNotUseable = {}
239 | sectionNotUseable.sectionTitle = g_i18n:getText("ui_AvailableTypesDlg_sectionTitle_notUseable")
240 | sectionNotUseable.sectionOrder = 99
241 | sectionNotUseable.items = {}
242 | table.insert(data, sectionNotUseable)
243 |
244 | -- create table for groupName --> idx searching
245 | local groupNameSettingsByGroupNameToIdx = {}
246 | for idx, gns in pairs(VIPOrderManager.groupNameSettings) do
247 | groupNameSettingsByGroupNameToIdx[gns.groupName] = idx
248 | end
249 |
250 | local relevantFillTypes = {};
251 | VIPOrderManager:GetRelevantFillTypes(relevantFillTypes)
252 | for index, ft in pairs(relevantFillTypes) do
253 | local ftConfig = ft.ftConfig
254 |
255 | local item = {}
256 | item.title = string.format("%s (%s)", ft.title, ft.name)
257 | item.hudOverlayFilename = g_fillTypeManager:getFillTypeByName(ft.name).hudOverlayFilename
258 | item.minOrderLevel = ftConfig.minOrderLevel
259 | item.probability = ftConfig.probability
260 | item.quantityCorrectionFactor = ft.ftConfig.quantityCorrectionFactor
261 | item.sortAttribut = Utils.getNoNil(ft.animalTypeName, "")
262 |
263 | -- item.acceptingStationsString = ft.acceptingStationsString
264 |
265 | if ft.isUsable ~= nil and not ft.isUsable then
266 | item.msg = ft.notUsableMsg
267 | table.insert(sectionNotUseable.items, item)
268 | else
269 | item.msg = MyTools:tableToString(ftConfig.msg, "; ")
270 |
271 | -- add food consumtion for animals
272 | -- if ft.isAnimal then
273 | -- local strFoodConsumption = VIPOrderManager:GetAnimalFoodConsumptionPerMonthStringByFillTypeIdx(g_fillTypeManager:getFillTypeIndexByName(ft.name))
274 | -- item.msg = item.msg .. "; " .. strFoodConsumption
275 | -- end
276 |
277 |
278 | if groupNameSections[ftConfig.groupName] == nil then
279 | local newSection = {}
280 | newSection.sectionTitle = g_i18n:getText("ui_AvailableTypesDlg_sectionTitle_" .. ftConfig.groupName)
281 | newSection.sectionOrder = groupNameSettingsByGroupNameToIdx[ftConfig.groupName]
282 | if newSection.sectionTitle == nil or newSection.sectionTitle == "" or string.find(newSection.sectionTitle, "Missing '") then -- "Missing 'ui_AvailableTypesDlg_sectionTitle_fruit' in l10n_de.xml"
283 | newSection.sectionTitle = "** " .. ftConfig.groupName .. " **"
284 | end
285 |
286 | newSection.items = {}
287 | table.insert(data, newSection)
288 | groupNameSections[ftConfig.groupName] = newSection
289 | end
290 |
291 | table.insert(groupNameSections[ftConfig.groupName].items, item)
292 | end
293 | end
294 |
295 | -- order section items
296 | -- table.sort(sectionAnimal.items, function(a,b) return a.title < b.title end)
297 | table.sort(sectionNotUseable.items, CompItem)
298 |
299 | for index, section in pairs(groupNameSections) do
300 | table.sort(section.items, CompItem)
301 | end
302 |
303 | -- order sections
304 | table.sort(data, CompSection)
305 |
306 | -- create and show dialog
307 | OrderFrame.availableTypesDlg = nil
308 | local modDir = VIPOrderManager.dir
309 | g_gui:loadProfiles(modDir .. "gui/guiProfiles.xml")
310 | local availableTypesDlgFrame = AvailableTypesDlgFrame.new(g_i18n)
311 | g_gui:loadGui(modDir .. "gui/AvailableTypesDlgFrame.xml", "AvailableTypesDlgFrame", availableTypesDlgFrame)
312 | OrderFrame.availableTypesDlg = g_gui:showDialog("AvailableTypesDlgFrame")
313 |
314 | if OrderFrame.availableTypesDlg ~= nil then
315 | OrderFrame.availableTypesDlg.target:InitData(data)
316 | end
317 | dbPrintf("OrderFrame:onShowAvailableTypes() --> End function")
318 | end
319 |
320 | function CompItem(a,b)
321 | -- if a.minOrderLevel ~= b.minOrderLevel then
322 | -- return a.minOrderLevel < b.minOrderLevel
323 | if a.probability ~= b.probability then
324 | return a.probability > b.probability
325 | else
326 | return a.sortAttribut .. a.title < b.sortAttribut .. b.title
327 | end
328 | end
329 |
330 | function CompSection(a,b)
331 | return a.sectionOrder < b.sectionOrder
332 | end
--------------------------------------------------------------------------------
/VIPOrderManagerDefaults.lua:
--------------------------------------------------------------------------------
1 | -- Author: Fetty42
2 | -- Date: 20.10.2024
3 | -- Version: 1.4.0.0
4 |
5 | VIPOrderManager.isAnimalOrdersWished= true
6 |
7 | -- orders definition for order level 1 and own field area of 1 ha
8 | VIPOrderManager.countOrderItemsRange = {min=3, max=5}
9 | VIPOrderManager.quantityFactor = {min=6, max=6}
10 | -- VIPOrderManager.quantityFactor = {min=5, max=7}
11 | VIPOrderManager.payoutFactor = {min=4, max=6}
12 |
13 | -- Depending on the OrderLeven, special correction factors for count, quantity and payout
14 | VIPOrderManager.orderLevelCorrectionFactors = {}
15 | VIPOrderManager.orderLevelCorrectionFactors[1] = {0.40, 0.60, 1.00}
16 | VIPOrderManager.orderLevelCorrectionFactors[2] = {0.65, 0.80, 1.00}
17 | VIPOrderManager.orderLevelCorrectionFactors[3] = {0.90, 1.00, 1.00}
18 |
19 |
20 | -- Constants for filltype selection
21 | VIPOrderManager.fillTypesNoPriceList = {}
22 | VIPOrderManager.acceptOwnPlaceableProductionPointsAsSellingStation = true -- accept own placeable production points if fill types is not also loadable at the same time
23 |
24 |
25 | -- constants
26 | VIPOrderManager.maxVIPOrdersCount = 4 -- Count of already calculated orders (preview)
27 | VIPOrderManager.abortFeeInPercent = 35
28 | VIPOrderManager.allowSumQuantitySameFT = false -- Summarize quantity of same filetypes
29 | VIPOrderManager.ownFieldArea = 1 -- min field area
30 | VIPOrderManager.rangeAnimalAgeDifInMonths = {min=6, max=12}
31 | VIPOrderManager.rangeAnimalDummyPrice = {min=500, max=800}
32 |
33 | VIPOrderManager.limitedGroupsPercent = {} -- Max share of limited groups
34 | -- VIPOrderManager.limitedGroupsPercent["animal"] = 50
35 | -- VIPOrderManager.limitedGroupsPercent["production"] = 30
36 |
37 | VIPOrderManager.numPrioTrysForGroup = 100
38 |
39 | VIPOrderManager.groupNameSettings = {}
40 | table.insert(VIPOrderManager.groupNameSettings, {groupName="basic crop", sectionOrder=1, probability=55})
41 | table.insert(VIPOrderManager.groupNameSettings, {groupName="windrowed, silaged, chopped", sectionOrder=2, probability=25})
42 | table.insert(VIPOrderManager.groupNameSettings, {groupName="animal", sectionOrder=3, probability=65})
43 | table.insert(VIPOrderManager.groupNameSettings, {groupName="production easy", sectionOrder=4, probability=25})
44 | table.insert(VIPOrderManager.groupNameSettings, {groupName="production", sectionOrder=5, probability=20})
45 |
46 |
47 | -- overwrite group name which comes from the ftConfig defaults
48 | VIPOrderManager.defaultGroupNameOverwriting = {}
49 | VIPOrderManager.defaultGroupNameOverwriting["GOATMILK"] = "production easy"
50 | VIPOrderManager.defaultGroupNameOverwriting["FORAGE"] = "production easy"
51 |
52 |
53 | -- groupName=""
54 | -- isAllowed (true, false) - whether the fill type is offered
55 | -- minOrderLevel {(1-n)(, (1-n), (1-n))} - from which level the fill type is offered (1:default, 2:existing, 3:self owned)
56 | -- quantityCorrectionFactor (> 0) - Factor for the correction of the quantity calculation
57 | -- probability {(1-n)(, (1-n), (1-n))} - The probability with which this filltype is taken when selected. (1:default, 2:existing, 3:sef owned)
58 | VIPOrderManager.ftConfigs =
59 | {
60 | -- Not Allowed
61 | STONE = {isAllowed=false, minOrderLevel={1}, quantityCorrectionFactor=1.0, probability={0}}, -- Steine
62 | ROUNDBALE = {isAllowed=false, minOrderLevel={1}, quantityCorrectionFactor=1.0, probability={0}}, -- Rundballen
63 | ROUNDBALE_WOOD = {isAllowed=false, minOrderLevel={1}, quantityCorrectionFactor=1.0, probability={0}}, -- RundballenHolz
64 | SQUAREBALE = {isAllowed=false, minOrderLevel={1}, quantityCorrectionFactor=1.0, probability={0}}, -- Quaderballen
65 | WATER = {isAllowed=false, minOrderLevel={1}, quantityCorrectionFactor=1.0, probability={0}}, -- Wasser
66 | LIME = {isAllowed=false, minOrderLevel={1}, quantityCorrectionFactor=1.0, probability={0}}, -- Kalk
67 | SOYBEANSTRAW = {isAllowed=false, minOrderLevel={1}, quantityCorrectionFactor=1.0, probability={0}}, -- Sojabohnen Stroh
68 | EMPTYPALLET = {isAllowed=false, minOrderLevel={1}, quantityCorrectionFactor=1.0, probability={0}}, -- leere Paletten
69 |
70 | -- defaults
71 | DEFAULT_FRUITTYPE = {groupName="basic crop", isUnknown=true, isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=0.5, probability={30}}, -- for unknown fruittypes
72 | DEFAULT_FILLTYPE = {groupName="production", isUnknown=true, isAllowed=true, minOrderLevel={5,4,2}, quantityCorrectionFactor=1.0, probability={2, 5, 15}}, -- for unknown filltypes (booster possible)
73 | DEFAULT_ANIMALTYPE = {groupName="animal", isUnknown=true, isAllowed=true, minOrderLevel={4,3,2}, quantityCorrectionFactor=2.0, probability={40, 60, 70}}, -- for unknown animals (booster possible)
74 |
75 | -- standard animals (booster possible)
76 | ANIMALTYPE_CHICKEN = {groupName="animal", isAllowed=true, minOrderLevel={2,1,1}, quantityCorrectionFactor=3.0, probability={30, 40, 50}, quantityCorrectionFactorMaizePlus=1.5},
77 | ANIMALTYPE_SHEEP = {groupName="animal", isAllowed=true, minOrderLevel={3,2,1}, quantityCorrectionFactor=3.5, probability={30, 35, 50}, quantityCorrectionFactorMaizePlus=1.5},
78 | ANIMALTYPE_COW = {groupName="animal", isAllowed=true, minOrderLevel={4,3,2}, quantityCorrectionFactor=2.0, probability={20, 30, 50}, quantityCorrectionFactorMaizePlus=1.0},
79 | ANIMALTYPE_PIG = {groupName="animal", isAllowed=true, minOrderLevel={4,3,2}, quantityCorrectionFactor=5.0, probability={20, 30, 50}, quantityCorrectionFactorMaizePlus=2.5},
80 | ANIMALTYPE_HORSE = {groupName="animal", isAllowed=true, minOrderLevel={4,3,2}, quantityCorrectionFactor=0.7, probability={20, 30, 50}, quantityCorrectionFactorMaizePlus=0.7},
81 |
82 | -- other animals (booster possible)
83 | ANIMALTYPE_BULL = {groupName="animal", isAllowed=true, minOrderLevel={4,3,2}, quantityCorrectionFactor=0.4, probability={5, 7, 20}}, -- Hof Bergmann
84 | ANIMALTYPE_CAT = {groupName="animal", isAllowed=true, minOrderLevel={4,3,2}, quantityCorrectionFactor=0.2, probability={5, 7, 10}}, -- Hof Bergmann
85 | ANIMALTYPE_RABBIT = {groupName="animal", isAllowed=true, minOrderLevel={4,3,2}, quantityCorrectionFactor=1.0, probability={10, 15, 30}}, -- Hof Bergmann
86 | ANIMALTYPE_PULLET = {groupName="animal", isAllowed=true, minOrderLevel={4,3,2}, quantityCorrectionFactor=2.0, probability={20, 30, 50}}, -- Hof Bergmann
87 | ANIMALTYPE_GOAT = {groupName="animal", isAllowed=true, minOrderLevel={3,2,1}, quantityCorrectionFactor=2.0, probability={30, 35, 50}, quantityCorrectionFactorMaizePlus=1.5}, -- TerraLifePlus
88 |
89 | -- Animal products (booster possible)
90 | HONEY = {groupName="production easy", isAllowed=true, minOrderLevel={2}, quantityCorrectionFactor=0.3, probability={25}}, -- Honig
91 | EGG = {groupName="production easy", isAllowed=true, minOrderLevel={2,1,1}, quantityCorrectionFactor=0.7, probability={15, 20, 25}}, -- Eier
92 | WOOL = {groupName="production easy", isAllowed=true, minOrderLevel={3,2,1}, quantityCorrectionFactor=0.7, probability={15, 17, 25}}, -- Wolle
93 | MILK = {groupName="production easy", isAllowed=true, minOrderLevel={4,3,2}, quantityCorrectionFactor=1.0, probability={10, 15, 25}}, -- Milch
94 | GOATMILK = {groupName="production easy", isAllowed=true, minOrderLevel={4,3,2}, quantityCorrectionFactor=1.0, probability={10, 15, 25}}, -- Ziegenmilch
95 | LIQUIDMANURE = {groupName="production easy", isAllowed=true, minOrderLevel={4,3,2}, quantityCorrectionFactor=0.1, probability={10, 15, 25}}, -- Gülle
96 | MANURE = {groupName="production easy", isAllowed=true, minOrderLevel={4,3,2}, quantityCorrectionFactor=0.1, probability={10, 15, 25}}, -- Mist
97 |
98 | -- Basic crops (incl. Premium Expansion)
99 | BARLEY = {groupName="basic crop", isAllowed=true, minOrderLevel={1}, quantityCorrectionFactor=1.0, probability={30}}, -- Gerste
100 | WHEAT = {groupName="basic crop", isAllowed=true, minOrderLevel={1}, quantityCorrectionFactor=1.0, probability={30}}, -- Weizen
101 | OAT = {groupName="basic crop", isAllowed=true, minOrderLevel={1}, quantityCorrectionFactor=1.0, probability={30}}, -- Hafer
102 | CANOLA = {groupName="basic crop", isAllowed=true, minOrderLevel={1}, quantityCorrectionFactor=1.0, probability={30}}, -- Raps
103 | SORGHUM = {groupName="basic crop", isAllowed=true, minOrderLevel={1}, quantityCorrectionFactor=1.0, probability={30}}, -- Sorghumhirse
104 | SOYBEAN = {groupName="basic crop", isAllowed=true, minOrderLevel={1}, quantityCorrectionFactor=1.0, probability={30}}, -- Sojabohnen
105 | SUNFLOWER = {groupName="basic crop", isAllowed=true, minOrderLevel={2}, quantityCorrectionFactor=1.0, probability={30}}, -- Sonnenblumen
106 | MAIZE = {groupName="basic crop", isAllowed=true, minOrderLevel={2}, quantityCorrectionFactor=1.0, probability={30}}, -- Mais
107 | SUGARBEET = {groupName="basic crop", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=1.0, probability={30}}, -- Zuckerrüben
108 | POTATO = {groupName="basic crop", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=1.0, probability={30}}, -- Kartoffeln
109 | OLIVE = {groupName="basic crop", isAllowed=true, minOrderLevel={4}, quantityCorrectionFactor=1.0, probability={30}}, -- Oliven
110 | GRAPE = {groupName="basic crop", isAllowed=true, minOrderLevel={4}, quantityCorrectionFactor=1.0, probability={30}}, -- Trauben
111 | COTTON = {groupName="basic crop", isAllowed=true, minOrderLevel={5}, quantityCorrectionFactor=1.0, probability={30}}, -- Baumwolle
112 | SUGARCANE = {groupName="basic crop", isAllowed=true, minOrderLevel={5}, quantityCorrectionFactor=1.0, probability={30}}, -- Zuckerrohr
113 | PARSNIP = {groupName="basic crop", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=0.6, probability={30}, neededFruittype="PARSNIP"}, -- Premium Expansion
114 | BEETROOT = {groupName="basic crop", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=0.6, probability={30}, neededFruittype="BEETROOT"}, -- Premium Expansion
115 | CARROT = {groupName="basic crop", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=0.6, probability={30}, neededFruittype="CARROT"}, -- Premium Expansion
116 |
117 | -- Tree products
118 | WOOD = {groupName="production easy", isAllowed=true, minOrderLevel={2}, quantityCorrectionFactor=2.0, probability={30}}, -- Holz
119 | WOODCHIPS = {groupName="production easy", isAllowed=true, minOrderLevel={2}, quantityCorrectionFactor=0.8, probability={30}}, -- Hackschnitzel
120 |
121 | -- Greenhouse products (booster possible)
122 | STRAWBERRY = {groupName="production easy", isAllowed=true, minOrderLevel={3,2,1}, quantityCorrectionFactor=0.8, probability={15, 20, 30}}, -- Erdbeeren
123 | TOMATO = {groupName="production easy", isAllowed=true, minOrderLevel={3,2,1}, quantityCorrectionFactor=0.8, probability={15, 20, 30}}, -- Tomaten
124 | LETTUCE = {groupName="production easy", isAllowed=true, minOrderLevel={3,2,1}, quantityCorrectionFactor=0.8, probability={15, 20, 30}}, -- Salat
125 |
126 | -- Factory products
127 | SEEDS = {groupName="production easy", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=1.0, probability={0, 20, 20}}, -- Samen
128 | DIESEL = {groupName="production easy", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=1.0, probability={0, 20, 20}}, -- Diesel
129 | FORAGE = {groupName="production easy", isAllowed=true, minOrderLevel={2}, quantityCorrectionFactor=1.0, probability={20}},
130 | SUGARBEET_CUT = {groupName="production easy", isAllowed=true, minOrderLevel={4}, quantityCorrectionFactor=0.4, probability={20}}, -- Zuckerrübenschnitzel
131 | POTATO_CUT = {groupName="production easy", isAllowed=true, minOrderLevel={4}, quantityCorrectionFactor=0.4, probability={20}},
132 |
133 | -- Straw, grass and chaff
134 | STRAW = {groupName="windrowed, silaged, chopped", isAllowed=true, minOrderLevel={2}, quantityCorrectionFactor=0.4, probability={20}}, -- Stroh
135 | GRASS_WINDROW = {groupName="windrowed, silaged, chopped", isAllowed=true, minOrderLevel={2}, quantityCorrectionFactor=0.4, probability={20}}, -- Gras
136 | DRYGRASS_WINDROW = {groupName="windrowed, silaged, chopped", isAllowed=true, minOrderLevel={2}, quantityCorrectionFactor=0.4, probability={20}}, -- Heu
137 | SILAGE = {groupName="windrowed, silaged, chopped", isAllowed=true, minOrderLevel={2}, quantityCorrectionFactor=0.5, probability={30}, probabilityMaizePlus=20, quantityCorrectionFactorMaizePlus=0.3}, -- Silage
138 | CHAFF = {groupName="windrowed, silaged, chopped", isAllowed=true, minOrderLevel={2}, quantityCorrectionFactor=0.4, probability={30}, probabilityMaizePlus=20, quantityCorrectionFactorMaizePlus=0.3}, -- Häckselgut
139 |
140 | -- MaizePlus
141 | GRASS_FERMENTED = {groupName="windrowed, silaged, chopped", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={20}},
142 | CHOPPEDMAIZE = {groupName="windrowed, silaged, chopped", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=0.7, probability={30}},
143 | CHOPPEDMAIZE_FERMENTED = {groupName="windrowed, silaged, chopped", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=0.7, probability={30}},
144 | CCM = {groupName="production easy", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={20}},
145 | CCMRAW = {groupName="production easy", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={20}},
146 | GRAINGRIST = {groupName="production easy", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={20}},
147 |
148 | -- TerraLifePlus
149 | WINTERWHEAT = {groupName="basic crop", isAllowed=true, minOrderLevel={1}, quantityCorrectionFactor=1.0, probability={30}},
150 | WINTERBARLEY = {groupName="basic crop", isAllowed=true, minOrderLevel={1}, quantityCorrectionFactor=1.0, probability={30}},
151 | TRITICALE = {groupName="basic crop", isAllowed=true, minOrderLevel={1}, quantityCorrectionFactor=1.0, probability={30}},
152 | SPELT = {groupName="basic crop", isAllowed=true, minOrderLevel={1}, quantityCorrectionFactor=1.0, probability={30}},
153 | RYE = {groupName="basic crop", isAllowed=true, minOrderLevel={1}, quantityCorrectionFactor=1.0, probability={30}},
154 | VETCHRYE = {groupName="basic crop", isAllowed=true, minOrderLevel={1}, quantityCorrectionFactor=1.0, probability={30}},
155 | MUSTARD = {groupName="basic crop", isAllowed=true, minOrderLevel={1}, quantityCorrectionFactor=1.0, probability={30}},
156 | LINSEED = {groupName="basic crop", isAllowed=true, minOrderLevel={1}, quantityCorrectionFactor=1.0, probability={30}},
157 | SILAGEMAIZE = {groupName="basic crop", isAllowed=true, minOrderLevel={2}, quantityCorrectionFactor=1.0, probability={30}},
158 | SILAGESORGHUM = {groupName="basic crop", isAllowed=true, minOrderLevel={2}, quantityCorrectionFactor=1.0, probability={30}},
159 | STARCHPOTATO = {groupName="basic crop", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=1.0, probability={30}},
160 | FODDERBEET = {groupName="basic crop", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=1.0, probability={30}},
161 | FODDERCARROT = {groupName="basic crop", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=0.6, probability={30}},
162 | ONION = {groupName="basic crop", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=0.6, probability={30}},
163 |
164 |
165 | -- MaizePlus - only allowed if fruittype exists
166 | -- CARROT = {isAllowed=true, minOrderLevel=3, quantityCorrectionFactor=0.4, probability=70, neededFruittype="CARROT"},
167 | CLOVER_WINDROW = {groupName="windrowed, silaged, chopped", isAllowed=true, minOrderLevel={2}, quantityCorrectionFactor=0.4, probability={20}, neededFruittype="CLOVER"},
168 | DRYCLOVER_WINDROW = {groupName="windrowed, silaged, chopped", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={20}, neededFruittype="CLOVER"},
169 | CLOVER_FERMENTED = {groupName="windrowed, silaged, chopped", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={20}, neededFruittype="CLOVER"},
170 | ALFALFA_WINDROW = {groupName="windrowed, silaged, chopped", isAllowed=true, minOrderLevel={2}, quantityCorrectionFactor=0.4, probability={20}, neededFruittype="ALFALFA"},
171 | DRYALFALFA_WINDROW = {groupName="windrowed, silaged, chopped", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={20}, neededFruittype="ALFALFA"},
172 | ALFALFA_FERMENTED = {groupName="windrowed, silaged, chopped", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={20}, neededFruittype="ALFALFA"},
173 | DRYHORSEGRASS_WINDROW = {groupName="windrowed, silaged, chopped", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={20}, neededFruittype="HORSEGRASS"},
174 | HORSEGRASS_FERMENTED = {groupName="windrowed, silaged, chopped", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={20}, neededFruittype="HORSEGRASS"},
175 |
176 | -- other new Filltypes
177 | LUCERNE_WINDROW = {groupName="windrowed, silaged, chopped", isAllowed=true, minOrderLevel={2}, quantityCorrectionFactor=0.4, probability={20}, neededFruittype="LUCERNE"},
178 | DRYLUCERNE_WINDROW = {groupName="windrowed, silaged, chopped", isAllowed=true, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={20}, neededFruittype="LUCERNE"},
179 |
180 | -- MaizePlus - not allowed because is only buyable
181 | CROP_WINDROW = {isAllowed=false, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={0}},
182 | WETGRASS_WINDROW = {isAllowed=false, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={0}},
183 | SEMIDRYGRASS_WINDROW = {isAllowed=false, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={0}},
184 | BREWERSGRAIN = {isAllowed=false, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={0}},
185 | BREWERSGRAIN_FERMENTED = {isAllowed=false, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={0}},
186 | BEETPULP = {isAllowed=false, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={0}},
187 | BEETPULP_FERMENTED = {isAllowed=false, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={0}},
188 | MOLASSES = {isAllowed=false, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={0}},
189 | CLEAREDWATER = {isAllowed=false, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={0}},
190 | HAYPELLETS = {isAllowed=false, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={0}},
191 | CHICKENFOOD = {isAllowed=false, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={0}},
192 | FEEDPELLETS = {isAllowed=false, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={0}},
193 | HORSEFOOD = {isAllowed=false, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={0}},
194 | MINERALS = {isAllowed=false, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={0}},
195 | PIGFOOD2 = {isAllowed=false, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={0}},
196 | POWERFOOD = {isAllowed=false, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={0}},
197 | SHEEPFOOD = {isAllowed=false, minOrderLevel={3}, quantityCorrectionFactor=0.4, probability={0}}
198 | }
--------------------------------------------------------------------------------
/modDesc.xml:
--------------------------------------------------------------------------------
1 |
2 | Fetty42
3 | 1.4.0.0
4 |
5 | VIP Order Manager
6 | VIP Auftrags Manager
7 | Gestionnaire De Commandes VIP
8 | Менеджер VIP-заказов
9 |
10 |
11 | true" durch "false" ersetzen. Ist dann aber nur für diesen Spielstand deaktiviert.
47 |
48 | Update 1.3.1
49 | - Korrektur der nicht sichtbaren Spaltenüberschriften
50 | - kleinere Anpassungen an der Konfiguration
51 |
52 | Update 1.3.0
53 | - Ein Zielstandort kann jetzt markiert werden (Hotspot)
54 | - Tieraufträge werden jetzt unterstützt (Verkauf erfolgt um 8 Uhr morgens automatisch, wenn das angeforderte Alter erreicht ist; Gesundheit der Tiere muss bei mindestens 75% liegen)
55 | - Französische Übersetzung vervollständigt (Danke an BOB51160)
56 |
57 | Update 1.2.0
58 | - Unterstützung für MaizePlus
59 | - Wahrscheinlichkeiten für die Verwendung von jeweiligen Fülltypen
60 | - Übersetzung ins Russische (Dank an Gonimy-Vetrom)
61 |
62 | Update 1.1.1
63 | - Probleme mit eigenen Verkaufsstationen und Produktionen behoben
64 |
65 | Update 1.1.0
66 | - Berücksichtigung von bereits eigenen Tierhaltungen und Produktionen
67 | - erste kleine Multiplayer-Anpassungen (noch nicht multiplayerkompatibel)]]>
68 |
69 | true" with "false". Is then but only deactivated for this savegame
105 |
106 | Translated with www.DeepL.com/Translator (free version)
107 | Update 1.3.1
108 | - Correction of the invisible column headers
109 | - Minor adjustments to the configuration
110 |
111 | Update 1.3.0
112 | - A target location can now be marked (hotspot)
113 | - Animal orders are now supported (sale takes place automatically at 8 a.m. when the requested age is reached; health of the animals must be at least 75%)
114 | - French translation completed (thanks to BOB51160)
115 |
116 | Update 1.2.0
117 | - Support for MaizePlus
118 | - Probabilities for the use of specific fill types
119 | - Translation into Russian (thanks to Gonimy-Vetrom)
120 |
121 | Update 1.1.1
122 | - Fixed problems with own selling stations and productions
123 |
124 | Update 1.1.0
125 | - Consideration of already own animal husbandries and productions
126 | - first smal multiplayer adjustments (not yet multiplayer compatible)]]>
127 |
128 | true" par "false" à la 5e ligne. Mais cela ne sera désactivé que pour cette sauvegarde
164 |
165 | Update 1.3.1
166 | - correction des en-têtes de colonnes non visibles
167 | - ajustements mineurs de la configuration
168 |
169 | Update 1.3.0
170 | - Il est désormais possible de marquer un site cible (hotspot)
171 | - Les commandes d'animaux sont désormais prises en charge (la vente a lieu automatiquement à 8 heures du matin lorsque l'âge demandé est atteint ; la santé des animaux doit être d'au moins 75%)
172 | - Traduction française complétée (merci à BOB51160)
173 |
174 | Update 1.2.0
175 | - Prise en charge de MaizePlus
176 | - Probabilités d'utilisation de chaque type de remplissage
177 | - Traduction en russe (merci à Gonimy-Vetrom)
178 |
179 | Update 1.1.1
180 | - Correction de problèmes avec les propres points de vente et productions
181 |
182 | Update 1.1.0
183 | - Prise en compte des élevages et des productions déjà propres à l'entreprise
184 | - premières petites adaptations multijoueurs (pas encore compatibles avec le multijoueur)]]>
185 |
186 | true" con "false" nella quinta riga. Tuttavia, questo viene disattivato solo per questo punteggio
222 |
223 | Aggiornamento 1.3.1
224 | - Correzione delle intestazioni invisibili delle colonne
225 | - Piccole modifiche alla configurazione
226 |
227 | Aggiornamento 1.3.0
228 | - È ora possibile contrassegnare un luogo di destinazione (hotspot)
229 | - Gli ordini di animali sono ora supportati (la vendita avviene automaticamente alle 8 del mattino al raggiungimento dell'età richiesta; lo stato di salute degli animali deve essere almeno del 75%)
230 | - Traduzione francese completata (grazie a BOB51160)
231 |
232 | Aggiornamento 1.2.0
233 | - Supporto per MaizePlus
234 | - Probabilità di utilizzo dei rispettivi tipi di riempimento
235 | - Traduzione in russo (grazie a Gonimy-Vetrom)
236 |
237 | Aggiornamento 1.1.1
238 | - Problemi con le proprie stazioni di vendita e produzioni risolti
239 |
240 | Aggiornamento 1.1.0
241 | - Vengono Considerati allevamenti e produzioni già di proprietà
242 | - prime piccole modifiche al multiplayer (non ancora compatibile con il multiplayer)]]>
243 |
244 | true" на "false". Однако после этого она будет деактивирована только для этого балла
279 |
280 | Обновление 1.3.1
281 | - Исправление невидимых заголовков столбцов
282 | - Незначительные изменения в конфигурации
283 |
284 | Обновление 1.3.0
285 | - Теперь можно отметить местоположение цели (Hotspot)
286 | - Теперь поддерживается заказ животных (продажа происходит автоматически в 8 часов утра при достижении требуемого возраста; здоровье животных должно быть не менее 75%)
287 | - Перевод на французский язык завершен (спасибо BOB51160)
288 |
289 | Обновление 1.2.0
290 | - Поддержка MaizePlus
291 | - Вероятность использования определённого заполнения types
292 | - Перевод на русский язык (спасибо Gonimy-Vetrom)
293 |
294 | Обновление 1.1.1
295 | - Исправлены проблемы с собственными точками продаж и производствами
296 |
297 | Обновление 1.1.0
298 | - Учитывается, есть ли в собственности загоны для животных и производства
299 | - Первые небольшие корректировки для многопользовательской игры (ещё не совместим с многопользовательской игрой)]]>
300 |
301 |
302 | icon_VIPOM.dds
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 | Durchblättern VIP Aufträge
322 | Flip VIP Orders
323 | Inverser les commandes VIP
324 | Vedi Ordini VIP correnti
325 | Взглянуть VIP-заказы
326 |
327 |
328 | Anzeige des VIP Auftragsdialogs
329 | Shows VIP Orders Dialog
330 | Affiche la boîte de dialogue des commandes VIP
331 | Mostra la panoramica degli Ordini VIP
332 | Обзор VIP-заказов
333 |
334 |
335 |
336 |
337 | Abbruch aktuellen VIP Auftrag
338 | Aborting current VIP Orders
339 | Annulation des commandes VIP en cours
340 | Annulla gli Ordini VIP correnti
341 | Отказаться от текущих VIP-заказов
342 |
343 |
344 | Du musst eine Abbruchgebühr von %s bezahlen. Für die bereits abgeschlossenen Teilaufträge erhältst du %s.
345 | You have to pay a aborting fee of %s. For the already completed partial orders you will receive %s.
346 | Vous devez payer des frais d'abandon de %s. Pour les commandes partielles déjà terminées, vous recevrez %s.
347 | Devi pagare una commissione di %s per l'annullamento. Per gli ordini parziali già consegnati ricevi una somma di %s.
348 | За отказ вам необходимо возместить убытки в размере %s. За уже выполненную часть заказов вы получите %s.
349 |
350 |
351 |
352 |
353 | Aktueller VIP Auftrag
354 | Current VIP Order
355 | Commande VIP en cours
356 | Ordine VIP corrente
357 | Текущий VIP-заказ
358 |
359 |
360 | Nächster VIP Auftrag
361 | Next VIP Order
362 | Prochaine commande VIP
363 | Prossimo Ordine VIP
364 | Следующий VIP-заказ
365 |
366 |
367 | Auszahlung: %s
368 | Payout: %s
369 | Paiement: %s
370 | Pagamento: %s
371 | Выплата: %s
372 |
373 |
374 | Der aktuelle VIP-Auftrag wurde abgeschlossen.
375 | Current VIP order was completed.
376 | La commande VIP actuelle a été complétée.
377 | Ordine VIP corrente completato.
378 | Текущий VIP-заказ был завершён.
379 |
380 |
381 | Monate
382 | months
383 | Mois
384 | mesi
385 | мес.
386 |
387 |
388 | ** Freie Wahl **
389 | ** Free choice **
390 | ** Libre choix **
391 | ** Scelta libera **
392 | ** Свободный выбор **
393 |
394 |
395 | ** Automatisch **
396 | ** Automatic **
397 | ** Automatique **
398 | ** Automatico **
399 | ** Автоматический **
400 |
401 |
402 | Stk.
403 | pcs.
404 | pcs.
405 | pz.
406 | шт.
407 |
408 |
409 | %s "%s" geliefert für den aktuellen VIP-Auftrag
410 | %s "%s" delivered for the current VIP order
411 | %s "%s" livrées pour la commande VIP en cours
412 | %s "%s" consegnate per l'ordine VIP in corso
413 | %s "%s" доставленных для текущего VIP-заказа
414 |
415 |
416 |
417 |
418 | Übersicht der VIP-Aufträge
419 | Overview VIP Orders
420 | Aperçu des commandes VIP
421 | Panoramica Ordini VIP
422 | Обзор VIP-заказов
423 |
424 |
425 | Produkt
426 | Product
427 | Produit
428 | Prodotto
429 | Продукция
430 |
431 |
432 | Angefordert
433 | Requested
434 | Demandé
435 | Richiesto
436 | Запрошено
437 |
438 |
439 | Geliefert
440 | Delivered
441 | Livré
442 | Consegnato
443 | Доставлено
444 |
445 |
446 | Auszahlung
447 | Payout
448 | Paiement
449 | Pagamento
450 | Выплата
451 |
452 |
453 | Lieferstation
454 | Delivery station
455 | Poste de livraison
456 | Luogo di Consegna
457 | Станция доставки
458 |
459 |
460 | Schließen
461 | Close
462 | Fermer
463 | Chiuso
464 | Закрыть
465 |
466 |
467 | Abbruch des aktuellen VIP Auftrags
468 | Abort current VIP Order
469 | Annuler la commande VIP en cours
470 | Annulla l'Ordine VIP corrente
471 | Отказаться от текущего VIP-заказа
472 |
473 |
474 | Markierung setzen
475 | Tag place
476 | Mettre un marqueur
477 | Impostare il marcatore
478 | Установить маркер
479 |
480 |
481 | Markierung löschen
482 | Untag place
483 | Supprimer la marque
484 | Cancellare il marcatore
485 | Удалить маркер
486 |
487 |
488 | Verfügbare Lieferprodukte anzeigen
489 | Show available delivery products
490 | Afficher les produits de livraison disponibles
491 | Mostra i prodotti di consegna disponibili
492 | Показать доступные товары для доставки
493 |
494 |
495 | Level %s - Auszahlung: %s (Aktiv)
496 | Level %s - Payout: %s (Active)
497 | Level %s - Paiement: %s (Actif)
498 | Livello %s - Pagamento: %s (Attivo)
499 | Уровень %s - Выплата: %s (активный)
500 |
501 |
502 | Level %s - Auszahlung: %s
503 | Level %s - Payout: %s
504 | Level %s - Paiement: %s
505 | Livello %s - Pagamento: %s
506 | Уровень %s - Выплата: %s
507 |
508 |
509 | Verfügbare Lieferprodukte
510 | Available delivery products
511 | Produits de livraison disponibles
512 | Prodotti di consegna disponibili
513 | Доступные товары для доставки
514 |
515 |
516 | Lieferprodukt
517 | Delivery product
518 | Produit livré
519 | Consegna prodotto
520 | Продукт доставки
521 |
522 |
523 | min. Level
524 | min. level
525 | min. Level
526 | min. livello
527 | мин. уровень
528 |
529 |
530 | Wahrscheinlichkeit
531 | Probability
532 | Probabilité
533 | Probabilità
534 | Вероятность
535 |
536 |
537 | Kommentar
538 | Comment
539 | Commentaire
540 | Commento
541 | Комментарий
542 |
543 |
544 | Korr. Menge
545 | Corr. Quantity
546 | Corr. Quantité
547 | Corr. Quantità
548 | Корр. Количество
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 | Fruchttypen
557 | Fruit Types
558 | Types de remplissage disponibles
559 | Tipi di riempimento disponibili
560 | Доступные типы наполнения
561 |
562 |
563 | Fülltypen
564 | Fill Types
565 | Types de remplissage disponibles
566 | Tipi di riempimento disponibili
567 | Доступные типы наполнения
568 |
569 |
570 | Tiere
571 | Animals
572 | Types de remplissage disponibles
573 | Tipi di riempimento disponibili
574 | Доступные типы наполнения
575 |
576 |
577 | Nicht verwendbar
578 | Not Useable
579 | Types de remplissage disponibles
580 | Tipi di riempimento disponibili
581 | Доступные типы наполнения
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
--------------------------------------------------------------------------------
/VIPOrderManager.lua:
--------------------------------------------------------------------------------
1 | -- Author: Fetty42
2 | -- Date: 20.10.2024
3 | -- Version: 1.4.0.0
4 |
5 | local dbPrintfOn = false
6 | local dbInfoPrintfOn = false
7 |
8 | local function dbInfoPrintf(...)
9 | if dbInfoPrintfOn then
10 | print(string.format(...))
11 | end
12 | end
13 |
14 | local function dbPrintf(...)
15 | if dbPrintfOn then
16 | print(string.format(...))
17 | end
18 | end
19 |
20 | local function dbPrintHeader(ftName)
21 | if dbPrintfOn then
22 | print(string.format("Call %s: g_currentMission:getIsServer()=%s | g_currentMission:getIsClient()=%s", ftName, g_currentMission:getIsServer(), g_currentMission:getIsClient()))
23 | end
24 | end
25 |
26 | local function Printf(...)
27 | print(string.format(...))
28 | end
29 |
30 | VIPOrderManager = {}; -- Class
31 |
32 | -- update delay
33 | VIPOrderManager.updateDelta = 0; -- time since the last update
34 | VIPOrderManager.updateRate = 1000; -- milliseconds until next update
35 | VIPOrderManager.InitDone = false
36 |
37 | -- Info display
38 | VIPOrderManager.showVIPOrder = 1 -- 0=off, 1=Current, 2=Next
39 | VIPOrderManager.infoDisplayPastTime = 0
40 | VIPOrderManager.infoDisplayMaxShowTime = 20000 -- How long the info is displayed
41 |
42 | -- Constants for output
43 | VIPOrderManager.outputStartPoint = {x=0.01, y=0.40} -- links, mitte
44 | VIPOrderManager.outputFontSize = 0.016 -- links, mitte
45 | VIPOrderManager.colors = {}
46 | VIPOrderManager.colors[1] = {'col_white', {1, 1, 1, 1}}
47 | VIPOrderManager.colors[2] = {'col_black', {0, 0, 0, 1}}
48 | VIPOrderManager.colors[3] = {'col_grey', {0.7411, 0.7450, 0.7411, 1}}
49 | VIPOrderManager.colors[4] = {'col_blue', {0.0044, 0.15, 0.6376, 1}}
50 | VIPOrderManager.colors[5] = {'col_red', {0.8796, 0.0061, 0.004, 1}}
51 | VIPOrderManager.colors[6] = {'col_green', {0.0263, 0.3613, 0.0212, 1}}
52 | VIPOrderManager.colors[7] = {'col_yellow', {0.9301, 0.7605, 0.0232, 1}}
53 | VIPOrderManager.colors[8] = {'col_pink', {0.89, 0.03, 0.57, 1}}
54 | VIPOrderManager.colors[9] = {'col_turquoise', {0.07, 0.57, 0.35, 1}}
55 | VIPOrderManager.colors[10] = {'col_brown', {0.1912, 0.1119, 0.0529, 1}}
56 |
57 | -- global variables
58 | VIPOrderManager.dir = g_currentModDirectory
59 | VIPOrderManager.modName = g_currentModName
60 |
61 | VIPOrderManager.existingProductionOutputs = {} -- 1 --> existing | 2 --> self owned
62 | VIPOrderManager.existingAnimalHusbandryOutputs = {} -- 1 --> existing | 2 --> self owned
63 | VIPOrderManager.VIPOrders = {} -- List of orders {level, entries{[Name] = {fillTypeName, title, quantity, fillLevel, payout, targetStation, isAnimal, neededAgeInMonths}}}
64 |
65 | VIPOrderManager.outputLines = {} -- Output lines for the draw() function (text, size, bold, colorId, x, y)
66 | VIPOrderManager.infoHud = nil -- VID Order Info HUD
67 | VIPOrderManager.OrderDlg = nil
68 |
69 | VIPOrderManager.successSound = createSample("success")
70 | loadSample(VIPOrderManager.successSound, "data/sounds/ui/uiSuccess.ogg", false)
71 | VIPOrderManager.failSound = createSample("fail")
72 | loadSample(VIPOrderManager.failSound, "data/sounds/ui/uiFail.ogg", false)
73 |
74 |
75 |
76 | source(Utils.getFilename("MyTools.lua", VIPOrderManager.dir))
77 | source(Utils.getFilename("VIPOrderManagerDefaults.lua", VIPOrderManager.dir))
78 | source(Utils.getFilename("InfoHUD.lua", VIPOrderManager.dir))
79 | source(VIPOrderManager.dir .. "gui/OrderFrame.lua")
80 |
81 | function VIPOrderManager:loadMap(name)
82 | dbPrintHeader("VIPOrderManager:loadMap()")
83 |
84 | if g_currentMission:getIsClient() then
85 | Player.registerActionEvents = Utils.appendedFunction(Player.registerActionEvents, VIPOrderManager.registerActionEvents);
86 | Enterable.onRegisterActionEvents = Utils.appendedFunction(Enterable.onRegisterActionEvents, VIPOrderManager.registerActionEvents);
87 | -- VIPOrderManager.eventName = {};
88 |
89 | FSBaseMission.saveSavegame = Utils.appendedFunction(FSBaseMission.saveSavegame, VIPOrderManager.saveSettings);
90 | FSBaseMission.onFinishedLoading = Utils.appendedFunction(FSBaseMission.onFinishedLoading, VIPOrderManager.loadSettings);
91 | --VIPOrderManager:loadSettings();
92 |
93 | SellingStation.addFillLevelFromTool = Utils.overwrittenFunction(SellingStation.addFillLevelFromTool, VIPOrderManager.sellingStation_addFillLevelFromTool)
94 |
95 | g_messageCenter:subscribe(MessageType.HOUR_CHANGED, self.onHourChanged, self)
96 | end
97 | math.randomseed(getDate("%S")+getDate("%M"))
98 | end;
99 |
100 |
101 | function VIPOrderManager:onHourChanged(hour)
102 | dbPrintHeader("VIPOrderManager:onHourChanged()")
103 |
104 | if VIPOrderManager.VIPOrders ~= nil and VIPOrderManager.VIPOrders[1] ~= nil then
105 | local farmId = g_currentMission.player.farmId;
106 | local isWarning = false
107 | local currentVipOrder = VIPOrderManager.VIPOrders[1]
108 |
109 | -- prepare subType to fillType
110 | local subTypeIndexToFillTypeName
111 |
112 | for _,husbandry in pairs(g_currentMission.husbandrySystem.clusterHusbandries) do
113 | local placeable = husbandry:getPlaceable()
114 | if placeable.ownerFarmId == farmId then
115 | local placeableName = placeable:getName()
116 |
117 | dbPrintf(" - husbandry placeables: Name=%s | AnimalType=%s | NumOfAnimals=%s | getNumOfClusters=%s", placeableName, husbandry.animalTypeName, placeable:getNumOfAnimals(), placeable:getNumOfClusters())
118 |
119 | for idx, cluster in ipairs(placeable:getClusters()) do
120 | dbPrintf(" - Cluster: numAnimals=%s | age=%s | health=%s | subTypeName=%s | subTypeTitle=%s"
121 | , cluster.numAnimals, cluster.age, cluster.health, g_currentMission.animalSystem.subTypes[cluster.subTypeIndex].name, g_currentMission.animalSystem.subTypes[cluster.subTypeIndex].visuals[1].store.name)
122 |
123 | local orderEntry = currentVipOrder.entries[g_currentMission.animalSystem.subTypes[cluster.subTypeIndex].name]
124 | if orderEntry ~= nil then
125 | dbPrintf(" --> fitting order entry exists with: quantity=%s | fillLevel=%s | neededAgeInMonths=%s", orderEntry.quantity, orderEntry.fillLevel, orderEntry.neededAgeInMonths)
126 | if cluster.age >= orderEntry.neededAgeInMonths and cluster.health >= 75 then
127 | local numAninmalsToSell = math.min(orderEntry.quantity - orderEntry.fillLevel, cluster.numAnimals)
128 |
129 | if numAninmalsToSell > 0 then
130 | local sellPrice = cluster:getSellPrice() * numAninmalsToSell
131 |
132 | cluster.numAnimals = cluster.numAnimals - numAninmalsToSell
133 |
134 | -- clean up
135 | if cluster.numAnimals <= 0 then
136 | table.remove(placeable:getClusters(), idx)
137 | end
138 |
139 | local msgTxt = string.format(g_i18n:getText("VIPOrderManager_AnimalsDelivered"), numAninmalsToSell, orderEntry.title)
140 | dbPrintf(" --> " .. msgTxt)
141 | g_currentMission:addIngameNotification(FSBaseMission.INGAME_NOTIFICATION_INFO, msgTxt)
142 | g_currentMission:addMoney(sellPrice, g_currentMission.player.farmId, MoneyType.SOLD_ANIMALS, true, true);
143 |
144 | orderEntry.fillLevel = orderEntry.fillLevel + numAninmalsToSell
145 |
146 | VIPOrderManager.showVIPOrder = 1;
147 | VIPOrderManager.infoDisplayPastTime = 0
148 | VIPOrderManager:UpdateOutputLines()
149 | end
150 | end
151 | end
152 | end
153 | end
154 | end
155 | end
156 | end
157 |
158 |
159 | function VIPOrderManager:registerActionEvents()
160 | -- dbPrintHeader("VIPOrderManager:registerActionEvents()")
161 |
162 | if g_currentMission:getIsClient() then --isOwner
163 | -- local result, actionEventId = InputBinding.registerActionEvent(g_inputBinding, 'ShowCurrentVIPOrder',self, VIPOrderManager.ShowCurrentVIPOrder ,false ,true ,false ,true)
164 | local result, actionEventId = g_inputBinding:registerActionEvent('ShowCurrentVIPOrder',InputBinding.NO_EVENT_TARGET, VIPOrderManager.ShowCurrentVIPOrder ,false ,true ,false ,true)
165 | dbPrintf("Result=%s | actionEventId=%s | g_currentMission:getIsClient()=%s", result, actionEventId, g_currentMission:getIsClient())
166 | if result and actionEventId then
167 | g_inputBinding:setActionEventTextVisibility(actionEventId, true)
168 | g_inputBinding:setActionEventActive(actionEventId, true)
169 | g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_VERY_LOW) -- GS_PRIO_VERY_HIGH, GS_PRIO_HIGH, GS_PRIO_LOW, GS_PRIO_VERY_LOW
170 |
171 | -- table.insert(VIPOrderManager.eventName, actionEventId);
172 | -- g_inputBinding.events[actionEventId].displayIsVisible = true;
173 | dbPrintf("Action event inserted successfully")
174 | end
175 | local result2, actionEventId2 = g_inputBinding:registerActionEvent('ShowVIPOrderDlg',InputBinding.NO_EVENT_TARGET, VIPOrderManager.ShowVIPOrderDlg ,false ,true ,false ,true)
176 | dbPrintf("Result2=%s | actionEventId2=%s | g_currentMission:getIsClient()=%s", result2, actionEventId2, g_currentMission:getIsClient())
177 | if result2 and actionEventId2 then
178 | g_inputBinding:setActionEventTextVisibility(actionEventId2, true)
179 | g_inputBinding:setActionEventActive(actionEventId2, true)
180 | g_inputBinding:setActionEventTextPriority(actionEventId2, GS_PRIO_VERY_LOW) -- GS_PRIO_VERY_HIGH, GS_PRIO_HIGH, GS_PRIO_LOW, GS_PRIO_VERY_LOW
181 |
182 | -- table.insert(VIPOrderManager.eventName, actionEventId2);
183 | -- g_inputBinding.events[actionEventId2].displayIsVisible = true;
184 | dbPrintf("Action event inserted successfully")
185 | end
186 |
187 | if infoHud == nil then
188 | ---@diagnostic disable-next-line: lowercase-global
189 | infoHud = InfoHUD.new()
190 | infoHud:setVisible(true)
191 | end
192 | -- hud:delete()
193 | end
194 | end
195 |
196 |
197 | --
198 | function VIPOrderManager:ShowVIPOrderDlg(actionName, keyStatus, arg3, arg4, arg5)
199 | dbPrintHeader("VIPOrderManager:ShowVIPOrderDlg()")
200 |
201 | VIPOrderManager.OrderDlg = nil
202 | g_gui:loadProfiles(VIPOrderManager.dir .. "gui/guiProfiles.xml")
203 | local orderFrame = OrderFrame.new(g_i18n)
204 | g_gui:loadGui(VIPOrderManager.dir .. "gui/OrderFrame.xml", "OrderFrame", orderFrame)
205 | VIPOrderManager.OrderDlg = g_gui:showDialog("OrderFrame")
206 |
207 | if VIPOrderManager.OrderDlg ~= nil then
208 | VIPOrderManager.OrderDlg.target:setVIPOrders(VIPOrderManager.VIPOrders)
209 |
210 | end
211 |
212 | -- print("** Start DebugUtil.printTableRecursively() ************************************************************")
213 | -- print("g_currentMission:")
214 | -- DebugUtil.printTableRecursively(g_currentMission, ".", 0, 4)
215 | -- print("** End DebugUtil.printTableRecursively() **************************************************************")
216 |
217 | end
218 |
219 |
220 | -- Payout complete orders less a abort fee for incomplete orders.
221 | function VIPOrderManager:AbortCurrentVIPOrder()
222 | dbPrintHeader("VIPOrderManager:AbortCurrentVIPOrder()")
223 |
224 | local sumAbortFee, sumPayout = VIPOrderManager:GetSumAbortFeeAndSumPayout()
225 |
226 | -- g_gui:showYesNoDialog({text=g_i18n:getText("tour_text_start"), title="", callback=self.reactToDialog, target=self})
227 | local msgText = string.format(g_i18n:getText("VIPOrderManager_DlgMsg_AbortCurrentVIPOrder"), g_i18n:formatMoney(sumAbortFee, 0, true), g_i18n:formatMoney(sumPayout, 0, true))
228 | g_gui:showYesNoDialog({text=msgText, title=g_i18n:getText("VIPOrderManager_DlgTitel_AbortCurrentVIPOrder"), callback=VIPOrderManager.reactToDialog_AbortCurrentVIPOrder, target=self})
229 | end
230 |
231 |
232 | function VIPOrderManager:reactToDialog_AbortCurrentVIPOrder(yes)
233 | dbPrintHeader("VIPOrderManager:reactToDialog_AbortCurrentVIPOrder()")
234 |
235 | if yes and VIPOrderManager.VIPOrders[1] ~= nil then
236 | local sumAbortFee, sumPayout = VIPOrderManager:GetSumAbortFeeAndSumPayout()
237 |
238 | playSample(VIPOrderManager.failSound ,1 ,1 ,1 ,0 ,0)
239 |
240 | -- show message and payout
241 | -- dbPrintf(" sumAbortFee=%s | sumPayout=%s", g_i18n:formatMoney(sumAbortFee, 0, true), g_i18n:formatMoney(sumPayout, 0, true))
242 | g_currentMission:addMoney(sumPayout, g_currentMission.player.farmId, MoneyType.MISSIONS, true, true);
243 | g_currentMission:addMoney(sumAbortFee, g_currentMission.player.farmId, MoneyType.MISSIONS, true, true);
244 |
245 | table.remove(VIPOrderManager.VIPOrders, 1)
246 | VIPOrderManager:RestockVIPOrders()
247 | if VIPOrderManager.OrderDlg ~= nil then
248 | VIPOrderManager.OrderDlg.target:setVIPOrders(VIPOrderManager.VIPOrders)
249 | end
250 | end
251 | end
252 |
253 |
254 | function VIPOrderManager:GetSumAbortFeeAndSumPayout()
255 | dbPrintHeader("VIPOrderManager:GetSumAbortFeeAndSumPayout()")
256 |
257 | local sumPayout = 0
258 | local sumAbortFee = 0
259 |
260 | for _, vipOrderEntry in pairs(VIPOrderManager.VIPOrders[1].entries) do
261 | local requiredQuantity = vipOrderEntry.quantity - math.ceil(vipOrderEntry.fillLevel)
262 |
263 | if requiredQuantity > 0 then
264 | -- incomplete order ==> calculate fee (10%)
265 | sumAbortFee = sumAbortFee - (vipOrderEntry.payout / 100 * VIPOrderManager.abortFeeInPercent)
266 | else
267 | -- complete order ==> calculate payout
268 | sumPayout = sumPayout + vipOrderEntry.payout
269 | end
270 | end
271 | return sumAbortFee, sumPayout
272 | end
273 |
274 |
275 | function VIPOrderManager:RestockVIPOrders()
276 | dbPrintHeader("VIPOrderManager:RestockVIPOrders()")
277 |
278 | if g_currentMission:getIsClient() and g_currentMission.player.farmId > 0 then
279 | -- new VIPOrder
280 | local orderLevel = 0
281 | if #VIPOrderManager.VIPOrders > 0 then
282 | orderLevel = VIPOrderManager.VIPOrders[#VIPOrderManager.VIPOrders].level
283 | end
284 | while (#VIPOrderManager.VIPOrders < VIPOrderManager.maxVIPOrdersCount) do
285 | local newEntries = {}
286 | orderLevel = orderLevel + 1
287 | dbPrintf(" - Create new VIPOrder with level " .. orderLevel)
288 | VIPOrderManager:calculateAndFillOrder(newEntries, orderLevel)
289 | table.insert(VIPOrderManager.VIPOrders, {level = orderLevel, entries = newEntries})
290 | end
291 | self.showVIPOrder = 1
292 | self.infoDisplayPastTime = 0
293 | VIPOrderManager:UpdateOutputLines()
294 | end
295 | -- print("** Start DebugUtil.printTableRecursively() ************************************************************")
296 | -- DebugUtil.printTableRecursively(VIPOrderManager.VIPOrders, ".", 0, 3)
297 | -- print("** End DebugUtil.printTableRecursively() **************************************************************")
298 | end
299 |
300 |
301 | function VIPOrderManager:GetExistingProductionAndAnimalHusbandryOutputs()
302 | dbPrintHeader("VIPOrderManager:GetExistingProductionAndAnimalHusbandryOutputs()")
303 |
304 | VIPOrderManager.existingProductionOutputs = {}
305 | VIPOrderManager.existingAnimalHusbandryOutputs = {}
306 | local farmId = g_currentMission.player.farmId;
307 | local isMilk = 0
308 | local isLiquidManure = 0
309 | local isManure = 0
310 | local foundAnimalTypeNames = {}
311 |
312 | -- look for own husbandries
313 | dbPrintf(" - Num cluster Husbandries: %s", MyTools:getCountElements(g_currentMission.husbandrySystem.clusterHusbandries))
314 | for _,husbandry in pairs(g_currentMission.husbandrySystem.clusterHusbandries) do
315 | local placeable = husbandry:getPlaceable()
316 | local selfOwned = placeable.ownerFarmId == farmId
317 |
318 | local name = placeable:getName()
319 | local specHusbandryLiquidManure = placeable.spec_husbandryLiquidManure
320 | local specHusbandryMilk = placeable.spec_husbandryMilk
321 | local specHusbandryStraw = placeable.spec_husbandryStraw
322 | local isManureActive = false
323 | if specHusbandryStraw ~= nil then
324 | isManureActive = specHusbandryStraw.isManureActive
325 | end
326 |
327 | dbPrintf(" - husbandry placeables: Name=%s | selfOwned=%s | AnimalType=%s | specMilk=%s | specLiquidManure=%s | specStraw=%s | isManureActive=%s", name, selfOwned, husbandry.animalTypeName, tostring(specHusbandryMilk), tostring(specHusbandryLiquidManure), tostring(specHusbandryStraw), isManureActive)
328 |
329 | -- remember for later to list all animal subtypes
330 | foundAnimalTypeNames[husbandry.animalTypeName] = math.max(foundAnimalTypeNames[husbandry.animalTypeName] or 0, selfOwned and 2 or 1)
331 |
332 | isMilk = specHusbandryMilk ~= nil and math.max(isMilk, selfOwned and 2 or 1) or isMilk
333 | isLiquidManure = specHusbandryLiquidManure ~= nil and math.max(isLiquidManure, selfOwned and 2 or 1) or isLiquidManure
334 | isManure = isManureActive and math.max(isManure, selfOwned and 2 or 1) or isManure
335 | end
336 |
337 | -- insert animal output products
338 | if isMilk > 0 then
339 | VIPOrderManager.existingAnimalHusbandryOutputs.MILK = isMilk
340 | end
341 | if isLiquidManure > 0 then
342 | VIPOrderManager.existingAnimalHusbandryOutputs.LIQUIDMANURE = isLiquidManure
343 | end
344 | if isManure > 0 then
345 | VIPOrderManager.existingAnimalHusbandryOutputs.MANURE = isManure
346 | end
347 | if foundAnimalTypeNames["CHICKEN"] ~= nil then
348 | VIPOrderManager.existingAnimalHusbandryOutputs.EGG = foundAnimalTypeNames["CHICKEN"]
349 | end
350 | if foundAnimalTypeNames["SHEEP"] ~= nil then
351 | VIPOrderManager.existingAnimalHusbandryOutputs.WOOL = foundAnimalTypeNames["SHEEP"]
352 | end
353 | if foundAnimalTypeNames["GOAT"] ~= nil then
354 | VIPOrderManager.existingAnimalHusbandryOutputs.GOATMILK = foundAnimalTypeNames["GOAT"]
355 | end
356 |
357 | -- insert animal fill types
358 | for i, fillTypeIdx in pairs(g_fillTypeManager:getFillTypesByCategoryNames("ANIMAL HORSE")) do
359 | local fillType = g_fillTypeManager:getFillTypeByIndex(fillTypeIdx)
360 | local animalSubType = g_currentMission.animalSystem.fillTypeIndexToSubType[fillTypeIdx]
361 |
362 | if animalSubType ~= nil then
363 | local animalName = g_currentMission.animalSystem.typeIndexToName[animalSubType.typeIndex]
364 | if foundAnimalTypeNames[animalName] ~= nil then
365 | VIPOrderManager.existingAnimalHusbandryOutputs[fillType.name] = foundAnimalTypeNames[animalName]
366 | end
367 | end
368 | end
369 |
370 | -- look for own productions and insert output products
371 | dbPrintf("")
372 | dbPrintf(" - Num Production Points: %s", g_currentMission.productionChainManager:getNumOfProductionPoints())
373 | -- if g_currentMission.productionChainManager.farmIds[farmId] ~= nil and g_currentMission.productionChainManager.farmIds[farmId].productionPoints ~= nil then
374 | -- for _, productionPoint in pairs(g_currentMission.productionChainManager.farmIds[farmId].productionPoints) do
375 | if g_currentMission.productionChainManager.productionPoints ~= nil then
376 | for _, productionPoint in pairs(g_currentMission.productionChainManager.productionPoints) do
377 |
378 | local selfOwned = productionPoint:getOwnerFarmId() == farmId
379 | local name = productionPoint.owningPlaceable:getName()
380 | dbPrintf(" - Production: Name=%s | farmId=%s | selfOwned=%s", name, productionPoint:getOwnerFarmId(), selfOwned)
381 |
382 | for fillTypeId, fillLevel in pairs(productionPoint.storage.fillLevels) do
383 | local fillTypeId = fillTypeId
384 | local fillTypeName = g_currentMission.fillTypeManager.fillTypes[fillTypeId].name
385 | local fillTypeTitle = g_currentMission.fillTypeManager.fillTypes[fillTypeId].title
386 | local isInput = false
387 |
388 | -- prüfen ob input type
389 | if productionPoint.inputFillTypeIds[fillTypeId] ~= nil then
390 | isInput = productionPoint.inputFillTypeIds[fillTypeId]
391 | end
392 |
393 | for _, production in pairs(productionPoint.activeProductions) do
394 | for _, input in pairs(production.inputs) do
395 | -- status 3 = läuft nicht weil ausgang voll
396 | if input.type == fillTypeId then
397 | isInput = true
398 | end
399 | end
400 | end
401 | if not isInput then
402 | dbPrintf(" - fillTypeName=%s | fillTypeTitle=%s | isInput=%s", fillTypeName, fillTypeTitle, isInput)
403 | VIPOrderManager.existingProductionOutputs[fillTypeName] = math.max(VIPOrderManager.existingProductionOutputs[fillTypeName] or 0, selfOwned and 2 or 1)
404 | end
405 | end
406 | end
407 | end
408 |
409 | -- if dbPrintfOn then
410 | -- DebugUtil.printTableRecursively(VIPOrderManager.existingAnimalHusbandryOutputs, ".", 0, 3)
411 | -- DebugUtil.printTableRecursively(VIPOrderManager.existingProductionOutputs, ".", 0, 3)
412 | -- end
413 | end
414 |
415 |
416 | function VIPOrderManager:calculateAndFillOrder(VIPOrder, orderLevel)
417 | dbPrintHeader("VIPOrderManager:calculateAndFillOrder()")
418 |
419 | local relevantFillTypes = {};
420 | VIPOrderManager:GetRelevantFillTypes(relevantFillTypes)
421 |
422 | -- set the special corrections faktors depending on the current order level and the own field area
423 | -- for level=1, 20, 1 do
424 | -- local factorCount = ((1 + level*0.04)-0.04)
425 | -- local factorQuantity = ((1 + level*level*0.005) - 0.005)
426 | -- local factorPayout = 1/ ((1 + level*0.05) - 0.05)
427 | -- dbPrintf("Level %2i: factorCount=%f | factorQuantity=%f | factorPayout=%f",
428 | -- level, factorCount, factorQuantity, factorPayout)
429 | -- end
430 |
431 |
432 | local specCorFactorCount = orderLevel^(1/4)
433 | local specCorFactorQuantity = orderLevel^(1/3)
434 | local specCorFactorPayout = (1.0 / (specCorFactorQuantity*specCorFactorCount))*1.1
435 | dbPrintf("Create new VIP Order: Level %s", orderLevel)
436 | dbPrintf(" Initial basic correction factors:")
437 | dbPrintf(" - Count factor = %.2f", specCorFactorCount)
438 | dbPrintf(" - Quantity factor = %.2f", specCorFactorQuantity)
439 | dbPrintf(" - Payout factor = %.2f", specCorFactorPayout)
440 |
441 | local ownFieldSizeFactor = math.max(1, VIPOrderManager.ownFieldArea^(1/2))
442 | dbPrintf(" Basic correction factors adjusted by the size of the own fields:")
443 | dbPrintf(" - own field size = " .. VIPOrderManager.ownFieldArea)
444 | dbPrintf(" - own field size factor = " .. ownFieldSizeFactor)
445 | dbPrintf(" - adjusted quantity factor from %.2f to %.2f", specCorFactorQuantity, specCorFactorQuantity * ownFieldSizeFactor)
446 | dbPrintf(" - adjusted payout factor from %.2f to %.2f", specCorFactorPayout, (1.0 / (specCorFactorQuantity*specCorFactorCount))*1.1)
447 | local specCorFactorQuantity = specCorFactorQuantity * ownFieldSizeFactor
448 | local specCorFactorPayout = (1.0 / (specCorFactorQuantity*specCorFactorCount))*1.1
449 |
450 | -- if necessary overright by Correction factors for easier beginning
451 | if VIPOrderManager.orderLevelCorrectionFactors[orderLevel] ~= nil then
452 | specCorFactorCount = VIPOrderManager.orderLevelCorrectionFactors[orderLevel][1]
453 | specCorFactorQuantity = VIPOrderManager.orderLevelCorrectionFactors[orderLevel][2]
454 | specCorFactorPayout = VIPOrderManager.orderLevelCorrectionFactors[orderLevel][3]
455 | dbPrintf(" If necessary overright by Correction factors for easier beginning:")
456 | dbPrintf(" - Count factor = %.2f", specCorFactorCount)
457 | dbPrintf(" - Quantity factor = %.2f", specCorFactorQuantity)
458 | dbPrintf(" - Payout factor = %.2f", specCorFactorPayout)
459 | end
460 |
461 | -- create random order items
462 | local countFillTypes = #relevantFillTypes
463 | local countOrderItems = math.floor(math.random(VIPOrderManager.countOrderItemsRange.min, VIPOrderManager.countOrderItemsRange.max) * specCorFactorCount + 0.5)
464 | dbPrintf(" Calculate order item count:")
465 | dbPrintf(" - min count = " .. VIPOrderManager.countOrderItemsRange.min)
466 | dbPrintf(" - max count = " .. VIPOrderManager.countOrderItemsRange.max)
467 | dbPrintf(" - Count factor = " .. specCorFactorCount)
468 | dbPrintf(" ==> Count order items = " .. countOrderItems)
469 |
470 | -- local maxLimitedOrderItems = math.floor(orderLevel / 100 * VIPOrderManager.isLimitedPercentage)
471 | local activeLimits ={}
472 | -- dbPrintf(" Max allowed limited order items: %s percent from %s = %s", VIPOrderManager.isLimitedPercentage, orderLevel, maxLimitedOrderItems)
473 |
474 | local i = 0
475 | while (i < countOrderItems) do
476 | i = i + 1
477 | dbPrintf(string.format(" %s. Order Item:", i))
478 |
479 | -- dice group name
480 | local groupNameSetting = nil
481 | repeat
482 | local isNextTryForGroup = false
483 | groupNameSetting = VIPOrderManager.groupNameSettings[math.random(1, #VIPOrderManager.groupNameSettings)]
484 |
485 | local random = math.random() * 100
486 | isNextTryForGroup = random > groupNameSetting.probability
487 |
488 | until(not isNextTryForGroup)
489 |
490 | dbPrintf(" - diced group: %s", groupNameSetting.groupName)
491 |
492 |
493 | -- dice fill type
494 | local fillType = nil
495 | local relevantFillType = nil
496 | local numPrioTrysForGroup = VIPOrderManager.numPrioTrysForGroup
497 | repeat
498 | local isNextTry = false
499 | relevantFillType = relevantFillTypes[math.random(1, countFillTypes)]
500 | local ftConfig = relevantFillType.ftConfig
501 |
502 | -- is animal but not first subtype
503 | if not isNextTry and relevantFillType.isAnimal then
504 | if relevantFillType.animalTypeCount == 1 then
505 | -- select animal sub type to be used
506 | local searchAnimalTypeIndex = relevantFillType.animalTypeIndex
507 | repeat
508 | relevantFillType = relevantFillTypes[math.random(1, countFillTypes)]
509 | until(relevantFillType.isAnimal == nil or not relevantFillType.isAnimal or relevantFillType.animalTypeIndex ~= searchAnimalTypeIndex)
510 | ftConfig = relevantFillType.ftConfig
511 | else
512 | dbPrintf(" - animal %s (%s) is not first subtype of '%s '(Count=%s)", relevantFillType.name, relevantFillType.title, relevantFillType.animalTypeName, relevantFillType.animalTypeCount)
513 | isNextTry = true
514 | end
515 | end
516 |
517 | -- is not usable
518 | if not isNextTry and not relevantFillType.isUsable ~= nil and not relevantFillType.isUsable then
519 | isNextTry = true
520 | dbPrintf(" - ft %s (%s) is not usable because: %s", relevantFillType.name, relevantFillType.title, relevantFillType.notUsableMsg)
521 | end
522 |
523 | -- is order-level high enough?
524 | if not isNextTry and ftConfig.minOrderLevel > orderLevel then
525 | isNextTry = true
526 | dbPrintf(" - ft %s (%s) requireds a minimum order-level from %s. The current order-level is %s --> isNextTry=%s", relevantFillType.name, relevantFillType.title, ftConfig.minOrderLevel, orderLevel, isNextTry)
527 | end
528 |
529 | -- animal orders wished?
530 | if not isNextTry and not VIPOrderManager.isAnimalOrdersWished and relevantFillType.isAnimal then
531 | isNextTry = true
532 | dbPrintf(" - ft %s (%s) is animal but animals are not wished --> isNextTry=%s", relevantFillType.name, relevantFillType.title, isNextTry)
533 | end
534 |
535 | -- Exists probability
536 | if not isNextTry and ftConfig.probability ~= nil and ftConfig.probability < 100 then
537 | local probability = ftConfig.probability
538 | local random = math.random() * 100
539 | isNextTry = random > probability
540 | dbPrintf(" - ft %s (%s) has probability: probability=%s, random=%s --> isNextTry=%s", relevantFillType.name, relevantFillType.title, probability, random, isNextTry)
541 | end
542 |
543 | -- limited group?
544 | if not isNextTry and ftConfig.groupName ~= nil and VIPOrderManager.limitedGroupsPercent[ftConfig.groupName] ~= nil then
545 | if activeLimits[ftConfig.groupName] == nil then
546 | activeLimits[ftConfig.groupName] = math.max(1, math.floor(countOrderItems / 100 * VIPOrderManager.limitedGroupsPercent[ftConfig.groupName]))
547 | end
548 |
549 | dbPrintf(" - Existing limited order for group '%s': %s percent from %s (min 1) --> even more available: %s", ftConfig.groupName, VIPOrderManager.limitedGroupsPercent[ftConfig.groupName], countOrderItems, activeLimits[ftConfig.groupName])
550 | if activeLimits[ftConfig.groupName] <= 0 then
551 | isNextTry = true
552 | dbPrintf(" - ft %s (%s) is limited by group '%s' --> next try", relevantFillType.name, relevantFillType.title, ftConfig.groupName)
553 | else
554 | activeLimits[ftConfig.groupName] = activeLimits[ftConfig.groupName] -1
555 | dbPrintf(" --> choose limited filltype: %s (%s)", relevantFillType.name, relevantFillType.title)
556 | end
557 | end
558 |
559 | if not isNextTry and groupNameSetting.groupName ~= ftConfig.groupName then
560 | if numPrioTrysForGroup > 0 then
561 | numPrioTrysForGroup = numPrioTrysForGroup - 1
562 | dbPrintf(" -> Searching for '%s', diced %s (%s) = '%s' -> try again", groupNameSetting.groupName, relevantFillType.name, relevantFillType.title, ftConfig.groupName)
563 | isNextTry = true
564 | else
565 | dbPrintf(" -> Last searching for '%s' failed!", groupNameSetting.groupName)
566 | end
567 | end
568 |
569 | until(not isNextTry)
570 |
571 | local quantityCorrectionFactor = 1
572 | if relevantFillType.ftConfig.quantityCorrectionFactor ~= nil then
573 | quantityCorrectionFactor = relevantFillType.ftConfig.quantityCorrectionFactor
574 | end
575 |
576 | dbPrintf(" - FillType: %s (%s)| groupName = %s | filltype quantity factor = %.2f", relevantFillType.name, relevantFillType.title, relevantFillType.ftConfig.groupName, quantityCorrectionFactor)
577 |
578 | local randomQuantityFaktor = math.random(VIPOrderManager.quantityFactor.min, VIPOrderManager.quantityFactor.max) * specCorFactorQuantity
579 | local randomPayoutFactor = math.random(VIPOrderManager.payoutFactor.min, VIPOrderManager.payoutFactor.max) * specCorFactorPayout / quantityCorrectionFactor
580 | local orderItemQuantity = math.floor(randomQuantityFaktor * 1000 / relevantFillType.priceMax * quantityCorrectionFactor)
581 |
582 | -- special animal calculations
583 | local orderItemNeededAgeInMonths = nil
584 | if relevantFillType.isAnimal then
585 | orderItemNeededAgeInMonths = VIPOrderManager:getRandomNeededAgeInMonth(relevantFillType.name)
586 | --
587 | -- relevantFillType.priceMax = VIPOrderManager:GetAnimalSellPriceByFillTypeIdxAndAge(g_fillTypeManager:getFillTypeIndexByName(relevantFillType.name), orderItemNeededAgeInMonths)
588 | -- orderItemQuantity = math.floor(randomQuantityFaktor * 1000 / relevantFillType.priceMax * quantityCorrectionFactor) -- keine Verwendung von SellPrice, da zu Sprunghaft!
589 | end
590 |
591 | dbPrintf(" - final quantity factor = %.2f", randomQuantityFaktor)
592 | dbPrintf(" - final payout factor = %.2f", randomPayoutFactor)
593 |
594 |
595 | if orderItemQuantity > 1000 then
596 | orderItemQuantity = math.floor(orderItemQuantity / 1000) * 1000
597 | elseif orderItemQuantity > 100 then
598 | orderItemQuantity = math.floor(orderItemQuantity / 100) * 100
599 | elseif orderItemQuantity > 10 then
600 | orderItemQuantity = math.floor(orderItemQuantity / 10) * 10
601 | end
602 | dbPrintf(" ==> Quantity = %.2f * 1000 / %.2f * %.2f = %s", randomQuantityFaktor, relevantFillType.priceMax, quantityCorrectionFactor, orderItemQuantity)
603 |
604 | local orderItemPayout = math.floor(orderItemQuantity * relevantFillType.priceMax * randomPayoutFactor/100)*100
605 | dbPrintf(" ==> Payout = %.2f * %.2f * %.2f = %s", orderItemQuantity, relevantFillType.priceMax, randomPayoutFactor, orderItemPayout)
606 |
607 | -- target station
608 | local orderItemTargetStation = nil
609 | if #relevantFillType.acceptingStations > 0 then
610 | orderItemTargetStation = relevantFillType.acceptingStations[math.random(1, #relevantFillType.acceptingStations)]
611 | dbPrintf(" ==> target station = %s", orderItemTargetStation.owningPlaceable:getName())
612 | end
613 |
614 | if VIPOrder[relevantFillType.name] ~= nil then
615 | if VIPOrderManager.allowSumQuantitySameFT and not relevantFillType.isAnimal then
616 | -- Summ double entries
617 | VIPOrder[relevantFillType.name].quantity = VIPOrder[relevantFillType.name].quantity + orderItemQuantity/2
618 | VIPOrder[relevantFillType.name].payout = VIPOrder[relevantFillType.name].payout + orderItemPayout/2
619 | dbPrintf(" Double --> Sum order items")
620 | else
621 | i = i - 1 -- try again
622 | dbPrintf(" Double --> discard current order item and try again")
623 | end
624 | else
625 | local orderItemTitle = relevantFillType.title
626 | if relevantFillType.isAnimal then
627 | orderItemTitle = VIPOrderManager:GetAnimalTitleByFillTypeIdx(g_fillTypeManager:getFillTypeIndexByName(relevantFillType.name), orderItemNeededAgeInMonths)
628 | end
629 |
630 | VIPOrder[relevantFillType.name] = {fillTypeName=relevantFillType.name, title=orderItemTitle, quantity=orderItemQuantity, fillLevel=0, payout=orderItemPayout, targetStation=orderItemTargetStation, isAnimal=relevantFillType.isAnimal, neededAgeInMonths=orderItemNeededAgeInMonths}
631 | end
632 | end
633 | end
634 |
635 |
636 | -- animalSubType.sellPrice.keyframes[]
637 | -- [1] = verkaufspreis
638 | -- time = ab alter
639 | function VIPOrderManager:GetAnimalSellPriceByFillTypeIdxAndAge(fillTypeIdx, neededAgeInMonths)
640 | local animalSubType = g_currentMission.animalSystem.fillTypeIndexToSubType[fillTypeIdx]
641 | local animalSellPrice = 0
642 | local animalAge = neededAgeInMonths == nil and 0 or neededAgeInMonths
643 |
644 | for i, sellPriceKeyframe in pairs(animalSubType.sellPrice.keyframes) do
645 | if animalAge >= sellPriceKeyframe.time then
646 | animalSellPrice = sellPriceKeyframe[1]
647 | end
648 | end
649 | return animalSellPrice
650 | end
651 |
652 | -- animalSubType.input.food.keyframes[]
653 | -- [1] = menge futter
654 | -- time = ab alter
655 | function VIPOrderManager:GetAnimalFoodConsumptionPerMonthByFillTypeIdxAndAge(fillTypeIdx, neededAgeInMonths)
656 | local animalSubType = g_currentMission.animalSystem.fillTypeIndexToSubType[fillTypeIdx]
657 | local animalFoodConsumptionPerMonth = 0
658 | local animalAge = neededAgeInMonths == nil and 0 or neededAgeInMonths
659 |
660 | for i, foodKeyframe in pairs(animalSubType.input.food.keyframes) do
661 | if animalAge >= foodKeyframe.time then
662 | animalFoodConsumptionPerMonth = foodKeyframe[1]
663 | end
664 | end
665 | return animalFoodConsumptionPerMonth
666 | end
667 |
668 |
669 | function VIPOrderManager:GetAnimalFoodConsumptionPerMonthStringByFillTypeIdx(fillTypeIdx)
670 | local animalSubType = g_currentMission.animalSystem.fillTypeIndexToSubType[fillTypeIdx]
671 | local animalFoodConsumptionPerMonth = 0
672 | local animalAge = neededAgeInMonths == nil and 0 or neededAgeInMonths
673 |
674 | local output = "Monthly Food Consumption per Age:"
675 | for i, foodKeyframe in pairs(animalSubType.input.food.keyframes) do
676 | local str = string.format("%s->%s | ", foodKeyframe.time, foodKeyframe[1])
677 | output = output .. str
678 | end
679 | return output
680 | end
681 |
682 |
683 |
684 | function VIPOrderManager:getRandomNeededAgeInMonth(fillTypeName)
685 | local animalSubType = g_currentMission.animalSystem.nameToSubType[fillTypeName]
686 | local maxMinAge = animalSubType.visuals[#animalSubType.visuals].minAge
687 |
688 | local desiredDiff = math.random(VIPOrderManager.rangeAnimalAgeDifInMonths.min, VIPOrderManager.rangeAnimalAgeDifInMonths.max)
689 | return maxMinAge + desiredDiff
690 | end
691 |
692 |
693 | function VIPOrderManager:CalculateOwnFieldArea()
694 | dbPrintHeader("VIPOrderManager:CalculateOwnFieldArea()")
695 |
696 | -- Calculate full farmland
697 | local farmlands = g_farmlandManager:getOwnedFarmlandIdsByFarmId(g_currentMission.player.farmId)
698 |
699 | local fieldAreaOverall = 0.0
700 | for i, id in pairs(farmlands) do
701 | local farmland = g_farmlandManager:getFarmlandById(id)
702 |
703 | -- Fields area
704 | local fieldCount = 0
705 | local fieldAreaSum = 0.0
706 | local fields = g_fieldManager.farmlandIdFieldMapping[farmland.id]
707 | if fields ~= nil then
708 | for fieldIndex, field in pairs(fields) do
709 | fieldCount = fieldCount + 1
710 | fieldAreaSum = fieldAreaSum + field.fieldArea
711 | dbPrintf(" Field: fieldId=%s | name=%s | fieldArea =%s", field.fieldId, field.name, g_i18n:formatArea(field.fieldArea, 2))
712 | end
713 | end
714 |
715 | if fieldCount > 0 and fieldAreaSum <= 0.01 and farmland.totalFieldArea ~= nil then
716 | dbPrintf(" sum single field sizes to small --> using farmland.totalFieldArea")
717 | fieldAreaSum = farmland.totalFieldArea
718 | end
719 |
720 | fieldAreaOverall = fieldAreaOverall + fieldAreaSum
721 |
722 | dbPrintf(" --> %s. Owned Farmland: id=%s | FieldCount=%s | FieldAreaSum=%s", i, farmland.id, fieldCount, g_i18n:formatArea(fieldAreaSum, 2))
723 | end
724 | dbPrintf(" ==> Field Area Overall: %s", g_i18n:formatArea(fieldAreaOverall, 2))
725 |
726 | -- if fieldAreaOverall > 0.01 then
727 | -- return math.ceil(fieldAreaOverall*100)/100
728 | -- else
729 | -- return 0
730 | -- end
731 |
732 | return MyTools:round(fieldAreaOverall, 2)
733 | end
734 |
735 |
736 | function VIPOrderManager:GetFillTypeConfig(possibleFT)
737 | -- dbPrintHeader("VIPOrderManager:GetFillTypeConfig()")
738 |
739 | local ftName = possibleFT.name
740 | local isAnimal = possibleFT.isAnimal
741 | local ftConfig = VIPOrderManager.ftConfigs[ftName]
742 |
743 | if ftConfig == nil then
744 | if g_fruitTypeManager:getFruitTypeByName(ftName) ~= nil and not isAnimal then
745 | ftConfig = VIPOrderManager.ftConfigs["DEFAULT_FRUITTYPE"]
746 | dbInfoPrintf("VIPOrderManager - '%s': fruit type without config. Take config 'DEFAULT_FRUITTYPE'", ftName)
747 | elseif isAnimal then
748 | local configName = "ANIMALTYPE_" .. string.upper(possibleFT.animalTypeName)
749 | if VIPOrderManager.ftConfigs[configName] == nil then
750 | configName = "DEFAULT_ANIMALTYPE"
751 | if possibleFT.animalTypeCount == 1 then -- print only once
752 | dbInfoPrintf("VIPOrderManager - '%s': animal type without config. Take config 'DEFAULT_ANIMALTYPE'", animalTypeName)
753 | end
754 | end
755 |
756 | ftConfig = VIPOrderManager.ftConfigs[configName]
757 | else
758 | ftConfig = VIPOrderManager.ftConfigs["DEFAULT_FILLTYPE"]
759 | dbInfoPrintf("VIPOrderManager - '%s': fill type without config. Take config 'DEFAULT_FILLTYPE'", ftName)
760 | end
761 |
762 | VIPOrderManager.ftConfigs[ftName] = ftConfig
763 | end
764 |
765 | local ftConfigCopy = MyTools:deepcopy(ftConfig)
766 | ftConfigCopy.minOrderLevel = ftConfig.minOrderLevel[1]
767 | ftConfigCopy.probability = ftConfig.probability[1]
768 | ftConfigCopy.msg = {}
769 |
770 | if VIPOrderManager.defaultGroupNameOverwriting[ftName] ~= nil then
771 | ftConfigCopy.groupName = VIPOrderManager.defaultGroupNameOverwriting[ftName]
772 | end
773 |
774 |
775 | -- ftconfig overwrite for minOrderLevel and probability if fitting AnimalHusbandry already exists
776 | if VIPOrderManager.existingAnimalHusbandryOutputs[ftName] and (possibleFT.isUsable == nil or possibleFT.isUsable) then
777 | local existingOrSelfOwnedLevel = VIPOrderManager.existingAnimalHusbandryOutputs[ftName]
778 |
779 | if ftConfig.minOrderLevel ~= nil and ftConfig.minOrderLevel[2] ~= nil and ftConfig.minOrderLevel[3] ~= nil then
780 | local msg
781 | ftConfigCopy.minOrderLevel = ftConfig.minOrderLevel[existingOrSelfOwnedLevel+1]
782 | if existingOrSelfOwnedLevel == 1 then
783 | msg = string.format("Decrease 'minOrderLevel' as animal husbandry already exists but is not owned: %s --> %s", ftConfig.minOrderLevel[1], ftConfigCopy.minOrderLevel)
784 | else
785 | msg = string.format("Decrease 'minOrderLevel' as animal husbandry is already owned: %s --> %s", ftConfig.minOrderLevel[1], ftConfigCopy.minOrderLevel)
786 | end
787 | dbPrintf(" - " .. msg)
788 | table.insert(ftConfigCopy.msg, msg)
789 | end
790 |
791 | if ftConfig.probability ~= nil and ftConfig.probability[2] ~= nil and ftConfig.probability[3] ~= nil then
792 | local msg
793 | ftConfigCopy.probability = ftConfig.probability[existingOrSelfOwnedLevel+1]
794 | if existingOrSelfOwnedLevel == 1 then
795 | msg = string.format("Increase 'Probability' as animal husbandry already exists but is not owned: %s --> %s", ftConfig.probability[1], ftConfigCopy.probability)
796 | else
797 | msg = string.format("Increase 'Probability' as animal husbandry is already owned: %s --> %s", ftConfig.probability[1], ftConfigCopy.probability)
798 | end
799 | dbPrintf(" - " .. msg)
800 | table.insert(ftConfigCopy.msg, msg)
801 | end
802 | end
803 |
804 | -- ftconfig overwrite for minOrderLevel and probability if fitting Production already exists
805 | if VIPOrderManager.existingProductionOutputs[ftName] and ftConfigCopy.msg[1] == nil and (possibleFT.isUsable == nil or possibleFT.isUsable) then
806 | local existingOrSelfOwnedLevel = VIPOrderManager.existingProductionOutputs[ftName]
807 |
808 | if ftConfig.minOrderLevel ~= nil and ftConfig.minOrderLevel[2] ~= nil and ftConfig.minOrderLevel[3] ~= nil then
809 | local msg
810 | ftConfigCopy.minOrderLevel = ftConfig.minOrderLevel[existingOrSelfOwnedLevel+1]
811 | if existingOrSelfOwnedLevel == 1 then
812 | msg = string.format("Decrease 'minOrderLevel' as production already exists but is not owned: %s --> %s", ftConfig.minOrderLevel[1], ftConfigCopy.minOrderLevel)
813 | else
814 | msg = string.format("Decrease 'minOrderLevel' as production is already owned: %s --> %s", ftConfig.minOrderLevel[1], ftConfigCopy.minOrderLevel)
815 | end
816 | dbPrintf(" - " .. msg)
817 | table.insert(ftConfigCopy.msg, msg)
818 | end
819 |
820 | if ftConfig.probability ~= nil and ftConfig.probability[2] ~= nil and ftConfig.probability[3] ~= nil then
821 | local msg
822 | ftConfigCopy.probability = ftConfig.probability[existingOrSelfOwnedLevel+1]
823 | if existingOrSelfOwnedLevel == 1 then
824 | msg = string.format("Increase 'Probability' as production already exists but is not owned: %s --> %s", ftConfig.probability[1], ftConfigCopy.probability)
825 | else
826 | msg = string.format("Increase 'Probability' as production is already owned: %s --> %s", ftConfig.probability[1], ftConfigCopy.probability)
827 | end
828 | dbPrintf(" - " .. msg)
829 | table.insert(ftConfigCopy.msg, msg)
830 | end
831 | end
832 |
833 | -- ftconfig overwrite for quantityCorrectionFactor if FS22_MaizePlus mod is present and loaded
834 | local isMaizePlus = g_modManager:getModByName("FS22_MaizePlus") ~= nil and g_modIsLoaded["FS22_MaizePlus"]
835 | local isTerraLifePlus = g_modManager:getModByName("FS22_TerraLifePlus") ~= nil and g_modIsLoaded["FS22_TerraLifePlus"] and VIPOrderManager:isTerraLife()
836 | if isMaizePlus or isTerraLifePlus then
837 | if ftConfig.quantityCorrectionFactorMaizePlus ~= nil then
838 | ftConfigCopy.quantityCorrectionFactor = ftConfig.quantityCorrectionFactorMaizePlus
839 | local msg = string.format("Overwrite 'quantityCorrectionFactor' as MOD MaizePlus/TerraLifePlus is in use: %s --> %s", ftConfig.quantityCorrectionFactor, ftConfigCopy.quantityCorrectionFactor)
840 | dbPrintf(" - " .. msg)
841 | table.insert(ftConfigCopy.msg, msg)
842 | end
843 |
844 | if ftConfig.probabilityMaizePlus ~= nil then
845 | local msg = string.format("Overwrite 'probability' as MOD MaizePlus/TerraLifePlus is in use: %s --> %s", ftConfigCopy.probability, ftConfig.probabilityMaizePlus)
846 | ftConfigCopy.probability = ftConfig.probabilityMaizePlus
847 | dbPrintf(" - " .. msg)
848 | table.insert(ftConfigCopy.msg, msg)
849 | end
850 | end
851 |
852 | return ftConfigCopy
853 | end
854 |
855 |
856 | function VIPOrderManager:GetRelevantFillTypes(relevantFillTypes)
857 | dbPrintHeader("VIPOrderManager:GetRelevantFillTypes()")
858 |
859 | VIPOrderManager.ownFieldArea = VIPOrderManager:CalculateOwnFieldArea()
860 | VIPOrderManager:GetExistingProductionAndAnimalHusbandryOutputs()
861 |
862 |
863 | local possibleFillTypes = {}
864 | VIPOrderManager:addAllSellableFillTypes(possibleFillTypes)
865 | VIPOrderManager:addAllAnimalFillTypes(possibleFillTypes)
866 |
867 | if dbPrintfOn then
868 | dbPrintf(" Possible filltypes:")
869 | for index, possibleFT in pairs(possibleFillTypes) do
870 | local tempNameOutput = string.format("%s (%s)", possibleFT.name, possibleFT.title)
871 | dbPrintf(" - %-50s: priceMax=%5.3f | pricePerLiter=%5.3f | literPerSqm=%5.3f| Stations=%s", tempNameOutput, possibleFT.priceMax, possibleFT.pricePerLiter, possibleFT.literPerSqm, possibleFT.acceptingStationsString)
872 | end
873 | dbPrintf("")
874 | end
875 |
876 | -- Validate FillTypes
877 | dbPrintf("Validating filltypes:")
878 | for index, possibleFT in pairs(possibleFillTypes) do
879 | dbPrintf(" Validate FillTypes: " .. index .. " --> " .. possibleFT.name .. " (" .. possibleFT.title .. ")")
880 | local notUsableWarning = nil
881 | local tempNameOutput = string.format("%s (%s)", possibleFT.name, possibleFT.title)
882 | local defaultWarningText = string.format(" - %-50s | pricePerLiterMax=%f | ", tempNameOutput, possibleFT.priceMax)
883 | local ftConfig = VIPOrderManager:GetFillTypeConfig(possibleFT)
884 | possibleFT.ftConfig = ftConfig
885 |
886 | -- not allowed
887 | if notUsableWarning == nil and not ftConfig.isAllowed then
888 | notUsableWarning = "Not usable, because is not allowed per definition"
889 | end
890 |
891 | -- not allowed because probability == 0
892 | if notUsableWarning == nil and ftConfig.probability == 0 then
893 | notUsableWarning = "Not usable, because probability = 0"
894 | end
895 |
896 |
897 | -- existing fruittype is not useable
898 | local fruitType = g_fruitTypeManager:getFruitTypeByName(possibleFT.name)
899 | if notUsableWarning == nil and fruitType ~= nil and not fruitType.shownOnMap then
900 | notUsableWarning = string.format("Not usable, because the current map does not support this existing fruittype (not shown on map)")
901 | end
902 |
903 | -- needed original fruit type not available on this map
904 | local neededFruitType = ftConfig.neededFruittype
905 | if notUsableWarning == nil and neededFruitType ~= nil and g_fruitTypeManager:getFruitTypeByName(neededFruitType) == nil then
906 | notUsableWarning = string.format("Not usable, because needed fruittype (%s) is missing", neededFruitType)
907 | end
908 |
909 | -- not sell able
910 | if notUsableWarning == nil and not possibleFT.showOnPriceTable then
911 | notUsableWarning = "Not usable, because not show on price list"
912 | end
913 |
914 | -- without sell price
915 | if notUsableWarning == nil and possibleFT.priceMax <= 0 then
916 | if VIPOrderManager.fillTypesNoPriceList[possibleFT.name] == 1 and possibleFT.pricePerLiter > 0 then
917 | possibleFT.priceMax = possibleFT.pricePerLiter
918 | else
919 | notUsableWarning = "Not usable, because no or negative price per liter defined"
920 | end
921 | end
922 |
923 | possibleFT.isUsable = true
924 | possibleFT.notUsableMsg = ""
925 | if notUsableWarning ~= nil then
926 | dbPrintf(defaultWarningText .. notUsableWarning)
927 | possibleFT.isUsable = false
928 | possibleFT.notUsableMsg = notUsableWarning
929 | end
930 | table.insert(relevantFillTypes, possibleFT)
931 | end
932 |
933 | -- output relevant filltypes
934 | dbPrintf("")
935 | dbPrintf("Relevant filltypes:")
936 | for _, v in pairs(relevantFillTypes) do
937 | local tempNameOutput = string.format("%s (%s)", v.name, v.title)
938 | dbPrintf(" - %-50s | isUsable=%-5s | price=%9s | minOrderLevel=%s | probability=%3s | Stations=%s | ConfigMsg=%s | notUsableMsg=%s", tempNameOutput, v.isUsable, string.format("%.4f", v.priceMax), v.ftConfig.minOrderLevel, v.ftConfig.probability, tostring(v.acceptingStationsString), v.ftConfig.msg, v.notUsableMsg)
939 | end
940 | dbPrintf("")
941 | dbPrintf("")
942 | end
943 |
944 |
945 | function VIPOrderManager:addAllSellableFillTypes(possibleFillTypes)
946 | dbPrintHeader("VIPOrderManager:addAllSellableFillTypes()")
947 |
948 | for _, station in pairs(g_currentMission.storageSystem.unloadingStations) do
949 | local placeable = station.owningPlaceable
950 | local production = placeable.spec_productionPoint
951 | dbPrintf("Station: getName=%s | typeName=%s | categoryName=%s | isSellingPoint=%s | currentSavegameId=%s | placeable.ownerFarmId=%s | g_currentMission:getFarmId()=%s",
952 | placeable:getName(), tostring(placeable.typeName), tostring(placeable.storeItem.categoryName), tostring(station.isSellingPoint), placeable.currentSavegameId, placeable.ownerFarmId, g_currentMission:getFarmId())
953 | -- PRODUCTIONPOINTS, SILOS, ANIMALPENS
954 |
955 | if station.isSellingPoint ~= nil and station.isSellingPoint == true and (VIPOrderManager.acceptOwnPlaceableProductionPointsAsSellingStation or placeable.ownerFarmId ~= g_currentMission:getFarmId()) then
956 | for fillTypeIndex, isAccepted in pairs(station.acceptedFillTypes) do
957 | local fillType = g_fillTypeManager:getFillTypeByIndex(fillTypeIndex)
958 |
959 | -- accept for own placeable production points only fill types that are not also loadable at the same time
960 | if isAccepted
961 | and placeable.ownerFarmId == g_currentMission:getFarmId()
962 | and production ~= nil
963 | and production.productionPoint.loadingStation ~= nil
964 | and production.productionPoint.loadingStation.supportedFillTypes[fillTypeIndex] then
965 | isAccepted = false
966 | dbPrintf(" - own placeable production point: filltype %s-%s (%s) is not supported as it is also loadable", fillTypeIndex, fillType.name, fillType.title)
967 | end
968 |
969 | if isAccepted == true then
970 |
971 | -- Unknown filltype
972 | local extraMsg = ""
973 | if VIPOrderManager.ftConfigs[fillType.name] == nil then
974 | extraMsg = " *** Unknown filltype without configuration ***"
975 | end
976 |
977 | dbPrintf(" - filltype: %s-%s (%s)%s", fillTypeIndex, fillType.name, fillType.title, extraMsg)
978 | local price = station:getEffectiveFillTypePrice(fillTypeIndex)
979 |
980 | if possibleFillTypes[fillTypeIndex] == nil then
981 | possibleFillTypes[fillTypeIndex] = {}
982 | possibleFillTypes[fillTypeIndex].priceMax = price
983 | possibleFillTypes[fillTypeIndex].acceptingStations = {}
984 | possibleFillTypes[fillTypeIndex].acceptingStationsString =""
985 | possibleFillTypes[fillTypeIndex].name = fillType.name
986 | possibleFillTypes[fillTypeIndex].title = fillType.title
987 | possibleFillTypes[fillTypeIndex].pricePerLiter = fillType.pricePerLiter
988 | possibleFillTypes[fillTypeIndex].showOnPriceTable = fillType.showOnPriceTable
989 | possibleFillTypes[fillTypeIndex].literPerSqm = g_fruitTypeManager:getFillTypeLiterPerSqm(fillTypeIndex, 0)
990 | possibleFillTypes[fillTypeIndex].isFruitType = g_fruitTypeManager:getFruitTypeByName(fillType.name) ~= nil
991 | else
992 | if price > possibleFillTypes[fillTypeIndex].priceMax then
993 | possibleFillTypes[fillTypeIndex].priceMax = price
994 | end
995 | end
996 |
997 | -- append station to station list and to stationString
998 | table.insert(possibleFillTypes[fillTypeIndex].acceptingStations, station)
999 | if possibleFillTypes[fillTypeIndex].acceptingStationsString ~= "" then
1000 | possibleFillTypes[fillTypeIndex].acceptingStationsString = possibleFillTypes[fillTypeIndex].acceptingStationsString .. ", "
1001 | end
1002 | possibleFillTypes[fillTypeIndex].acceptingStationsString = possibleFillTypes[fillTypeIndex].acceptingStationsString .. station.owningPlaceable:getName()
1003 | end
1004 | end
1005 | else
1006 | dbPrintf(" - Station not relevant: Name=%s | isSellingPoint=%s | placeable.ownerFarmId=%s", placeable:getName(), station.isSellingPoint, placeable.ownerFarmId)
1007 | end
1008 | end
1009 | return possibleFillTypes
1010 | end
1011 |
1012 |
1013 | function VIPOrderManager:addAllAnimalFillTypes(possibleFillTypes)
1014 | dbPrintHeader("VIPOrderManager:addAllAnimalFillTypes()")
1015 |
1016 | local animalTypeIndexes = {}
1017 |
1018 | for i, fillTypeIdx in pairs(g_fillTypeManager:getFillTypesByCategoryNames("ANIMAL HORSE")) do
1019 | local fillType = g_fillTypeManager:getFillTypeByIndex(fillTypeIdx)
1020 | local animalSubType = g_currentMission.animalSystem.fillTypeIndexToSubType[fillTypeIdx]
1021 | if animalSubType == nil then
1022 | dbPrintf("VIPOrderManager:addAllAnimalFillTypes warning: animal filltype without animalSubType: %s-%s (%s)",fillTypeIdx, fillType.name, fillType.title)
1023 | else
1024 | local animalStoreTitle = VIPOrderManager:GetAnimalTitleByFillTypeIdx(fillTypeIdx)
1025 |
1026 | -- get animal species
1027 | local animalType = g_currentMission.animalSystem:getTypeByIndex(animalSubType.typeIndex)
1028 | local animalTypeName = animalType.name
1029 |
1030 |
1031 | -- print("** Start DebugUtil.printTableRecursively() ************************************************************")
1032 | -- print("fillType:")
1033 | -- DebugUtil.printTableRecursively(fillType, ".", 0, 3)
1034 | -- print("** End DebugUtil.printTableRecursively() **************************************************************")
1035 |
1036 | -- print("** Start DebugUtil.printTableRecursively() ************************************************************")
1037 | -- print("g_currentMission.animalSystem:")
1038 | -- DebugUtil.printTableRecursively(g_currentMission.animalSystem, ".", 0, 1)
1039 | -- print("** End DebugUtil.printTableRecursively() **************************************************************")
1040 |
1041 | -- printf("FillType: %s (%s) - animalTypeIndex=%s | MinBuyPrice=%s", fillType.name, fillType.title, animalSubType.typeIndex, animalSubType.buyPrice.keyframes[1][1])
1042 | -- for ii, visual in pairs(animalSubType.visuals) do
1043 | -- printf(" - canBeBought=%s | minAge=%s | name=%s", visual.store.canBeBought, visual.minAge, visual.store.name)
1044 | -- end
1045 |
1046 | -- Unknown filltype
1047 | local extraMsg = ""
1048 | if VIPOrderManager.ftConfigs[fillType.name] == nil then
1049 | extraMsg = " *** Unknown filltype without configuration ***"
1050 | end
1051 |
1052 | dbPrintf(" - filltype: %s-%s (%s) %s", fillTypeIdx, fillType.name, animalStoreTitle, extraMsg)
1053 | -- local price = animalSubType.buyPrice.keyframes[1][1]
1054 | local price = math.floor(math.random(VIPOrderManager.rangeAnimalDummyPrice.min, VIPOrderManager.rangeAnimalDummyPrice.max))
1055 |
1056 | if possibleFillTypes[fillTypeIdx] == nil then
1057 | possibleFillTypes[fillTypeIdx] = {}
1058 | else
1059 | dbPrintf("VIPOrderManager:addAllAnimalFillTypes warning: animal filltype already exists: %s-%s (%s)", fillTypeIdx, fillType.name, animalStoreTitle)
1060 | end
1061 | possibleFillTypes[fillTypeIdx].priceMax = price
1062 | possibleFillTypes[fillTypeIdx].acceptingStations = {}
1063 | possibleFillTypes[fillTypeIdx].name = fillType.name
1064 | possibleFillTypes[fillTypeIdx].title = animalStoreTitle
1065 | possibleFillTypes[fillTypeIdx].pricePerLiter = fillType.pricePerLiter
1066 | possibleFillTypes[fillTypeIdx].showOnPriceTable = true
1067 | possibleFillTypes[fillTypeIdx].literPerSqm = 0
1068 | -- only for animals
1069 | possibleFillTypes[fillTypeIdx].isAnimal = true
1070 | possibleFillTypes[fillTypeIdx].animalTypeIndex = animalSubType.typeIndex
1071 | possibleFillTypes[fillTypeIdx].animalTypeName = animalTypeName
1072 |
1073 | -- count animal subtypes
1074 | if animalTypeIndexes[animalSubType.typeIndex] == nil then
1075 | animalTypeIndexes[animalSubType.typeIndex] = 1
1076 | else
1077 | animalTypeIndexes[animalSubType.typeIndex] = animalTypeIndexes[animalSubType.typeIndex] + 1
1078 | end
1079 | possibleFillTypes[fillTypeIdx].animalTypeCount = animalTypeIndexes[animalSubType.typeIndex]
1080 | end
1081 | end
1082 | end
1083 |
1084 |
1085 | function VIPOrderManager:ShowCurrentVIPOrder()
1086 | dbPrintHeader("VIPOrderManager:ShowCurrentVIPOrder()")
1087 |
1088 | -- dbPrintf(" current showVIPOrder=%s | new showVIPOrder=%s", VIPOrderManager.showVIPOrder, (VIPOrderManager.showVIPOrder + 1) % 4)
1089 |
1090 | VIPOrderManager.showVIPOrder = (VIPOrderManager.showVIPOrder + 1) % 3 -- only 0, 1 or 2
1091 | if VIPOrderManager.showVIPOrder > 0 then
1092 | VIPOrderManager:UpdateOutputLines();
1093 | end
1094 | VIPOrderManager.infoDisplayPastTime = 0
1095 | end
1096 |
1097 |
1098 | function VIPOrderManager:GetPayoutTotal(orderEntries)
1099 | dbPrintHeader("VIPOrderManager:GetPayoutTotal()")
1100 |
1101 | local payoutTotal = 0
1102 | for _, entry in pairs(orderEntries) do
1103 | payoutTotal = payoutTotal + entry.payout
1104 | end
1105 | return payoutTotal
1106 | end
1107 |
1108 | -- return: boolean, IsOrderCompleted
1109 | function VIPOrderManager:UpdateOutputLines()
1110 | -- dbPrintHeader("VIPOrderManager:UpdateOutputLines()")
1111 |
1112 | if #VIPOrderManager.VIPOrders < 2 then
1113 | return
1114 | end
1115 |
1116 | local posX = VIPOrderManager.outputStartPoint.x
1117 | local posY = VIPOrderManager.outputStartPoint.y
1118 | local fontSize = VIPOrderManager.outputFontSize
1119 | local isOrderCompleted = true
1120 | local payoutTotal = 0
1121 | VIPOrderManager.outputLines = {} -- Output lines for the draw() function (text, size, bold, colorId, x, y)
1122 |
1123 | local title = g_i18n:getText("VIPOrderManager_CurrentVIPOrder")
1124 | local VIPOrder = VIPOrderManager.VIPOrders[1]
1125 |
1126 | if VIPOrderManager.showVIPOrder == 2 then
1127 | VIPOrder = VIPOrderManager.VIPOrders[2]
1128 | title = g_i18n:getText("VIPOrderManager_NextVIPOrder")
1129 | end
1130 | local level = VIPOrder.level
1131 |
1132 | -- calculate max text widths
1133 | -- local maxTitelTextWidth = 0
1134 | -- local maxQuantityTextWidth = 0
1135 | -- for _, vipOrderEntry in pairs(VIPOrder) do
1136 | -- local fillTypeTitle = vipOrderEntry.title
1137 | -- local titelTextWidth = getTextWidth(fontSize, " " .. fillTypeTitle .. " ")
1138 | -- local requiredQuantity = vipOrderEntry.quantity - math.ceil(vipOrderEntry.fillLevel)
1139 | -- local quantityTextWidth = getTextWidth(fontSize, g_i18n:formatNumber(requiredQuantity, 0))
1140 |
1141 | -- if titelTextWidth > maxTitelTextWidth then
1142 | -- maxTitelTextWidth = titelTextWidth
1143 | -- end
1144 |
1145 | -- if quantityTextWidth > maxQuantityTextWidth then
1146 | -- maxQuantityTextWidth = quantityTextWidth
1147 | -- end
1148 | -- end
1149 | local headerLine = string.format("%s (Level: %s):", title, level)
1150 | table.insert(VIPOrderManager.outputLines, {text = headerLine, size = fontSize, bold = true, align=RenderText.ALIGN_LEFT, colorId = 7, x = posX, y = posY})
1151 | posY = posY - fontSize
1152 |
1153 | local maxTextWidth = getTextWidth(fontSize, headerLine) + 0.005
1154 | local posXIncrease = getTextWidth(fontSize, " 999.999 ")
1155 |
1156 | for _, vipOrderEntry in pairs(VIPOrder.entries) do
1157 | local fillTypeTitle = vipOrderEntry.title
1158 | local requiredQuantity = vipOrderEntry.quantity - math.ceil(vipOrderEntry.fillLevel)
1159 |
1160 | local line = string.format(" %s ", g_i18n:formatNumber(requiredQuantity, 0))
1161 | local fillLevelColor = 7;
1162 | if requiredQuantity <= 0 then
1163 | fillLevelColor = 6
1164 | end
1165 | table.insert(VIPOrderManager.outputLines, {text = line, size = fontSize, bold = false, align=RenderText.ALIGN_RIGHT, colorId = fillLevelColor, x = posX + posXIncrease, y = posY})
1166 |
1167 | local line = string.format(" %s", fillTypeTitle)
1168 | if vipOrderEntry.targetStation ~= nil then
1169 | line = line .. " --> " .. vipOrderEntry.targetStation.owningPlaceable:getName()
1170 | end
1171 | table.insert(VIPOrderManager.outputLines, {text = line, size = fontSize, bold = false, align=RenderText.ALIGN_LEFT, colorId = fillLevelColor, x = posX + posXIncrease, y = posY})
1172 | posY = posY - fontSize
1173 | local textWidth = getTextWidth(fontSize, line)
1174 | if (textWidth + posXIncrease > maxTextWidth) then
1175 | maxTextWidth = textWidth + posXIncrease
1176 | end
1177 |
1178 | isOrderCompleted = isOrderCompleted and requiredQuantity <= 0
1179 | payoutTotal = payoutTotal + vipOrderEntry.payout
1180 | end
1181 |
1182 | local line = string.format(g_i18n:getText("VIPOrderManager_Payout"), g_i18n:formatMoney(payoutTotal, 0, true)) --, false)) -- g_i18n:formatMoney(value, bool Währung ausgeben, bool Währung vor dem Betrag?)
1183 | table.insert(VIPOrderManager.outputLines, {text = line, size = fontSize, bold = true, align=RenderText.ALIGN_LEFT, colorId = 7, x = posX, y = posY})
1184 | posY = posY - fontSize
1185 |
1186 | if infoHud ~= nil then
1187 | infoHud:setPosition(VIPOrderManager.outputStartPoint.x - 0.005, VIPOrderManager.outputStartPoint.y + 0.005 + fontSize)
1188 | infoHud:setDimension(maxTextWidth + 0.01, VIPOrderManager.outputStartPoint.y - posY + fontSize)
1189 | end
1190 |
1191 | return isOrderCompleted and MyTools:getCountElements(VIPOrder.entries) > 0
1192 | end
1193 |
1194 |
1195 | function VIPOrderManager:MakePayout(orderEntries)
1196 | dbPrintHeader("VIPOrderManager:MakePayout()")
1197 |
1198 | playSample(VIPOrderManager.successSound ,1 ,1 ,1 ,0 ,0)
1199 |
1200 | -- show message
1201 | g_currentMission:addIngameNotification(FSBaseMission.INGAME_NOTIFICATION_OK, g_i18n:getText("VIPOrderManager_OrderCompleted"))
1202 |
1203 | -- Pay out profit
1204 | local payoutTotal = VIPOrderManager:GetPayoutTotal(orderEntries)
1205 | g_currentMission:addMoney(payoutTotal, g_currentMission.player.farmId, MoneyType.MISSIONS, true, true);
1206 | end
1207 |
1208 |
1209 | function VIPOrderManager:update(dt)
1210 | -- dbPrintHeader("VIPOrderManager:update()")
1211 |
1212 | VIPOrderManager.updateDelta = VIPOrderManager.updateDelta + dt;
1213 | VIPOrderManager.infoDisplayPastTime = VIPOrderManager.infoDisplayPastTime + dt
1214 |
1215 | if VIPOrderManager.updateDelta > VIPOrderManager.updateRate and VIPOrderManager.InitDone then
1216 | VIPOrderManager.updateDelta = 0;
1217 |
1218 | if VIPOrderManager.infoDisplayPastTime > VIPOrderManager.infoDisplayMaxShowTime then
1219 | VIPOrderManager.showVIPOrder = 0;
1220 | VIPOrderManager.infoDisplayPastTime = 0
1221 | end
1222 |
1223 | if g_currentMission:getIsClient() and g_gui.currentGui == nil and g_currentMission.player.farmId > 0 then
1224 | local isOrderCompleted = VIPOrderManager:UpdateOutputLines()
1225 | if isOrderCompleted then
1226 | VIPOrderManager:MakePayout(VIPOrderManager.VIPOrders[1].entries)
1227 | table.remove(VIPOrderManager.VIPOrders, 1)
1228 | end
1229 | if #VIPOrderManager.VIPOrders < VIPOrderManager.maxVIPOrdersCount then
1230 | VIPOrderManager:RestockVIPOrders()
1231 | end
1232 | end
1233 | end
1234 |
1235 | if infoHud ~= nil then
1236 | if #VIPOrderManager.VIPOrders > 0 and #VIPOrderManager.outputLines > 0 then
1237 | infoHud:setVisible(VIPOrderManager.showVIPOrder > 0)
1238 | else
1239 | infoHud:setVisible(false)
1240 | end
1241 | end
1242 | end
1243 |
1244 |
1245 | function VIPOrderManager:draw()
1246 | -- dbPrintHeader("VIPOrderManager:draw()")
1247 |
1248 | -- Only render when no other GUI is open
1249 | if g_gui.currentGuiName ~= "InGameMenu" and VIPOrderManager.showVIPOrder > 0 and VIPOrderManager.InitDone then --if g_gui.currentGui == nil
1250 | for _, line in ipairs(VIPOrderManager.outputLines) do
1251 | VIPOrderManager:renderText(line.x, line.y, line.size, line.text, line.bold, line.colorId, line.align)
1252 | end;
1253 | end
1254 |
1255 | if infoHud ~= nil then
1256 | infoHud:draw()
1257 | end
1258 | end
1259 |
1260 |
1261 | function VIPOrderManager:renderText(x, y, size, text, bold, colorId, align)
1262 | -- dbPrintHeader("VIPOrderManager:renderText()")
1263 |
1264 | setTextColor(table.unpack(VIPOrderManager.colors[colorId][2]))
1265 | setTextBold(bold)
1266 | setTextAlignment(align)
1267 | renderText(x, y, size, text)
1268 |
1269 | -- Back to defaults
1270 | setTextBold(false)
1271 | setTextColor(table.unpack(VIPOrderManager.colors[1][2])) --Back to default color which is white
1272 | setTextAlignment(RenderText.ALIGN_LEFT)
1273 | end
1274 |
1275 |
1276 | function VIPOrderManager:saveSettings()
1277 | dbPrintHeader("VIPOrderManager:saveSettings()")
1278 |
1279 | local savegameFolderPath = g_currentMission.missionInfo.savegameDirectory.."/";
1280 | if savegameFolderPath == nil then
1281 | savegameFolderPath = ('%ssavegame%d'):format(getUserProfileAppPath(), g_currentMission.missionInfo.savegameIndex.."/");
1282 | end;
1283 | local key = "VIPOrderManager";
1284 | local storePlace = g_currentMission.storeSpawnPlaces[1];
1285 | local xmlFile = createXMLFile(key, savegameFolderPath.."VIPOrderManager.xml", key);
1286 | -- setXMLString(xmlFile, key.."#XMLFileVersion", "1.0");
1287 | setXMLString(xmlFile, key.."#XMLFileVersion", "2.0");
1288 |
1289 | local settingKey = string.format("%s.Settings", key)
1290 | -- setXMLInt(xmlFile, key.."#orderLevel", VIPOrderManager.currentOrderLevel);
1291 | setXMLInt(xmlFile, settingKey..".maxVIPOrdersCount", VIPOrderManager.maxVIPOrdersCount)
1292 | setXMLBool(xmlFile, settingKey..".isAnimalOrdersWished", VIPOrderManager.isAnimalOrdersWished)
1293 | setXMLInt(xmlFile, settingKey..".countOrderItemsRange#Min", VIPOrderManager.countOrderItemsRange.min)
1294 | setXMLInt(xmlFile, settingKey..".countOrderItemsRange#Max", VIPOrderManager.countOrderItemsRange.max)
1295 | setXMLInt(xmlFile, settingKey..".quantityFactor#Min", VIPOrderManager.quantityFactor.min)
1296 | setXMLInt(xmlFile, settingKey..".quantityFactor#Max", VIPOrderManager.quantityFactor.max)
1297 | setXMLInt(xmlFile, settingKey..".payoutFactor#Min", VIPOrderManager.payoutFactor.min)
1298 | setXMLInt(xmlFile, settingKey..".payoutFactor#Max", VIPOrderManager.payoutFactor.max)
1299 |
1300 | local iOrder = 0
1301 | for _, vipOrder in pairs(VIPOrderManager.VIPOrders) do
1302 | local orderKey = string.format("%s.VIPOrders.VIPOrder(%d)", key, iOrder)
1303 | setXMLInt(xmlFile, orderKey.."#level", vipOrder.level)
1304 |
1305 | local iEntry = 0
1306 | for _, orderEntry in pairs(vipOrder.entries) do
1307 | local entryKey = string.format("%s.entry(%d)", orderKey, iEntry)
1308 | setXMLString(xmlFile, entryKey.."#fillTypeName", orderEntry.fillTypeName)
1309 | setXMLInt(xmlFile, entryKey.."#quantity", orderEntry.quantity)
1310 | setXMLInt(xmlFile, entryKey.."#fillLevel", math.ceil(orderEntry.fillLevel))
1311 | setXMLInt(xmlFile, entryKey.."#payout", orderEntry.payout)
1312 |
1313 | setXMLString(xmlFile, entryKey.."#fillTypeTitle_OnlyAsInfo", orderEntry.title)
1314 | if orderEntry.targetStation ~= nil then
1315 | setXMLInt(xmlFile, entryKey.."#targetStationSavegameId", orderEntry.targetStation.owningPlaceable.currentSavegameId)
1316 | setXMLString(xmlFile, entryKey.."#targetStationName_OnlyAsInfo", orderEntry.targetStation.owningPlaceable:getName())
1317 | end
1318 |
1319 | -- for animal
1320 | if orderEntry.isAnimal then
1321 | setXMLBool(xmlFile, entryKey.."#isAnimal", orderEntry.isAnimal)
1322 | setXMLInt(xmlFile, entryKey.."#neededAgeInMonths", orderEntry.neededAgeInMonths)
1323 | end
1324 |
1325 | iEntry = iEntry + 1
1326 | end
1327 | iOrder = iOrder + 1
1328 | end
1329 | saveXMLFile(xmlFile);
1330 | delete(xmlFile);
1331 | end
1332 |
1333 | function VIPOrderManager:loadSettings()
1334 | dbPrintHeader("VIPOrderManager:loadSettings()")
1335 |
1336 | local savegameFolderPath = g_currentMission.missionInfo.savegameDirectory
1337 | if savegameFolderPath == nil then
1338 | savegameFolderPath = ('%ssavegame%d'):format(getUserProfileAppPath(), g_currentMission.missionInfo.savegameIndex)
1339 | end;
1340 | savegameFolderPath = savegameFolderPath.."/"
1341 | local key = "VIPOrderManager"
1342 |
1343 | if fileExists(savegameFolderPath.."VIPOrderManager.xml") then
1344 | local xmlFile = loadXMLFile(key, savegameFolderPath.."VIPOrderManager.xml")
1345 |
1346 | local XMLFileVersion = getXMLString(xmlFile, key.."#XMLFileVersion")
1347 |
1348 | if XMLFileVersion == "2.0" then
1349 | local settingKey = string.format("%s.Settings", key)
1350 | VIPOrderManager.maxVIPOrdersCount = Utils.getNoNil(getXMLInt(xmlFile, settingKey..".maxVIPOrdersCount"), VIPOrderManager.maxVIPOrdersCount)
1351 | VIPOrderManager.isAnimalOrdersWished = Utils.getNoNil(getXMLBool(xmlFile, settingKey..".isAnimalOrdersWished"), VIPOrderManager.isAnimalOrdersWished)
1352 |
1353 | VIPOrderManager.countOrderItemsRange.min = Utils.getNoNil(getXMLInt(xmlFile, settingKey..".countOrderItemsRange#Min"), VIPOrderManager.countOrderItemsRange.min)
1354 | VIPOrderManager.countOrderItemsRange.max = Utils.getNoNil(getXMLInt(xmlFile, settingKey..".countOrderItemsRange#Max"), VIPOrderManager.countOrderItemsRange.max)
1355 | VIPOrderManager.quantityFactor.min = Utils.getNoNil(getXMLInt(xmlFile, settingKey..".quantityFactor#Min"), VIPOrderManager.quantityFactor.min)
1356 | VIPOrderManager.quantityFactor.max = Utils.getNoNil(getXMLInt(xmlFile, settingKey..".quantityFactor#Max"), VIPOrderManager.quantityFactor.max)
1357 | VIPOrderManager.payoutFactor.min = Utils.getNoNil(getXMLInt(xmlFile, settingKey..".payoutFactor#Min"), VIPOrderManager.payoutFactor.min)
1358 | VIPOrderManager.payoutFactor.max = Utils.getNoNil(getXMLInt(xmlFile, settingKey..".payoutFactor#Max"), VIPOrderManager.payoutFactor.max)
1359 |
1360 | local iOrder = 0
1361 | while true do
1362 | local orderKey = string.format("%s.VIPOrders.VIPOrder(%d)", key, iOrder)
1363 | if hasXMLProperty(xmlFile, orderKey) then
1364 | local vipOrder = {level=nil, entries={}}
1365 | local level = getXMLInt(xmlFile, orderKey.."#level")
1366 | vipOrder.level = level
1367 |
1368 | local iEntry = 0
1369 | while true do
1370 | local entryKey = string.format("%s.entry(%d)", orderKey, iEntry)
1371 | if hasXMLProperty(xmlFile, entryKey) then
1372 | local error = false
1373 | local fillTypeName = getXMLString(xmlFile, entryKey.."#fillTypeName")
1374 | local quantity = getXMLInt(xmlFile, entryKey.."#quantity")
1375 | local fillLevel = Utils.getNoNil(getXMLInt(xmlFile, entryKey.."#fillLevel"), 0)
1376 | local payout = getXMLInt(xmlFile, entryKey.."#payout")
1377 |
1378 | -- for animal
1379 | local isAnimal = getXMLBool(xmlFile, entryKey.."#isAnimal")
1380 | local neededAgeInMonths = getXMLInt(xmlFile, entryKey.."#neededAgeInMonths")
1381 |
1382 | local targetStationSavegameId = getXMLInt(xmlFile, entryKey.."#targetStationSavegameId")
1383 | local targetStationName = getXMLString(xmlFile, entryKey.."#targetStationName_OnlyAsInfo")
1384 | -- dbPrintf("loadSettings: %s | %s", targetStationSavegameId, targetStationName)
1385 | local targetStation = VIPOrderManager:getStationBySavegameId(targetStationSavegameId)
1386 |
1387 | -- check if target station still exists
1388 | if targetStationName ~= nil and targetStation == nil then
1389 | print(string.format("VIPOrderManager: Warning, the target station \"%s\" no longer exists", targetStationName))
1390 | end
1391 | -- check if filltype still exists
1392 | local fillType = g_fillTypeManager:getFillTypeByName(fillTypeName)
1393 | if fillType == nil then
1394 | error = true
1395 | print(string.format("VIPOrderManager: Warning, the filltype \"%s\" no longer exists", fillTypeName))
1396 | else
1397 | local ftTitle
1398 | if isAnimal then
1399 | ftTitle = VIPOrderManager:GetAnimalTitleByFillTypeIdx(fillType.index, neededAgeInMonths)
1400 | else
1401 | ftTitle = fillType.title
1402 | end
1403 | vipOrder.entries[fillTypeName] = {fillTypeName=fillTypeName, title=ftTitle, quantity=quantity, fillLevel=fillLevel, payout=payout, targetStation=targetStation, isAnimal=isAnimal, neededAgeInMonths=neededAgeInMonths}
1404 | end
1405 | iEntry = iEntry + 1
1406 | else
1407 | break
1408 | end
1409 | end
1410 | table.insert(VIPOrderManager.VIPOrders, vipOrder)
1411 | iOrder = iOrder + 1
1412 | else
1413 | break
1414 | end
1415 | end
1416 | end
1417 |
1418 | delete(xmlFile);
1419 | end;
1420 |
1421 | VIPOrderManager.InitDone = true
1422 | return VIPOrderManager.isLoaded;
1423 | end
1424 |
1425 |
1426 | function VIPOrderManager:getStationBySavegameId(targetStationSavegameId)
1427 | dbPrintHeader("VIPOrderManager:getStationBySavegameId()")
1428 |
1429 | for _, station in pairs(g_currentMission.storageSystem.unloadingStations) do
1430 | if station.owningPlaceable ~= nil and station.owningPlaceable.currentSavegameId == targetStationSavegameId then
1431 | return station
1432 | end
1433 | end
1434 | return nil
1435 | end
1436 |
1437 |
1438 | function VIPOrderManager:GetAnimalTitleByFillTypeIdx(fillTypeIdx, neededAgeInMonths)
1439 | local animalSubType = g_currentMission.animalSystem.fillTypeIndexToSubType[fillTypeIdx]
1440 | local animalStoreTitle = "Unknown animal title"
1441 | local animalAge = neededAgeInMonths == nil and 0 or neededAgeInMonths
1442 |
1443 | for i, visual in pairs(animalSubType.visuals) do
1444 | if animalAge >= visual.minAge then
1445 | animalStoreTitle = visual.store.name
1446 | end
1447 | end
1448 |
1449 | if neededAgeInMonths ~= nil then
1450 | animalStoreTitle = animalStoreTitle .. string.format(" (%s %s)", neededAgeInMonths, g_i18n:getText("VIPOrderManager_Months"))
1451 | end
1452 |
1453 | return animalStoreTitle
1454 | end
1455 |
1456 |
1457 | -- Observe "SellingStation.addFillLevelFromTool" when products are sold at points of sale
1458 | function VIPOrderManager.sellingStation_addFillLevelFromTool(station, superFunc, farmId, deltaFillLevel, fillType, fillInfo, toolType)
1459 | dbPrintHeader("VIPOrderManager:sellingStation_addFillLevelFromTool()")
1460 |
1461 | local moved = 0
1462 | moved = superFunc(station, farmId, deltaFillLevel, fillType, fillInfo, toolType)
1463 |
1464 | local ft = g_fillTypeManager:getFillTypeByIndex(fillType)
1465 | local stationCategoryName = ""
1466 | if station.owningPlaceable ~= nil and station.owningPlaceable.storeItem ~= nil then
1467 | stationCategoryName = station.owningPlaceable.storeItem.categoryName
1468 | end
1469 | -- dbPrintf(" stationCategoryName=%s | moved=%s | deltaFillLevel=%s | ftName=%s (%s) | ftIndex=%s | toolType=%s", tostring(stationCategoryName), tostring(moved), tostring(deltaFillLevel), ft.name, ft.title, tostring(fillType), tostring(toolType))
1470 |
1471 | if moved > 0 and VIPOrderManager.VIPOrders ~= nil and VIPOrderManager.VIPOrders[1] ~= nil then
1472 | local orderEntry = VIPOrderManager.VIPOrders[1].entries[ft.name]
1473 | -- dbPrintf(" Anzahl Order Items=%s", TyTools:getCountElements(VIPOrderManager.currentVIPOrder))
1474 | if orderEntry ~= nil then
1475 | if orderEntry.targetStation == nil or orderEntry.targetStation == station then
1476 | orderEntry.fillLevel = math.min(orderEntry.fillLevel + moved, orderEntry.quantity)
1477 | VIPOrderManager.showVIPOrder = 1;
1478 | VIPOrderManager.infoDisplayPastTime = 0
1479 | VIPOrderManager:UpdateOutputLines()
1480 | end
1481 | end
1482 | end
1483 |
1484 | return moved
1485 | end
1486 |
1487 |
1488 | function VIPOrderManager:isTerraLife()
1489 | local mapDirectory = g_mpLoadingScreen.missionInfo.map.baseDirectory
1490 | if mapDirectory == "" then
1491 | --wenn mapDirectory leer ist, handelt es sich um die Basemaps
1492 | return false
1493 | elseif fileExists(mapDirectory .. "dlcDesc.xml") then
1494 | --wenn dlcDesc existiert, handelt es sich um DLC-Map
1495 | return false
1496 | else
1497 | local path = mapDirectory .. "modDesc.xml"
1498 | local xmlFile = XMLFile.load("TempDesc", path)
1499 | if xmlFile:hasProperty("moddesc.terraLife") then
1500 | return true
1501 | else
1502 | return false
1503 | end
1504 | xmlFile:delete()
1505 | end
1506 | end
1507 |
1508 |
1509 | function VIPOrderManager:onLoad(savegame)end;
1510 | function VIPOrderManager:onUpdate(dt)end;
1511 | function VIPOrderManager:deleteMap()end;
1512 | function VIPOrderManager:keyEvent(unicode, sym, modifier, isDown)end;
1513 | function VIPOrderManager:mouseEvent(posX, posY, isDown, isUp, button)end;
1514 |
1515 | addModEventListener(VIPOrderManager);
1516 |
1517 |
1518 |
--------------------------------------------------------------------------------