NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

combatnavigation.py (6971B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\behaviors\actions\combatnavigation.py
      2 import random
      3 import math
      4 from behaviors.const.behaviorroles import ROLE_COMMANDER, ROLE_DPS, ROLE_TACKLER
      5 from behaviors.exceptions import BehaviorAuthoringException
      6 from behaviors.tasks import Task
      7 from behaviors.utility.dogmatic import get_my_attribute_value
      8 from ccpProfile import TimedFunction
      9 import logging
     10 from dogma.const import attributeBehaviorCombatOrbitRange
     11 logger = logging.getLogger(__name__)
     12 DEFAULT_COMBAT_ORBIT_RANGE = 10000.0
     13 DEFAULT_COMBAT_ATTACK_RANGE = 30000.0
     14 COMBAT_ATTACK_RANGE_FACTOR = 3.0
     15 DEFAULT_MAXIMUM_ORBIT_RANGE = 100000.0
     16 FALLOFF_ORBIT_DISTANCE_FACTOR = 0.25
     17 MISSILE_RANGE_ORBIT_DISTANCE_FACTOR = 0.75
     18 OPTIMAL_ORBIT_DISTANCE_FACTOR = 0.75
     19 COMBAT_WARP_AT_DISTANCE_FACTOR = 50000.0
     20 DEFAULT_ANCHOR_ORBIT_RANGE = (1000.0, 4000.0)
     21 FLEET_NAVIGATION_BY_ROLE = {ROLE_DPS: {'orbitTarget': ROLE_COMMANDER,
     22             'orbitRange': DEFAULT_ANCHOR_ORBIT_RANGE},
     23  ROLE_TACKLER: {'orbitTarget': 'target'}}
     24 
     25 class GetCombatOrbitAndAttackRange(Task):
     26 
     27     @TimedFunction('behaviors::actions::combatnavigation::GetCombatOrbitRange::OnEnter')
     28     def OnEnter(self):
     29         self.SetStatusToSuccess()
     30         if not self._should_calculate_orbit_and_attack_range():
     31             return
     32         orbit_range, attack_range = self._get_desired_orbit_and_attack_range()
     33         if orbit_range > attack_range:
     34             raise BehaviorAuthoringException('Behavior=%s for entity_type=%s has less attack range than orbit range', self.behaviorTree.GetBehaviorId(), self.context.mySlimItem.typeID)
     35         self.SendBlackboardValue(self.attributes.orbitRangeAddress, orbit_range)
     36         self.SendBlackboardValue(self.attributes.attackRangeAddress, attack_range)
     37 
     38     def _should_calculate_orbit_and_attack_range(self):
     39         return self.GetLastBlackboardValue(self.attributes.orbitRangeAddress) is None
     40 
     41     def _get_desired_orbit_and_attack_range(self):
     42         behavior_orbit_range = getattr(self.attributes, 'orbitRange', 0)
     43         attack_range = getattr(self.attributes, 'attackRange', 0)
     44         if behavior_orbit_range and attack_range:
     45             return (behavior_orbit_range, attack_range)
     46         calculated_orbit_range, calculated_attack_range = self._calculate_orbit_and_attack_range()
     47         if not calculated_orbit_range and not behavior_orbit_range:
     48             raise BehaviorAuthoringException('Behavior=%s for entity_type=%s missing orbitRange or optimalRange from address, might be missing task=GetMyMinOptimalAndFalloff', self.behaviorTree.GetBehaviorId(), self.context.mySlimItem.typeID)
     49         orbit_range = behavior_orbit_range or min(calculated_orbit_range, DEFAULT_MAXIMUM_ORBIT_RANGE)
     50         dogma_orbit_range = get_my_attribute_value(self, attributeBehaviorCombatOrbitRange)
     51         if dogma_orbit_range > 0:
     52             orbit_range = min(orbit_range, dogma_orbit_range)
     53         return (orbit_range, attack_range or calculated_attack_range)
     54 
     55     def _calculate_orbit_and_attack_range(self):
     56         min_optimal, min_falloff = self._get_min_optimal_and_falloff_from_addresses()
     57         if not min_falloff:
     58             orbit_range = min_optimal * OPTIMAL_ORBIT_DISTANCE_FACTOR
     59             attack_range = min_optimal
     60         else:
     61             orbit_range = min_optimal + min_falloff * FALLOFF_ORBIT_DISTANCE_FACTOR
     62             attack_range = min_optimal + min_falloff * COMBAT_ATTACK_RANGE_FACTOR
     63         return (orbit_range or DEFAULT_COMBAT_ORBIT_RANGE, attack_range or DEFAULT_COMBAT_ATTACK_RANGE)
     64 
     65     def _get_min_optimal_and_falloff_from_addresses(self):
     66         min_optimal = min_falloff = 0.0
     67         if self.HasAttribute('minOptimalAddress'):
     68             min_optimal = self.GetLastBlackboardValue(self.attributes.minOptimalAddress)
     69         if self.HasAttribute('minFalloffAddress'):
     70             min_falloff = self.GetLastBlackboardValue(self.attributes.minFalloffAddress)
     71         return (min_optimal, min_falloff)
     72 
     73 
     74 class GetTargetToOrbit(Task):
     75 
     76     @TimedFunction('behaviors::actions::combatnavigation::GetTargetToOrbit::OnEnter')
     77     def OnEnter(self):
     78         self.SetStatusToSuccess()
     79         commanderId = self.GetLastBlackboardValue(self.attributes.commanderAddress)
     80         if self._ShouldOrbitCommander(commanderId):
     81             self.SendBlackboardValue(self.attributes.orbitTargetAddress, commanderId)
     82         else:
     83             combatTargetId = self.GetLastBlackboardValue(self.attributes.combatTargetAddress)
     84             self.SendBlackboardValue(self.attributes.orbitTargetAddress, combatTargetId)
     85 
     86     def _ShouldOrbitCommander(self, commanderId):
     87         if commanderId is None:
     88             return False
     89         if self.context.myItemId == commanderId:
     90             return False
     91         role = self.GetLastBlackboardValue(self.attributes.roleAddress)
     92         if not role:
     93             return False
     94         if role not in FLEET_NAVIGATION_BY_ROLE or FLEET_NAVIGATION_BY_ROLE[role]['orbitTarget'] != ROLE_COMMANDER:
     95             return False
     96         return True
     97 
     98 
     99 class GetFleetCombatOrbitRangeByRole(Task):
    100 
    101     @TimedFunction('behaviors::actions::combatnavigation::GetFleetCombatOrbitAndAttackRangeByRole::OnEnter')
    102     def OnEnter(self):
    103         self.SetStatusToSuccess()
    104         orbitRange = self._GetCommanderOrbitRangeByRole()
    105         self.SendBlackboardValue(self.attributes.orbitRangeAddress, orbitRange)
    106 
    107     def _GetCommanderOrbitRangeByRole(self):
    108         role = self.GetLastBlackboardValue(self.attributes.roleAddress)
    109         if role in FLEET_NAVIGATION_BY_ROLE:
    110             minOrbitRange, maxOrbitRange = FLEET_NAVIGATION_BY_ROLE[role]['orbitRange']
    111         else:
    112             minOrbitRange, maxOrbitRange = DEFAULT_ANCHOR_ORBIT_RANGE
    113         return random.randrange(minOrbitRange, maxOrbitRange)
    114 
    115 
    116 class GetCombatWarpAtDistance(Task):
    117 
    118     @TimedFunction('behaviors::actions::combatnavigation::GetCombatWarpAtDistance::OnEnter')
    119     def OnEnter(self):
    120         self.SetStatusToSuccess()
    121         if self._already_has_combat_warp_at_distance():
    122             return
    123         combat_warp_at_distance = self._get_combat_warp_at_distance()
    124         self.SendBlackboardValue(self.attributes.combatWarpAtDistanceAddress, combat_warp_at_distance)
    125 
    126     def _already_has_combat_warp_at_distance(self):
    127         return self.GetLastBlackboardValue(self.attributes.combatWarpAtDistanceAddress) is not None
    128 
    129     def _get_combat_warp_at_distance(self):
    130         combat_orbit_range = self._get_combat_orbit_range()
    131         if not combat_orbit_range:
    132             raise BehaviorAuthoringException('Behavior=%s for entity=%s has no combat_orbit_range for GetCombatWarpAtDistance' % (self.behaviorTree.GetBehaviorId(), self.context.myItemId))
    133         factor = 1.0 - 1.0 / math.exp((combat_orbit_range / COMBAT_WARP_AT_DISTANCE_FACTOR) ** 2.0)
    134         return factor * combat_orbit_range
    135 
    136     def _get_combat_orbit_range(self):
    137         return self.GetLastBlackboardValue(self.attributes.combatOrbitRangeAddress)