359 | function SoilSampler:getCanStartSoilSampling() |
360 | local spec = self.spec_soilSampler |
361 | local x, _, z = getWorldTranslation(spec.samplingNode) |
362 | local farmlandId = g_farmlandManager:getFarmlandIdAtWorldPosition(x, z) |
363 | if farmlandId == nil then -- no valid farmland, or not buyable |
364 | return false, g_i18n:getText("warning_youDontHaveAccessToThisLand") |
365 | end |
366 | |
367 | local landOwner = g_farmlandManager:getFarmlandOwner(farmlandId) |
368 | local accessible = landOwner ~= 0 and g_currentMission.accessHandler:canFarmAccessOtherId(self:getActiveFarm(), landOwner) |
369 | if not accessible then |
370 | return false, g_i18n:getText("warning_youDontHaveAccessToThisLand") |
371 | end |
372 | |
373 | if self.getIsMotorStarted ~= nil then |
374 | if not self:getIsMotorStarted() then |
375 | return false, g_i18n:getText("warning_motorNotStarted") |
376 | end |
377 | else |
378 | local rootAttacherVehicle = self:getRootVehicle() |
379 | if rootAttacherVehicle ~= self then |
380 | if rootAttacherVehicle.getIsMotorStarted ~= nil then |
381 | if not rootAttacherVehicle:getIsMotorStarted() then |
382 | return false, g_i18n:getText("warning_motorNotStarted") |
383 | end |
384 | end |
385 | end |
386 | end |
387 | |
388 | if self.getFoldAnimTime ~= nil then |
389 | local time = self:getFoldAnimTime() |
390 | if time > spec.foldMaxLimit or time < spec.foldMinLimit then |
391 | return false, self.spec_foldable.unfoldWarning |
392 | end |
393 | end |
394 | |
395 | return not self.spec_soilSampler.isSampling |
396 | end |
35 | function SoilSampler.initSpecialization() |
36 | local schema = Vehicle.xmlSchema |
37 | schema:setXMLSpecializationType("SoilSampler") |
38 | |
39 | schema:register(XMLValueType.NODE_INDEX, "vehicle.soilSampler#node", "Sampling Node") |
40 | schema:register(XMLValueType.FLOAT, "vehicle.soilSampler#radius", "Sampling radius", 10) |
41 | |
42 | schema:register(XMLValueType.STRING, "vehicle.soilSampler#actionNameTake", "Take sample input action name", "IMPLEMENT_EXTRA") |
43 | schema:register(XMLValueType.STRING, "vehicle.soilSampler#actionNameSend", "Send sample input action name", "IMPLEMENT_EXTRA3") |
44 | |
45 | schema:register(XMLValueType.STRING, "vehicle.soilSampler#animationName", "Sampling animation name") |
46 | schema:register(XMLValueType.FLOAT, "vehicle.soilSampler#animationSpeed", "Sampling animation speed", 1) |
47 | |
48 | schema:register(XMLValueType.FLOAT, "vehicle.soilSampler#foldMinLimit", "Fold min. limit", 0) |
49 | schema:register(XMLValueType.FLOAT, "vehicle.soilSampler#foldMaxLimit", "Fold max. limit", 1) |
50 | |
51 | schema:register(XMLValueType.STRING, "vehicle.soilSampler.samplesAnimation#name", "Samples animation name") |
52 | schema:register(XMLValueType.FLOAT, "vehicle.soilSampler.samplesAnimation#speed", "Samples animation speed", 1) |
53 | schema:register(XMLValueType.INT, "vehicle.soilSampler.samplesAnimation#minSamples", "Min. samples", 0) |
54 | schema:register(XMLValueType.INT, "vehicle.soilSampler.samplesAnimation#maxSamples", "Max. samples", 0) |
55 | |
56 | schema:register(XMLValueType.FLOAT, "vehicle.soilSampler.visualSamples#updateTime", "Update time", 0.5) |
57 | |
58 | schema:register(XMLValueType.NODE_INDEX, "vehicle.soilSampler.visualSamples.visualSample(?)#node", "Visual sample node") |
59 | |
60 | schema:setXMLSpecializationType() |
61 | |
62 | local schemaSavegame = Vehicle.xmlSchemaSavegame |
63 | schemaSavegame:register(XMLValueType.INT, "vehicles.vehicle(?)." .. SoilSampler.SPEC_NAME .. "#numCollectedSamples", "Num collected samples") |
64 | end |
95 | function SoilSampler:onLoad(savegame) |
96 | self.spec_soilSampler = self["spec_" .. SoilSampler.SPEC_NAME] |
97 | local spec = self.spec_soilSampler |
98 | |
99 | local baseName = "vehicle.soilSampler" |
100 | |
101 | spec.samplingNode = self.xmlFile:getValue(baseName .. "#node", nil, self.components, self.i3dMappings) |
102 | spec.samplingRadius = self.xmlFile:getValue(baseName .. "#radius", 10) |
103 | |
104 | local actionNameTake = self.xmlFile:getValue(baseName .. "#actionNameTake", "IMPLEMENT_EXTRA") |
105 | spec.inputActionTake = InputAction[actionNameTake] or InputAction.IMPLEMENT_EXTRA |
106 | |
107 | local actionNameSend = self.xmlFile:getValue(baseName .. "#actionNameSend", "IMPLEMENT_EXTRA3") |
108 | spec.inputActionSend = InputAction[actionNameSend] or InputAction.IMPLEMENT_EXTRA |
109 | |
110 | spec.isSampling = false |
111 | |
112 | spec.animationName = self.xmlFile:getValue(baseName .. "#animationName") |
113 | spec.animationSpeed = self.xmlFile:getValue(baseName .. "#animationSpeed", 1) |
114 | |
115 | spec.numCollectedSamples = 0 |
116 | |
117 | spec.foldMinLimit = self.xmlFile:getValue(baseName .. "#foldMinLimit", 0) |
118 | spec.foldMaxLimit = self.xmlFile:getValue(baseName .. "#foldMaxLimit", 1) |
119 | |
120 | spec.samplesAnimation = {} |
121 | spec.samplesAnimation.name = self.xmlFile:getValue(baseName .. ".samplesAnimation#name") |
122 | spec.samplesAnimation.speed = self.xmlFile:getValue(baseName .. ".samplesAnimation#speed", 1) |
123 | spec.samplesAnimation.minSamples = self.xmlFile:getValue( baseName .. ".samplesAnimation#minSamples", 0) |
124 | spec.samplesAnimation.maxSamples = self.xmlFile:getValue( baseName .. ".samplesAnimation#maxSamples", 0) |
125 | |
126 | spec.visualSampleUpdateTime = self.xmlFile:getValue(baseName .. ".visualSamples#updateTime", 0.5) |
127 | spec.visualSampleUpdated = true |
128 | spec.visualSamples = {} |
129 | local i = 0 |
130 | while true do |
131 | local visualSampleKey = string.format("%s.visualSamples.visualSample(%d)", baseName, i) |
132 | if not self.xmlFile:hasProperty(visualSampleKey) then |
133 | break |
134 | end |
135 | |
136 | local node = self.xmlFile:getValue(visualSampleKey .. "#node", nil, self.components, self.i3dMappings) |
137 | if node ~= nil then |
138 | setVisibility(node, false) |
139 | table.insert(spec.visualSamples, node) |
140 | end |
141 | |
142 | i = i + 1 |
143 | end |
144 | |
145 | spec.texts = {} |
146 | spec.texts.takeSample = g_i18n:getText("action_takeSoilSample", self.customEnvironment) |
147 | spec.texts.sendSoilSamples = g_i18n:getText("action_sendSoilSamples", self.customEnvironment) |
148 | spec.texts.numSamplesTaken = g_i18n:getText("info_numSamplesTaken", self.customEnvironment) |
149 | spec.texts.infoSamplesSend = g_i18n:getText("info_samplesSend", self.customEnvironment) |
150 | |
151 | if g_precisionFarming ~= nil then |
152 | spec.soilMap = g_precisionFarming.soilMap |
153 | spec.coverMap = g_precisionFarming.coverMap |
154 | spec.farmlandStatistics = g_precisionFarming.farmlandStatistics |
155 | end |
156 | end |
445 | function SoilSampler:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection) |
446 | if self.isClient then |
447 | local spec = self.spec_soilSampler |
448 | self:clearActionEventsTable(spec.actionEvents) |
449 | if isActiveForInputIgnoreSelection then |
450 | local _, actionEventId = self:addActionEvent(spec.actionEvents, spec.inputActionTake, self, SoilSampler.actionEventStartSample, false, true, false, true, nil) |
451 | g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_HIGH) |
452 | g_inputBinding:setActionEventText(actionEventId, spec.texts.takeSample) |
453 | |
454 | _, actionEventId = self:addActionEvent(spec.actionEvents, spec.inputActionSend, self, SoilSampler.actionEventSendSamples, false, true, false, true, nil) |
455 | g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_HIGH) |
456 | g_inputBinding:setActionEventText(actionEventId, spec.texts.sendSoilSamples) |
457 | |
458 | SoilSampler.updateActionEventState(self) |
459 | |
460 | spec.soilMap:setRequireMinimapDisplay(self:getFoldAnimTime() > 0, self, self:getIsSelected()) |
461 | spec.soilMap:setMinimapAdditionalElementLinkNode(spec.samplingNode) |
462 | spec.soilMap:setMinimapAdditionalElementRealSize(spec.samplingRadius * 2, spec.samplingRadius * 2) |
463 | end |
464 | end |
465 | end |
200 | function SoilSampler:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
201 | local spec = self.spec_soilSampler |
202 | if spec.isSampling then |
203 | if self.isClient then |
204 | if not spec.visualSampleUpdated then |
205 | if self:getAnimationTime(spec.animationName) >= spec.visualSampleUpdateTime then |
206 | local sampleIndex = self:getNormalizedSampleIndex() |
207 | |
208 | for i=1, #spec.visualSamples do |
209 | setVisibility(spec.visualSamples[i], i <= sampleIndex) |
210 | end |
211 | spec.visualSampleUpdated = false |
212 | end |
213 | end |
214 | end |
215 | |
216 | if not self:getIsAnimationPlaying(spec.animationName) then |
217 | spec.isSampling = false |
218 | self:setAnimationTime(spec.animationName, 0, false) |
219 | |
220 | if spec.soilMap:getMinimapAdditionalElementLinkNode() == spec.samplingNode then |
221 | spec.soilMap:setMinimapSamplingState(false) |
222 | end |
223 | |
224 | self:processSoilSampling() |
225 | self.speedLimit = math.huge |
226 | end |
227 | end |
228 | |
229 | if isActiveForInputIgnoreSelection and spec.numCollectedSamples > 0 then |
230 | g_currentMission:addExtraPrintText(string.format(spec.texts.numSamplesTaken, spec.numCollectedSamples)) |
231 | end |
232 | end |
400 | function SoilSampler:processSoilSampling() |
401 | if self.isServer then |
402 | local spec = self.spec_soilSampler |
403 | if spec.soilMap ~= nil then |
404 | local length = spec.samplingRadius |
405 | local octagon = SoilSampler.SAMPLING_OCTAGON |
406 | for i=1, #octagon do |
407 | local position = octagon[i] |
408 | local xs, _, zs = localToWorld(spec.samplingNode, position[1] * length, position[2] * length, position[3] * length) |
409 | local xw, _, zw = localToWorld(spec.samplingNode, position[4] * length, position[5] * length, position[6] * length) |
410 | local xh, _, zh = localToWorld(spec.samplingNode, position[7] * length, position[8] * length, position[9] * length) |
411 | |
412 | spec.coverMap:analyseArea(xs, zs, xw, zw, xh, zh, nil, self:getOwnerFarmId()) |
413 | end |
414 | end |
415 | end |
416 | end |
420 | function SoilSampler:sendTakenSoilSamples(noEventSend) |
421 | local spec = self.spec_soilSampler |
422 | |
423 | if self.isServer then |
424 | if spec.soilMap ~= nil then |
425 | spec.soilMap:analyseSoilSamples(self:getOwnerFarmId(), spec.numCollectedSamples) |
426 | end |
427 | end |
428 | |
429 | if self.isClient then |
430 | for i=1, #spec.visualSamples do |
431 | setVisibility(spec.visualSamples[i], false) |
432 | end |
433 | |
434 | self:playAnimation(spec.samplesAnimation.name, -spec.samplesAnimation.speed, self:getAnimationTime(spec.samplesAnimation.name), true) |
435 | end |
436 | |
437 | spec.numCollectedSamples = 0 |
438 | SoilSampler.updateActionEventState(self) |
439 | |
440 | SoilSamplerSendEvent.sendEvent(self, noEventSend) |
441 | end |
326 | function SoilSampler:setNumCollectedSoilSamples(num, updateVisuals) |
327 | local spec = self.spec_soilSampler |
328 | spec.numCollectedSamples = num or (spec.numCollectedSamples + 1) |
329 | |
330 | if updateVisuals then |
331 | local sampleIndex = self:getNormalizedSampleIndex() |
332 | for j=1, #spec.visualSamples do |
333 | setVisibility(spec.visualSamples[j], j <= sampleIndex) |
334 | end |
335 | |
336 | local stopTime = (sampleIndex - spec.samplesAnimation.minSamples) / (spec.samplesAnimation.maxSamples - spec.samplesAnimation.minSamples) |
337 | self:setAnimationTime(spec.samplesAnimation.name, stopTime, true) |
338 | end |
339 | end |
267 | function SoilSampler:startSoilSampling(noEventSend) |
268 | local spec = self.spec_soilSampler |
269 | spec.isSampling = true |
270 | |
271 | if self.isServer then |
272 | if not self:getIsLowered(false) then |
273 | local attacherVehicle = self:getAttacherVehicle() |
274 | if attacherVehicle ~= nil then |
275 | local jointDesc = attacherVehicle:getAttacherJointDescFromObject(self) |
276 | if jointDesc.allowsLowering then |
277 | local jointDescIndex = attacherVehicle:getAttacherJointIndexFromObject(self) |
278 | attacherVehicle:setJointMoveDown(jointDescIndex, true, false) |
279 | end |
280 | end |
281 | end |
282 | |
283 | local farmlandStatistics, isOnField, farmlandId = self:getPFStatisticInfo() |
284 | if farmlandStatistics ~= nil and isOnField and farmlandId ~= nil then |
285 | spec.farmlandStatistics:updateStatistic(farmlandId, "numSoilSamples", 1) |
286 | spec.farmlandStatistics:updateStatistic(farmlandId, "soilSampleCosts", spec.soilMap:getPricePerSoilSample()) |
287 | end |
288 | |
289 | self.speedLimit = 0 |
290 | end |
291 | |
292 | self:playAnimation(spec.animationName, spec.animationSpeed, self:getAnimationTime(spec.animationName), true) |
293 | |
294 | self:setNumCollectedSoilSamples(spec.numCollectedSamples + 1, false) |
295 | |
296 | if self:getIsActiveForInput(true) then |
297 | spec.soilMap:setMinimapSamplingState(true) |
298 | end |
299 | |
300 | if self.isClient then |
301 | if (spec.numCollectedSamples - 1) % #spec.visualSamples == 0 then |
302 | for i=1, #spec.visualSamples do |
303 | setVisibility(spec.visualSamples[i], false) |
304 | end |
305 | |
306 | self:playAnimation(spec.samplesAnimation.name, -spec.samplesAnimation.speed, self:getAnimationTime(spec.samplesAnimation.name), true) |
307 | else |
308 | local sampleIndex = self:getNormalizedSampleIndex() |
309 | local stopTime = (sampleIndex - spec.samplesAnimation.minSamples) / (spec.samplesAnimation.maxSamples - spec.samplesAnimation.minSamples) |
310 | if self:getAnimationTime(spec.samplesAnimation.name) < stopTime then |
311 | self:setAnimationStopTime(spec.samplesAnimation.name, stopTime) |
312 | self:playAnimation(spec.samplesAnimation.name, spec.samplesAnimation.speed, self:getAnimationTime(spec.samplesAnimation.name), true) |
313 | end |
314 | end |
315 | |
316 | spec.visualSampleUpdated = false |
317 | end |
318 | |
319 | SoilSampler.updateActionEventState(self) |
320 | |
321 | SoilSamplerStartEvent.sendEvent(self, noEventSend) |
322 | end |