Skip to content

Commit

Permalink
Refill on the field, for now only stationary waiting until refilled.
Browse files Browse the repository at this point in the history
- Works for sowing machines, sprayers and tree planters.

TODO:
- Translation texts are not really understandable
- All the test scenarios ...
  • Loading branch information
schwiti6190 committed Oct 5, 2024
1 parent 5d2f2b2 commit deb0a05
Show file tree
Hide file tree
Showing 9 changed files with 226 additions and 18 deletions.
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 auf dem Feld auffüllen]]></Text>
<Text language="en"><![CDATA[Refill tool on the field]]></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
23 changes: 10 additions & 13 deletions scripts/ai/AIDriveStrategyCourse.lua
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,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 +248,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
end

function AIDriveStrategyCourse:initializeImplementControllers(vehicle)
Expand Down Expand Up @@ -499,11 +490,12 @@ 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)
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,11 +504,16 @@ function AIDriveStrategyCourse:unhold()
self:debug("Hold reset")
end
self.held:reset()
self.fuelSaveActiveWhileHeld = false
end

--- Are we currently being held?
function AIDriveStrategyCourse:isBeingHeld()
return self.held:get()
local isHeld = self.held:get()
if not isHeld then
self.fuelSaveActiveWhileHeld = false
end
return isHeld
end

--- Freeze (force speed to 0), but keep everything up and running otherwise, showing all debug
Expand Down
129 changes: 127 additions & 2 deletions scripts/ai/AIDriveStrategyFieldWorkCourse.lua
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ function AIDriveStrategyFieldWorkCourse:init(task, job)
self.aiOffsetX, self.aiOffsetZ = 0, 0
self.debugChannel = CpDebug.DBG_FIELDWORK
self.waitingForPrepare = CpTemporaryObject(false)

self.fillingTimer = CpTemporaryObject(true)
end

function AIDriveStrategyFieldWorkCourse:delete()
Expand Down Expand Up @@ -806,7 +806,7 @@ end

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

-----------------------------------------------------------------------------------------------------------------------
--- Waiting for refilling on the field
-----------------------------------------------------------------------------------------------------------------------

function AIDriveStrategyFieldWorkCourse:prepareFilling()
--- Gather the correct fill unit to open the cover and so on..
self.fillingTimer:set(false, 30 * 1000)
local validSowingMachines, validSprayers, validTreePlanters = {}, {}, {}
local fillUnitsData = {}
if not g_currentMission.missionInfo.helperBuySeeds then
local sowingMachines, found = AIUtil.getAllChildVehiclesWithSpecialization(self.vehicle, SowingMachine)
if found then
for _, s in pairs(sowingMachines) do
table.insert(fillUnitsData,
{implement = s, fillUnitIndex = s.spec_sowingMachine.fillUnitIndex})
end
end
validSowingMachines = sowingMachines
end
local sprayers, found = AIUtil.getAllChildVehiclesWithSpecialization(self.vehicle, Sprayer)
if found then
for _, s in pairs(sprayers) do
if not s:getIsSprayerExternallyFilled() then
table.insert(validSprayers, s)
table.insert(fillUnitsData,
{implement = s, fillUnitIndex = s.spec_sprayer.fillUnitIndex})
end
end
validSprayers = sprayers
end
if not g_currentMission.missionInfo.helperBuySeeds then
local treePlanters, found = AIUtil.getAllChildVehiclesWithSpecialization(self.vehicle, TreePlanter)
if found then
for _, s in pairs(treePlanters) do
table.insert(fillUnitsData,
{implement = s, fillUnitIndex = s.spec_treePlanter.fillUnitIndex})
end
end
validTreePlanters = treePlanters
end

local implements = {unpack(validSowingMachines), unpack(validSprayers), unpack(validTreePlanters)}

self.fillingData = {
implements = implements,
fillUnitsData = fillUnitsData,
lastFillLevels = {}
}
for _, data in ipairs(self.fillingData.fillUnitsData) do
if data.implement:getFillUnitFillLevel(data.fillUnitIndex) <= 0 then
data.implement:aiPrepareLoading(data.fillUnitIndex)
end
end

