LUADOC - Farming Simulator 19

Printable Version

HusbandryModuleAnimals

Functions

new

Description
Creating manager
Definition
new()
Return Values
tableinstanceinstance of object
Code
32function HusbandryModuleAnimal:new(customMt)
33 local self = HusbandryModuleBase:new(customMt or HusbandryModuleAnimal_mt)
34 return self
35end

delete

Description
Deletes instance
Definition
delete()
Code
39function HusbandryModuleAnimal:delete()
40 for i=#self.animals, 1, -1 do
41 local animal = self.animals[i]
42 self:removeSingleAnimal(animal, true)
43 animal:delete()
44 end
45 self:updateVisualAnimals()
46
47 if self.animalLoadingTrigger ~= nil then
48 self.animalLoadingTrigger:delete()
49 self.animalLoadingTrigger = nil
50 end
51
52 if self.husbandryId ~= 0 then
53 delete(self.husbandryId)
54 end
55end

initDataStructures

Description
Initialize data structures
Definition
initDataStructures()
Code
59function HusbandryModuleAnimal:initDataStructures()
60 HusbandryModuleAnimal:superClass().initDataStructures(self)
61
62 self.animalType = ""
63
64 self.updateVisuals = false
65
66 self.animalsToAdd = nil
67 self.renamingTasks = nil
68 self.animals = {}
69 self.typedAnimals = {}
70
71 self.reproductionRatesPerDay = {}
72 self.newAnimalPercentages = {}
73
74 self.visualIdToAnimal = {}
75 self.visualAnimals = {}
76
77 self.maxNumAnimals = 0
78 self.carryingCapacity = 0
79
80 self.navMeshNode = nil
81 self.animalHusbandryXMLFilename = ""
82 self.placementRaycastDistance = 2.0
83 self.husbandryId = 0
84 self.animalLoadingTrigger = nil
85 self.rideableDeliveryArea = {}
86 self.rideableDeliveryArea.startNode = nil
87 self.rideableDeliveryArea.widthNode = nil
88 self.rideableDeliveryArea.heightNode = nil
89
90 local profileClass = Utils.getPerformanceClassId()
91 if profileClass >= GS_PROFILE_VERY_HIGH then
92 self.maxNumVisualAnimals = 25
93 elseif profileClass >= GS_PROFILE_HIGH then
94 self.maxNumVisualAnimals = 20
95 else
96 self.maxNumVisualAnimals = 16
97 end
98
99 self.isDirtyFlag = 0
100end

load

