positionalControl.py (8681B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\inflight\positionalControl.py 2 import blue 3 import uthread2 4 import tacticalNavigation.controlPaths as controlPaths 5 from eve.common.script.sys.eveCfg import IsControllingStructure 6 from evegraphics.wrappers.vectorFunctions import AverageVectorFunction 7 from eve.client.script.ui.services.menuSvcExtras.movementFunctions import GetSelectedShipAndFighters, GoToPoint 8 _SW_CYLINDER = 1 9 _SW_SLICE = 2 10 _SW_CONE = 3 11 _SW_PROJECTED_SPHERE = 4 12 13 class PositionalControl: 14 __notifyevents__ = ['OnBallparkCall'] 15 16 def __init__(self): 17 self._cameraController = None 18 self._currentPath = None 19 self._activeIDs = [] 20 self._finalizeFunction = None 21 self._updateRunning = False 22 self._moduleID = None 23 self._effectID = None 24 self._isMoving = False 25 self._isTargeting = False 26 sm.RegisterNotify(self) 27 28 def IsActive(self): 29 return self._currentPath is not None 30 31 def IsFirstPointSet(self): 32 if self._currentPath: 33 return self._currentPath.IsFirstPointSet() 34 else: 35 return False 36 37 def OnSceneMouseExit(self): 38 if self.IsMoveCommandActive() and not self.IsFirstPointSet(): 39 self.AbortCommand() 40 41 def IsMoveCommandActive(self): 42 return self._finalizeFunction == self._MoveSelected 43 44 def SetCameraController(self, cameraController): 45 self._cameraController = cameraController 46 if self._currentPath is None: 47 self.AbortCommand() 48 49 def AbortCommand(self, *args): 50 if self._currentPath is not None: 51 self._currentPath.Abort() 52 self._currentPath = None 53 self._activeIDs = [] 54 self._finalizeFunction = None 55 self._isTargeting = False 56 self._EnableUpdate(False) 57 if self._isMoving: 58 overlay = sm.GetService('tactical').GetOverlay() 59 overlay.DisableMoveMode() 60 self._isMoving = False 61 62 def _GetMoveOrigin(self, activeIDs): 63 lookAtID = self._cameraController.GetCamera().GetLookAtItemID() 64 michelle = sm.GetService('michelle') 65 if lookAtID == session.shipid: 66 return michelle.GetBall(session.shipid) 67 balls = [] 68 for fighterID in activeIDs: 69 ball = michelle.GetBall(fighterID) 70 if ball is not None: 71 balls.append(ball) 72 73 if len(balls) == 0: 74 return michelle.GetBall(session.shipid) 75 if len(balls) == 1: 76 return balls[0] 77 return AverageVectorFunction(balls).GetBlueFunction() 78 79 def StartMoveCommand(self): 80 activeIDs = [] 81 shipSelected, fighterIDs = GetSelectedShipAndFighters() 82 if shipSelected and not IsControllingStructure(): 83 activeIDs.append(session.shipid) 84 activeIDs.extend(fighterIDs) 85 self._activeIDs = activeIDs 86 if len(activeIDs) < 1: 87 return 88 if self._currentPath is not None: 89 self._currentPath.Abort() 90 originCurve = self._GetMoveOrigin(activeIDs) 91 self._currentPath = controlPaths.SinglePointPath() 92 self._currentPath.Start(originCurve) 93 overlay = sm.GetService('tactical').GetOverlay() 94 overlay.EnableMoveMode(originCurve) 95 self._isMoving = True 96 self._finalizeFunction = self._MoveSelected 97 self._EnableUpdate(True) 98 99 def _StartTargetedEffect(self): 100 destination = self._currentPath.GetEndPosition() 101 superWeaponMgr = sm.RemoteSvc('superWeaponMgr') 102 superWeaponMgr.ActivateSinglePointTargetedModule(self._moduleID, self._effectID, destination) 103 104 def _StartSlasherEffect(self): 105 p0, p1 = self._currentPath.GetPath() 106 superWeaponMgr = sm.RemoteSvc('superWeaponMgr') 107 superWeaponMgr.ActivateSlashModule(self._moduleID, p0, p1) 108 109 def _GetModuleBehavior(self, moduleItem): 110 areaIndicator = None 111 doomsdayAOEShape = getattr(moduleItem, 'doomsdayAOEShape', None) 112 maxRange = getattr(moduleItem, 'maxRange', None) 113 fixedRange = getattr(moduleItem, 'doomsdayRangeIsFixed', False) 114 aoeRange = getattr(moduleItem, 'doomsdayAOERange', None) 115 damageRadius = getattr(moduleItem, 'doomsdayDamageRadius', None) 116 if doomsdayAOEShape == _SW_PROJECTED_SPHERE: 117 areaIndicator = controlPaths.SphereAreaIndication(aoeRange) 118 elif doomsdayAOEShape == _SW_SLICE: 119 areaIndicator = controlPaths.SliceAreaIndication(damageRadius) 120 elif doomsdayAOEShape == _SW_CONE: 121 areaIndicator = controlPaths.ConeAreaIndication() 122 elif doomsdayAOEShape == _SW_CYLINDER: 123 areaIndicator = controlPaths.CylinderAreaIndication(damageRadius) 124 return (fixedRange, maxRange, areaIndicator) 125 126 def StartEffectTargeting(self, sourceID, moduleID, effect, targetPointCount): 127 if self._currentPath is not None: 128 self._currentPath.Abort() 129 self._moduleID = moduleID 130 self._effectID = effect.effectID 131 self._isTargeting = True 132 michelle = sm.GetService('michelle') 133 ball = michelle.GetBall(sourceID) 134 radius = getattr(ball, 'radius', 0) 135 if targetPointCount == 2.0: 136 self._currentPath = controlPaths.ArcPath(baseDistance=radius) 137 self._finalizeFunction = self._StartSlasherEffect 138 else: 139 self._currentPath = controlPaths.SinglePointPath(agressive=True, baseDistance=radius) 140 self._finalizeFunction = self._StartTargetedEffect 141 module = sm.GetService('godma').GetItem(moduleID) 142 fixedRange, moduleRange, areaIndicator = self._GetModuleBehavior(module) 143 if moduleRange is not None: 144 self._currentPath.SetMaxDistance(moduleRange) 145 self._currentPath.SetFixedDistance(fixedRange) 146 self._currentPath.Start(ball, areaIndicator) 147 self._activeIDs = [sourceID] 148 self._EnableUpdate(True) 149 150 def _StartFighterAbilites(self): 151 selectedPoint = self._ConvertPositionToGlobalSpace(self._currentPath.GetEndPosition()) 152 sm.GetService('fighters').ActivateAbilitySlotsAtPoint(self._activeIDs, self._abilitySlotID, selectedPoint) 153 154 def StartFighterAbilityTargeting(self, fighterIDs, abiltySlotID): 155 if len(fighterIDs) < 1: 156 return 157 if self._currentPath is not None: 158 self._currentPath.Abort() 159 originCurve = self._GetMoveOrigin(fighterIDs) 160 self._currentPath = controlPaths.SinglePointPath() 161 self._currentPath.Start(originCurve) 162 self._abilitySlotID = abiltySlotID 163 self._activeIDs = fighterIDs 164 self._finalizeFunction = self._StartFighterAbilites 165 self._EnableUpdate(True) 166 167 def _EnableUpdate(self, enable): 168 if enable and not self._updateRunning: 169 uthread2.StartTasklet(self._UpdateThread) 170 self._updateRunning = enable 171 172 def _Finalize(self): 173 try: 174 self._finalizeFunction() 175 finally: 176 self.AbortCommand() 177 178 def _ConvertPositionToGlobalSpace(self, position): 179 bp = sm.GetService('michelle').GetBallpark() 180 if bp is None: 181 return 182 egopos = bp.GetCurrentEgoPos() 183 destination = (position[0] + egopos[0], position[1] + egopos[1], position[2] + egopos[2]) 184 return destination 185 186 def _MoveSelected(self): 187 destination = self._ConvertPositionToGlobalSpace(self._currentPath.GetEndPosition()) 188 if destination is None: 189 return 190 GoToPoint(destination) 191 tn = sm.GetService('tacticalNavigation') 192 tn.IndicateMoveCommand(self._activeIDs, destination) 193 194 def AddPoint(self): 195 if self._currentPath is None or self._cameraController is None: 196 return 197 self._currentPath.UpdatePosition(self._cameraController) 198 self._currentPath.AddPoint() 199 sm.GetService('audio').SendUIEvent('msg_ComboEntryEnter_play') 200 if self._currentPath.IsComplete(): 201 uthread2.StartTasklet(self._Finalize) 202 203 def _UpdateThread(self): 204 while self._updateRunning: 205 if self._currentPath is not None and self._cameraController is not None: 206 self._currentPath.UpdatePosition(self._cameraController) 207 blue.synchro.Yield() 208 209 def OnBallparkCall(self, functionName, callArgument, **kwargs): 210 if functionName in ('WarpTo',) and callArgument[0] == session.shipid: 211 self.AbortCommand() 212 213 def OnSessionChanged(self, isremote, session, change): 214 self.AbortCommand() 215 216 def IsTargeting(self): 217 return self._isTargeting