Skip to content

Commit

Permalink
Merge pull request #3505 from Courseplay/RefillOnTheField
Browse files Browse the repository at this point in the history
 Refill on the field, for now only stationary waiting until refilled.
  • Loading branch information
Tensuko authored Oct 11, 2024
2 parents cb62981 + 6c3f418 commit 92fbb8e
Show file tree
Hide file tree
Showing 39 changed files with 496 additions and 23 deletions.
3 changes: 2 additions & 1 deletion Courseplay.lua
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ function Courseplay.removePlayerActionEvents(player)
end

--- Registers all cp specializations.
---@param typeManager TypeManager
---@param typeManager table
function Courseplay.register(typeManager)
--- TODO: make this function async.
for typeName, typeEntry in pairs(typeManager.types) do
Expand All @@ -352,6 +352,7 @@ function Courseplay.register(typeManager)
CpInfoTexts.register(typeManager, typeName, typeEntry.specializations)
CpShovelPositions.register(typeManager, typeName, typeEntry.specializations)
end
typeManager:addSpecialization("fillableImplement", "aiLoadable")
end
TypeManager.finalizeTypes = Utils.prependedFunction(TypeManager.finalizeTypes, Courseplay.register)

Expand Down
16 changes: 16 additions & 0 deletions config/MasterTranslations.xml
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,22 @@
<Text language="de"><![CDATA[Debuginformationen für das Fahrzeug ein- oder ausschalten. Visuell und Logeinträge.]]></Text>
<Text language="en"><![CDATA[Enables/disables debug for this vehicle.]]></Text>
</Translation>
<Translation name="CP_vehicle_setting_refillOnTheField_title">
<Text language="de"><![CDATA[Gerät auffüllen]]></Text>
<Text language="en"><![CDATA[Refill tool]]></Text>
</Translation>
<Translation name="CP_vehicle_setting_refillOnTheField_tooltip">
<Text language="de"><![CDATA[Gerät wartet auf dem Feld, um aufgefüllt zu werden.]]></Text>
<Text language="en"><![CDATA[Tool waits on the field to be refilled.]]></Text>
</Translation>
<Translation name="CP_vehicle_setting_refillOnTheField_waiting">
<Text language="de"><![CDATA[Warten]]></Text>
<Text language="en"><![CDATA[Waiting]]></Text>
</Translation>
<Translation name="CP_vehicle_setting_refillOnTheField_active">
<Text language="de"><![CDATA[Aktiv]]></Text>
<Text language="en"><![CDATA[Active]]></Text>
</Translation>
</Category>
<Category name="Vehicle bunker silo settings">
<Translation name="CP_vehicle_setting_subTitle_bunkerSilo">
Expand Down
12 changes: 12 additions & 0 deletions config/VehicleSettingsSetup.xml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,18 @@
<Setting classType="AIParameterSettingList" name="fullThreshold" min="40" max="100" incremental="5" default="85" unit="4" isVisible="areCombineUnloaderSettingsVisible"/>
<!--Silage additives needed?-->
<Setting classType="AIParameterBooleanSetting" name="useAdditiveFillUnit" defaultBool="false" isVisible="isAdditiveFillUnitSettingVisible" isExpertModeOnly="true"/>
<Setting classType="AIParameterSettingList" name="refillOnTheField" isVisible="isRefillOnTheFieldSettingVisible" default="1">
<Values>
<Value name="REFILL_ON_FIELD_DISABLED">0</Value>
<Value name="REFILL_ON_FIELD_WAITING">1</Value>
<!-- <Value name="REFILL_ON_FIELD_ACTIVE">2</Value> -->
</Values>
<Texts>
<Text prefix="false">CP_deactivated</Text>
<Text>waiting</Text>
<Text>active</Text>
</Texts>
</Setting>
</SettingSubTitle>

<SettingSubTitle title="bunkerSilo" isVisible="areBunkerSiloSettingsVisible">
Expand Down
1 change: 1 addition & 0 deletions modDesc.xml
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ Changelog 7.1.0.0:
<sourceFile filename="scripts/ai/controllers/FoldableController.lua"/>
<sourceFile filename="scripts/ai/controllers/PlowController.lua"/>
<sourceFile filename="scripts/ai/controllers/PalletFillerController.lua"/>
<sourceFile filename="scripts/ai/controllers/TreePlanterController.lua"/>

