Skip to content

Commit

Permalink
Redesigned the way autotargeter selects potential targets to improve …
Browse files Browse the repository at this point in the history
…performance when dealing with large numbers of balls

Improved performance of dronehelper and autotargeter filterTargets routines
Fixed wrong flag name for alliance members
Clear list of rep broadcasts on session change
  • Loading branch information
kg committed Dec 18, 2010
1 parent 6a2b1bc commit dfad882
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 114 deletions.
233 changes: 125 additions & 108 deletions AutoTargeter/autotargeter.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import destiny import destiny
import uthread import uthread
import trinity import trinity
from util import Memoized


prefs = {} prefs = {}
serviceInstance = None serviceInstance = None
Expand All @@ -33,6 +34,35 @@ def getPref(key, default):
def notifyPrefsChanged(newPrefsJson): def notifyPrefsChanged(newPrefsJson):
global prefs global prefs
prefs = json.loads(newPrefsJson) prefs = json.loads(newPrefsJson)

if serviceInstance:
serviceInstance.populateEligibleBalls()

FlagHostileNPC = set(["HostileNPC"])
FlagHostilePlayer = set(["StandingBad", "StandingHorrible", "AtWarCanFight"])
FlagNeutralPlayer = set(["StandingNeutral"])
FlagFriendlyPlayer = set(["StandingGood", "StandingHigh", "SameFleet", "SameAlliance", "SameCorp"])

TargetableCategories = set([const.categoryEntity, const.categoryDrone, const.categoryShip])

class BallInfo:
def __init__(self, ball, slimItem):
self.id = slimItem.itemID
self.ball = ball
self.slimItem = slimItem
self.flag = getFlagName(slimItem)

def updateFlag(self):
self.flag = getFlagName(self.slimItem)

@property
def isEligible(self):
return (
(getPref("TargetHostileNPCs", False) and self.flag in FlagHostileNPC) or
(getPref("TargetHostilePlayers", False) and self.flag in FlagHostilePlayer) or
(getPref("TargetNeutralPlayers", False) and self.flag in FlagNeutralPlayer) or
(getPref("TargetFriendlyPlayers", False) and self.flag in FlagFriendlyPlayer)
)


class AutoTargeterSvc: class AutoTargeterSvc:
__notifyevents__ = [ __notifyevents__ = [
Expand All @@ -45,22 +75,25 @@ class AutoTargeterSvc:


def __init__(self): def __init__(self):
self.disabled = False self.disabled = False
self.__updateTimer = SafeTimer(500, self.updateTargets) self.__updateTimer = SafeTimer(1000, self.updateTargets)
self.__potentialTargets = [] self.__balls = {}
self.__lockedTargets = [] self.__eligibleBalls = set()
self.warping = False self.__lockedTargets = set()


runOnMainThread(self.populateTargets) runOnMainThread(self.populateBalls)


def getDistance(self, targetID): def getDistance(self, targetID):
ballpark = eve.LocalSvc("michelle").GetBallpark() ballpark = eve.LocalSvc("michelle").GetBallpark()
return ballpark.DistanceBetween(eve.session.shipid, targetID) return ballpark.DistanceBetween(eve.session.shipid, targetID)


def makeTargetSorter(self, currentTargets): def makeTargetSorter(self, currentTargets):
gd = Memoized(self.getDistance)
gp = Memoized(getPriority)

def targetSorter(lhs, rhs): def targetSorter(lhs, rhs):
# Highest priority first # Highest priority first
priLhs = getPriority(targetID=lhs) priLhs = gp(targetID=lhs)
priRhs = getPriority(targetID=rhs) priRhs = gp(targetID=rhs)
result = cmp(priRhs, priLhs) result = cmp(priRhs, priLhs)


if result == 0: if result == 0:
Expand All @@ -70,8 +103,8 @@ def targetSorter(lhs, rhs):
) )


