target.py (14352B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\objectives\client\objective_task\target.py 2 import evetypes 3 import localization 4 import logging 5 import threadutils 6 import uthread2 7 from carbon.common.script.util.format import FmtDist 8 from carbonui.uicore import uicore 9 import eve.client.script.parklife.states as states 10 import log 11 from objectives.client.objective_task.base import ObjectiveTask, ObjectiveTaskGroup 12 from objectives.client.objective_task.generic import ProgressTask, ValueRangeTask 13 from objectives.client.ui.objective_task_widget import ProgressBarTaskWidget 14 from objectives.common.util import value_as_set 15 logger = logging.getLogger('objectives') 16 17 class TargetTask(ObjectiveTask): 18 objective_task_content_id = 24 19 20 def __init__(self, target = None, **kwargs): 21 self._slim_item = None 22 self._target = None 23 self._slim_item_tasklet = None 24 self._use_custom_title = bool(kwargs.get('title')) 25 super(TargetTask, self).__init__(hidden=(not self._use_custom_title), **kwargs) 26 self.target = target 27 28 def get_values(self): 29 result = super(TargetTask, self).get_values() 30 result['slim_item'] = self._slim_item 31 result['item_id'] = self.item_id 32 result['type_id'] = self.type_id 33 result['dungeon_object_id'] = self.dungeon_object_id 34 return result 35 36 @property 37 def target(self): 38 return self._target 39 40 @target.setter 41 def target(self, value): 42 if self._target == value: 43 return 44 self._target = value 45 self._slim_item = None 46 if isinstance(self._target, dict): 47 if self.type_id: 48 self._set_target_title(evetypes.GetName(self.type_id)) 49 self.update() 50 else: 51 self._slim_item = self._target 52 if self._slim_item_tasklet: 53 self._slim_item_tasklet.kill() 54 if self._target: 55 self._slim_item_tasklet = uthread2.start_tasklet(self._initialize_slim_item) 56 57 @property 58 def item_id(self): 59 if self._slim_item: 60 return self._slim_item.itemID 61 if self._target: 62 return self._target.get('item_id', None) 63 64 @property 65 def type_id(self): 66 if self._slim_item: 67 return self._slim_item.typeID 68 if self._target: 69 return self._target.get('type_id', None) 70 71 @property 72 def group_id(self): 73 if self._slim_item: 74 return self._slim_item.groupID 75 if self._target: 76 return self._target.get('group_id', None) 77 78 @property 79 def dungeon_object_id(self): 80 if self._slim_item: 81 return getattr(self._slim_item, 'dunObjectID', None) 82 if self._target: 83 return self._target.get('dungeon_object_id', None) 84 85 def _set_target_title(self, value): 86 if self._use_custom_title: 87 return 88 if self._title == value: 89 return 90 self._title = value 91 self.hidden = not bool(self._title) 92 93 def _initialize_slim_item(self): 94 while not self._slim_item: 95 if self.item_id: 96 self._slim_item = sm.GetService('michelle').GetItem(self.item_id) 97 elif self.type_id or self.group_id or self.dungeon_object_id: 98 self._find_target() 99 if not self._slim_item: 100 uthread2.sleep(0.5) 101 102 title = None 103 if self._slim_item.nameID: 104 title = localization.GetByMessageID(self._slim_item.nameID) 105 elif self._slim_item.charID: 106 try: 107 character_info = cfg.eveowners.Get(self._slim_item.charID) 108 title = character_info.name 109 except KeyError: 110 pass 111 112 if not title: 113 title = evetypes.GetName(self.type_id) 114 self._slim_item_tasklet = None 115 self._set_target_title(title) 116 self._set_target_highlight() 117 self._slim_item_initialized() 118 self.update() 119 120 def _find_target(self): 121 if self.dungeon_object_id: 122 from nodegraph.client.getters.object import GetDungeonObject 123 dungeon_object = GetDungeonObject(dungeon_object_id=self.dungeon_object_id).get_values() 124 if dungeon_object: 125 self._slim_item = dungeon_object['slim_item'] 126 else: 127 from nodegraph.client.getters.object import FindClosestObject 128 target = FindClosestObject(type_id=self.type_id, group_id=self.group_id).get_values() 129 if target and 'slim_item' in target: 130 self._slim_item = target['slim_item'] 131 132 def _set_target_highlight(self): 133 from nodegraph.client.actions.highlights import HighlightSpaceObject 134 self.highlight = HighlightSpaceObject(item_id=self.item_id) 135 136 def _slim_item_initialized(self): 137 pass 138 139 def mouse_down(self, ui_widget): 140 item_id = self.item_id 141 sm.GetService('stateSvc').SetState(item_id, states.selected, 1) 142 sm.GetService('menu').TacticalItemClicked(item_id) 143 sm.GetService('menu').TryExpandActionMenu(item_id, ui_widget) 144 145 def click(self): 146 camera = sm.GetService('sceneManager').GetActiveSpaceCamera() 147 if camera: 148 camera.Track(self.item_id) 149 150 def double_click(self, *args): 151 if uicore.cmd.IsSomeCombatCommandLoaded(): 152 return 153 if self._slim_item: 154 sm.GetService('menu').Activate(self._slim_item) 155 156 def get_context_menu(self): 157 return sm.GetService('menu').CelestialMenu(self.item_id) 158 159 def _stop(self): 160 if self._slim_item_tasklet: 161 self._slim_item_tasklet.kill() 162 self._slim_item_tasklet = None 163 164 @staticmethod 165 def get_custom_task_id(target): 166 try: 167 if isinstance(target, dict): 168 return target.get('item_id') or target.get('dungeon_object_id') or target.get('type_id') or target.get('group_id') or None 169 return target.itemID 170 except: 171 log.LogException() 172 return None 173 174 175 class TargetsTaskGroup(ObjectiveTaskGroup): 176 TASK = TargetTask 177 KEY = 'targets' 178 objective_task_content_id = None 179 180 def __init__(self, targets = None, **kwargs): 181 super(TargetsTaskGroup, self).__init__(**kwargs) 182 self._update_targets(targets) 183 184 def update_value(self, key, value): 185 super(TargetsTaskGroup, self).update_value(key, value) 186 if key == self.KEY: 187 self._update_targets(value) 188 189 def _update_targets(self, targets): 190 self.clear_tasks() 191 if targets is None: 192 targets = [] 193 elif not isinstance(targets, list): 194 targets = [targets] 195 for target in targets: 196 self._add_target(target, start_task=False) 197 198 self.all_tasks_added() 199 200 def _get_task_by_item_id(self, item_id): 201 if item_id in self.tasks: 202 return self.tasks[item_id] 203 for task in self.tasks.itervalues(): 204 if task.item_id == item_id: 205 return task 206 207 def _add_target(self, target, start_task = False): 208 task_id = self.TASK.get_custom_task_id(target) 209 self.add_task(task_id=task_id, target=target, start_task=start_task) 210 211 212 class BaseTargetsTask(ObjectiveTaskGroup): 213 objective_task_content_id = None 214 TASK = TargetTask 215 __notifyevents__ = ['OnBallAdded', 'DoBallRemove'] 216 217 def start(self): 218 self.clear_tasks() 219 if self._is_active: 220 self.update() 221 else: 222 super(BaseTargetsTask, self).start() 223 224 def _start(self): 225 super(BaseTargetsTask, self)._start() 226 self._find_targets() 227 228 def OnBallAdded(self, slim_item): 229 if self._validate_target(slim_item): 230 self._add_target(slim_item) 231 232 def DoBallRemove(self, ball, *args, **kwargs): 233 if ball is not None: 234 self.remove_task(task_id=ball.id) 235 236 def _find_targets(self): 237 ballpark = sm.GetService('michelle').GetBallpark() 238 if not ballpark: 239 return 240 for ball_id in ballpark.balls.iterkeys(): 241 if ball_id == session.shipid: 242 continue 243 slim_item = ballpark.GetInvItem(ball_id) 244 if slim_item and self._validate_target(slim_item): 245 self._add_target(slim_item, start_task=False) 246 247 self.all_tasks_added() 248 249 def _validate_target(self, slim_item): 250 return True 251 252 def _add_target(self, slim_item, start_task = True): 253 self.add_task(task_id=slim_item.itemID, target=slim_item, start_task=start_task) 254 255 256 class TargetsTask(BaseTargetsTask): 257 258 def __init__(self, type_ids = None, group_ids = None, type_list_id = None, objective_target_groups = None, item_ids = None, dungeon_object_ids = None, *args, **kwargs): 259 self._item_ids = value_as_set(item_ids) 260 self._dungeon_object_ids = value_as_set(dungeon_object_ids) 261 self._objective_target_groups = value_as_set(objective_target_groups) 262 self._type_ids = value_as_set(type_ids) 263 self._group_ids = value_as_set(group_ids) 264 self._type_list_id = None 265 self._type_ids_from_type_list = set() 266 if type_list_id: 267 self._update_type_list() 268 super(TargetsTask, self).__init__(*args, **kwargs) 269 270 @property 271 def item_ids(self): 272 return self._item_ids 273 274 @item_ids.setter 275 def item_ids(self, value): 276 if self._item_ids == value: 277 return 278 self._item_ids = value_as_set(value) 279 self._parameter_updated() 280 281 @property 282 def dungeon_object_ids(self): 283 return self._dungeon_object_ids 284 285 @dungeon_object_ids.setter 286 def dungeon_object_ids(self, value): 287 if self._dungeon_object_ids == value: 288 return 289 self._dungeon_object_ids = value_as_set(value) 290 self._parameter_updated() 291 292 @property 293 def type_ids(self): 294 return self._type_ids 295 296 @type_ids.setter 297 def type_ids(self, value): 298 if self._type_ids == value: 299 return 300 self._type_ids = value_as_set(value) 301 self._parameter_updated() 302 303 @property 304 def group_ids(self): 305 return self._group_ids 306 307 @group_ids.setter 308 def group_ids(self, value): 309 if self._group_ids == value: 310 return 311 self._group_ids = value_as_set(value) 312 self._parameter_updated() 313 314 @property 315 def objective_target_groups(self): 316 return self._objective_target_groups 317 318 @objective_target_groups.setter 319 def objective_target_groups(self, value): 320 if self._objective_target_groups == value: 321 return 322 self._objective_target_groups = value_as_set(value) 323 self._parameter_updated() 324 325 @property 326 def type_list_id(self): 327 return self._type_list_id 328 329 @type_list_id.setter 330 def type_list_id(self, value): 331 if self._type_list_id == value: 332 return 333 self._type_list_id = value 334 self._update_type_list() 335 self._parameter_updated() 336 337 def _update_type_list(self): 338 if not self._type_list_id: 339 self._type_ids_from_type_list.clear() 340 else: 341 try: 342 type_ids = evetypes.GetTypeIDsByListID(self._type_list_id) 343 except Exception as e: 344 logger.exception('%s: Failed to get type list', self.__class__.__name__) 345 return 346 347 self._type_ids_from_type_list = set(type_ids) 348 349 @uthread2.debounce(0.1) 350 def _parameter_updated(self): 351 self.clear_tasks() 352 if self.is_active: 353 self._find_targets() 354 self.update() 355 356 def _validate_target(self, slim_item): 357 if self._objective_target_groups and getattr(slim_item, 'objectiveTargetGroup', None) in self._objective_target_groups: 358 return True 359 if self._type_ids and getattr(slim_item, 'typeID', None) in self._type_ids: 360 return True 361 if self._group_ids and getattr(slim_item, 'groupID', None) in self._group_ids: 362 return True 363 if self._type_ids_from_type_list and getattr(slim_item, 'typeID', None) in self._type_ids_from_type_list: 364 return True 365 if self._item_ids and getattr(slim_item, 'itemID', None) in self._item_ids: 366 return True 367 if self._dungeon_object_ids and getattr(slim_item, 'dunObjectID', None) in self._dungeon_object_ids: 368 return True 369 return False 370 371 372 class GetWithinRangeTask(TargetTask): 373 objective_task_content_id = 7 374 WIDGET = ProgressBarTaskWidget 375 376 def __init__(self, distance = 500, **kwargs): 377 self._distance = distance 378 self._target_ball = None 379 self._max_distance = distance + 1 380 self._distance_to_target = self._max_distance 381 super(GetWithinRangeTask, self).__init__(**kwargs) 382 383 @property 384 def distance(self): 385 return self._distance 386 387 @distance.setter 388 def distance(self, value): 389 if self._distance == value: 390 return 391 self._distance = value 392 self._max_distance = max(self._max_distance, self._distance + 1) 393 self.update() 394 395 def _slim_item_initialized(self): 396 super(GetWithinRangeTask, self)._slim_item_initialized() 397 ballpark = sm.GetService('michelle').GetBallpark() 398 self._target_ball = ballpark.GetBall(self.item_id) 399 self._update_distance_routine() 400 401 @threadutils.threaded 402 def _update_distance_routine(self): 403 while self.is_active: 404 value = max(0, self._target_ball.surfaceDist - self.distance) 405 if self._distance_to_target != value: 406 self._distance_to_target = value 407 self._max_distance = max(self._max_distance, self._distance_to_target) 408 self.update() 409 self.completed = self._distance_to_target == 0 410 uthread2.sleep(1) 411 412 @property 413 def progress(self): 414 return 1.0 - min(self._distance_to_target / float(self._max_distance), 1.0) 415 416 @property 417 def value(self): 418 return FmtDist(self._distance_to_target, 0) 419 420 421 class TargetWithProgressTask(TargetTask, ProgressTask): 422 objective_task_content_id = 32 423 WIDGET = ProgressBarTaskWidget 424 425 426 class TargetWithValueRangeTask(TargetTask, ValueRangeTask): 427 objective_task_content_id = 43 428 WIDGET = ProgressBarTaskWidget