baseHangarBehaviours.py (13797B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\view\hangarBehaviours\baseHangarBehaviours.py 2 from __future__ import absolute_import 3 import evetypes 4 import trinity 5 import logging 6 import geo2 7 import uthread2 8 from cosmetics.common.ships.skins.static_data.skin_type import ShipSkinType 9 from fsdBuiltData.common.graphicIDs import GetSofFactionName 10 from inventorycommon.util import GetSubSystemTypeIDs 11 import evegraphics.utils as gfxutils 12 from eve.common.script.net import eveMoniker 13 from eveSpaceObject.spaceobjanimation import SetShipAnimationStance, TriggerDefaultStates 14 from eve.client.script.ui.inflight.shipstance import get_ship_stance 15 from eve.client.script.environment.model.turretSet import TurretSet 16 from eve.client.script.environment.sofService import GetSofService 17 from eve.client.script.environment.spaceObject.cosmeticsManager import CosmeticsManager 18 from evegraphics.CosmeticsLoader import CosmeticsLoader 19 from . import modularHangarBehavioursConstants as hConst 20 log = logging.getLogger(__name__) 21 22 class BaseHangarShipBehaviour(object): 23 MIN_SHIP_BOBBING_TIME = 10 24 MAX_SHIP_BOBBING_TIME = 300 25 MIN_SHIP_BOBBING_HALF_DISTANCE = 100 26 27 def __init__(self): 28 self._activeMaterialSetID = None 29 self._activeSkinID = None 30 self.log = log 31 self.shipAnchorPoint = (0.0, 0.0, 0.0) 32 self.shipSwitchingInProcess = False 33 self.turretSets = {} 34 self.cosmeticsLoader = CosmeticsLoader((CosmeticsLoader.ALLIANCE, CosmeticsLoader.CORP)) 35 36 def LoadShipModel(self, itemID, typeID): 37 self.shipSwitchingInProcess = True 38 model = self._LoadSOFShipModel(itemID, typeID) 39 model.name = str(itemID) 40 model.FreezeHighDetailMesh() 41 self.SetShipDirtLevel(itemID, model) 42 self.SetShipKillCounter(itemID, model) 43 self.SetupShipAnimation(model, typeID, itemID) 44 self.SetShipDamage(itemID, model) 45 self.FitTurrets(itemID, typeID, model) 46 self.SetInHangarVariables(model) 47 self.shipSwitchingInProcess = False 48 return model 49 50 def CleanScene(self): 51 self.turretSets = None 52 53 def _LoadSOFShipModel(self, itemID, typeID): 54 self._activeSkinID = None 55 self._activeMaterialSetID = None 56 skin_state = self.GetShipSkinState(itemID, typeID) 57 if skin_state: 58 if skin_state.skin_type == ShipSkinType.THIRD_PARTY_SKIN: 59 thirdPartyDNA = CosmeticsManager.CreateSOFDNAfromSkinState(skin_state, typeID) 60 ship = GetSofService().spaceObjectFactory.BuildFromDNA(thirdPartyDNA) 61 CosmeticsManager.UpdatePatternProjectionParametersFromSkinState(skin_state, ship, typeID) 62 blend_mode = skin_state.skin_data.slot_layout.pattern_blend_mode 63 if blend_mode is not None: 64 CosmeticsManager.SetBlendMode(ship, blendMode=blend_mode) 65 return ship 66 if skin_state.skin_type == ShipSkinType.FIRST_PARTY_SKIN: 67 self._activeSkinID = skin_state.skin_data.skin_id 68 self._activeMaterialSetID = sm.GetService('cosmeticsSvc').GetFirstPartySkinMaterialSetID(self._activeSkinID) 69 elif skin_state.skin_type == ShipSkinType.NO_SKIN: 70 pass 71 shipDna = gfxutils.BuildSOFDNAFromTypeID(typeID, materialSetID=self._activeMaterialSetID, multiHullTypeIDList=GetSubSystemTypeIDs(itemID, typeID)) 72 if shipDna is None: 73 self.log.error('%s._LoadSOFShip(itemID = %s, typeID = %s): Trying to show a SOF ship that is not in the SOF' % (self, itemID, typeID)) 74 return 75 return GetSofService().spaceObjectFactory.BuildFromDNA(shipDna) 76 77 def SetupShipAnimation(self, model, typeID, itemID): 78 if model is None: 79 return 80 if not evetypes.Exists(typeID): 81 return 82 SetShipAnimationStance(model, get_ship_stance(itemID, typeID)) 83 TriggerDefaultStates(model) 84 85 def SetShipDirtLevel(self, itemID, model): 86 dirtTimeStamp = eveMoniker.GetShipAccess().GetDirtTimestamp(itemID) 87 dirtLevel = gfxutils.CalcDirtLevelFromAge(dirtTimeStamp) 88 model.dirtLevel = dirtLevel 89 90 def SetShipKillCounter(self, itemID, model): 91 killCounter = sm.RemoteSvc('shipKillCounter').GetItemKillCountPlayer(itemID) 92 model.displayKillCounterValue = min(killCounter, 999) 93 94 def SetShipDamage(self, itemID, model, steps = 1, duration = 0.1): 95 dogmaLocation = sm.GetService('clientDogmaIM').GetDogmaLocation() 96 dogmaLocation.LoadItem(itemID) 97 shipState = dogmaLocation.GetDamageStateEx(itemID) 98 if shipState is None: 99 self.log.error('%s.SetShipDamage(itemID = %s, model = %s): Got no shipstate from dogma', self, itemID, model) 100 return False 101 shieldState, armorState, hullState = shipState 102 if isinstance(shieldState, tuple): 103 shieldState = shieldState[0] 104 if model is not None: 105 if model.impactOverlay is not None: 106 damage = model.impactOverlay.hullDamageFactor 107 if damage > 0.1 and armorState > 0.99 and hullState > 0.99: 108 uthread2.start_tasklet(self.ImpactUpdateThread, model) 109 return True 110 model.SetImpactDamageState(shieldState, armorState, hullState, True) 111 return False 112 113 def ImpactUpdateThread(self, model): 114 if model.impactOverlay is None: 115 self.log.error('ImpactUpdateThread: impactOverlay not initialized on hull') 116 return 117 overlay = model.impactOverlay 118 originalHullDamageState = overlay.GetLastDamageState() 119 hullProgress = originalHullDamageState[2] 120 armorProgress = originalHullDamageState[1] 121 shieldState = originalHullDamageState[0] 122 initialProgress = hullProgress + armorProgress 123 stepSize = (2.0 - initialProgress) / hConst.REPAIR_DRONES_REPAIR_DURATION 124 uthread2.sleep(hConst.REPAIR_DRONES_START_DELAY) 125 overlay.hullRepairing.fading = hConst.REPAIR_DRONE_HULL_REPAIR_EFFECT_SPEED[0] 126 overlay.armorRepairing.fading = hConst.REPAIR_DRONE_ARMOR_REPAIR_EFFECT_SPEED[0] 127 while hullProgress < 1.0: 128 if model is None: 129 return 130 model.SetImpactDamageState(shieldState, armorProgress, min(hullProgress, 1.0), True) 131 uthread2.sleep(1.0) 132 hullProgress += stepSize 133 134 overlay.hullRepairing.fading = hConst.REPAIR_DRONE_HULL_REPAIR_EFFECT_SPEED[1] 135 overlay.armorRepairing.fading = hConst.REPAIR_DRONE_ARMOR_REPAIR_EFFECT_SPEED[1] 136 while armorProgress < 0.8: 137 if model is None: 138 return 139 model.SetImpactDamageState(1.0, armorProgress, 1.0, True) 140 uthread2.sleep(1.0) 141 armorProgress += stepSize 142 143 overlay.armorRepairing.fading = hConst.REPAIR_DRONE_ARMOR_REPAIR_EFFECT_SPEED[2] 144 while armorProgress < 1.0: 145 if model is None: 146 return 147 model.SetImpactDamageState(1.0, armorProgress, 1.0, True) 148 uthread2.sleep(1.0) 149 armorProgress += stepSize 150 151 model.SetImpactDamageState(1.0, 1.0, 1.0, True) 152 153 def FitTurrets(self, itemID, typeID, model): 154 graphicID = evetypes.GetGraphicID(typeID) 155 sofFactionName = GetSofFactionName(graphicID) 156 self.turretSets = TurretSet.FitTurrets(itemID, model, sofFactionName) 157 self._SetHighLodForTurrets(model) 158 159 def SetInHangarVariables(self, model): 160 if model is None: 161 return 162 model.SetControllerVariable('inHangar', 1.0) 163 164 def UpdateTurretState(self, dogmaItem): 165 if dogmaItem.itemID not in self.turretSets: 166 return 167 turret = self.turretSets[dogmaItem.itemID] 168 if dogmaItem.IsOnline(): 169 turret.Online() 170 else: 171 turret.Offline() 172 173 def _SetHighLodForTurrets(self, model): 174 for turretSet in model.turretSets: 175 turretSet.FreezeHighDetailLOD() 176 177 def GetShipSkinState(self, itemID, typeID): 178 return sm.GetService('cosmeticsSvc').GetAppliedSkinState(session.charid, itemID) 179 180 def ShouldSwitchSkin(self, skinID): 181 return skinID != getattr(self._activeSkinID, 'skinID', None) and not self.shipSwitchingInProcess 182 183 def GetLocatorsFromSet(self, model, locatorSetName): 184 if model is None: 185 return [] 186 return model.GetTransformedLocatorsFromSet(locatorSetName) 187 188 def SetAnchorPoint(self, hangarModel, hangarScene): 189 raise NotImplementedError("%s does not implement 'SetAnchorPoint'", self) 190 191 def PlaceShip(self, model, typeID): 192 raise NotImplementedError("%s does not implement 'PlaceShip'", self) 193 194 def GetShipCenter(self, model, typeID): 195 raise NotImplementedError("%s does not implement 'GetShipCenter'", self) 196 197 def AnimateShipEntry(self, model, typeID, scene = None, duration = 5.0): 198 self.PlaceShip(model, typeID) 199 200 def AnimateReflectionProbeEntry(self, reflectionProbe, duration = 5.0): 201 self.PlaceReflectionProbe(reflectionProbe) 202 203 def PlaceReflectionProbe(self, reflectionProbe): 204 if reflectionProbe: 205 reflectionProbe.lockPosition = True 206 reflectionProbe.position = self.shipAnchorPoint 207 208 def ApplyShipBobbing(self, model, initialPosition, deltaPosition, cycleLengthInSec): 209 curve = trinity.Tr2CurveVector3() 210 topPosition = geo2.Vec3Add(initialPosition, deltaPosition) 211 bottomPosition = geo2.Vec3Subtract(initialPosition, deltaPosition) 212 curve.AddKey(0.0, initialPosition, trinity.Tr2CurveInterpolation.HERMITE) 213 curve.AddKey(0.25 * cycleLengthInSec, bottomPosition, trinity.Tr2CurveInterpolation.HERMITE) 214 curve.AddKey(0.75 * cycleLengthInSec, topPosition, trinity.Tr2CurveInterpolation.HERMITE) 215 curve.AddKey(1.0 * cycleLengthInSec, initialPosition, trinity.Tr2CurveInterpolation.HERMITE) 216 curve.x.extrapolationAfter = trinity.Tr2CurveExtrapolation.CYCLE 217 curve.y.extrapolationAfter = trinity.Tr2CurveExtrapolation.CYCLE 218 curve.z.extrapolationAfter = trinity.Tr2CurveExtrapolation.CYCLE 219 model.modelTranslationCurve = trinity.Tr2TranslationAdapter() 220 model.modelTranslationCurve.curve = curve 221 222 223 class BaseHangarShipDroneBehaviour(object): 224 225 def __init__(self): 226 self.dronesActive = False 227 self.seekTargetBehaviourData = None 228 self.collisionAvoidanceBehaviourData = None 229 self.repairDroneBehaviourGroup = None 230 self.hasEllipsoid = False 231 232 def Setup(self, hangarModel, shipModel): 233 self.repairDroneBehaviourGroup = self.GetRepairDroneBehaviourGroup(hangarModel) 234 self.seekTargetBehaviourData = self.GetSeekTargetData(self.repairDroneBehaviourGroup) 235 self.collisionAvoidanceBehaviourData = self.GetCollisionAvoidanceData(hangarModel) 236 if self.seekTargetBehaviourData: 237 self.seekTargetBehaviourData.ResetBehavior() 238 self.SetRepairDroneCount(shipModel.boundingSphereRadius) 239 self.dronesActive = False 240 241 def SplitBoundingBox(self): 242 if self.seekTargetBehaviourData: 243 self.seekTargetBehaviourData.SplitBoundingBox() 244 245 def GetSeekTargetData(self, repairDroneBehaviourGroup): 246 behavior = repairDroneBehaviourGroup.Find('trinity.SeekTarget') 247 for data in behavior: 248 return data 249 250 def GetCollisionAvoidanceData(self, hangarModel): 251 behavior = hangarModel.Find('trinity.CollisionAvoidance') 252 for data in behavior: 253 return data 254 255 def GetRepairDroneBehaviourGroup(self, hangarModel): 256 behaviorGroups = hangarModel.Find('trinity.BehaviorGroup') 257 for each in behaviorGroups: 258 if each.name == 'RepairDrone': 259 return each 260 261 def GetShipArmorImpactLifeTime(self, shipModel): 262 return shipModel.impactOverlay.GetArmorImpactLifeTime() 263 264 def GetDronesActive(self): 265 return self.dronesActive 266 267 def SetDronesActive(self, value): 268 self.dronesActive = value 269 self.seekTargetBehaviourData.SetupShipRepair() 270 271 def SetTarget(self, shipModel): 272 self.seekTargetBehaviourData.SetTarget(shipModel) 273 274 def SetExit(self): 275 if self.seekTargetBehaviourData: 276 self.seekTargetBehaviourData.SetExit(True) 277 self.dronesActive = False 278 279 def StartRepairDroneSequence(self, itemID, shipModel, shipBehaviour): 280 self.SetEllipsoidVolume(shipModel) 281 self.SetTarget(shipModel) 282 if shipModel.boundingSphereRadius >= 2250: 283 self.SplitBoundingBox() 284 sec = self.GetShipArmorImpactLifeTime(shipModel) 285 if self.seekTargetBehaviourData: 286 self.seekTargetBehaviourData.SetTotalRepairTime(sec) 287 self.seekTargetBehaviourData.onFirstDroneArrivedCallback = lambda : self.StartEffectAndTimer(itemID, shipModel, shipBehaviour) 288 289 def StartEffectAndTimer(self, itemID, shipModel, shipBehaviour): 290 shipBehaviour.SetShipDamage(itemID, shipModel) 291 292 def SetRepairDroneCount(self, boundingRadius): 293 raise NotImplementedError("%s does not implement 'SetCount'", self) 294 295 def SetEllipsoidVolume(self, shipModel): 296 if self.collisionAvoidanceBehaviourData and self.seekTargetBehaviourData: 297 volume = trinity.EveEllipsoidVolume() 298 scale = 1.5 299 volume.shape = (shipModel.shapeEllipsoidRadius[0] * scale, shipModel.shapeEllipsoidRadius[1] * scale, shipModel.shapeEllipsoidRadius[2] * scale) 300 volume.innerShape = shipModel.shapeEllipsoidRadius 301 volume.position = shipModel.translationCurve.value 302 self.collisionAvoidanceBehaviourData.exclusionVolumes[0] = volume 303 self.hasEllipsoid = True