if result == 0: if result == 0:
distLhs = self.getDistance(lhs) distLhs = gd(lhs)
distRhs = self.getDistance(rhs) distRhs = gd(rhs)
result = cmp(distLhs, distRhs) result = cmp(distLhs, distRhs)


return result return result
Expand All @@ -91,7 +124,7 @@ def getMaxTargets(self):
)) ))
return max(maxTargets - reservedSlots, 0) return max(maxTargets - reservedSlots, 0)


def filterTargets(self, ids): def filterTargets(self, bis):
targetSvc = sm.services['target'] targetSvc = sm.services['target']
ballpark = eve.LocalSvc("michelle").GetBallpark() ballpark = eve.LocalSvc("michelle").GetBallpark()
if not ballpark: if not ballpark:
Expand All @@ -105,51 +138,25 @@ def filterTargets(self, ids):
return [] return []
elif isPlayerJumping(): elif isPlayerJumping():
return [] return []
elif myBall.isCloaked:
return []


result = [] result = []


maxTargetRange = self.getMaxTargetRange() maxTargetRange = self.getMaxTargetRange()


for id in ids: for bi in bis:
ball = ballpark.GetBall(id) if not isBallTargetable(bi.ball):
if not ball:
continue
if not isBallTargetable(ball):
continue

slimItem = ballpark.GetInvItem(id)
if not slimItem:
continue continue


if getPriority(slimItem=slimItem) < 0: if getPriority(slimItem=bi.slimItem) < 0:
continue continue


flag = getFlagName(slimItem) distance = ballpark.DistanceBetween(eve.session.shipid, bi.id)
if flag == "HostileNPC":
if not getPref("TargetHostileNPCs", False):
continue
elif ((flag == "StandingBad") or
(flag == "StandingHorrible") or
(flag == "AtWarCanFight")):
if not getPref("TargetHostilePlayers", False):
continue
elif flag == "StandingNeutral":
if not getPref("TargetNeutralPlayers", False):
continue
elif ((flag == "StandingGood") or
(flag == "StandingHigh") or
(flag == "SameGang") or
(flag == "SameFleet") or
(flag == "Alliance") or
(flag == "SameCorp")):
if not getPref("TargetFriendlyPlayers", False):
continue

distance = ballpark.DistanceBetween(eve.session.shipid, id)
if distance > maxTargetRange: if distance > maxTargetRange:
continue continue


result.append(id) result.append(bi.id)


return result return result


Expand All @@ -171,57 +178,62 @@ def updateTargets(self):
return return


currentTargets = self.filterTargets([ currentTargets = self.filterTargets([
id for id in self.__lockedTargets self.__balls[id] for id in self.__lockedTargets
if id in targetSvc.targets if id in targetSvc.targets
]) ])
exclusionSet = set(targetSvc.targeting + targetSvc.autoTargeting + currentTargets) exclusionSet = set(targetSvc.targeting + targetSvc.autoTargeting + currentTargets)
targetSorter = self.makeTargetSorter(exclusionSet) targetSorter = self.makeTargetSorter(exclusionSet)


targets = self.filterTargets(self.__potentialTargets) targets = self.filterTargets(self.__eligibleBalls)
targets.sort(targetSorter) targets.sort(targetSorter)


if len(targets): currentlyTargeting = set([
currentlyTargeting = set([ id for id in (targetSvc.targeting + targetSvc.autoTargeting)
id for id in (targetSvc.targeting + targetSvc.autoTargeting) if id in self.__lockedTargets
if id in self.__lockedTargets ])
])

maxNewTargets = max(
maxTargets - len(currentlyTargeting),
0
)
targets = set(targets[0:maxTargets])

currentTargets.sort(targetSorter)
currentTargets = set(currentTargets)

targetsToUnlock = (currentTargets - targets) - currentlyTargeting
targetsToLock = (targets - set(targetSvc.targets)) - currentlyTargeting
targetsToLock = list(targetsToLock)[0:maxNewTargets]