<sourceFile filename="scripts/ai/AIDriveStrategyCourse.lua"/>
<sourceFile filename="scripts/ai/AIDriveStrategyDriveToFieldWorkStart.lua"/>
Expand Down
27 changes: 14 additions & 13 deletions scripts/ai/AIDriveStrategyCourse.lua
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ AIDriveStrategyCourse.onRaisingEvent = "onRaising"
AIDriveStrategyCourse.onLoweringEvent = "onLowering"
AIDriveStrategyCourse.onFinishedEvent = "onFinished"
AIDriveStrategyCourse.onStartEvent = "onStart"
AIDriveStrategyCourse.onStartRefillingEvent = "onStartRefilling"
AIDriveStrategyCourse.onStopRefillingEvent = "onStopRefilling"
AIDriveStrategyCourse.onUpdateRefillingEvent = "onUpdateRefilling"
AIDriveStrategyCourse.updateEvent = "update"
AIDriveStrategyCourse.deleteEvent = "delete"
--- A row has just been finished, implements are being raised and about to start the actual turn
Expand All @@ -50,6 +53,7 @@ function AIDriveStrategyCourse:init(task, job)
self.registeredInfoTexts = {}
--- To temporary hold a vehicle (will force speed to 0)
self.held = CpTemporaryObject()
self.fuelSaveActiveWhileHeld = false

self.currentTask = task
self.job = job
Expand Down Expand Up @@ -247,17 +251,7 @@ end

--- Checks if any controller disables fuel save, for example a round baler that is dropping a bale.
function AIDriveStrategyCourse:isFuelSaveAllowed()
--[[ TODO: implement this, when fuel save is implemented for every vehicle combo and not only harvesters.
for _, controller in pairs(self.controllers) do
---@type ImplementController
if controller:isEnabled() then
if not controller:isFuelSaveAllowed() then
return false
end
end
end
]]
return false
return self.fuelSaveActiveWhileHeld and self:isBeingHeld()
end

function AIDriveStrategyCourse:initializeImplementControllers(vehicle)
Expand Down Expand Up @@ -293,11 +287,15 @@ end

--- Raises a event for the controllers.
function AIDriveStrategyCourse:raiseControllerEvent(eventName, ...)
self:raiseControllerEventWithLambda(eventName, function () end, ...)
end

function AIDriveStrategyCourse:raiseControllerEventWithLambda(eventName, lambda, ...)
for _, controller in pairs(self.controllers) do
---@type ImplementController
if controller:isEnabled() then
if controller[eventName] then
controller[eventName](controller, ...)
lambda(controller[eventName](controller, ...))
end
end
end
Expand Down Expand Up @@ -499,11 +497,13 @@ end
--- Hold the vehicle (set speed to 0) temporary. This is meant to be used for other vehicles to coordinate movements,
--- for instance tell a vehicle it should not move as the other vehicle is driving around it.
---@param milliseconds number milliseconds to hold
function AIDriveStrategyCourse:hold(milliseconds)
---@param fuelSaveAllowed boolean enables the fuel save, while the vehicle is being held.
function AIDriveStrategyCourse:hold(milliseconds, fuelSaveAllowed)
if not self.held:get() then
self:debug('Hold requested for %.1f seconds', milliseconds / 1000)
end
self.held:set(true, milliseconds)
self.fuelSaveActiveWhileHeld = fuelSaveAllowed
end

--- Release a hold anytime, even before it is released automatically after the time given at hold()
Expand All @@ -512,6 +512,7 @@ function AIDriveStrategyCourse:unhold()
self:debug("Hold reset")
end
self.held:reset()
self.fuelSaveActiveWhileHeld = false
end

--- Are we currently being held?
Expand Down
6 changes: 3 additions & 3 deletions scripts/ai/AIDriveStrategyFieldWorkCourse.lua
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ function AIDriveStrategyFieldWorkCourse:init(task, job)
self.aiOffsetX, self.aiOffsetZ = 0, 0
self.debugChannel = CpDebug.DBG_FIELDWORK
self.waitingForPrepare = CpTemporaryObject(false)

end

function AIDriveStrategyFieldWorkCourse:delete()
Expand Down Expand Up @@ -267,7 +266,7 @@ function AIDriveStrategyFieldWorkCourse:initializeImplementControllers(vehicle)

self:addImplementController(vehicle, SoilSamplerController, nil, defaultDisabledStates, "spec_soilSampler")
self:addImplementController(vehicle, StumpCutterController, StumpCutter, defaultDisabledStates)