Description
Loads data from xml
Definition
load(table xmlFile, string xmlKey, table rootNode)
Arguments
tablexmlFilehandle
stringxmlKeyfrom which to read the configuration
tablerootNodeof the husbandry
Return Values
booleantrueif loading was successful else false
Code
108function HusbandryModuleAnimal:load(xmlFile, configKey, rootNode, owner)
109 if not HusbandryModuleAnimal:superClass().load(self, xmlFile, configKey, rootNode, owner) then
110 return false
111 end
112
113 if not hasXMLProperty(xmlFile, configKey) then
114 return false
115 end
116
117 self.animalType = getXMLString(xmlFile, configKey .. "#type")
118 if self.animalType == nil then
119 g_logManager:error("Missing animal type for husbandry!")
120 return false
121 end
122
123 if self.animalType ~= nil then
124 local animals = g_animalManager:getAnimalsByType(self.animalType)
125 if animals == nil then
126 g_logManager:error("Animal type '%s' not found!", self.animalType)
127 return false
128 end
129
130 for _, subType in ipairs(animals.subTypes) do
131 self.reproductionRatesPerDay[subType.fillType] = 0
132 self.newAnimalPercentages[subType.fillType] = 0
133 end
134 end
135
136 self.navMeshNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, configKey .. "#navmeshNode"))
137 if self.navMeshNode == nil then
138 g_logManager:error("Invalid navMeshIndex in '%s'!", getName(rootNode))
139 return false
140 end
141
142 self.rideableDeliveryArea = {}
143 self.rideableDeliveryArea.startNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, configKey .. "#rideableDeliveryStartNode"))
144 self.rideableDeliveryArea.widthNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, configKey .. "#rideableDeliveryWidthNode"))
145 self.rideableDeliveryArea.heightNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, configKey .. "#rideableDeliveryHeightNode"))
146
147 self.animalHusbandryXMLFilename = Utils.getNoNil(getXMLString(xmlFile, configKey .. "#husbandryFileName"), "")
148 self.animalHusbandryXMLFilename = Utils.getFilename(self.animalHusbandryXMLFilename, g_currentMission.baseDirectory)
149 if self.animalHusbandryXMLFilename == "" then
150 g_logManager:error("Missing animal husbandry xml filename!")
151 return false
152 end
153
154 self.placementRaycastDistance = Utils.getNoNil(getXMLFloat(xmlFile, configKey .. "#placementRaycastDistance"), 2.0)
155
156 self.maxNumAnimals = Utils.getNoNil(getXMLInt(xmlFile, configKey .. "#maxNumAnimals"), 16)
157 self.carryingCapacity = Utils.getNoNil(getXMLInt(xmlFile, configKey .. "#carryingCapacity"), 16)
158
159 local animalLoadTriggerId = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, configKey .. "#animalLoadTriggerNode"))
160 if animalLoadTriggerId ~= nil then
161 self.animalLoadingTrigger = AnimalLoadingTrigger:new(self.owner.isServer, self.owner.isClient)
162 if self.animalLoadingTrigger ~= nil then
163 self.animalLoadingTrigger:load(animalLoadTriggerId, self.owner)
164 self.animalLoadingTrigger:register(true)
165 end
166 end
167
168 if self.animalType == "HORSE" then
169 self.maxNumVisualAnimals = math.min(self.maxNumAnimals, 16)
170 self.maxNumAnimals = math.min(self.maxNumAnimals, 16)
171 end
172
173 local maxAnimals = (2^HusbandryModuleAnimal.SEND_NUM_BITS) - 1
174 if self.maxNumAnimals > maxAnimals then
175 g_logManager:warning("Maximum number of animals reached! Maximum is '%d'!", maxAnimals)
176 self.maxNumAnimals = maxAnimals
177 end
178
179 self.isDirtyFlag = self.owner:getNextDirtyFlag()
180
181 return true
182end

finalizePlacement

Description
Called when husbandry is placed
Definition
finalizePlacement()
Return Values
booltrueif successful
Code
187function HusbandryModuleAnimal:finalizePlacement()
188 if not HusbandryModuleAnimal:superClass().finalizePlacement(self) then
189 return false
190 end
191
192 self.husbandryId = createAnimalHusbandry(self.animalType, self.navMeshNode, self.animalHusbandryXMLFilename, self.placementRaycastDistance, true)
193
194 if self.husbandryId == 0 then
195 g_logManager:error("Could not create animal husbandry!")
196 return false
197 end
198
199 return true
200end

readStream

Description
Reads network stream
Definition
readStream(integer streamId, table connection)
Arguments
integerstreamIdnetwork stream identification
tableconnectionconnection information
Code
206function HusbandryModuleAnimal:readStream(streamId, connection)
207 HusbandryModuleAnimal:superClass().readStream(self, streamId, connection)
208
209 self.animalsToAdd = {}
210
211 local numAnimals = streamReadUInt16(streamId)
212 for i = 1, numAnimals do
213 local animalObjectId = NetworkUtil.readNodeObjectId(streamId)
214 table.insert(self.animalsToAdd, animalObjectId)
215 end
216end

writeStream