end

function AIDriveStrategyFieldWorkCourse:updateFilling()
--- Trys to load if possible
if self.fillingData == nil then
return
end

local isFilling = false
for _, implement in ipairs(self.fillingData.implements) do
local spec = implement.spec_fillUnit
local activatable = spec.fillTrigger.activatable
if not spec.fillTrigger.isFilling then
if activatable:getIsActivatable(true) then
activatable:run()
end
else
isFilling = true
end
end
for _, data in ipairs(self.fillingData.fillUnitsData) do
local fillLevel = data.implement:getFillUnitFillLevel(data.fillUnitIndex)
if #self.fillingData.lastFillLevels == 0 then
if self.fillingData.lastFillLevels[data.implement] == nil then
self.fillingData.lastFillLevels[data.implement] = {}
end
self.fillingData.lastFillLevels[data.implement][data.fillUnitIndex] = fillLevel
else
isFilling = isFilling or self.fillingData.lastFillLevels[data.implement][data.fillUnitIndex] ~= fillLevel

self.fillingData.lastFillLevels[data.implement][data.fillUnitIndex] = fillLevel
end
end
if isFilling then
self.fillingTimer:set(false, 10 * 1000)
end

return self.fillingTimer:get()
end

function AIDriveStrategyFieldWorkCourse:finishedFilling()
if self.fillingData == nil then
return
end
for _, data in ipairs(self.fillingData.fillUnitsData) do
data.implement:aiFinishLoading()
end
end

--- Allows the usage of the function while cp is active.
local function getIsActivatable(activatable, superFunc, allowAILoad)
local rootVehicle = activatable.vehicle.rootVehicle
local ret
if allowAILoad and rootVehicle:getIsCpActive() then
local oldFunc = activatable.vehicle.getIsActiveForInput
activatable.vehicle.getIsActiveForInput = function ()
return true
end

ret = superFunc(activatable)

activatable.vehicle.getIsActiveForInput = oldFunc
else
ret = superFunc(activatable)
end
return ret
end
FillActivatable.getIsActivatable = Utils.overwrittenFunction(FillActivatable.getIsActivatable, getIsActivatable)


-----------------------------------------------------------------------------------------------------------------------
--- 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
5 changes: 5 additions & 0 deletions scripts/ai/jobs/CpAIJob.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
---@field superClass function
---@field getIsLooping function
---@field resetTasks function
---@field skipCurrentTask function
---@field tasks table
---@field groupedParameters table
---@field isServer boolean
Expand Down Expand Up @@ -69,6 +70,10 @@ function CpAIJob:setupCpJobParameters(jobParameters)
self.cpJobParameters:validateSettings()
end

function CpAIJob:isFinishingAllowed(message)
return true
end

--- Gets the first task to start with.
function CpAIJob:getStartTaskIndex()
if self.currentTaskIndex ~= 0 or self.isDirectStart or self:isTargetReached() then
Expand Down
25 changes: 24 additions & 1 deletion scripts/ai/jobs/CpAIJobFieldWork.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ function CpAIJobFieldWork:setupTasks(isServer)
self.attachHeaderTask = CpAITaskAttachHeader(isServer, self)
self.driveToFieldWorkStartTask = CpAITaskDriveTo(isServer, self)
self.fieldWorkTask = CpAITaskFieldWork(isServer, self)
-- self.refuelTask = CpAITaskRefuel(isServer, self)
end

function CpAIJobFieldWork:onPreStart()
CpAIJob.onPreStart(self)
self:removeTask(self.attachHeaderTask)
self:removeTask(self.driveToFieldWorkStartTask)
self:removeTask(self.fieldWorkTask)
-- self:removeTask(self.refuelTask)
local vehicle = self:getVehicle()
if vehicle and (AIUtil.hasCutterOnTrailerAttached(vehicle)
or AIUtil.hasCutterAsTrailerAttached(vehicle)) then
Expand All @@ -40,15 +42,36 @@ function CpAIJobFieldWork:onPreStart()
end
self:addTask(self.driveToFieldWorkStartTask)
self:addTask(self.fieldWorkTask)
---TODO: only if refuelling is possible ..
-- self:addTask(self.refuelTask)
end

