/*
Miner Class
Primary Miner hebavior module for EVEBot
-- CyberTech
*/
objectdef obj_Miner
{
variable obj_Combat Combat
variable string SVN_REVISION = "$Rev: 709 $"
variable int Version
variable time NextPulse
variable int PulseIntervalInSeconds = 2
variable index:entity LockedTargets
variable iterator Target
variable int TotalTrips = 0 /* Total Times we've had to transfer to hanger */
variable time TripStartTime
variable int PreviousTripSeconds = 0
variable int TotalTripSeconds = 0
variable int AverageTripSeconds = 0
variable string CurrentState
variable bool CombatAbort = FALSE
variable int SanityCheckCounter = 0
variable bool SanityCheckAbort = FALSE
variable float64 LastUsedCargoCapacity = 0
; Are we running out of asteroids to target?
variable bool ConcentrateFire = FALSE
method Initialize()
{
BotModules:Insert["Miner"]
This.TripStartTime:Set[${Time.Timestamp}]
Event[OnFrame]:AttachAtom[This:Pulse]
UI:UpdateConsole["obj_Miner: Initialized", LOG_MINOR]
/* Initialize combat */
This.Combat:Initialize
/* Set it to defensive */
This.Combat.CurrentState:Set["IDLE"]
This.Combat:SetMode["DEFENSIVE"]
}
method Shutdown()
{
Event[OnFrame]:DetachAtom[This:Pulse]
}
method Pulse()
{
if ${EVEBot.Paused}
{
return
}
if !${Config.Common.BotModeName.Equal[Miner]}
{
; There's no reason at all for the miner to check state if it's not a miner
return
}
if ${Time.Timestamp} >= ${This.NextPulse.Timestamp}
{
This:SetState[]
SanityCheckCounter:Inc
This.NextPulse:Set[${Time.Timestamp}]
This.NextPulse.Second:Inc[${This.PulseIntervalInSeconds}]
This.NextPulse:Update
}
}
function ProcessState()
{
if !${Config.Common.BotModeName.Equal[Miner]}
{
; There's no reason at all for the miner to check state if it's not a miner
return
}
/* No reason to do our shit if we're not safe */
if !${Social.IsSafe}
{
UI:UpdateConsole["Miner: Social unsafe! Cleaning up and fleeing"]
call This.Cleanup_Environment
call Combat.Flee
Combat.Override:Set[TRUE]
return
}
switch ${This.CurrentState}
{
case IDLE
break
case ABORT
Call Station.Dock
Call This.Abort_Check
break
case BASE
call Cargo.TransferOreToHangar
;call Station.CheckList
SanityCheckCounter:Set[0]
SanityCheckAbort:Set[FALSE]
LastUsedCargoCapacity:Set[0]
call Station.Undock
break
case MINE
call This.Mine
break
case HAUL
UI:UpdateConsole["Hauling"]
call Hauler.Haul
break
case DROPOFF
switch ${Config.Miner.DeliveryLocationTypeName}
{
case Station
; Gets info about the crystals currently loaded
call Ship.SetActiveCrystals
if ${EVE.Bookmark[${Config.Miner.DeliveryLocation}](exists)}
{
call Ship.WarpToBookMarkName "${Config.Miner.DeliveryLocation}"
}
else
{
call Station.Dock
}
break
case Hangar Array
call Ship.WarpToBookMarkName "${Config.Miner.DeliveryLocation}"
call Cargo.TransferOreToCorpHangarArray
break
case Jetcan
UI:UpdateConsole["Warning: Cargo filled during jetcan mining, delays may occur"]
call Cargo.TransferOreToJetCan
This:NotifyHaulers[]
break
Default
UI:UpdateConsole["ERROR: Delivery Location Type ${Config.Miner.DeliveryLocationTypeName} unknown"]
EVEBot.ReturnToStation:Set[TRUE]
break
}
SanityCheckCounter:Set[0]
SanityCheckAbort:Set[FALSE]
LastUsedCargoCapacity:Set[0]
break
case RUNNING
UI:UpdateConsole["Running Away"]
call Station.Dock
EVEBot.ReturnToStation:Set[TRUE]
break
}
}
method SetState()
{
if ${EVEBot.ReturnToStation} && ${_Me.InStation} == FALSE
{
This.CurrentState:Set["ABORT"]
return
}
if ${EVEBot.ReturnToStation}
{
This.CurrentState:Set["IDLE"]
return
}
if ${_Me.InStation} == TRUE
{
This.CurrentState:Set["BASE"]
return
}
if ${_Me.Ship.UsedCargoCapacity} <= ${Config.Miner.CargoThreshold} && \
${SanityCheckAbort} == FALSE
{
This.CurrentState:Set["MINE"]
return
}
if ${_Me.Ship.UsedCargoCapacity} > ${Config.Miner.CargoThreshold} || \
${EVEBot.ReturnToStation} || \
${SanityCheckAbort} == TRUE
{
This.CurrentState:Set["DROPOFF"]
return
}
This.CurrentState:Set["Unknown"]
}
function Abort_Check()
{
call Config.Common.IncAbortCount
; abort check, this will allow the bot to continue botting if it is a temp abort or something that can
; if there is no abort type it will pause the script like before and wait...
if ${This.CombatAbort}
{
UI:UpdateConsole["Warning: Paused. Combat type abort."]
if ((${_Me.Ship.ArmorPct} < ${Config.Combat.MinimumArmorPct}) && ${Ship.ArmorRepairUnits} == 0)
{
UI:UpdateConsole["Warning: Script paused due to Armor Precentage."]
Script:Pause
}
; To.Do NEED TO ADD CHECK FOR HULL REPAIRER in SHIP OBJECT.
if ((${_Me.Ship.StructurePct} < 100))
{
UI:UpdateConsole["Warning: Aborted. Script paused due to Structure Percentage."]
Script:Pause
}
if ${_Me.Ship.ShieldPct} < 100
{
UI:UpdateConsole["Warning: Waiting for Shields to Regen."]
while ${_Me.Ship.ShieldPct} < 95
{
wait 20
}
}
UI:UpdateConsole["Continuing"]
EVEBot.ReturnToStation:Set[FALSE]
This.CombatAbort:Set[FALSE]
Return
}
UI:UpdateConsole["Warning: Aborted - Script Paused - Check Logs "]
Script:Pause
}
; Enable defenses, launch drones
function Prepare_Environment()
{
call Ship.OpenCargo
}
function Cleanup_Environment()
{
call Ship.Drones.ReturnAllToDroneBay
;;;call Ship.CloseCargo
}
function Statslog()
{
variable string Hours = ${Math.Calc[(${Script.RunningTime}/1000/60/60)%60].Int.LeadingZeroes[2]}
variable string Minutes = ${Math.Calc[(${Script.RunningTime}/1000/60)%60].Int.LeadingZeroes[2]}
variable string Seconds = ${Math.Calc[(${Script.RunningTime}/1000)%60].Int.LeadingZeroes[2]}
UI:UpdateStatStatus["Run ${This.TotalTrips} Done - Took ${ISXEVE.SecsToString[${This.PreviousTripSeconds}]}"]
UI:UpdateStatStatus["Total Run Time: ${Hours}:${Minutes}:${Seconds} - Average Run Time: ${ISXEVE.SecsToString[${Math.Calc[${This.TotalTripSeconds}/${This.TotalTrips}]}]}"]
}
function Mine()
{
variable int TargetJammedCounter=0
variable int BuddyCounter
variable string buddyTest
variable bool buddyOnline
if ${_Me.InStation} != FALSE
{
UI:UpdateConsole["DEBUG: obj_Miner.Mine called while zoning or while in station!"]
return
}
This.TripStartTime:Set[${Time.Timestamp}]
; Find an asteroid field, or stay at current one if we're near one.
call Asteroids.MoveToField FALSE
call This.Prepare_Environment
call Asteroids.UpdateList
variable int DroneCargoMin = ${Math.Calc[(${Ship.CargoMinimumFreeSpace}*1.4)]}
variable int Counter = 0
UI:UpdateConsole["Mining"]
while (${Social.IsSafe} && !${EVEBot.ReturnToStation} && \
${_Me.Ship.UsedCargoCapacity} <= ${Config.Miner.CargoThreshold} )
{
if ${Ship.TotalMiningLasers} == 0
{
UI:UpdateConsole["Warning: No mining lasers detected, docking"]
EVEBot.ReturnToStation:Set[TRUE]
return
}
if ${Config.Combat.LaunchCombatDrones} && \
${Ship.Drones.CombatDroneShortage}
{
/* TODO - This should pick up drones from station instead of just docking */
UI:UpdateConsole["Warning: Drone shortage detected, docking"]
EVEBot.ReturnToStation:Set[TRUE]
return
}
if ${_Me.Ship.UsedCargoCapacity} != ${LastUsedCargoCapacity}
{
;UI:UpdateConsole["DEBUG: ${_Me.Ship.UsedCargoCapacity} != ${LastUsedCargoCapacity}"]
SanityCheckCounter:Set[0]
LastUsedCargoCapacity:Set[${_Me.Ship.UsedCargoCapacity}]
}
if (!${Config.Miner.IceMining} && \
${SanityCheckCounter} > MINER_SANITY_CHECK_INTERVAL)
{
UI:UpdateConsole["Warning: Cargo volume hasn't changed in a while, docking"]
SanityCheckAbort:Set[TRUE]
break
}
if ${Config.Combat.LaunchCombatDrones} && \
${Ship.Drones.DronesInSpace} == 0 && \
!${Ship.InWarp}
{
Ship.Drones:LaunchAll[]
}
if ${_Me.Ship.MaxLockedTargets} == 0 && \
${Ship.Drones.DronesInSpace} == 0
{
TargetJammedCounter:Inc
if ${TargetJammedCounter} > 200
{
TargetJammedCounter:Set[0]
UI:UpdateConsole["Warning: Ship target jammed, no drones available. Changing Belts"]
call Asteroids.MoveToField TRUE
}
}
else
{
TargetJammedCounter:Set[0]
}
if ${Social.PlayerInRange[${Config.Miner.AvoidPlayerRange}]}
{
UI:UpdateConsole["Avoiding player: Changing Belts"]
call This.Cleanup_Environment
call Asteroids.MoveToField TRUE
call This.Prepare_Environment
}
/* TODO: CyberTech: Move this to the state machine, have it check for when the system is clear */
if ${Config.Miner.StandingDetection} && \
${Social.StandingDetection[${Config.Miner.LowestStanding}]}
{
EVEBot.ReturnToStation:Set[TRUE]
UI:UpdateConsole["Warning: Low Standing player in system, docking"]
}
if ${Config.Miner.DeliveryLocationTypeName.Equal[Jetcan]} && ${Ship.CargoHalfFull}
{
call Cargo.TransferOreToJetCan
This:NotifyHaulers[]
/* needed a wait here because it would try to move the same item more than once */
wait 20
}
if (${_Me.Ship.ArmorPct} < ${Config.Combat.MinimumArmorPct} || \
${_Me.Ship.ShieldPct} < ${Config.Combat.MinimumShieldPct})
{
/*
TODO - CyberTech: This should be checked in a defensive class that runs regardless of which bot module is active
instead of being checked in each module
*/
UI:UpdateConsole["Armor is at ${_Me.Ship.ArmorPct}: ${Me.Ship.Armor}/${Me.Ship.MaxArmor}", LOG_CRITICAL]
UI:UpdateConsole["Shield is at ${_Me.Ship.ShieldPct}: ${Me.Ship.Shield}/${Me.Ship.MaxShield}", LOG_CRITICAL]
UI:UpdateConsole["Miner aborting due to defensive status", LOG_CRITICAL]
EVEBot.ReturnToStation:Set[TRUE]
This.CombatAbort:Set[TRUE]
return
}
if ${Ship.InWarp}
{
wait 10
continue
}
if ${Ship.TotalActivatedMiningLasers} < ${Ship.TotalMiningLasers}
{
; We've got idle lasers, and available targets. Do something with them.
while ${_Me.GetTargeting} > 0
{
wait 10
}
Me:DoGetTargets[LockedTargets]
LockedTargets:GetIterator[Target]
if ${Target:First(exists)}
do
{
if ${_Me.Ship.UsedCargoCapacity} > ${Config.Miner.CargoThreshold}
{
break
}
if ${Target.Value.CategoryID} != ${Asteroids.AsteroidCategoryID}
{
continue
}
variable int TargetID
TargetID:Set[${Target.Value.ID}]
/* TODO: CyberTech - this concentrates fire fine if there's only 1 target, but if there's multiple targets it still prefers to distribute. Ice mining shouldn't distribute */
if (${This.ConcentrateFire} || \
${Config.Miner.IceMining} || \
!${Config.Miner.DistributeLasers} || \
!${Ship.IsMiningAsteroidID[${TargetID}]})
{
Target.Value:MakeActiveTarget
while ${Target.Value.ID} != ${Me.ActiveTarget.ID}
{
wait 5
}
if ${_Me.Ship.UsedCargoCapacity} > ${Config.Miner.CargoThreshold}
{
break
}
call Ship.Approach ${TargetID} ${Ship.OptimalMiningRange}
call Ship.ActivateFreeMiningLaser
if (${Ship.Drones.DronesInSpace} > 0 && \
${Config.Miner.UseMiningDrones})
{
Ship.Drones:ActivateMiningDrones
}
}
}
while ${Target:Next(exists)}
}
if (!${Config.Miner.IceMining} || \
(${Ship.TotalActivatedMiningLasers} == 0))
{
if ${Math.Calc[${_Me.GetTargets} + ${_Me.GetTargeting}]} < ${Ship.SafeMaxLockedTargets}
{
call Asteroids.TargetNext
This.ConcentrateFire:Set[!${Return}]
;echo DEBUG: Target Locking: ${Math.Calc[${_Me.GetTargets} + ${_Me.GetTargeting}].Int} out of ${Ship.SafeMaxLockedTargets} (Limited Asteroids: ${This.ConcentrateFire})
}
else
{
if ( ${_Me.GetTargets} >= ${Ship.SafeMaxLockedTargets} && \
${Ship.TotalMiningLasers} > ${Ship.SafeMaxLockedTargets} )
{
This.ConcentrateFire:Set[TRUE]
}
}
}
wait 10
}
if ${Config.Miner.BookMarkLastPosition}
{
Bookmarks:StoreLocation
}
call This.Cleanup_Environment
if ${Social.IsSafe}
{
This.TotalTrips:Inc
This.PreviousTripSeconds:Set[${This.TripDuration}]
This.TotalTripSeconds:Inc[${This.PreviousTripSeconds}]
This.AverageTripSeconds:Set[${Math.Calc[${This.TotalTripSeconds}/${This.TotalTrips}]}]
UI:UpdateConsole["Cargo Hold has reached threshold, returning"]
call ChatIRC.Say "Cargo Hold has reached threshold"
call This.Statslog
}
else
{
Combat.Override:Set[TRUE]
call Combat.Flee
}
}
member:int TripDuration()
{
return ${Math.Calc64[${Time.Timestamp} - ${This.TripStartTime.Timestamp}]}
}
member:float VolumePerCycle(string AsteroidType)
{
}
method NotifyHaulers()
{
/* notify hauler there is ore in space */
variable string tempString
tempString:Set["${_Me.CharID},${_Me.SolarSystemID},${Entity[GroupID, GROUP_ASTEROIDBELT].ID}"]
relay all -event EVEBot_Miner_Full ${tempString}
/* TO MANUALLY CALL A HAULER ENTER THIS IN THE CONSOLE
* relay all -event EVEBot_Miner_Full "${Me.CharID},${Me.SolarSystemID},0"
*/
}
}