hangarView.py (51808B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\view\hangarView.py 2 from __future__ import absolute_import 3 import math 4 import random 5 import evecamera 6 import evegraphics.utils as gfxutils 7 import evetypes 8 import geo2 9 import inventorycommon.const as invconst 10 import evegraphics.settings as gfxsettings 11 import signals 12 import telemetry 13 import logging 14 import trinity 15 import uthread 16 import uthread2 17 import blue 18 from . import hangarRegistry as hangar 19 from eveuniverse.security import securityClassHighSec, is_high_sec_or_higher_solar_system, is_low_sec_or_lower_solar_system 20 from fsdBuiltData.common.soundIDs import GetSoundEventName 21 from eve.client.script.environment.sofService import GetSofService 22 from eve.client.script.ui.camera.cameraUtil import IsDynamicCameraMovementEnabled 23 from eve.client.script.ui.services.viewStateSvc import View 24 from eve.client.script.ui.station.navigation import HangarLayer 25 from eve.client.script.ui.view.viewStateConst import ViewState 26 from eve.common.lib import appConst as const 27 from eve.common.script.sys.idCheckers import IsTriglavianSystem 28 from eveSpaceObject import spaceobjanimation 29 from evegraphics.graphicEffects.skinChange import ChangeSkin, GetModelsToBeRemovedFromScene 30 from fsdBuiltData.common.graphicIDs import GetGraphicFile, GetSofHullName, GetSofFactionName, GetSofRaceName, GetSofLayoutNames, GetControllerVariableOverrides 31 from inventorycommon.util import IsSubsystemFlagVisible 32 from shipcosmetics.client.fittingsgateway.fittingsSignals import on_ship_cosmetics_changed 33 from shipprogression.boarding_moment.boardingMomentSvc import GetBoardingMomentService 34 from shipprogression.boarding_moment import get_boarding_moment_details, should_autoplay_boarding_moment, get_ship_shape_group, get_ship_size_group, get_ship_faction_group, get_unique_moment_id 35 from shipprogression.boarding_moment.skip import SkipController 36 from shipprogression.boarding_moment.ui.boarding_ui_controller import BoardingUIController 37 from stackless_response_router.exceptions import TimeoutException 38 from evegraphics.CosmeticsLoader import CosmeticsLoader 39 from uthread2 import call_after_simtime_delay 40 from evetypes import GetGraphicID 41 from eveaudio.helpers import CreateAudioObserver 42 from cosmetics.client.ships.ship_skin_signals import on_skin_state_set 43 from cosmetics.common.ships.skins.static_data.skin_type import ShipSkinType 44 from uihider import CommandBlockerService 45 log = logging.getLogger(__name__) 46 REPLACE_DOCK = 1 47 REPLACE_SWITCHSHIPS = 2 48 REPLACE_UPDATE = 3 49 ACTIVITY_LEVEL_LOW = 0 50 ACTIVITY_LEVEL_MID = 1 51 ACTIVITY_LEVEL_HIGH = 2 52 HANGAR_DOCKING_STATE = 0 53 HANGAR_DOCKED_STATE = 1 54 HANGAR_UNDOCKING_STATE = 2 55 USE_CITADEL_HANGAR = False 56 PROPAGANDA_LAYOUT_NAME = 'hangar_announcements' 57 58 class HangarView(View): 59 __guid__ = 'viewstate.HangarView' 60 __notifyevents__ = ['OnDogmaItemChange', 61 'OnDogmaAttributeChanged', 62 'ProcessActiveShipChanged', 63 'OnDamageStateChanged', 64 'OnDirtLevelChanged', 65 'OnStanceActive', 66 'OnGraphicSettingsChanged', 67 'OnEndChangeDevice', 68 'OnRepairDone', 69 'OnSpinThresholdReached', 70 'OnHangarViewStateUpdated_Local', 71 'OnSessionChanged', 72 'OnItemChangeProcessed', 73 'OnCorpLogoReady', 74 'OnAllianceLogoReady'] 75 __dependencies__ = ['godma', 76 'loading', 77 'station', 78 'invCache', 79 'sceneManager', 80 'clientDogmaIM', 81 'cosmeticsSvc', 82 'photo', 83 'dockingHeroNotification'] 84 __overlays__ = {'sidePanels'} 85 __layerClass__ = HangarLayer 86 HANGAR_TYPE_OVERRIDE = None 87 HANGAR_TYPE_OVERRIDE_VALUES = hangar.GetHangarTypeOverrideKeys() 88 89 @classmethod 90 def SetHangarOverride(cls, override): 91 cls.HANGAR_TYPE_OVERRIDE = override 92 hangar.HANGAR_TYPE_OVERRIDE = override 93 currentView = sm.GetService('viewState').GetCurrentView() 94 if currentView is not None and currentView.name == 'hangar': 95 currentView.ReloadView() 96 97 def __init__(self): 98 View.__init__(self) 99 self.scenePath = '' 100 self.activeShipItem = None 101 self.activeShipModel = None 102 self.activeHangarScene = None 103 self.activeHangarModel = None 104 self.log = log 105 self.activeHangarType = None 106 self.sceneNeedsApplying = False 107 self.restartHangarControllers = False 108 self.skipDockingAnimation = False 109 self.currentSceneGraphicID = -1 110 self.currentHangarGraphicID = -1 111 self.shipBehaviour = None 112 self.droneBehaviour = None 113 self._backupLights = None 114 self._vfxMultiEffect = None 115 self._fsbThread = None 116 self._starting_boarding_moment = False 117 self._undocking_in_progress = False 118 self._undocking_started_signal = signals.Signal() 119 self.cosmeticsLoader = CosmeticsLoader((CosmeticsLoader.ALLIANCE, CosmeticsLoader.CORP)) 120 self.initialFogSceneSetting = 1.0 121 self._retriggerableFadeFromBlackTasklet = None 122 on_ship_cosmetics_changed.connect(self.OnShipCosmeticsChanged) 123 on_skin_state_set.connect(self._on_skin_state_set) 124 125 def _on_skin_state_set(self, ship_instance_id, skin_state): 126 if ship_instance_id != session.shipid: 127 return 128 log.info('SKIN STATES - space object %s received on_skin_state_set with %s' % (ship_instance_id, skin_state)) 129 if skin_state is not None: 130 self.OnActiveShipSkinChange(self.GetActiveShipItemID(), None, updateSkin=True, reloadSubsystems=True) 131 else: 132 log.error('Failed to apply SKIN to ship: SKIN state is missing for ship: %s', ship_instance_id) 133 134 def GetActiveShipTypeID(self): 135 if self.activeShipItem is None: 136 return 137 return self.activeShipItem.typeID 138 139 def GetActiveShipItemID(self): 140 if self.activeShipItem is None: 141 return 142 return self.activeShipItem.itemID 143 144 @telemetry.ZONE_METHOD 145 def ShowView(self, **kwargs): 146 if not session.stationid and not session.structureid: 147 return 148 if self.activeHangarScene is None: 149 self.SetUpModels() 150 if self.sceneManager.GetActiveScene() is None or self.sceneNeedsApplying: 151 self.sceneManager.ApplyScene(self.activeHangarScene, ViewState.Hangar) 152 self.DisableReflectionProbe() 153 self.DisableShadows() 154 self.sceneNeedsApplying = False 155 View.ShowView(self, **kwargs) 156 settings.user.ui.Set('defaultDockingView', ViewState.Hangar) 157 if session.structureid: 158 settings.user.ui.Set('defaultStructureView', ViewState.Hangar) 159 sm.GetService('loginCampaignService').try_displaying_rookie_reward_pointer() 160 if self._starting_boarding_moment: 161 self.play_boarding_moment() 162 163 @telemetry.ZONE_METHOD 164 def HideView(self, **kwargs): 165 sceneManager = sm.GetService('sceneManager') 166 fisRenderjob = sceneManager.GetFisRenderJob() 167 if fisRenderjob: 168 fisRenderjob.overrideSettings.shadowQuality = None 169 fisRenderjob.overrideSettings.reflectionQuality = None 170 fisRenderjob.PropagateSettings() 171 172 def GetStationItemID(self): 173 itemID = None 174 if hasattr(self, 'station') and self.station is not None: 175 if self.station.GetStationItem() is not None: 176 itemID = self.station.GetStationItem().itemID 177 return itemID 178 179 def SetUpModels(self): 180 self.activeShipModel = None 181 self.activeShipItem = self.GetShipItemFromHangar(session.shipid) 182 scMethods = hangar.GetHangarBehaviours(self.GetStationType(), self.GetActiveShipTypeID(), self.GetStationItemID()) 183 self.shipBehaviour = scMethods['ship']() 184 self.droneBehaviour = scMethods['drone']() 185 self.LoadAndSetupScene(self.GetActiveShipTypeID()) 186 self.UpdateActivityLevel() 187 188 def CleanUp(self): 189 self.layer.camera = None 190 self.sceneManager.UnregisterScene(ViewState.Hangar) 191 self.ClearScene() 192 193 def OnDocking(self): 194 uthread.new(self.ReplaceExistingShipModel, REPLACE_DOCK) 195 196 def OnSpinThresholdReached(self, spins): 197 if self.activeHangarModel is not None: 198 self.activeHangarModel.SetControllerVariable('spinCounter', spins) 199 200 def OnItemChangeProcessed(self, item, itemInfo): 201 if hasattr(self.shipBehaviour, 'OnItemChangeProcessed'): 202 self.shipBehaviour.OnItemChangeProcessed(item, itemInfo) 203 204 def OnHangarViewStateUpdated_Local(self, structureID, hangarViewState): 205 self.updateHangarState(hangarViewState) 206 207 def updateHangarState(self, hangarViewState = None): 208 if session.structureid is None or self.activeHangarModel is None: 209 return 210 if not hangar.isHangarModular(self.GetStationType(), self.GetActiveShipTypeID(), self.GetStationItemID()): 211 return 212 if hangarViewState is None: 213 svc = sm.GetService('structureHangarViewSvc') 214 if svc is None: 215 return 216 hangarViewState = svc.GetStructureHangarState() 217 self.shipBehaviour.UpdateStructureState(hangarViewState, self.activeHangarModel) 218 219 def OnHangarToHangar(self): 220 uthread.new(self.ReplaceExistingShipModel, REPLACE_DOCK, fade=False) 221 222 def LoadAndSetupScene(self, shipTypeID): 223 self._undocking_in_progress = False 224 itemID = self.GetStationItemID() 225 self.shipBehaviour.SetDockingEffectGraphicID(hangar.GetDockingEffectGraphicID(self.GetStationType(), self.GetActiveShipTypeID(), itemID)) 226 self.shipBehaviour.SetEnlistmentDockingEnabled(hangar.isEnlistmentDockingEnabled(self.GetStationType(), self.GetActiveShipTypeID(), itemID)) 227 isANewHangar = hangar.GetHangarType(self.GetStationType(), self.GetActiveShipTypeID(), itemID) != self.activeHangarType 228 if HangarView.HANGAR_TYPE_OVERRIDE is not None or isANewHangar or self.activeHangarScene is not None: 229 self.currentHangarGraphicID = hangar.GetHangarModelGraphicID(self.GetStationType(), shipTypeID, itemID) 230 self.activeHangarScene = self.LoadScene(shipTypeID, itemID) 231 self.activeHangarModel = self._LoadHangarModel(self.currentHangarGraphicID) 232 self.shipBehaviour.SetAnchorPoint(self.activeHangarModel, self.activeHangarScene) 233 self.activeHangarScene.objects.append(self.activeHangarModel) 234 self.activeHangarType = hangar.GetHangarType(self.GetStationType(), self.GetActiveShipTypeID(), itemID) 235 self.StartHangarAnimations(self.activeHangarScene) 236 uthread2.StartTasklet(self.updateCorruptionAndSuppressionStates) 237 self.updateHangarState() 238 self.restartHangarControllers = True 239 240 def updateCorruptionAndSuppressionStates(self): 241 if self.activeHangarModel is None: 242 return 243 try: 244 css = sm.GetService('corruptionSuppressionSvc') 245 if css is not None and hasattr(session, 'solarsystemid2'): 246 suppressionStage, corruptionStage = (0, 0) 247 maximumSuppressionStage = max(len(css.GetSuppressionStages()), 5) 248 maximumCorruptionStage = max(len(css.GetCorruptionStages()), 5) 249 corruptionStateData = css.GetCurrentSystemCorruption_Cached() 250 if corruptionStateData is not None: 251 corruptionStage = corruptionStateData.stage or 0 252 suppressionStateData = css.GetCurrentSystemSuppression_Cached() 253 if suppressionStateData is not None: 254 suppressionStage = suppressionStateData.stage or 0 255 suppression = float(suppressionStage) / float(maximumSuppressionStage) 256 corruption = float(corruptionStage) / float(maximumCorruptionStage) 257 self.activeHangarModel.SetControllerVariable('corruption', corruption) 258 self.activeHangarModel.SetControllerVariable('suppression', suppression) 259 if corruption > 0.0 or suppression > 0.0: 260 self.restartHangarControllers = True 261 except TimeoutException: 262 self.LogError('hangarView.updateCorruptionAndSuppressionStates: Timeout when getting corruption/suppression data') 263 264 def _LoadHangarModel(self, graphicID): 265 hangarModel = self._LoadSOFHangarModel(graphicID) 266 controllerOverrides = GetControllerVariableOverrides(graphicID, {}) 267 for name, value in controllerOverrides.iteritems(): 268 hangarModel.SetControllerVariable(name, float(value)) 269 270 return hangarModel 271 272 def StartHangarControllers(self): 273 if self.activeHangarModel: 274 try: 275 self.activeHangarModel.StartControllers() 276 except AttributeError: 277 pass 278 279 def _LoadSOFHangarModel(self, graphicID): 280 if IsTriglavianSystem(session.solarsystemid2) and session.stationid: 281 hull = GetSofHullName(graphicID) 282 stationGraphicId = cfg.mapSolarSystemContentCache.npcStations[session.stationid].graphicID 283 faction = GetSofFactionName(stationGraphicId) 284 race = GetSofRaceName(stationGraphicId) 285 hangarDna = '%s:%s:%s' % (hull, faction, race) 286 else: 287 typeID = self.GetStationType() 288 outerStationGID = GetGraphicID(typeID) 289 hull = GetSofHullName(graphicID) 290 faction = GetSofFactionName(outerStationGID) 291 race = GetSofRaceName(outerStationGID) 292 layouts = list(GetSofLayoutNames(graphicID)) 293 if is_low_sec_or_lower_solar_system(session.solarsystemid2) and PROPAGANDA_LAYOUT_NAME in layouts: 294 layouts.remove(PROPAGANDA_LAYOUT_NAME) 295 layoutString = '' 296 if layouts is not None and len(layouts) > 0: 297 layoutString = 'layout?' + ';'.join(layouts) 298 factionOverride = hangar.GetHangarFactionDataOverwrite(typeID, self.GetActiveShipTypeID(), self.GetStationItemID()) 299 if factionOverride is not None: 300 hangarDna = '%s:%s:%s:%s' % (hull, 301 factionOverride, 302 race, 303 layoutString) 304 else: 305 hangarDna = '%s:%s:%s:%s' % (hull, 306 faction, 307 race, 308 layoutString) 309 if hangarDna is None: 310 self.LogError('%s._LoadSOFHangar(graphicID = %s): Trying to show a SOF hangar that is not in the SOF, Loading up scene only' % (self, graphicID)) 311 return 312 return GetSofService().spaceObjectFactory.BuildFromDNA(hangarDna) 313 314 @telemetry.ZONE_METHOD 315 def LoadView(self, change = None, **kwargs): 316 self.station.CleanUp() 317 self.station.StopAllStationServices() 318 self.station.Setup() 319 self.SetUpModels() 320 self.skipDockingAnimation = not IsDynamicCameraMovementEnabled() 321 if 'lastView' in kwargs: 322 lastView = kwargs.get('lastView') 323 if lastView.name == 'structure': 324 self.skipDockingAnimation = True 325 View.LoadView(self, **kwargs) 326 327 def LoadCamera(self, cameraID = None, reopen = False): 328 cam = sm.GetService('sceneManager').SetPrimaryCamera(self.GetCameraID()) 329 if not hangar.isHangarCapital(self.GetStationType(), self.GetActiveShipTypeID(), self.GetStationItemID()): 330 camDist = 2050 331 if self.activeHangarModel and hasattr(self.activeHangarModel, 'locatorSets'): 332 maxCamDistanceLocatorSet = self.activeHangarModel.locatorSets.FindByName('maxCameraDistance') 333 if maxCamDistanceLocatorSet and len(maxCamDistanceLocatorSet.locators) > 0: 334 locatorPosition = maxCamDistanceLocatorSet.locators[0][0] 335 camDist = geo2.Vec3Length(locatorPosition) 336 cam.SetMinMaxZoomDefaults(camDist, 10.0) 337 self._ConfigureCameraDockingAnimation(cam) 338 if not reopen or self.activeShipModel is None: 339 self.ReplaceExistingShipModel(REPLACE_UPDATE, fade=True) 340 341 def GetCameraID(self): 342 isInStation = session.stationid or session.structureid 343 itemID = self.GetStationItemID() 344 if hangar.isHangarModular(self.GetStationType(), self.GetActiveShipTypeID(), itemID): 345 if hangar.isHangarCapital(self.GetStationType(), self.GetActiveShipTypeID(), itemID): 346 return evecamera.CAM_MODULARHANGAR_CAPITAL 347 else: 348 return evecamera.CAM_MODULARHANGAR 349 else: 350 if not isInStation or not hangar.isHangarCapital(self.GetStationType(), self.GetActiveShipTypeID(), itemID): 351 return evecamera.CAM_HANGAR 352 return evecamera.CAM_CAPITALHANGAR 353 354 @telemetry.ZONE_METHOD 355 def UnloadView(self): 356 self.CleanUp() 357 358 def ReloadView(self): 359 sm.GetService('viewState').ActivateView(ViewState.Hangar) 360 361 def ClearScene(self): 362 if self.shipBehaviour is not None: 363 self.shipBehaviour.CleanScene() 364 self.shipBehaviour = None 365 if self.activeHangarScene: 366 self.activeHangarScene.objects.removeAt(-1) 367 self.activeHangarScene.postprocess = None 368 self.activeHangarScene = None 369 self.activeHangarModel = None 370 self.activeShipModel = None 371 self._vfxMultiEffect = None 372 self.activeShipItem = None 373 self.shipBehaviour = None 374 self.droneBehaviour = None 375 self.activeHangarType = None 376 self.sceneNeedsApplying = False 377 self._fsbThread = None 378 self._retriggerableFadeFromBlackTasklet = None 379 380 def LoadScene(self, shipTypeID, itemID = None): 381 self.currentSceneGraphicID = hangar.GetHangarSceneGraphicID(self.GetStationType(), shipTypeID, itemID) 382 stationGraphicFile = GetGraphicFile(self.currentSceneGraphicID) 383 if stationGraphicFile is None: 384 self.LogError("Could not find a graphic file for graphicID '%s', returning and showing nothing" % self.currentSceneGraphicID) 385 if HangarView.HANGAR_TYPE_OVERRIDE is not None: 386 trinity.Load(stationGraphicFile, nonCached=True) 387 scene, _ = self.sceneManager.LoadScene(stationGraphicFile, registerKey=ViewState.Hangar, applyScene=False) 388 self.sceneNeedsApplying = True 389 if scene is not None: 390 if scene.postprocess is not None: 391 if scene.postprocess.fog.intensity is not None: 392 self.initialFogSceneSetting = scene.postprocess.fog.intensity 393 return scene 394 395 def fadeToFromBlack(self, fadeToBlack, isQuick = None): 396 if self._vfxMultiEffect is None: 397 return 398 if isQuick is not None: 399 self._vfxMultiEffect.SetControllerVariable('F2B_isQuick', float(isQuick)) 400 self._vfxMultiEffect.SetControllerVariable('F2B_isBlack', float(fadeToBlack)) 401 if self._retriggerableFadeFromBlackTasklet is not None: 402 self._retriggerableFadeFromBlackTasklet.kill() 403 self._retriggerableFadeFromBlackTasklet = None 404 405 def ReplaceExistingShipModel(self, eventType, fade = True, skipAnimation = False): 406 itemID = self.GetActiveShipItemID() 407 typeID = self.GetActiveShipTypeID() 408 if not itemID or not typeID: 409 return 410 if self._starting_boarding_moment: 411 fade = True 412 if hangar.isHangarModular(self.GetStationType(), typeID, self.GetStationItemID()): 413 self._ReplaceExistingShipModelModular(eventType, itemID, typeID, skipAnimation) 414 else: 415 newModel = self.shipBehaviour.LoadShipModel(itemID, typeID) 416 isTooBig = self.IsShipTooBigToAnimate(typeID) 417 if fade and (eventType == REPLACE_SWITCHSHIPS or isTooBig): 418 if not self._starting_boarding_moment: 419 self._FadeFromBlackHandler(0.5, True) 420 if self.activeShipModel: 421 self.RemoveModelWithNameFromScene(self.activeShipModel.name) 422 self.AddModelToScene(newModel) 423 else: 424 self.AddModelToScene(newModel) 425 self.GetCamera().SetShip(newModel, typeID) 426 if eventType == REPLACE_UPDATE or isTooBig or not IsDynamicCameraMovementEnabled(): 427 if fade and not self._starting_boarding_moment: 428 self._FadeFromBlackHandler(0.75, False) 429 self.shipBehaviour.PlaceShip(newModel, typeID) 430 self.shipBehaviour.PlaceReflectionProbe(self.activeHangarScene.reflectionProbe) 431 self.SetHangarControllerStates(HANGAR_DOCKING_STATE if IsDynamicCameraMovementEnabled() else HANGAR_DOCKED_STATE) 432 self.PlayUpdateShipSequence(fade) 433 elif eventType == REPLACE_DOCK: 434 duration = 12.0 435 self.shipBehaviour.AnimateShipEntry(newModel, typeID, duration=duration) 436 self.shipBehaviour.AnimateReflectionProbeEntry(self.activeHangarScene.reflectionProbe, duration) 437 self.SetHangarControllerStates(HANGAR_DOCKING_STATE) 438 self.PlayDockSequence(duration) 439 elif eventType == REPLACE_SWITCHSHIPS: 440 if skipAnimation: 441 self.shipBehaviour.PlaceShip(newModel, typeID) 442 else: 443 duration = 7.0 444 self.shipBehaviour.AnimateShipEntry(newModel, typeID, duration=duration) 445 self.shipBehaviour.AnimateReflectionProbeEntry(self.activeHangarScene.reflectionProbe, duration) 446 self.PlaySwitchShipSequence(duration) 447 self._SetUpLightingRig(self.activeShipModel) 448 if self.activeHangarScene: 449 shipSkinModels = GetModelsToBeRemovedFromScene(self.activeHangarScene) 450 for ship in shipSkinModels: 451 self.activeHangarScene.objects.remove(ship) 452 453 if self.activeShipModel is not None: 454 self.ConfigureVFXMultiEffect(eventType == REPLACE_DOCK) 455 if self.restartHangarControllers: 456 self.StartHangarControllers() 457 self.restartHangarControllers = False 458 459 def _FadeFromBlackHandler(self, delay, isQuick = None): 460 if self._retriggerableFadeFromBlackTasklet is not None: 461 self._retriggerableFadeFromBlackTasklet.kill() 462 self._retriggerableFadeFromBlackTasklet = call_after_simtime_delay(self.fadeToFromBlack, delay, False, isQuick) 463 464 def SetHangarControllerStates(self, dockingState): 465 self.activeHangarModel.SetControllerVariable('Docking_State', dockingState) 466 467 def IsShipTooBigToAnimate(self, typeID): 468 if hangar.isHangarCapital(self.GetStationType(), self.GetActiveShipTypeID(), self.GetStationItemID()): 469 return False 470 groupID = evetypes.GetGroupID(typeID) 471 return groupID in (invconst.groupSupercarrier, 472 invconst.groupTitan, 473 invconst.groupDreadnought, 474 invconst.groupForceAux, 475 invconst.groupLancerDreadnought) 476 477 def PlayDockSequence(self, duration): 478 endPos = self.shipBehaviour.GetAnimEndPosition() 479 startPos = self.shipBehaviour.GetAnimStartPosition() 480 camera = self.GetCamera() 481 camera.AnimEnterHangar(self.activeShipModel, startPos=startPos, endPos=endPos, duration=duration) 482 483 def GetCamera(self): 484 return sm.GetService('sceneManager').GetRegisteredCamera(self.GetCameraID()) 485 486 def GetAllDockedShips(self): 487 if hangar.isHangarModular(self.GetStationType(), self.GetActiveShipTypeID(), self.GetStationItemID()): 488 if hasattr(self.shipBehaviour, 'GetAllDockedShips'): 489 return self.shipBehaviour.GetAllDockedShips() 490 else: 491 return [self.activeShipModel] 492 493 def PlaySwitchShipSequence(self, duration): 494 endPos = self.shipBehaviour.GetAnimEndPosition() 495 startPos = self.shipBehaviour.GetAnimStartPosition() 496 camera = self.GetCamera() 497 camera.AnimSwitchShips(self.activeShipModel, startPos=startPos, endPos=endPos, duration=duration) 498 499 def PlayUpdateShipSequence(self, fade = True): 500 endPos = self.shipBehaviour.GetAnimEndPosition() 501 self.GetCamera().PlaceShip(endPos) 502 503 def StartHangarAnimations(self, scene): 504 for obj in scene.objects: 505 try: 506 children = obj.children 507 except AttributeError: 508 continue 509 510 for fx in children: 511 if fx.name.startswith('sfx_'): 512 fx.display = True 513 514 def ConfigureVFXMultiEffect(self, makeSceneBlack = False): 515 if self.activeHangarScene is None or self.activeHangarScene.postprocess is None: 516 return 517 if self._vfxMultiEffect is None: 518 self._vfxMultiEffect = trinity.Load(GetGraphicFile(hangar.HANGAR_VFX_TRIGGERS_MULTIEFFECT_GID)) 519 self.activeHangarScene.objects.append(self._vfxMultiEffect) 520 shaderQuality = gfxsettings.Get(gfxsettings.GFX_SHADER_QUALITY) 521 if self._vfxMultiEffect is not None and shaderQuality is not None: 522 self._vfxMultiEffect.SetControllerVariable('shaderQuality', int(shaderQuality) - 1) 523 if self._vfxMultiEffect is not None: 524 self._vfxMultiEffect.SetParameter('PostProcess', self.activeHangarScene.postprocess) 525 self._vfxMultiEffect.SetParameter('ship', self.activeShipModel) 526 self._vfxMultiEffect.SetParameter('Hangar', self.activeHangarModel) 527 if self.IsHangarModular(): 528 dock = self.shipBehaviour.GetActiveDock() 529 if dock is not None: 530 self._vfxMultiEffect.SetParameter('activeDock', dock) 531 shipTypeID = self.GetActiveShipTypeID() 532 hType = hangar.GetHangarIdentifier(self.GetStationType(), shipTypeID, self.GetStationItemID()) 533 self._vfxMultiEffect.SetControllerVariable('HangarType', float(hType)) 534 self._vfxMultiEffect.SetControllerVariable('initialSceneFog', float(self.initialFogSceneSetting)) 535 unique_moment_id = get_unique_moment_id(shipTypeID) 536 if unique_moment_id != 0.0: 537 shape_group = 0.0 538 else: 539 shape_group = get_ship_shape_group(shipTypeID, self.activeShipModel) 540 size_group = get_ship_size_group(shipTypeID, self.activeShipModel.GetBoundingSphereRadius()) 541 faction_group = get_ship_faction_group(shipTypeID) 542 self._vfxMultiEffect.SetControllerVariable('shipShape', float(shape_group)) 543 self._vfxMultiEffect.SetControllerVariable('ShipSize', float(size_group)) 544 self._vfxMultiEffect.SetControllerVariable('faction', float(faction_group)) 545 self._vfxMultiEffect.SetControllerVariable('SpecificShip', float(unique_moment_id)) 546 if makeSceneBlack: 547 self._vfxMultiEffect.SetControllerVariable('F2B_isBlack', 1.0) 548 for controller in self._vfxMultiEffect.controllers: 549 controller.Start() 550 551 for curveSet in self._vfxMultiEffect.curveSets: 552 curveSet.Play() 553 554 def RemoveModelWithNameFromScene(self, modelName): 555 if self.activeHangarScene: 556 modelToRemove = self.activeHangarScene.objects.FindByName(modelName) 557 if modelToRemove: 558 self.activeHangarScene.objects.remove(modelToRemove) 559 560 def AddModelToScene(self, model): 561 if self.activeHangarScene and model: 562 self.activeHangarScene.objects.append(model) 563 self.activeShipModel = model 564 self._SetUpLightingRig(self.activeShipModel) 565 enabledCosmetics = sm.GetService('cosmeticsSvc').get_enabled_ship_cosmetics(session.shipid) 566 uthread.new(self.cosmeticsLoader.SetCosmeticsOnShip, self.activeShipModel, enabledCosmetics) 567 568 def PreSkinChange(self, oldModel, newModel): 569 self.activeShipModel = newModel 570 571 def PostSkinChange(self, oldModel, newModel): 572 self._SetUpLightingRig(self.activeShipModel) 573 enabledCosmetics = sm.GetService('cosmeticsSvc').get_enabled_ship_cosmetics(session.shipid) 574 uthread.new(self.cosmeticsLoader.SetCosmeticsOnShip, self.activeShipModel, enabledCosmetics) 575 576 def _SetUpLightingRig(self, ship): 577 if self.activeHangarModel is None: 578 return 579 if hangar.isHangarModular(self.GetStationType(), self.GetActiveShipTypeID(), self.GetStationItemID()): 580 return 581 lightRigContainer = self.activeHangarModel.effectChildren.FindByName('ShipLights_Scaler') 582 typeID = self.GetActiveShipTypeID() 583 if ship is not None and lightRigContainer: 584 lightRigContainer.scaling = (ship.boundingSphereRadius, ship.boundingSphereRadius, ship.boundingSphereRadius) 585 shipCenter = self.shipBehaviour.GetShipCenter(ship, typeID) 586 lightRigContainer.translation = (lightRigContainer.translation[0], shipCenter[1], lightRigContainer.translation[2]) 587 588 def GetStationType(self): 589 if session.structureid: 590 if hasattr(self, 'invCache'): 591 return self.invCache.GetInventory(const.containerStructure).typeID 592 else: 593 stationItem = sm.GetService('station').stationItem 594 if stationItem is not None and hasattr(stationItem, 'stationTypeID'): 595 return sm.GetService('station').stationItem.stationTypeID 596 return 0 597 598 def GetShipItemFromHangar(self, shipID): 599 hangarInv = self.invCache.GetInventory(const.containerHangar) 600 hangarItems = hangarInv.List(const.flagHangar) 601 for each in hangarItems: 602 if each.itemID == shipID and each.categoryID == const.categoryShip: 603 return each 604 605 @telemetry.ZONE_METHOD 606 def StartExitAnimation(self): 607 self._undocking_in_progress = True 608 self._undocking_started_signal() 609 if hangar.isHangarModular(self.GetStationType(), self.GetActiveShipTypeID(), self.GetStationItemID()): 610 self.shipBehaviour.UpdateUndockStatus(1.0) 611 elif self.activeHangarModel is not None: 612 self.activeHangarModel.SetControllerVariable('Undock', 1.0) 613 self.activeHangarModel.SetControllerVariable('Docking_State', HANGAR_UNDOCKING_STATE) 614 if self.activeHangarScene is not None: 615 for curveSet in self.activeHangarScene.curveSets: 616 if curveSet.name == 'Undock': 617 curveSet.scale = 1.0 618 curveSet.PlayFrom(0.0) 619 break 620 621 @telemetry.ZONE_METHOD 622 def StopExitAnimation(self): 623 self._undocking_in_progress = False 624 if hangar.isHangarModular(self.GetStationType(), self.GetActiveShipTypeID(), self.GetStationItemID()): 625 self.shipBehaviour.UpdateUndockStatus(0.0) 626 else: 627 self.activeHangarModel.SetControllerVariable('Undock', 0.0) 628 self.activeHangarModel.SetControllerVariable('Docking_State', HANGAR_DOCKED_STATE) 629 if self.activeHangarScene is not None: 630 for curveSet in self.activeHangarScene.curveSets: 631 if curveSet.name == 'Undock': 632 curveSet.scale = -1.0 633 curveSet.PlayFrom(curveSet.GetMaxCurveDuration()) 634 break 635 636 def IsHangarModular(self): 637 return hangar.isHangarModular(self.GetStationType(), self.GetActiveShipTypeID(), self.GetStationItemID()) 638 639 def ProcessActiveShipChanged(self, shipID, oldShipID): 640 if shipID == oldShipID: 641 return 642 newShipItem = self.GetShipItemFromHangar(shipID) 643 if newShipItem is None: 644 return 645 self.activeShipItem = newShipItem 646 self._starting_boarding_moment = should_autoplay_boarding_moment(newShipItem.typeID) 647 if self.currentSceneGraphicID != hangar.GetHangarSceneGraphicID(self.GetStationType(), self.GetActiveShipTypeID(), self.GetStationItemID()): 648 self.ReloadView() 649 return 650 if self._starting_boarding_moment: 651 self.play_boarding_moment() 652 else: 653 if not self.IsHangarModular(): 654 self.fadeToFromBlack(True, True) 655 call_after_simtime_delay(self.ReplaceExistingShipModel, 0.2, REPLACE_SWITCHSHIPS) 656 657 def play_boarding_moment(self): 658 if self._undocking_in_progress: 659 return 660 uthread2.StartTasklet(self._play_boarding_moment) 661 662 def OnStanceActive(self, shipID, stanceID): 663 if shipID != session.shipid: 664 return 665 if self.activeShipModel is not None: 666 spaceobjanimation.SetShipAnimationStance(self.activeShipModel, stanceID) 667 668 def OnEndChangeDevice(self, *args): 669 self.shipBehaviour.PlaceReflectionProbe(self.activeHangarScene.reflectionProbe) 670 671 def OnGraphicSettingsChanged(self, *args): 672 self.shipBehaviour.PlaceReflectionProbe(self.activeHangarScene.reflectionProbe) 673 shaderQualityChanged = False 674 shadowQualityChanged = False 675 if len(args) > 0: 676 for each in args[0]: 677 shaderQualityChanged = shaderQualityChanged or 'shaderQuality' in each 678 shadowQualityChanged = shadowQualityChanged or 'shadowQuality' in each 679 680 if shaderQualityChanged: 681 currentView = sm.GetService('viewState').GetCurrentView() 682 if currentView is not None and currentView.name == 'hangar': 683 currentView.ReloadView() 684 685 def OnEndChangeDevice(self, *args): 686 pass 687 688 def DisableReflectionProbe(self): 689 sceneManager = sm.GetService('sceneManager') 690 fisRenderjob = sceneManager.GetFisRenderJob() 691 if fisRenderjob: 692 fisRenderjob.overrideSettings.reflectionQuality = gfxsettings.GFX_REFLECTION_QUALITY_OFF 693 fisRenderjob.PropagateSettings() 694 695 def DisableShadows(self): 696 sceneManager = sm.GetService('sceneManager') 697 fisRenderjob = sceneManager.GetFisRenderJob() 698 if fisRenderjob: 699 fisRenderjob.overrideSettings.shadowQuality = trinity.ShadowQuality.Disabled 700 fisRenderjob.PropagateSettings() 701 702 def OnActiveShipSkinChange(self, itemID, skinID, updateSkin = False, reloadSubsystems = False): 703 isModularHangar = hangar.isHangarModular(self.GetStationType(), self.GetActiveShipTypeID(), self.GetStationItemID()) 704 if updateSkin and (reloadSubsystems or self.shipBehaviour.ShouldSwitchSkin(skinID)) and itemID == session.shipid and itemID == self.GetActiveShipItemID() and self.activeShipModel: 705 if isModularHangar and evetypes.GetGroupID(self.GetActiveShipTypeID()) == const.groupTacticalDestroyer: 706 newShipModel = self.shipBehaviour.LoadShipModel(itemID, self.GetActiveShipTypeID(), skipSetupAnimation=True) 707 else: 708 newShipModel = self.shipBehaviour.LoadShipModel(itemID, self.GetActiveShipTypeID()) 709 if newShipModel is not None: 710 ChangeSkin(self.activeShipModel, newShipModel, self.activeHangarScene, self.PreSkinChange, self.PostSkinChange) 711 if isModularHangar: 712 self.shipBehaviour.ProcessSkinChange(newShipModel) 713 if self._vfxMultiEffect is not None: 714 self._vfxMultiEffect.SetControllerVariable('skipNextEntryAnimation', 1.0) 715 self.ConfigureVFXMultiEffect() 716 717 def OnShipCosmeticsChanged(self, ship_id, cosmetics_types): 718 stationType = self.GetStationType() 719 if stationType is 0 or not hasattr(self, 'station'): 720 return 721 if not hangar.isHangarModular(stationType, self.GetActiveShipTypeID(), self.GetStationItemID()): 722 uthread.new(self.cosmeticsLoader.SetCosmeticsOnShip, self.activeShipModel, cosmetics_types) 723 elif hasattr(self.shipBehaviour, 'OnShipCosmeticsChanged'): 724 self.shipBehaviour.OnShipCosmeticsChanged(ship_id, cosmetics_types) 725 726 def OnCorpLogoReady(self, _corpID, _size): 727 if not hangar.isHangarModular(self.GetStationType(), self.GetActiveShipTypeID(), self.GetStationItemID()): 728 self._UpdateShipCosmetics() 729 730 def OnAllianceLogoReady(self, _allianceID, _size): 731 if not hangar.isHangarModular(self.GetStationType(), self.GetActiveShipTypeID(), self.GetStationItemID()): 732 self._UpdateShipCosmetics() 733 734 def OnSessionChanged(self, _isremote, _session, change): 735 if not hangar.isHangarModular(self.GetStationType(), self.GetActiveShipTypeID(), self.GetStationItemID()): 736 if 'corpid' in change or 'allianceid' in change: 737 self._UpdateShipCosmetics() 738 739 def _UpdateShipCosmetics(self): 740 enabledCosmetics = sm.GetService('cosmeticsSvc').get_enabled_ship_cosmetics(session.shipid) 741 self.OnShipCosmeticsChanged(session.shipid, enabledCosmetics) 742 743 def OnDamageStateChanged(self, itemID, _attributeID, _newValue, _oldValue): 744 if self.GetActiveShipItemID() == itemID: 745 if self.droneBehaviour.GetDronesActive(): 746 self.droneBehaviour.StartRepairDroneSequence(itemID, self.activeShipModel, self.shipBehaviour) 747 else: 748 triggerDrones = self.shipBehaviour.SetShipDamage(itemID, self.activeShipModel) 749 if triggerDrones and self._vfxMultiEffect: 750 self._vfxMultiEffect.SetControllerVariable('triggerRepairDrones', 1.0) 751 752 def OnRepairDone(self, itemIDs): 753 if hasattr(self.shipBehaviour, 'OnShipsRepaired'): 754 self.shipBehaviour.OnShipsRepaired(itemIDs) 755 if session.shipid in itemIDs: 756 if self.droneBehaviour.GetSeekTargetData(self.activeHangarModel): 757 self.droneBehaviour.SetDronesActive(True) 758 759 def OnDirtLevelChanged(self, itemID): 760 if self.GetActiveShipItemID() == itemID: 761 self.shipBehaviour.SetShipDirtLevel(itemID, self.activeShipModel) 762 763 def OnDogmaItemChange(self, item, change): 764 if item.locationID == change.get(const.ixLocationID, None) and item.flagID == change.get(const.ixFlag): 765 return 766 if IsSubsystemFlagVisible(item.flagID): 767 if self.activeShipItem.itemID is not item.itemID: 768 self.OnActiveShipSkinChange(self.GetActiveShipItemID(), None, updateSkin=True, reloadSubsystems=True) 769 elif self.activeShipItem and self.activeShipModel is not None: 770 self.shipBehaviour.FitTurrets(self.activeShipItem.itemID, self.activeShipItem.typeID, self.activeShipModel) 771 772 def OnDogmaAttributeChanged(self, shipID, itemID, attributeID, value): 773 if shipID != session.shipid or attributeID != const.attributeIsOnline: 774 return 775 dogmaLocation = sm.GetService('clientDogmaIM').GetDogmaLocation() 776 if itemID not in dogmaLocation.dogmaItems: 777 return 778 dogmaItem = dogmaLocation.dogmaItems[itemID] 779 self.shipBehaviour.UpdateTurretState(dogmaItem) 780 781 def UpdateActivityLevel(self): 782 activityLevel = self._GetActivityLevel(len(self.station.guests)) 783 if self.activeHangarModel is not None: 784 self.activeHangarModel.SetControllerVariable('activityLevel', activityLevel) 785 if is_high_sec_or_higher_solar_system(session.solarsystemid2): 786 self.activeHangarModel.SetControllerVariable('enablePropaganda', 1.0) 787 788 def _GetActivityLevel(self, numGuests): 789 itemID = self.GetStationItemID() 790 midTH, highTH = hangar.GetHangarMidAndHighActivityThresholds(self.GetStationType(), self.GetActiveShipTypeID(), itemID) 791 if numGuests > highTH: 792 return ACTIVITY_LEVEL_HIGH 793 elif numGuests > midTH: 794 return ACTIVITY_LEVEL_MID 795 else: 796 return ACTIVITY_LEVEL_LOW 797 798 def _ConfigureCameraDockingAnimation(self, cam): 799 800 def _pickRandomAnim(mapping): 801 if len(mapping) < 1: 802 self.LogError('Hangar camera dock-animation mapping is misconfigured. defaulting to the basic dock') 803 return None 804 totalWeight = 0 805 thresholds = [] 806 for each in mapping: 807 if len(each) != 8: 808 self.LogError('Hangar camera dock-animation mapping is misconfigured. defaulting to the basic dock') 809 return None 810 totalWeight += each[0] 811 thresholds.append(totalWeight) 812 813 if totalWeight < 1: 814 return None 815 randomNbr = random.randint(0, totalWeight - 1) 816 i = 0 817 for i, t in enumerate(thresholds): 818 if randomNbr < t: 819 break 820 821 return mapping[i][1:8] 822 823 itemID = None 824 if self.station.GetStationItem() is not None: 825 itemID = self.station.GetStationItem().itemID 826 mapping = hangar.GetHangarDockCameraMapping(self.GetStationType(), self.GetActiveShipTypeID(), itemID) 827 c = _pickRandomAnim(mapping) 828 if c is not None and len(c) == 7: 829 cam.SetHangarAnimationParameters(tuple(c[0:2]), tuple(c[2:4]), tuple(c[4:6]), c[6]) 830 831 def _ReplaceExistingShipModelModular(self, eventType, itemID, typeID, skipAnimation): 832 if eventType == REPLACE_DOCK: 833 if not self._starting_boarding_moment: 834 self._FadeFromBlackHandler(0.5, False) 835 camera = self.GetCamera() 836 self.SetHangarControllerStates(HANGAR_DOCKING_STATE) 837 camera.AnimEnterHangar(self.activeShipModel, None, None) 838 if not self.shipBehaviour.IsInitialized(): 839 eventType = REPLACE_UPDATE 840 self.LogWarn('hangarView._ReplaceExistingShipModelModular: swap event received before initial load') 841 if eventType == REPLACE_UPDATE: 842 hangarItems = [] 843 if self.invCache is not None: 844 hangarInv = self.invCache.GetInventory(const.containerHangar) 845 hangarItems = hangarInv.List(const.flagHangar) 846 listOfOtherShips = [] 847 for each in hangarItems: 848 if each.categoryID == const.categoryShip: 849 if hasattr(each, 'singleton') and each.singleton: 850 listOfOtherShips.append(self.GetShipItemFromHangar(each.itemID)) 851 852 self.shipBehaviour.UpdateActiveShipIDs(self.GetActiveShipTypeID(), self.GetActiveShipItemID()) 853 self.shipBehaviour.populateDocksWithInventoryShips(listOfOtherShips, self.activeHangarScene, self.activeHangarModel) 854 ship = self.shipBehaviour.PlaceShip(itemID, typeID, self.skipDockingAnimation) 855 if ship is not None and self.activeShipModel is not None: 856 if ship.name == self.activeShipModel.name: 857 self.activeShipModel = ship 858 return 859 self.GetCamera().AnimEnterHangar(ship, None, None) 860 if not self._starting_boarding_moment: 861 self._FadeFromBlackHandler(0.5, False) 862 self.activeShipModel = ship 863 elif eventType == REPLACE_SWITCHSHIPS: 864 self.shipBehaviour.UpdateActiveShipIDs(self.GetActiveShipTypeID(), self.GetActiveShipItemID()) 865 ship = self.shipBehaviour.PlaceShip(itemID, typeID, self.skipDockingAnimation or skipAnimation) 866 self.activeShipModel = ship 867 if self.activeHangarModel is not None: 868 for each in self.activeHangarModel.controllers: 869 each.HandleEvent('platform_switch_audio') 870 871 def _play_boarding_moment(self): 872 ui_controller = BoardingUIController() 873 bmSvc = GetBoardingMomentService() 874 bmSvc.is_playing = True 875 sm.GetService('ui').SetUiToggleState(False) 876 sm.GetService('ui').HideUi(duration=1.0, except_layers=[ui_controller.get_layer()]) 877 command_blocker = CommandBlockerService.instance() 878 block_token = command_blocker.block(['cmd.category.window', 'window', 'menucore']) 879 self.fadeToFromBlack(True, True) 880 if self._vfxMultiEffect: 881 self._vfxMultiEffect.SetControllerVariable('firstShipBoarding_ME', 1.0) 882 self._vfxMultiEffect.SetControllerVariable('MomentSteps', 0.0) 883 uthread2.sleep(1.0) 884 self.ReplaceExistingShipModel(REPLACE_SWITCHSHIPS, skipAnimation=True) 885 trinity.WaitForResourceLoads() 886 moments, shape_group, size_group, faction_group, unique_moment_id = get_boarding_moment_details(self.GetActiveShipTypeID(), self.activeShipModel) 887 if not moments or self._undocking_in_progress: 888 ui_controller.Close() 889 sm.GetService('ui').SetUiToggleState(True) 890 sm.GetService('ui').ShowUi(duration=1.0) 891 block_token.dispose() 892 bmSvc.is_playing = False 893 if self._vfxMultiEffect: 894 self._vfxMultiEffect.SetControllerVariable('MomentSteps', 0.0) 895 self._vfxMultiEffect.SetControllerVariable('fsbSkip', 1.0) 896 return 897 if self._vfxMultiEffect: 898 self._vfxMultiEffect.SetControllerVariable('firstShipBoarding_ME', 1.0) 899 self._vfxMultiEffect.SetControllerVariable('MomentSteps', 0.0) 900 self._vfxMultiEffect.SetControllerVariable('shipShape', float(shape_group)) 901 self._vfxMultiEffect.SetControllerVariable('ShipSize', float(size_group)) 902 self._vfxMultiEffect.SetControllerVariable('faction', float(faction_group)) 903 self._vfxMultiEffect.SetControllerVariable('SpecificShip', float(unique_moment_id)) 904 oldNebulaIntensity = 1.0 905 oldReflectionIntensity = 1.0 906 if self.activeHangarScene: 907 oldNebulaIntensity = self.activeHangarScene.nebulaIntensity 908 oldReflectionIntensity = self.activeHangarScene.reflectionIntensity 909 self.activeHangarScene.nebulaIntensity = 0.2 910 self.activeHangarScene.reflectionIntensity = 0.1 911 bmSvc.SetSeen(self.GetActiveShipTypeID()) 912 scene_manager = sm.GetService('sceneManager') 913 scene_manager.UnregisterCamera(evecamera.CAM_VCS_CONSUMER) 914 vcs_camera = scene_manager.GetVirtualCamera() 915 vcs_camera.vcsInterface.SetScene(self.activeHangarScene) 916 ui_controller.SetContext(context={'typeID': self.GetActiveShipTypeID(), 917 'shape': shape_group, 918 'size': size_group, 919 'model': self.activeShipModel, 920 'moments': moments}) 921 922 def _offset_camera_by_locator(camera, locator_name): 923 if not locator_name: 924 return 925 camera_offset_pos = camera.positionBehaviours.FindByName('Offset') 926 camera_offset_poi = camera.pointOfInterestBehaviours.FindByName('Offset') 927 if not camera_offset_pos and not camera_offset_poi: 928 return 929 locator = self.activeShipModel.locators.FindByName(locator_name) 930 if locator and camera_offset_pos: 931 camera_offset_pos.offset = locator.transform[3][:3] 932 if locator and camera_offset_poi: 933 camera_offset_poi.offset = locator.transform[3][:3] 934 935 def _offset_camera_by_model_position(camera, offset): 936 camera_offset_pos = camera.positionBehaviours.FindByName('BoundingSphereOffset') 937 camera_offset_poi = camera.pointOfInterestBehaviours.FindByName('BoundingSphereOffset') 938 if camera_offset_pos: 939 camera_offset_pos.offset = offset 940 if camera_offset_poi: 941 camera_offset_poi.offset = offset 942 943 def _handle_cleanup(): 944 self._undocking_started_signal.disconnect(do_skip) 945 if self.GetCameraID() == evecamera.CAM_MODULARHANGAR: 946 self.GetCamera().SetShip(self.activeShipModel, self.GetActiveShipTypeID(), changingShip=False) 947 else: 948 self.GetCamera().SetShip(self.activeShipModel, self.GetActiveShipTypeID()) 949 if self._vfxMultiEffect: 950 self._vfxMultiEffect.SetControllerVariable('MomentSteps', 0.0) 951 self._vfxMultiEffect.SetControllerVariable('fsbSkip', 1.0) 952 scene_manager.SwitchFromVirtualCamera() 953 scene_manager.UnregisterCamera(vcs_camera.cameraID) 954 self.activeHangarScene.nebulaIntensity = oldNebulaIntensity 955 self.activeHangarScene.reflectionIntensity = oldReflectionIntensity 956 if hasattr(self.activeShipModel, 'observers'): 957 obs = self.activeShipModel.observers.FindByName('ship_sfx') 958 if obs is not None: 959 obs.observer.SendEvent('shipsounds_stop', True) 960 self.fadeToFromBlack(False, False) 961 skip_controller.Stop() 962 ui_controller.Close() 963 sm.GetService('ui').SetUiToggleState(True) 964 sm.GetService('ui').ShowUi(duration=1.0) 965 block_token.dispose() 966 if self.IsHangarModular(): 967 self.shipBehaviour.FinishFSB() 968 bmSvc.is_playing = False 969 970 def do_skip(): 971 _fsbThread.Kill() 972 _handle_cleanup() 973 974 def handle_fsb(): 975 soundID = evetypes.GetSoundID(self.GetActiveShipTypeID()) 976 fadedSleepDuration = 0.2 977 if soundID is not None: 978 soundUrl = GetSoundEventName(soundID) 979 if hasattr(self.activeShipModel, 'observers'): 980 obs = self.activeShipModel.observers.FindByName('ship_sfx') 981 if obs is not None: 982 obs.observer.SendEvent(unicode(soundUrl), True) 983 else: 984 newObserver = CreateAudioObserver('ship_sfx') 985 self.activeShipModel.observers.append(newObserver) 986 uthread2.sleep(0.1) 987 fadedSleepDuration = 0.1 988 newObserver.observer.SendEvent(unicode(soundUrl), True) 989 uthread2.sleep(fadedSleepDuration) 990 if self.IsHangarModular(): 991 self.shipBehaviour.PrepareFSB(self._vfxMultiEffect) 992 modelOffset = getattr(self.activeShipModel, 'boundingSphereCenter', (0.0, 0.0, 0.0)) 993 modelOffset = geo2.Vec3Scale(modelOffset, -1.0) 994 self.activeShipModel.clipSphereFactor = 0.001 995 scene_manager.SwitchToVirtualCamera() 996 for i, moment in enumerate(moments): 997 res_path = moment['camera'] 998 try: 999 camera = vcs_camera.vcsInterface.AddCameraFromFile(res_path) 1000 except Exception as exception: 1001 log.exception('Boarding Moment - error loading camera {}'.format(res_path)) 1002 continue 1003 1004 camera.positionAnchors.extend([self.activeShipModel]) 1005 camera.pointOfInterestAnchors.extend([self.activeShipModel]) 1006 _offset_camera_by_locator(camera, moment.get('locator', None)) 1007 _offset_camera_by_model_position(camera, modelOffset) 1008 vcs_camera.vcsInterface.LerpToCamera(camera, 0) 1009 animationLength = camera.animationTimelineLength 1010 if self._vfxMultiEffect: 1011 self._vfxMultiEffect.SetControllerVariable('MomentSteps', moment['step']) 1012 self._vfxMultiEffect.SetControllerVariable('boardingStepDuration', animationLength) 1013 ui_controller.TriggerStep(moment, animationLength) 1014 uthread2.sleep(animationLength) 1015 1016 vcs_camera.vcsInterface.LerpToCamera(vcs_camera.vcsInterface.externalCamera, 0) 1017 scene_manager.SnapLastCameraToVirtualCamera() 1018 _handle_cleanup() 1019 1020 if self._fsbThread is not None: 1021 self._fsbThread.Kill() 1022 _fsbThread = uthread2.start_tasklet(handle_fsb) 1023 self._fsbThread = _fsbThread 1024 skip_controller = SkipController(skip_func=do_skip) 1025 self._undocking_started_signal.connect(do_skip) 1026 skip_controller.Start(ui_controller.get_layer()) 1027 self._starting_boarding_moment = False