function CpAIJobFieldWork:setupJobParameters()
CpAIJob.setupJobParameters(self)
self:setupCpJobParameters(CpFieldWorkJobParameters(self))
end

function CpAIJobFieldWork:isFinishingAllowed(message)
local nextTaskIndex = self:getNextTaskIndex()
if message:isa(AIMessageErrorOutOfFill) then

local vehicle = self:getVehicle()
local setting = vehicle:getCpSettings().refillOnTheField

if setting:getValue() == CpVehicleSettings.REFILL_ON_FIELD_DISABLED then
return true
elseif setting:getValue() == CpVehicleSettings.REFILL_ON_FIELD_WAITING then
self.fieldWorkTask:setWaitingForRefuelActive()
elseif setting:getValue() == CpVehicleSettings.REFILL_ON_FIELD_ACTIVE then
self.fieldWorkTask:skip()
end
return false
end
return true
end

---@param vehicle table
---@param mission Mission
---@param mission table
---@param farmId number
---@param isDirectStart boolean disables the drive to by giants
---@param isStartPositionInvalid boolean resets the drive to target position by giants and the field position to the vehicle position.
Expand Down
20 changes: 20 additions & 0 deletions scripts/ai/tasks/CpAITaskFieldWork.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,33 @@ CpAITaskFieldWork = CpObject(CpAITask)

function CpAITaskFieldWork:reset()
self.startPosition = nil
self.waitingForRefuelActive = false
CpAITask.reset(self)
end

function CpAITaskFieldWork:setStartPosition(startPosition)
self.startPosition = startPosition
end

function CpAITaskFieldWork:setWaitingForRefuelActive()
self.waitingForRefuelActive = true
local cpSpec = self.vehicle.spec_cpAIFieldWorker
cpSpec.driveStrategy:prepareFilling()
end

function CpAITaskFieldWork:update(dt)
if self.waitingForRefuelActive then
self.vehicle:cpHold(150, true)
local cpSpec = self.vehicle.spec_cpAIFieldWorker
self.vehicle:setCpInfoTextActive(InfoTextManager.NEEDS_FILLING)
if cpSpec.driveStrategy:updateFilling() then
cpSpec.driveStrategy:finishedFilling()
self.waitingForRefuelActive = false
self.vehicle:resetCpActiveInfoText(InfoTextManager.NEEDS_FILLING)
end
end
end

--- Makes sure the cp fieldworker gets started.
function CpAITaskFieldWork:start()
if self.isServer then
Expand Down
8 changes: 6 additions & 2 deletions scripts/specializations/CpAIWorker.lua
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,10 @@ function CpAIWorker:stopCurrentAIJob(superFunc, message, ...)
end
end
end
local job = self:getJob()
if not job:isFinishingAllowed(message) then
return
end
end
superFunc(self, message,...)
end
Expand Down Expand Up @@ -417,10 +421,10 @@ function CpAIWorker:unfreezeCp()
end

--- Holds the driver for a given amount of milliseconds.
function CpAIWorker:cpHold(ms)
function CpAIWorker:cpHold(ms, fuelSaveAllowed)
local strategy = self:getCpDriveStrategy()
if strategy then
return strategy:hold(ms)
return strategy:hold(ms, fuelSaveAllowed)
end
end

Expand Down
6 changes: 6 additions & 0 deletions scripts/specializations/CpVehicleSettings.lua
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,12 @@ function CpVehicleSettings:generateSpeedSettingValuesAndTexts(setting, lastValue
return values, texts, math.min(lastValue, maxSpeed)
end

function CpVehicleSettings:isRefillOnTheFieldSettingVisible()
return AIUtil.hasChildVehicleWithSpecialization(self, Sprayer) or
AIUtil.hasChildVehicleWithSpecialization(self, SowingMachine) or
AIUtil.hasChildVehicleWithSpecialization(self, TreePlanter)
end

---------------------------------------------
--- Console Commands
---------------------------------------------
Expand Down

0 comments on commit deb0a05

Please sign in to comment.