Description
Writes network stream
Definition
writeStream(integer streamId, table connection)
Arguments
integerstreamIdnetwork stream identification
tableconnectionconnection information
Code
222function HusbandryModuleAnimal:writeStream(streamId, connection)
223 HusbandryModuleAnimal:superClass().writeStream(self, streamId, connection)
224
225 streamWriteUInt16(streamId, #self.animals)
226 for _, animal in ipairs(self.animals) do
227 local animalObjectId = NetworkUtil.getObjectId(animal)
228 NetworkUtil.writeNodeObjectId(streamId, animalObjectId)
229 end
230end

loadFromXMLFile

Description
Loads information from attributes and node. Retrives from xml file information.
Definition
loadFromXMLFile(table xmlFile, string key)
Arguments
tablexmlFileXML file handler
stringkeyXML base key
Code
236function HusbandryModuleAnimal:loadFromXMLFile(xmlFile, key)
237 HusbandryModuleAnimal:superClass().loadFromXMLFile(self, xmlFile, key)
238
239 self.animalsToAdd = {}
240 local i = 0
241 while true do
242 local animalKey = string.format("%s.animal(%d)", key, i)
243 if not hasXMLProperty(xmlFile, animalKey) then
244 break
245 end
246
247
248 local animal = Animal.createFromXMLFile(xmlFile, animalKey, self.owner.isServer, self.owner.isClient, self.owner)
249 if animal ~= nil then
250 animal:register()
251 table.insert(self.animalsToAdd, NetworkUtil.getObjectId(animal))
252 end
253
254 i = i + 1
255 end
256
257 local i = 0
258 while true do
259 local animalKey = string.format("%s.breeding(%d)", key, i)
260 if not hasXMLProperty(xmlFile, animalKey) then
261 break
262 end
263
264 local fillTypeName = getXMLString(xmlFile, animalKey.."#fillType")
265 local fillTypeIndex = g_fillTypeManager:getFillTypeIndexByName(fillTypeName)
266 if fillTypeIndex ~= nil then
267 self.newAnimalPercentages[fillTypeIndex] = getXMLFloat(xmlFile, animalKey.."#percentage") or 0
268 end
269
270 i = i + 1
271 end
272end

saveToXMLFile

Description
Save module to xml
Definition
saveToXMLFile(integer xmlFile, string key, table usedModNames)
Arguments
integerxmlFilefile handle
stringkeyxml key
tableusedModNames
Code
279function HusbandryModuleAnimal:saveToXMLFile(xmlFile, key, usedModNames)
280 HusbandryModuleAnimal:superClass().saveToXMLFile(self, xmlFile, key, usedModNames)
281
282 for i, animal in ipairs(self.animals) do
283 local animalKey = string.format("%s.animal(%d)", key, i-1)
284 animal:saveToXMLFile(xmlFile, animalKey, usedModNames)
285 end
286
287 local i = 0
288 for fillTypeIndex, percentage in pairs(self.newAnimalPercentages) do
289 if percentage > 0 then
290 local animalKey = string.format("%s.breeding(%d)", key, i)
291 setXMLString(xmlFile, animalKey.."#fillType", g_fillTypeManager:getFillTypeNameByIndex(fillTypeIndex))
292 setXMLFloat(xmlFile, animalKey.."#percentage", percentage)
293 i = i + 1
294 end
295 end
296end

update

Description
Update module
Definition
update(float dt)
Arguments
floatdtdelta time
Code
301function HusbandryModuleAnimal:update(dt)
302 HusbandryModuleAnimal:superClass().update(self, dt)
303
304 local needsUpdate = self.updateVisuals or self.animalsToAdd ~= nil or self.renamingTasks ~= nil or self.pendingRideables ~= nil
305
306 if isHusbandryReady(self.husbandryId) then
307 if self.animalsToAdd ~= nil then
308 for i=#self.animalsToAdd, 1, -1 do
309 local id = self.animalsToAdd[i]
310 local animal = NetworkUtil.getObject(id)
311 if animal ~= nil then
312 self:addSingleAnimal(animal, true)
313 table.remove(self.animalsToAdd, i)
314 end
315 end
316 if #self.animalsToAdd == 0 then
317 self.animalsToAdd = nil
318 self:updateBreeding(0)
319 end
320 end
321
322 if self.renamingTasks ~= nil then
323 for i=#self.renamingTasks, 1, -1 do
324 local data = self.renamingTasks[i]
325 local animal = NetworkUtil.getObject(data.animalId)
326 if animal ~= nil then
327 animal:setName(data.name)
328 table.remove(self.renamingTasks, i)
329 end
330 end
331
332 if #self.renamingTasks == 0 then
333 self.renamingTasks = nil
334 end
335 end
336
337 if self.updateVisuals then
338 self:updateVisualAnimals()
339 self.updateVisuals = false
340 end
341
342 if self.pendingRideables ~= nil then
343 for i=#self.pendingRideables, 1, -1 do
344 local animal = self.pendingRideables[i]
345 if animal:tryToFinishRideable() then
346 table.remove(self.pendingRideables, i)
347 end
348 end
349
350 if #self.pendingRideables == 0 then
351 self.pendingRideables = nil
352 end
353 end
354
355 needsUpdate = needsUpdate or self.animalsToAdd ~= nil
356 end
357
358 return needsUpdate
359end

getSupportsSubType

Description
Definition
getSupportsSubType()
Code
381function HusbandryModuleAnimal:getSupportsSubType(subType)
382 return subType.type == self.animalType
383end

addAnimals

Description
Definition
addAnimals()
Code
387function HusbandryModuleAnimal:addAnimals(animals, noEventSend)
388 local sendAnimals = {}
389
390 for _, animal in ipairs(animals) do
391 if self:addSingleAnimal(animal, true) then
392 table.insert(sendAnimals, animal)
393 end
394 end
395
396 if self.owner.isServer and noEventSend == nil or not noEventSend then
397 g_server:broadcastEvent(AnimalAddEvent:new(self.owner, sendAnimals), nil, nil, nil, true)
398 end
399end

addSingleAnimal

Description
Definition
addSingleAnimal()
Code
403function HusbandryModuleAnimal:addSingleAnimal(animal, noEventSend)
404 if #self.animals >= self.maxNumAnimals then
405 return false
406 end
407
408 if not self:getSupportsSubType(animal:getSubType()) then
409 return false
410 end
411
412 table.insert(self.animals, animal)
413
414 local fillTypeIndex = animal:getFillTypeIndex()
415 if self.typedAnimals[fillTypeIndex] == nil then
416 self.typedAnimals[fillTypeIndex] = {}
417 end
418 table.insert(self.typedAnimals[fillTypeIndex], animal)
419
420 animal:setOwner(self.owner)
421
422 if self.owner.isServer and noEventSend == nil or not noEventSend then
423 g_server:broadcastEvent(AnimalAddEvent:new(self.owner, {animal}), nil, nil, nil, true)
424 end
425
426 g_messageCenter:publish(MessageType.HUSBANDRY_ANIMALS_CHANGED, self.owner)
427
428 self:updateAnimalParameters()
429
430 self.updateVisuals = true
431 self.owner:raiseActive()
432
433 if animal:isa(RideableAnimal) then
434 if not animal:getIsRideableSetupDone() then
435 if self.pendingRideables == nil then
436 self.pendingRideables = {}
437 end
438 table.insert(self.pendingRideables, animal)
439 self.owner:raiseActive()
440 end
441 end
442
443 return true
444end

addPendingAnimal

Description
Definition
addPendingAnimal()
Code
448function HusbandryModuleAnimal:addPendingAnimal(animalObjectId)
449 if self.animalsToAdd == nil then
450 self.animalsToAdd = {}
451 end
452 table.insert(self.animalsToAdd, animalObjectId)
453
454 self.owner:raiseActive()
455end

removeAnimals

Description
Definition
removeAnimals()
Code
459function HusbandryModuleAnimal:removeAnimals(animals, noEventSend)
460 local sendAnimals = {}
461
462 for _, animal in ipairs(animals) do
463 if self:removeSingleAnimal(animal, true) then
464 table.insert(sendAnimals, animal)
465 end
466 end
467
468 if self.owner.isServer and (noEventSend == nil or not noEventSend) then
469 g_server:broadcastEvent(AnimalRemoveEvent:new(self.owner, sendAnimals), nil, nil, nil, true)
470 end
471end

removeSingleAnimal

Description
Definition
removeSingleAnimal()
Code
475function HusbandryModuleAnimal:removeSingleAnimal(animal, noEventSend)
476 local found = false
477
478 for i, storedAnimal in ipairs(self.animals) do
479 if storedAnimal == animal then
480 if self.owner.isServer and (noEventSend == nil or not noEventSend) then
481 g_server:broadcastEvent(AnimalRemoveEvent:new(self.owner, {animal}), nil, nil, nil, true)
482 end
483
484 table.remove(self.animals, i)
485
486 local fillTypeIndex = animal:getFillTypeIndex()
487 table.remove(self.typedAnimals[fillTypeIndex], 1)
488
489 found = true
490 break
491 end
492 end
493
494 if found then
495 local visualId = animal:getVisualId()
496 if visualId ~= nil then
497 removeHusbandryAnimal(self.husbandryId, visualId)
498 self.visualIdToAnimal[visualId] = nil
499 animal:setVisualId(nil)
500
501 local fillType = animal:getFillTypeIndex()
502 for k, visual in ipairs(self.visualAnimals[fillType].visuals) do
503 if visual.id == visualId then
504 table.remove(self.visualAnimals[fillType].visuals, k)
505 break
506 end
507 end
508
509 if #self.visualAnimals[fillType].visuals == 0 then
510 self.visualAnimals[fillType] = nil
511 end
512 end
513
514 g_messageCenter:publish(MessageType.HUSBANDRY_ANIMALS_CHANGED, self.owner)
515
516 self:updateAnimalParameters()
517
518 self.updateVisuals = true
519 self.owner:raiseActive()
520
521 return true
522 end
523
524 return false
525end

updateVisualAnimals

Description
Definition
updateVisualAnimals()
Code
529function HusbandryModuleAnimal:updateVisualAnimals()
530
531 local numAnimals = #self.animals
532 local maxVisualAnimals = math.min(numAnimals, self.maxNumVisualAnimals)
533
534 local usableAnimals = {}
535
536 local percentages = {}
537 for _, animal in ipairs(self.animals) do
538 local fillType = animal:getFillTypeIndex()
539 if percentages[fillType] == nil then
540 percentages[fillType] = 0
541 usableAnimals[fillType] = {}
542 end
543 percentages[fillType] = percentages[fillType] + 1
544
545 if animal:getVisualId() == nil then
546 table.insert(usableAnimals[fillType], animal)
547 end
548 end
549
550 local instances = {}
551 local fillTypeToIntance = {}
552 local numInstances = 0
553 for fillType, num in pairs(percentages) do
554 local percentage = 0
555 if #self.animals > 0 then
556 percentage = num / numAnimals
557 end
558 local instance = {fillType=fillType, count=math.max(1, math.floor(maxVisualAnimals*percentage))}
559 table.insert(instances, instance)
560 fillTypeToIntance[fillType] = instance
561 numInstances = numInstances + instance.count
562 end
563
564 local function sort(a1, a2)
565 return a1.count < a2.count
566 end
567 table.sort(instances, sort)
568
569 -- if there's dif we reduce/increase each type by 1 until dif is 0
570 local dif = maxVisualAnimals - numInstances
571 local i = 1
572 while dif ~= 0 do
573 local delta = MathUtil.sign(dif)
574 instances[i].count = instances[i].count + delta
575 dif = dif - delta
576
577 i = i + 1
578 if i > #instances then
579 i = 1
580 end
581 end
582
583 -- remove visual animals if not part of husbandry anymore
584 for k, visualAnimal in pairs(self.visualAnimals) do
585 if fillTypeToIntance[visualAnimal.fillType] == nil then
586 for i=1, #visualAnimal.visuals do
587 local visual = table.remove(visualAnimal.visuals, 1)
588 removeHusbandryAnimal(self.husbandryId, visual.id)
589 visual.animal:setVisualId(nil)
590 self.visualIdToAnimal[visual.id] = nil
591 end
592 self.visualAnimals[k] = nil
593 end
594 end
595
596 -- add or remove visual animals
597 for _, instance in ipairs(instances) do
598 local visualAnimal = self.visualAnimals[instance.fillType]
599 if visualAnimal == nil then
600 visualAnimal = {fillType=instance.fillType, visuals={}}
601 self.visualAnimals[instance.fillType] = visualAnimal
602 end
603
604 local dif = instance.count - #visualAnimal.visuals
605
606 if dif > 0 then
607 for i=1, dif do
608 local nextAnimal = table.remove(usableAnimals[visualAnimal.fillType], 1)
609 if nextAnimal == nil then
610 break
611 end
612
613 local subType = nextAnimal:getSubType()
614 local id = addHusbandryAnimal(self.husbandryId, subType.subTypeId-1)
615
616 if id ~= 0 then
617 setAnimalTextureTile(self.husbandryId, id, subType.texture.tileUIndex, subType.texture.tileVIndex)
618 self.visualIdToAnimal[id] = nextAnimal
619 nextAnimal:setVisualId(id)
620 table.insert(visualAnimal.visuals, {animal=nextAnimal, id=id})
621 end
622 end
623 elseif dif < 0 then
624 for j=1, math.abs(dif) do
625 local visual = table.remove(visualAnimal.visuals, 1)
626 if visual == nil then
627 break
628 end
629
630 removeHusbandryAnimal(self.husbandryId, visual.id)
631 visual.animal:setVisualId(nil)
632 self.visualIdToAnimal[visual.id] = nil
633 end
634 end
635 end
636
637 self:updateVisualDirt()
638end

updateAnimalParameters

Description
Definition
updateAnimalParameters()
Code
642function HusbandryModuleAnimal:updateAnimalParameters()
643
644 local averageWaterUsagePerDay = 0.0
645 local averageStrawUsagePerDay = 0.0
646 local averageFoodUsagePerDay = 0.0
647 local averageFoodSpillageProductionPerDay = 0.0
648 local averagePalletsProductionPerDay = 0.0
649 local averageManureProductionPerDay = 0.0
650 local averageLiquidManureProductionPerDay = 0.0
651 local averageMilkProductionPerDay = 0.0
652
653 for _, animal in ipairs(self.animals) do
654 local subType = animal:getSubType()
655
656 local input = subType.input
657 local output = subType.output
658 averageWaterUsagePerDay = averageWaterUsagePerDay + input.waterPerDay
659 averageStrawUsagePerDay = averageStrawUsagePerDay + input.strawPerDay
660 averageFoodUsagePerDay = averageFoodUsagePerDay + input.foodPerDay
661 averageFoodSpillageProductionPerDay = averageFoodSpillageProductionPerDay + output.foodSpillagePerDay
662 averagePalletsProductionPerDay = averagePalletsProductionPerDay + output.palletsPerDay
663 averageManureProductionPerDay = averageManureProductionPerDay + output.manurePerDay
664 averageLiquidManureProductionPerDay = averageLiquidManureProductionPerDay + output.liquidManurePerDay
665 averageMilkProductionPerDay = averageMilkProductionPerDay + output.milkPerDay
666 end
667
668 local numAnimals = #self.animals
669 averageWaterUsagePerDay = averageWaterUsagePerDay / numAnimals
670 averageStrawUsagePerDay = averageStrawUsagePerDay / numAnimals
671 averageFoodUsagePerDay = averageFoodUsagePerDay / numAnimals
672 averageFoodSpillageProductionPerDay = averageFoodSpillageProductionPerDay / numAnimals
673 averagePalletsProductionPerDay = averagePalletsProductionPerDay / numAnimals
674 averageManureProductionPerDay = averageManureProductionPerDay / numAnimals
675 averageLiquidManureProductionPerDay = averageLiquidManureProductionPerDay / numAnimals
676 averageMilkProductionPerDay = averageMilkProductionPerDay / numAnimals
677
678 local nbDays = 6.0
679 local maxNumAnimals = self.maxNumAnimals
680 local usageMultiplier = nbDays * maxNumAnimals
681 local waterCapacity = averageWaterUsagePerDay * usageMultiplier
682 local strawCapacity = averageStrawUsagePerDay * usageMultiplier
683 local foodCapacity = averageFoodUsagePerDay * usageMultiplier
684 local foodSpillageCapacity = averageFoodSpillageProductionPerDay * maxNumAnimals
685 local palletsCapacity = averagePalletsProductionPerDay * maxNumAnimals
686 local manureCapacity = averageManureProductionPerDay * maxNumAnimals
687 local liquidManureCapacity = averageLiquidManureProductionPerDay * maxNumAnimals
688 local milkCapacity = averageMilkProductionPerDay * maxNumAnimals
689
690 self.owner:setModuleParameters("water", waterCapacity, averageWaterUsagePerDay)
691 self.owner:setModuleParameters("straw", strawCapacity, averageStrawUsagePerDay)
692 self.owner:setModuleParameters("food", foodCapacity, averageFoodUsagePerDay)
693 self.owner:setModuleParameters("foodSpillage", foodSpillageCapacity, averageFoodSpillageProductionPerDay)
694 self.owner:setModuleParameters("pallets", palletsCapacity, averagePalletsProductionPerDay)
695 self.owner:setModuleParameters("manure", manureCapacity, averageManureProductionPerDay)
696 self.owner:setModuleParameters("liquidManure", liquidManureCapacity, averageLiquidManureProductionPerDay)
697 self.owner:setModuleParameters("milk", milkCapacity, averageMilkProductionPerDay)
698end

addRideable

Description
Adds rideable vehicle in the husbandry
Definition
addRideable(integer husbandry)
Arguments
integerhusbandryanimal id
Code
703function HusbandryModuleAnimal:addRideable(visualId, player)
704 local animal = self.visualIdToAnimal[visualId]
705 if animal ~= nil and animal:isa(RideableAnimal) then
706 if animal:getCanBeRidden() then
707 animal:activateRiding(player, false)
708 end
709 end
710end

removeRideable

Description
Removes rideable vehicle in the husbandry
Definition
removeRideable(integer husbandry)
Arguments
integerhusbandryanimal id
Code
715function HusbandryModuleAnimal:removeRideable(visualId)
716 local animal = self.visualIdToAnimal[visualId]
717 if animal ~= nil then
718 animal:deactivateRiding()
719 end
720end

isRideableInOnHusbandryGround

Description
Definition
isRideableInOnHusbandryGround()
Return Values
booltrueif animal is in the husbandry
Code
725function HusbandryModuleAnimal:isRideableInOnHusbandryGround(visualId)
726 local animal = self.visualIdToAnimal[visualId]
727 if animal ~= nil and animal:isa(RideableAnimal) then
728 return animal:isOnHusbandyGround()
729 end
730 return false
731end

getSupportsRiding

Description
Definition
getSupportsRiding()
Code
735function HusbandryModuleAnimal:getSupportsRiding(visualId)
736 local animal = self.visualIdToAnimal[visualId]
737 return animal ~= nil and animal:isa(RideableAnimal)
738end

getCanBeRidden

Description
Definition
getCanBeRidden()
Code
741function HusbandryModuleAnimal:getCanBeRidden(visualId)
742 local animal = self.visualIdToAnimal[visualId]
743 if animal ~= nil and animal:isa(RideableAnimal) then
744 return animal:getCanBeRidden()
745 end
746
747 return false
748end

hideAnimal

Description
Hide animal to husbandry
Definition
hideAnimal(integer visualId)
Arguments
integervisualIdanimal index in engine
Code
753function HusbandryModuleAnimal:hideAnimal(visualId)
754 if visualId ~= nil and visualId ~= 0 then
755 hideAnimal(self.husbandryId, visualId)
756 end
757end

showAnimal

Description
Show animal to husbandry
Definition
showAnimal(integer visualId)
Arguments
integervisualIdanimal index in engine
Code
762function HusbandryModuleAnimal:showAnimal(visualId)
763 if visualId ~= nil and visualId ~= 0 then
764 showAnimal(self.husbandryId, visualId)
765 end
766end

cleanAnimal

Description
Player cleans animal
Definition
cleanAnimal(integer visualId)
Arguments
integervisualIdanimal index in engine
Code
771function HusbandryModuleAnimal:cleanAnimal(visualId, dt)
772 local animal = self.visualIdToAnimal[visualId]
773
774 if animal ~= nil and animal.clean ~= nil then
775 animal:clean(dt)
776 end
777
778 self:updateVisualDirt()
779end

isAnimalDirty

Description
Definition
isAnimalDirty()
Code
783function HusbandryModuleAnimal:isAnimalDirty(visualId)
784 local animal = self.visualIdToAnimal[visualId]
785
786 if animal ~= nil then
787 return animal:getDirtScale() > 0.0
788 end
789 return false
790end

updateFitness

Description
Definition
updateFitness()
Code
794function HusbandryModuleAnimal:updateFitness()
795 for _, animal in ipairs(self.animals) do
796 if animal ~= nil and animal:isa(Horse) then
797 return animal:updateFitness()
798 end
799 end
800end

updateVisualDirt

Description
Definition
updateVisualDirt()
Code
804function HusbandryModuleAnimal:updateVisualDirt()
805 for visualId, animal in pairs(self.visualIdToAnimal) do
806 local rough, _, tiling, x = getAnimalShaderParameter(self.husbandryId, visualId, "RDT")
807 setAnimalShaderParameter(self.husbandryId, visualId, "RDT", rough, animal:getDirtScale(), tiling, x)
808 end
809end

updateBreeding

Description
Update reproduction information for the animals
Definition
updateBreeding(float dayToInterval)
Arguments
floatdayToInterval
Code
814function HusbandryModuleAnimal:updateBreeding(dayToInterval)
815 -- calculate reproduction rate ...
816
817 local totalAnimals = #self.animals
818 if self.owner.isServer then
819 for fillTypeIndex, animals in pairs(self.typedAnimals) do
820 local numAnimals = #animals
821 if numAnimals > 0 and totalAnimals < self.maxNumAnimals then
822 local subType = animals[1]:getSubType()
823 local birthRatePerDay = subType.breeding.birthRatePerDay
824 if birthRatePerDay > 0 then
825 local deltaTime = dayToInterval
826 local carryingCapacity = self.carryingCapacity
827 local birthIncrease = deltaTime * birthRatePerDay * ((carryingCapacity - numAnimals) / carryingCapacity) * numAnimals
828
829 self.newAnimalPercentages[fillTypeIndex] = self.newAnimalPercentages[fillTypeIndex] + birthIncrease
830 if self.newAnimalPercentages[fillTypeIndex] > 1 then
831 local numNewAnimals = math.floor(self.newAnimalPercentages[fillTypeIndex])
832
833 self.newAnimalPercentages[fillTypeIndex] = self.newAnimalPercentages[fillTypeIndex] - numNewAnimals
834 for i=1, numNewAnimals do
835 -- do not use local numAnimals because self.numAnimals gets updated when adding a new animal
836 if #self.animals >= self.maxNumAnimals then
837 break
838 end
839
840 local desc = g_animalManager:getAnimalsByType(subType.type)
841 local newAnimal = Animal.createFromFillType(self.owner.isServer, self.owner.isClient, self.owner, fillTypeIndex)
842 newAnimal:register()
843 self:addSingleAnimal(newAnimal)
844
845 -- update stats
846 if desc.stats.breeding ~= "" then
847 g_currentMission:farmStats(self.owner:getOwnerFarmId()):updateStats(desc.stats.breeding, 1)
848 end
849 end
850 end
851
852 -- values for stats
853 self.reproductionRatesPerDay[fillTypeIndex] = (self.owner:getGlobalProductionFactor() * numAnimals * birthRatePerDay) * 0.5
854 else
855 self.reproductionRatesPerDay[fillTypeIndex] = 0
856 end
857 else
858 self.reproductionRatesPerDay[fillTypeIndex] = 0
859 end
860 end
861 end
862end

getNumOfAnimals

Description
Gets the total number of animals
Definition
getNumOfAnimals(integer total)
Arguments
integertotalnumber of animals
Code
867function HusbandryModuleAnimal:getNumOfAnimals()
868 return #self.animals
869end

getMaxNumOfAnimals

Description
Gets the maximum number of animals
Definition
getMaxNumOfAnimals(integer max)
Arguments
integermaxnumber of animals
Code
874function HusbandryModuleAnimal:getMaxNumOfAnimals()
875 return self.maxNumAnimals
876end

getAnimalType

Description
Accessor to return the animal type
Definition
getAnimalType(string animalType)
Arguments
stringanimalType
Code
881function HusbandryModuleAnimal:getAnimalType()
882 return self.animalType
883end

getFillType

Description
Retrieves the filltype information of a subtype
Definition
getFillType()
Return Values
table
Code
897function HusbandryModuleAnimal:getFillType(subTypeId)
898 local animals = g_animalManager:getAnimalsByType(self.animalType)
899 if animals ~= nil then
900 for _, animal in pairs(animals.subTypes) do
901 if animal.subTypeId == subTypeId then
902 local fillType = g_fillTypeManager:getFillTypeByIndex(animal.fillType)
903 if fillType ~= nil then
904 return fillType
905 end
906 end
907 end
908 end
909 return nil
910end

getAnimals

Description
Definition
getAnimals()
Code
914function HusbandryModuleAnimal:getAnimals()
915 return self.animals
916end

getTypedAnimals

Description
Definition
getTypedAnimals()
Code
920function HusbandryModuleAnimal:getTypedAnimals()
921 return self.typedAnimals
922end

renameAnimal

Description
Definition
renameAnimal()
Code
926function HusbandryModuleAnimal:renameAnimal(animalId, name, noEventSend)
927 if self.renamingTasks == nil then
928 self.renamingTasks = {}
929 end
930
931 table.insert(self.renamingTasks, {animalId=animalId, name=name})
932 self.owner:raiseActive()
933
934 AnimalNameEvent.sendEvent(self.owner, animalId, name, noEventSend)
935end

getReproductionTimePerDay

Description
Definition
getReproductionTimePerDay()
Code
974function HusbandryModuleAnimal:getReproductionTimePerDay(fillTypeIndex)
975 local reproductionRatePerDay = self.reproductionRatesPerDay[fillTypeIndex]
976 if reproductionRatePerDay == nil or reproductionRatePerDay == 0 then
977 return nil
978 end
979
980 local reproductionDuration = 1.0 / reproductionRatePerDay
981 local reproMins = reproductionDuration * 24 * 60
982
983 return reproMins
984end

getAnimalName

Description
Definition
getAnimalName()
Code
988function HusbandryModuleAnimal:getAnimalName(visualId)
989 local animal = self.visualIdToAnimal[visualId]
990 if animal ~= nil and animal:isa(Horse) then
991 return animal:getName()
992 end
993 return ""
994end