62 | function FieldManager:loadMapData(xmlFile) |
63 | FieldManager:superClass().loadMapData(self) |
64 | |
65 | local mission = g_currentMission |
66 | self.mission = mission |
67 | |
68 | mission:addUpdateable(self) |
69 | |
70 | local terrainNode = mission.terrainRootNode |
71 | local fieldGroundSystem = mission.fieldGroundSystem |
72 | local sprayLevelMapId, sprayLevelFirstChannel, sprayLevelNumChannels = fieldGroundSystem:getDensityMapData(FieldDensityMap.SPRAY_LEVEL) |
73 | local sprayLevelMaxValue = fieldGroundSystem:getMaxValue(FieldDensityMap.SPRAY_LEVEL) |
74 | local plowLevelMapId, plowLevelFirstChannel, plowLevelNumChannels = fieldGroundSystem:getDensityMapData(FieldDensityMap.PLOW_LEVEL) |
75 | local plowLevelMaxValue = fieldGroundSystem:getMaxValue(FieldDensityMap.PLOW_LEVEL) |
76 | |
77 | self.limeLevelMaxValue = 0 |
78 | self.plowLevelMaxValue = plowLevelMaxValue |
79 | self.sprayLevelMaxValue = sprayLevelMaxValue |
80 | self.fruitModifiers = {} |
81 | |
82 | self.sprayLevelModifier = DensityMapModifier.new(sprayLevelMapId, sprayLevelFirstChannel, sprayLevelNumChannels, terrainNode) |
83 | self.plowLevelModifier = DensityMapModifier.new(plowLevelMapId, plowLevelFirstChannel, plowLevelNumChannels, terrainNode) |
84 | |
85 | |
86 | if Platform.gameplay.useLimeCounter then |
87 | local limeLevelMapId, limeLevelFirstChannel, limeLevelNumChannels = fieldGroundSystem:getDensityMapData(FieldDensityMap.LIME_LEVEL) |
88 | self.limeLevelMaxValue = fieldGroundSystem:getMaxValue(FieldDensityMap.LIME_LEVEL) |
89 | self.limeLevelModifier = DensityMapModifier.new(limeLevelMapId, limeLevelFirstChannel, limeLevelNumChannels, terrainNode) |
90 | end |
91 | |
92 | if Platform.gameplay.useStubbleShred then |
93 | local stubbleShredLevelMapId, stubbleShredLevelFirstChannel, stubbleShredLevelNumChannels = fieldGroundSystem:getDensityMapData(FieldDensityMap.STUBBLE_SHRED) |
94 | self.stubbleShredModifier = DensityMapModifier.new(stubbleShredLevelMapId, stubbleShredLevelFirstChannel, stubbleShredLevelNumChannels, terrainNode) |
95 | end |
96 | |
97 | local groundTypeMapId, groundTypeFirstChannel, groundTypeNumChannels = fieldGroundSystem:getDensityMapData(FieldDensityMap.GROUND_TYPE) |
98 | self.groundTypeModifier = DensityMapModifier.new(groundTypeMapId, groundTypeFirstChannel, groundTypeNumChannels, terrainNode) |
99 | |
100 | local groundAngleMapId, groundAngleFirstChannel, groundAngleNumChannels = fieldGroundSystem:getDensityMapData(FieldDensityMap.GROUND_ANGLE) |
101 | self.angleModifier = DensityMapModifier.new(groundAngleMapId, groundAngleFirstChannel, groundAngleNumChannels, terrainNode) |
102 | |
103 | local sprayTypeMapId, sprayTypeFirstChannel, sprayTypeNumChannels = fieldGroundSystem:getDensityMapData(FieldDensityMap.SPRAY_TYPE) |
104 | self.sprayTypeModifier = DensityMapModifier.new(sprayTypeMapId, sprayTypeFirstChannel, sprayTypeNumChannels, terrainNode) |
105 | |
106 | self.fieldFilter = DensityMapFilter.new(groundTypeMapId, groundTypeFirstChannel, groundTypeNumChannels) |
107 | self.fieldFilter:setValueCompareParams(DensityValueCompareType.GREATER, 0) |
108 | |
109 | if mission.weedSystem:getMapHasWeed() then |
110 | local weedMapId, weedFirstChannel, weedNumChannels = mission.weedSystem:getDensityMapData() |
111 | self.weedModifier = DensityMapModifier.new(weedMapId, weedFirstChannel, weedNumChannels, terrainNode) |
112 | end |
113 | |
114 | self.fieldGroundSystem = fieldGroundSystem |
115 | |
116 | local terrainDetailHeightId = mission.terrainDetailHeightId |
117 | self.terrainHeightTypeModifier = DensityMapModifier.new(terrainDetailHeightId, g_densityMapHeightManager.heightTypeFirstChannel, g_densityMapHeightManager.heightTypeNumChannels) |
118 | self.terrainHeightModifier = DensityMapModifier.new(terrainDetailHeightId, getDensityMapHeightFirstChannel(terrainDetailHeightId), getDensityMapHeightNumChannels(terrainDetailHeightId)) |
119 | |
120 | self.groundTypeSown = fieldGroundSystem:getFieldGroundValue(FieldGroundType.SOWN) |
121 | self.sprayTypeFertilizer = fieldGroundSystem:getFieldSprayValue(FieldSprayType.FERTILIZER) |
122 | self.sprayTypeLime = fieldGroundSystem:getFieldSprayValue(FieldSprayType.LIME) |
123 | |
124 | -- create list of valid/available fruit types |
125 | self.availableFruitTypeIndices = {} |
126 | for _, fruitType in ipairs(g_fruitTypeManager:getFruitTypes()) do |
127 | if fruitType.useForFieldJob and fruitType.allowsSeeding and fruitType.needsSeeding then |
128 | table.insert(self.availableFruitTypeIndices, fruitType.index) |
129 | end |
130 | end |
131 | self.fruitTypesCount = #self.availableFruitTypeIndices |
132 | |
133 | self.fieldIndexToCheck = 1 |
134 | |
135 | -- Connect farmlands to fields first. We need the farmlands to skip overriding owned fields (in order to have working starter fields) |
136 | g_asyncTaskManager:addSubtask(function() |
137 | for i, field in ipairs(self.fields) do |
138 | local posX, posZ = field:getCenterOfFieldWorldPosition() |
139 | local farmland = g_farmlandManager:getFarmlandAtWorldPosition(posX, posZ) |
140 | if farmland ~= nil then |
141 | field:setFarmland(farmland) |
142 | |
143 | if self.farmlandIdFieldMapping[farmland.id] == nil then |
144 | self.farmlandIdFieldMapping[farmland.id] = {} |
145 | end |
146 | |
147 | table.insert(self.farmlandIdFieldMapping[farmland.id], field) |
148 | else |
149 | Logging.error("Failed to find farmland in center of field '%s'", i) |
150 | end |
151 | end |
152 | end) |
153 | |
154 | -- New save game |
155 | if not mission.missionInfo.isValid and g_server ~= nil then |
156 | g_asyncTaskManager:addSubtask(function() |
157 | local index = 1 |
158 | |
159 | for _, field in pairs(self.fields) do |
160 | if field:getIsAIActive() and field.fieldMissionAllowed and field.farmland ~= nil and not field.farmland.isOwned then |
161 | -- Plan a random fruit for the NPC |
162 | local fruitIndex = self.availableFruitTypeIndices[math.random(1, #self.availableFruitTypeIndices)] |
163 | |
164 | if field.fieldGrassMission then |
165 | fruitIndex = FruitType.GRASS |
166 | end |
167 | field.plannedFruit = fruitIndex |
168 | |
169 | -- Assume the crop is growing |
170 | local fruitDesc = g_fruitTypeManager:getFruitTypeByIndex(fruitIndex) |
171 | local fieldState = FieldManager.FIELDSTATE_GROWING |
172 | |
173 | local plowState |
174 | if not mission.missionInfo.plowingRequiredEnabled then |
175 | plowState = self.plowLevelMaxValue |
176 | else |
177 | plowState = math.random(0, self.plowLevelMaxValue) |
178 | end |
179 | |
180 | local sprayLevel = math.random(0, self.sprayLevelMaxValue) |
181 | local limeState = math.random(0, self.limeLevelMaxValue) |
182 | |
183 | local weedValue = 0 |
184 | |
185 | -- Growth state is defined by the growth system which gives us a random |
186 | -- state that is possible on a new save. |
187 | local growthState = g_currentMission.growthSystem:getRandomInitialState(fruitIndex) |
188 | |
189 | if growthState == nil and fruitIndex == FruitType.GRASS then |
190 | -- Force grass |
191 | growthState = 2 |
192 | end |
193 | |
194 | -- growth state is nil when there is no initial state because it is not possible |
195 | if growthState ~= nil then |
196 | if fruitDesc.plantsWeed then |
197 | -- Add some randomness: older plants have higher chance of older weeds |
198 | if growthState > 4 then |
199 | weedValue = math.random(3, 9) |
200 | else |
201 | weedValue = math.random(1, 7) |
202 | end |
203 | end |
204 | |
205 | if growthState == fruitDesc.cutState then |
206 | fieldState = FieldManager.FIELDSTATE_HARVESTED |
207 | end |
208 | else |
209 | fieldState = math.random() < 0.5 and FieldManager.FIELDSTATE_CULTIVATED or FieldManager.FIELDSTATE_PLOWED |
210 | |
211 | if fieldState == FieldManager.FIELDSTATE_PLOWED then |
212 | plowState = self.plowLevelMaxValue |
213 | end |
214 | |
215 | fruitIndex = 0 |
216 | end |
217 | |
218 | for i = 1, table.getn(field.maxFieldStatusPartitions) do |
219 | self:setFieldPartitionStatus(field, field.maxFieldStatusPartitions, i, fruitIndex, fieldState, growthState, sprayLevel, false, plowState, weedValue, limeState) |
220 | end |
221 | |
222 | index = index + 1 |
223 | end |
224 | end |
225 | end) |
226 | elseif g_server ~= nil then |
227 | -- get current state of fields |
228 | for _, field in pairs(self.fields) do |
229 | g_asyncTaskManager:addSubtask(function() |
230 | self:findFieldFruit(field) |
231 | end) |
232 | end |
233 | end |
234 | |
235 | g_asyncTaskManager:addSubtask(function() |
236 | self:findFieldSizes() |
237 | end) |
238 | |
239 | g_asyncTaskManager:addSubtask(function() |
240 | g_farmlandManager:addStateChangeListener(self) |
241 | |
242 | if mission:getIsServer() then |
243 | if g_addCheatCommands then |
244 | addConsoleCommand("gsFieldSetFruit", "Sets a given fruit to field", "consoleCommandSetFieldFruit", self) |
245 | addConsoleCommand("gsFieldSetFruitAll", "Sets a given fruit to all fields", "consoleCommandSetFieldFruitAll", self) |
246 | addConsoleCommand("gsFieldSetGround", "Sets a given fruit to field", "consoleCommandSetFieldGround", self) |
247 | addConsoleCommand("gsFieldSetGroundAll", "Sets a given fruit to allfield", "consoleCommandSetFieldGroundAll", self) |
248 | end |
249 | end |
250 | |
251 | if g_addCheatCommands then |
252 | addConsoleCommand("gsFieldToggleStatus", "Shows field status", "consoleCommandToggleDebugFieldStatus", self) |
253 | end |
254 | end) |
255 | |
256 | -- On clients, force all fields to have some value so map at least shows them |
257 | g_asyncTaskManager:addSubtask(function() |
258 | if not mission:getIsServer() then |
259 | for _, field in pairs(self.fields) do |
260 | self:setFieldGround(field, FieldGroundType.CULTIVATED, field.fieldAngle, 0, 0, 0, 0, 0, 0, false, false) |
261 | end |
262 | end |
263 | end) |
264 | |
265 | g_messageCenter:subscribe(MessageType.FARM_PROPERTY_CHANGED, self.onFarmPropertyChanged, self) |
266 | g_messageCenter:subscribe(MessageType.YEAR_CHANGED, self.onYearChanged, self) |
267 | g_messageCenter:subscribe(MessageType.PERIOD_CHANGED, self.onPeriodChanged, self) |
268 | end |