self:addImplementController(vehicle, TreePlanterController, TreePlanter, {})

end

Expand Down Expand Up @@ -806,7 +805,7 @@ end

-----------------------------------------------------------------------------------------------------------------------
--- Convoy management
----------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------
function AIDriveStrategyFieldWorkCourse:getProgress()
return self.fieldWorkCourse:getProgress()
end
Expand All @@ -818,6 +817,7 @@ end
function AIDriveStrategyFieldWorkCourse:getFieldWorkProximity(node)
return self.fieldWorkerProximityController:getFieldWorkProximity(node)
end

-----------------------------------------------------------------------------------------------------------------------
--- Overwrite implement functions, to enable a different cp functionality compared to giants fieldworker.
--- TODO: might have to find a better solution for these kind of problems.
Expand Down
48 changes: 48 additions & 0 deletions scripts/ai/ImplementUtil.lua
Original file line number Diff line number Diff line change
Expand Up @@ -541,3 +541,51 @@ function ImplementUtil.getCanLoadTo(loadTargetImplement, implementToLoadFrom, di
return validTarget, targetFillUnitIndex, fillType, exactFillRootNode, alternativeFillType
end

--- Checks the passed in implements for a fill level change
--- and also caches the current fill levels.
--- Example input table format: {["implement"]["fillUnitIndex"] = 200}
---@param fillLevelData table<table, table<number, number>>
---@param reset boolean|nil
function ImplementUtil.hasFillLevelChanged(fillLevelData, reset)
local hasChanged = false
for implement, data in pairs(fillLevelData) do
for fillUnitIndex, fillLevel in pairs(data) do
local curFillLevel = implement:getFillUnitFillLevel(fillUnitIndex)
if reset then
fillLevelData[implement][fillUnitIndex] = -1
else
if fillLevel > -1 and curFillLevel ~= fillLevel then
hasChanged = true
end
fillLevelData[implement][fillUnitIndex] = curFillLevel
end
end
end
return hasChanged
end

--- Trys to start loading from triggers, pallets and so on nearby.
---@param implements table<table, ...>
---@return boolean refilling is currently refilling
function ImplementUtil.tryAndCheckRefillingFillUnits(implements)
local isFilling = false
for implement, _ in pairs(implements) do
local spec = implement.spec_fillUnit
local activatable = spec.fillTrigger.activatable
if not spec.fillTrigger.isFilling then
local rootVehicle = activatable.vehicle
if rootVehicle then
local oldFunc = rootVehicle.getIsActiveForInput
rootVehicle.getIsActiveForInput = function ()
return true
end
if activatable:getIsActivatable() then
activatable:run()
end
rootVehicle.getIsActiveForInput = oldFunc
end
end
isFilling = isFilling or spec.fillTrigger.isFilling
end
return isFilling
end
51 changes: 51 additions & 0 deletions scripts/ai/controllers/SowingMachineController.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ SowingMachineController = CpObject(ImplementController)
function SowingMachineController:init(vehicle, implement)
ImplementController.init(self, vehicle, implement)
self.sowingMachineSpec = self.implement.spec_sowingMachine
self.refillData = {
timer = CpTemporaryObject(true),
hasChanged = false,
lastFillLevels = {
[self.implement] = {
[self.sowingMachineSpec.fillUnitIndex] = -1
}
}
}
end

function SowingMachineController:update()
Expand Down Expand Up @@ -37,4 +46,46 @@ end

function SowingMachineController:onFinished()
self.implement:setIsTurnedOn(false)
end

-------------------------
--- Refill handling
-------------------------

function SowingMachineController:needsRefilling()
if not g_currentMission.missionInfo.helperBuySeeds then
if self.implement:getFillUnitFillLevel(self.sowingMachineSpec.fillUnitIndex) <= 0 then
return true
end
end
end

function SowingMachineController:onStartRefilling()
if self:needsRefilling() then
if self.implement.aiPrepareLoading ~= nil then
self.implement:aiPrepareLoading(self.sowingMachineSpec.fillUnitIndex)
end
self.refillData.timer:set(false, 30 * 1000)
end
self.refillData.hasChanged = false
ImplementUtil.hasFillLevelChanged(self.refillData.lastFillLevels, true)
end

function SowingMachineController:onUpdateRefilling()
if ImplementUtil.tryAndCheckRefillingFillUnits(self.refillData.lastFillLevels) or
ImplementUtil.hasFillLevelChanged(self.refillData.lastFillLevels) then
self.refillData.timer:set(false, 10 * 1000)
self.refillData.hasChanged = true
end
return self.refillData.timer:get(), self.refillData.hasChanged
end

function SowingMachineController:onStopRefilling()
if self.implement.aiFinishLoading ~= nil then
self.implement:aiFinishLoading()
end
local spec = self.implement.spec_fillUnit
if spec.fillTrigger.isFilling then
self.implement:setFillUnitIsFilling(false)
end
end
88 changes: 88 additions & 0 deletions scripts/ai/controllers/SprayerController.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,95 @@ SprayerController = CpObject(ImplementController)
--- Dummy placeholder for now
function SprayerController:init(vehicle, sprayer)
self.sprayer = sprayer
self.sprayerSpec = sprayer.spec_sprayer
ImplementController.init(self, vehicle, self.sprayer)
self.refillData = {
timer = CpTemporaryObject(true),
hasChanged = false,
lastFillLevels = {
[self.implement] = {
[self.implement:getSprayerFillUnitIndex()] = -1
}
}
}
for _, supportedSprayType in ipairs(self.sprayerSpec.supportedSprayTypes) do
for _, src in ipairs(self.sprayerSpec.fillTypeSources[supportedSprayType]) do
self:debug("Found additional tank for refilling: %s|%d", src.vehicle, src.fillUnitIndex)
if not self.refillData.lastFillLevels[src.vehicle] then
self.refillData.lastFillLevels[src.vehicle] = {}
end
self.refillData.lastFillLevels[src.vehicle][src.fillUnitIndex] = -1
end
end
end

-------------------------
--- Refill handling
-------------------------

function SprayerController:needsRefilling()
if self.sprayerSpec.isSlurryTanker and g_currentMission.missionInfo.helperSlurrySource > 1 or
self.sprayerSpec.isManureSpreader and g_currentMission.missionInfo.helperManureSource > 1 or
self.sprayerSpec.isFertilizerSprayer and g_currentMission.missionInfo.helperBuyFertilizer then

return false
end
ImplementUtil.hasFillLevelChanged(self.refillData.lastFillLevels)
for implement, data in pairs(self.refillData.lastFillLevels) do
for fillUnitIndex, fillLevel in pairs(data) do
if fillLevel <= 0 then
return true
end
end
end
end

function SprayerController:onStartRefilling(ignore)
if self:needsRefilling() then
if self.implement.aiPrepareLoading ~= nil then
self.implement:aiPrepareLoading(self.implement:getSprayerFillUnitIndex())
end
for _, supportedSprayType in ipairs(self.sprayerSpec.supportedSprayTypes) do
for _, src in ipairs(self.sprayerSpec.fillTypeSources[supportedSprayType]) do
if src.vehicle.aiPrepareLoading ~= nil then
src.vehicle:aiPrepareLoading(src.fillUnitIndex)
end
end
end
end
ImplementUtil.hasFillLevelChanged(self.refillData.lastFillLevels, true)
self.refillData.hasChanged = false
end

function SprayerController:onUpdateRefilling()
if ImplementUtil.tryAndCheckRefillingFillUnits(self.refillData.lastFillLevels) or
ImplementUtil.hasFillLevelChanged(self.refillData.lastFillLevels) then
self:debugSparse("Waiting for refilling to finish ..")
self.refillData.timer:set(false, 10 * 1000)
self.refillData.hasChanged = true
end
return self.refillData.timer:get(), self.refillData.hasChanged
end

function SprayerController:onStopRefilling()
if self.implement.aiFinishLoading ~= nil then
self.implement:aiFinishLoading()
end
local spec = self.implement.spec_fillUnit
if spec.fillTrigger.isFilling then
self.implement:setFillUnitIsFilling(false)
end
for _, supportedSprayType in ipairs(self.sprayerSpec.supportedSprayTypes) do
for _, src in ipairs(self.sprayerSpec.fillTypeSources[supportedSprayType]) do
if src.vehicle.aiFinishLoading ~= nil then
src.vehicle:aiFinishLoading()
end
spec = src.vehicle.spec_fillUnit
if spec.fillTrigger.isFilling then
src.vehicle:setFillUnitIsFilling(false)
end
end
end
end

local function processSprayerArea(sprayer, superFunc, ...)
Expand Down
Loading

0 comments on commit 92fbb8e

Please sign in to comment.