if len(targetsToUnlock): allLockedTargets = set(targetSvc.targeting + targetSvc.autoTargeting + targetSvc.targets)
log("Unlocking %s", ", ".join(getNamesOfIDs(targetsToUnlock))) maxNewTargets = max(maxTargets - len(allLockedTargets), 0)
for targetID in targetsToUnlock: targets = set(targets[0:maxTargets])
if targetID in self.__lockedTargets:
self.__lockedTargets.remove(targetID) currentTargets.sort(targetSorter)
setItemColor(targetID, None) currentTargets = set(currentTargets)

targetSvc.UnlockTarget(targetID)

if len(targetsToLock):
log("Locking %s", ", ".join(getNamesOfIDs(targetsToLock)))
for targetID in targetsToLock:
if targetID not in self.__lockedTargets:
self.__lockedTargets.append(targetID)
setItemColor(targetID, "Automatic Target")


uthread.pool( targetsToUnlock = (currentTargets - targets) - currentlyTargeting
"LockTarget", targetsToLock = (targets - set(targetSvc.targets)) - currentlyTargeting
targetSvc.TryLockTarget, targetsToLock = list(targetsToLock)[0:maxNewTargets]
targetID
) if len(targetsToUnlock):
log("Unlocking %s", ", ".join(getNamesOfIDs(targetsToUnlock)))
for targetID in targetsToUnlock:
if targetID in self.__lockedTargets:
self.__lockedTargets.remove(targetID)
setItemColor(targetID, None)

targetSvc.UnlockTarget(targetID)

if len(targetsToLock):
log("Locking %s", ", ".join(getNamesOfIDs(targetsToLock)))
for targetID in targetsToLock:
if targetID not in self.__lockedTargets:
self.__lockedTargets.append(targetID)
setItemColor(targetID, "Automatic Target")

uthread.pool(
"LockTarget",
self.tryLockTarget,
targetSvc, targetID
)


def populateTargets(self): def tryLockTarget(self, targetSvc, targetID):
try:
targetSvc.TryLockTarget(targetID)
except:
log("Failed to lock %r", targetID)

def populateBalls(self):
self.__balls = {}

ballpark = eve.LocalSvc("michelle").GetBallpark() ballpark = eve.LocalSvc("michelle").GetBallpark()
if not ballpark: if not ballpark:
return return
Expand All @@ -232,13 +244,11 @@ def populateTargets(self):
for id in self.__lockedTargets: for id in self.__lockedTargets:
setItemColor(id, "Automatic Target") setItemColor(id, "Automatic Target")


ids = list(ballpark.balls.keys())

lst = [] lst = []
for ballID in ids: for ballID, ball in ballpark.balls.iteritems():
slimItem = ballpark.GetInvItem(ballID) slimItem = ballpark.GetInvItem(ballID)
if slimItem: if slimItem:
lst.append((ballpark.GetBall(ballID), slimItem)) lst.append((ball, slimItem))


self._DoBallsAdded(lst) self._DoBallsAdded(lst)


Expand All @@ -251,31 +261,38 @@ def DoBallsAdded(self, lst, **kwargs):


def _DoBallsAdded(self, lst): def _DoBallsAdded(self, lst):
for (ball, slimItem) in lst: for (ball, slimItem) in lst:
isValidTarget = False if not slimItem.categoryID in TargetableCategories:
flag = getFlagName(slimItem) continue
if slimItem.itemID == eve.session.shipid:
continue

bi = BallInfo(ball, slimItem)
self.__balls[slimItem.itemID] = bi


if flag == "HostileNPC": if bi.isEligible:
self.__potentialTargets.append(slimItem.itemID) self.__eligibleBalls.add(bi)
elif ((flag == "StandingBad") or
(flag == "StandingHorrible") or def populateEligibleBalls(self):
(flag == "AtWarCanFight")): self.__eligibleBalls = set()
self.__potentialTargets.append(slimItem.itemID)
elif flag == "StandingNeutral": for ballInfo in self.__balls.itervalues():
self.__potentialTargets.append(slimItem.itemID) if ballInfo.isEligible:
elif ((flag == "StandingGood") or self.__eligibleBalls.add(ballInfo)
(flag == "StandingHigh") or
(flag == "SameGang") or
(flag == "SameFleet") or
(flag == "Alliance") or
(flag == "SameCorp")):
self.__potentialTargets.append(slimItem.itemID)


def DoBallRemove(self, ball, slimItem, *args, **kwargs): def DoBallRemove(self, ball, slimItem, *args, **kwargs):
if slimItem and (slimItem.itemID in self.__potentialTargets): if not slimItem:
self.__potentialTargets.remove(slimItem.itemID) return

id = slimItem.itemID
bi = self.__balls.get(id, None)
if bi:
del self.__balls[id]
if bi in self.__eligibleBalls:
self.__eligibleBalls.remove(bi)


def DoBallClear(self, solItem, **kwargs): def DoBallClear(self, solItem, **kwargs):
self.__potentialTargets = [] self.__balls = {}
self.__eligibleBalls = set()


def OnTargets(self, targets): def OnTargets(self, targets):
for each in targets: for each in targets:
Expand Down
10 changes: 10 additions & 0 deletions BroadcastHelper/broadcasthelper.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -35,12 +35,19 @@ def notifyPrefsChanged(newPrefsJson):
class BroadcastHelperSvc: class BroadcastHelperSvc:
__notifyevents__ = [ __notifyevents__ = [
"OnFleetBroadcast", "OnFleetBroadcast",
"OnSessionChanged",
] ]


def __init__(self): def __init__(self):
self.disabled = False self.disabled = False
self.__needReps = [] self.__needReps = []


def clear(self):
while len(self.__needReps) > 0:
item = self.__needReps[0]
self.__needReps.remove(item)
adjustPriority(item, 0)

def OnFleetBroadcast(self, broadcastType, arg1, charID, locationID, targetID): def OnFleetBroadcast(self, broadcastType, arg1, charID, locationID, targetID):
targetName = None targetName = None
locationName = None locationName = None
Expand Down Expand Up @@ -81,6 +88,9 @@ def needsReps(self, id):
item = self.__needReps[0] item = self.__needReps[0]
self.__needReps.remove(item) self.__needReps.remove(item)
adjustPriority(item, 0) adjustPriority(item, 0)

def OnSessionChanged(self, isRemote, session, change):
self.clear()


def initialize(): def initialize():
global serviceRunning, serviceInstance global serviceRunning, serviceInstance
Expand Down
11 changes: 6 additions & 5 deletions DroneHelper/dronehelper.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -157,12 +157,13 @@ def getCommonTarget(self, filtered=True):
return None return None


def getTargetSorter(self): def getTargetSorter(self):
getDistance = Memoized(self.getDistance) gp = Memoized(getPriority)
gd = Memoized(self.getDistance)


def targetSorter(lhs, rhs): def targetSorter(lhs, rhs):
# Highest priority first # Highest priority first
priLhs = getPriority(targetID=lhs) priLhs = gp(targetID=lhs)
priRhs = getPriority(targetID=rhs) priRhs = gp(targetID=rhs)
result = cmp(priRhs, priLhs) result = cmp(priRhs, priLhs)


if result == 0: if result == 0:
Expand All @@ -173,8 +174,8 @@ def targetSorter(lhs, rhs):
) )


if result == 0: if result == 0:
distLhs = getDistance(lhs) distLhs = gd(lhs)
distRhs = getDistance(rhs) distRhs = gd(rhs)
result = cmp(distLhs, distRhs) result = cmp(distLhs, distRhs)


return result return result
Expand Down
Loading

0 comments on commit dfad882

Please sign in to comment.