def decodeHitPoints(encodedPoints, collisionComponent): resultPoints = [] maxHitEffectCode = None maxDamagedComponentName = None for encodedPoint in encodedPoints: compIdx, hitEffectCode, startPoint, endPoint = DamageFromShotDecoder.decodeSegment( encodedPoint, collisionComponent) if startPoint == endPoint or compIdx < 0: continue if hitEffectCode > maxHitEffectCode: maxHitEffectCode = hitEffectCode maxDamagedComponentName = TankPartIndexes.getName(compIdx) hitTestRes = collisionComponent.collideLocal( compIdx, startPoint, endPoint) bbox = collisionComponent.getBoundingBox(compIdx) if not hitTestRes or hitTestRes < 0.0: width, height, depth = (bbox[1] - bbox[0]) / 256.0 directions = [ Math.Vector3(0.0, -height, 0.0), Math.Vector3(0.0, height, 0.0), Math.Vector3(-width, 0.0, 0.0), Math.Vector3(width, 0.0, 0.0), Math.Vector3(0.0, 0.0, -depth), Math.Vector3(0.0, 0.0, depth) ] for direction in directions: hitTestRes = collisionComponent.collideLocal( compIdx, startPoint + direction, endPoint + direction) if hitTestRes >= 0.0: break if hitTestRes is None or hitTestRes < 0.0: newPoint = collisionComponent.collideLocalPoint( compIdx, startPoint, MAX_FALLBACK_CHECK_DISTANCE) if newPoint.length > 0.0: hitRay = endPoint - startPoint hitTestRes = hitRay.length endPoint = newPoint startPoint = endPoint - hitRay if hitTestRes is None or hitTestRes < 0.0: continue minDist = hitTestRes hitDir = endPoint - startPoint hitDir.normalise() rot = Matrix() rot.setRotateYPR((hitDir.yaw, hitDir.pitch, 0.0)) matrix = Matrix() matrix.setTranslate(startPoint + hitDir * minDist) matrix.preMultiply(rot) effectGroup = DamageFromShotDecoder.__hitEffectCodeToEffectGroup[ hitEffectCode] componentName = TankPartIndexes.getName(compIdx) resultPoints.append( DamageFromShotDecoder.ShotPoint(componentName, matrix, effectGroup)) return (maxHitEffectCode, resultPoints, maxDamagedComponentName)
def activate(self): super(_VehicleNodeEffect, self).activate() vehicle = BigWorld.entities.get(self.__vehicleId) if vehicle is not None and vehicle.model is not None and vehicle.appearance is not None: self.__fakeModel = newFakeModel() node = vehicle.model.node( TankPartIndexes.getName(self._TANK_PART_INDEX)) node.attach(self.__fakeModel, self.__getTransform(vehicle)) self.bindToModel(self.__fakeModel, BigWorld.player().spaceID) self.start() return
def deactivate(self): super(_VehicleNodeEffect, self).deactivate() self.stop() if self.__vehicleId is not None and self.__fakeModel is not None: vehicle = BigWorld.entities.get(self.__vehicleId) if vehicle is not None and vehicle.model is not None: node = vehicle.model.node( TankPartIndexes.getName(self._TANK_PART_INDEX)) if node is not None: node.detach(self.__fakeModel) self.__fakeModel = None return
def addDamageSticker(self, code, componentIdx, stickerID, segStart, segEnd, collisionComponent): componentName = TankPartIndexes.getName(componentIdx) if not componentName: return componentStickers = self.__stickers[componentName] if code in componentStickers.damageStickers: return segment = segEnd - segStart segLen = segment.lengthSquared if segLen != 0: segStart -= 0.25 * segment / math.sqrt(segLen) handle = componentStickers.stickers.addDamageSticker(stickerID, segStart, segEnd) componentStickers.damageStickers[code] = DamageSticker(stickerID, segStart, segEnd, handle)
def addDamageSticker(self, code, componentIdx, stickerID, segStart, segEnd): componentStickers = self.__stickers[TankPartIndexes.getName( componentIdx)] if componentStickers.damageStickers.has_key(code): return segment = segEnd - segStart segLen = segment.lengthSquared if segLen != 0: segStart -= 0.25 * segment / math.sqrt(segLen) handle = componentStickers.stickers.addDamageSticker( stickerID, segStart, segEnd) componentStickers.damageStickers[code] = DamageSticker( stickerID, segStart, segEnd, handle)
def __getAttachedPartIdx(self, position, normal, tankPartIdx): partMatrix = Math.Matrix(self.__vEntity.model.node(TankPartIndexes.getName(tankPartIdx))) startPos = position + normal * 0.1 endPos = position - normal * 0.6 startPos = partMatrix.applyPoint(startPos) endPos = partMatrix.applyPoint(endPos) collisions = self.collisions.collideAllWorld(startPos, endPos) if collisions is not None: for collision in collisions: partIdx = collision[3] if partIdx in TankPartIndexes.ALL: return partIdx return tankPartIdx
def __correctTurretYaw(self, anchorHelper, defaultYaw): if not _SHOULD_CHECK_DECAL_UNDER_GUN: return defaultYaw else: partMatrix = Math.Matrix( self.__vEntity.model.node( TankPartIndexes.getName(anchorHelper.partIdx))) turretMat = Math.Matrix( self.compoundModel.node(TankPartNames.TURRET)) transformMatrix = math_utils.createRTMatrix( (turretMat.yaw, partMatrix.pitch, partMatrix.roll), partMatrix.translation) anchorLocationWS = self.__applyToAnchorLocation( anchorHelper.location, transformMatrix) position = anchorLocationWS.position direction = anchorLocationWS.normal up = anchorLocationWS.up fromTurretToHit = position - turretMat.translation if fromTurretToHit.dot(turretMat.applyVector((0, 0, 1))) < 0: return defaultYaw checkDirWorld = direction * 10.0 cornersWorldSpace = self.__getDecalCorners(position, direction, up, anchorHelper.descriptor) if cornersWorldSpace is None: return defaultYaw slotType = ANCHOR_TYPE_TO_SLOT_TYPE_MAP[ anchorHelper.descriptor.type] if slotType == GUI_ITEM_TYPE.PROJECTION_DECAL: turretLeftDir = turretMat.applyVector((1, 0, 0)) turretLeftDir.normalise() gunJoin = self.__vEntity.model.node('HP_gunJoint') fromGunJointToAnchor = gunJoin.position - position decalDiags = (cornersWorldSpace[0] - cornersWorldSpace[2], cornersWorldSpace[1] - cornersWorldSpace[3]) fromGunToHit = abs(fromGunJointToAnchor.dot(turretLeftDir)) halfDecalWidth = max((abs(decalDiag.dot(turretLeftDir)) for decalDiag in decalDiags)) * 0.5 if fromGunToHit > halfDecalWidth * _PROJECTION_DECAL_OVERLAPPING_FACTOR: return defaultYaw result = self.collisions.collideShape(TankPartIndexes.GUN, cornersWorldSpace, checkDirWorld) if result < 0.0: return defaultYaw turretYaw = _HANGAR_TURRET_SHIFT gunDir = turretMat.applyVector(Math.Vector3(0, 0, 1)) if Math.Vector3(0, 1, 0).dot(gunDir * fromTurretToHit) > 0.0: turretYaw = -turretYaw return turretYaw
def __updateAnchorsParams(self, tankPartsToUpdate): tankPartsMatrices = {} for tankPartIdx in TankPartIndexes.ALL: tankPartName = TankPartIndexes.getName(tankPartIdx) tankPartsMatrices[tankPartIdx] = Math.Matrix(self.__vEntity.model.node(tankPartName)) for slotType in SLOT_TYPES: for areaId in Area.ALL: anchorHelpers = self.__anchorsHelpers[slotType][areaId] for regionIdx, anchorHelper in anchorHelpers.iteritems(): attachedPartIdx = anchorHelper.attachedPartIdx if attachedPartIdx not in tankPartsToUpdate: continue anchorLocationWS = self.__getAnchorLocationWS(anchorHelper.location, anchorHelper.partIdx) self.__anchorsParams[slotType][areaId][regionIdx] = AnchorParams(anchorLocationWS, anchorHelper.descriptor, AnchorId(slotType, areaId, regionIdx))
def __getTransform(self, vehicle): predefinedTransform = _TransformationParser.getTransform( vehicle.typeDescriptor.name.split(':')[1], TankPartIndexes.getName(self._TANK_PART_INDEX), self._getModuleName(vehicle.typeDescriptor)) translation = predefinedTransform.get( 'offset') if predefinedTransform is not None else None scale = predefinedTransform.get( 'scale') if predefinedTransform is not None else None if translation is None or scale is None: minBounds, maxBounds, _ = vehicle.appearance.collisions.getBoundingBox( self._TANK_PART_INDEX) translation = translation or Math.Vector3( (minBounds[0] + maxBounds[0]) / 2.0, (minBounds[1] + maxBounds[1]) / 2.0, (minBounds[2] + maxBounds[2]) / 2.0) scale = scale or Math.Vector3(abs(minBounds[0] - maxBounds[0]), abs(minBounds[1] - maxBounds[1]), abs(minBounds[2] - maxBounds[2])) rotation = Math.Vector3(0.0, 0.0, 0.0) return math_utils.createSRTMatrix(scale, rotation, translation)
def __getAnchorLocationWS(self, anchorLocation, partIdx): partMatrix = Math.Matrix( self.__vEntity.model.node(TankPartIndexes.getName(partIdx))) return self.__applyToAnchorLocation(anchorLocation, partMatrix)
def checkNode(entity, nodeID): node = entity.model.node(TankPartIndexes.getName(nodeID)) print node.local
def getCustomizationTankPartName(areaId, regionIdx): return CustomizationTankPartNames.MASK if areaId == TankPartIndexes.GUN and regionIdx == C11N_MASK_REGION else TankPartIndexes.getName(areaId)
def decodeHitPoints(cls, encodedPoints, collisionComponent, maxComponentIdx=TankPartIndexes.ALL[-1], vehicleDesc=None): resultPoints = [] for encodedPoint in encodedPoints: compIdx, hitEffectCode, startPoint, endPoint = DamageFromShotDecoder.decodeSegment( encodedPoint, collisionComponent, maxComponentIdx, vehicleDesc) if startPoint == endPoint or compIdx < 0: continue convertedCompIdx = DamageFromShotDecoder.convertComponentIndex( compIdx, vehicleDesc) hitTestRes = collisionComponent.collideLocal( convertedCompIdx, startPoint, endPoint) bbox = collisionComponent.getBoundingBox(convertedCompIdx) if not hitTestRes or hitTestRes < 0.0: width, height, depth = (bbox[1] - bbox[0]) / 256.0 directions = [ Math.Vector3(0.0, -height, 0.0), Math.Vector3(0.0, height, 0.0), Math.Vector3(-width, 0.0, 0.0), Math.Vector3(width, 0.0, 0.0), Math.Vector3(0.0, 0.0, -depth), Math.Vector3(0.0, 0.0, depth) ] for direction in directions: hitTestRes = collisionComponent.collideLocal( convertedCompIdx, startPoint + direction, endPoint + direction) if hitTestRes >= 0.0: break if hitTestRes is None or hitTestRes < 0.0: newPoint = collisionComponent.collideLocalPoint( convertedCompIdx, startPoint, MAX_FALLBACK_CHECK_DISTANCE) if newPoint.length > 0.0: hitRay = endPoint - startPoint hitTestRes = hitRay.length endPoint = newPoint startPoint = endPoint - hitRay if hitTestRes is None or hitTestRes < 0.0: continue minDist = hitTestRes hitDir = endPoint - startPoint hitDir.normalise() rot = Matrix() rot.setRotateYPR((hitDir.yaw, hitDir.pitch, 0.0)) matrix = Matrix() matrix.setTranslate(startPoint + hitDir * minDist) matrix.preMultiply(rot) effectGroup = cls._HIT_EFFECT_CODE_TO_EFFECT_GROUP[hitEffectCode] componentName = TankPartIndexes.getName(compIdx) if not componentName and convertedCompIdx < 0: componentName = collisionComponent.getPartName( convertedCompIdx) if not componentName: componentName = TankPartNames.CHASSIS resultPoints.append( DamageFromShotDecoder.ShotPoint(componentName, matrix, hitEffectCode, effectGroup)) return resultPoints
def buyAndExit(self, purchaseItems): self._currentSettings = self._cleanSettings(self._currentSettings) for itemsKey in self._currentSettings: for camoName in self._currentSettings[itemsKey]: g_config.camouflages[itemsKey].setdefault(camoName, {}).update(self._currentSettings[itemsKey][camoName]) if self._currentSettings['remap']: newSettings = {'disable': g_config.disable, 'remap': g_config.camouflages['remap']} loadJson(g_config.ID, 'settings', newSettings, g_config.configPath, True) if self._currentSettings['custom']: for confFolderName in g_config.configFolders: configFolder = g_config.configFolders[confFolderName] loadJson(g_config.ID, 'settings', {key: g_config.camouflages['custom'][key] for key in configFolder}, g_config.configPath + 'camouflages/' + confFolderName + '/', True, False) if any(self._currentSettings.itervalues()): from ..processors import collectCamouflageData collectCamouflageData() self.itemsCache.onSyncCompleted -= self.__onCacheResync boughtOutfits = {season: self.service.getCustomOutfit(season) for season in SeasonType.COMMON_SEASONS} cart = getTotalPurchaseInfo(purchaseItems) nationName, vehicleName = g_currentVehicle.item.descriptor.name.split(':') vehConfig = g_config.outfitCache.get(nationName, {}).get(vehicleName, {}) for pItem in (x for x in purchaseItems if x.selected): seasonName = SEASON_TYPE_TO_NAME[pItem.group] if pItem.slot == GUI_ITEM_TYPE.CAMOUFLAGE: bItem, bComp = boughtOutfits[pItem.group].getContainer(pItem.areaID).slotFor(pItem.slot)._items.get( pItem.regionID, (None, None)) component = self._modifiedOutfits[pItem.group].getContainer(pItem.areaID).slotFor(pItem.slot).getComponent( pItem.regionID) if pItem.isDismantling and (not bItem or not bComp) or not pItem.isDismantling and pItem.item == bItem and \ component.palette == bComp.palette and component.patternSize == bComp.patternSize: vehConfig.get(seasonName, {}).get('camo', {}).pop(TankPartIndexes.getName(pItem.areaID), []) else: g_config.outfitCache.setdefault(nationName, {}).setdefault(vehicleName, {}).setdefault( seasonName, {}).setdefault('camo', {})[TankPartIndexes.getName(pItem.areaID)] = ( [pItem.item.id, component.palette, component.patternSize] if not pItem.isDismantling else []) g_config.hangarCamoCache.get(nationName, {}).get(vehicleName, {}).get(seasonName, {}).pop( TankPartIndexes.getName(pItem.areaID), {}) else: typeName = GUI_ITEM_TYPE_NAMES[pItem.slot] bItem = boughtOutfits[pItem.group].getContainer(pItem.areaID).slotFor(pItem.slot).getItem(pItem.regionID) if pItem.isDismantling and not bItem or not pItem.isDismantling and pItem.item == bItem: vehConfig.get(seasonName, {}).get(typeName, {}).get( TankPartIndexes.getName(pItem.areaID) if pItem.areaID < 4 else 'misc', {}).pop(str(pItem.regionID), None) else: g_config.outfitCache.setdefault(nationName, {}).setdefault(vehicleName, {}).setdefault( seasonName, {}).setdefault(typeName, {}).setdefault( TankPartIndexes.getName(pItem.areaID) if pItem.areaID < 4 else 'misc', {})[ str(pItem.regionID)] = (pItem.item.id if not pItem.isDismantling else None) for nationName in g_config.outfitCache.keys(): for vehicleName in g_config.outfitCache[nationName].keys(): for season in g_config.outfitCache[nationName][vehicleName].keys(): for itemType in g_config.outfitCache[nationName][vehicleName][season].keys(): if itemType == 'camo': if g_currentVehicle.item.turret.isGunCarriage: g_config.outfitCache[nationName][vehicleName][season][itemType].pop('turret', None) else: for areaName in g_config.outfitCache[nationName][vehicleName][season][itemType].keys(): if not g_config.outfitCache[nationName][vehicleName][season][itemType][areaName]: del g_config.outfitCache[nationName][vehicleName][season][itemType][areaName] if not g_config.outfitCache[nationName][vehicleName][season][itemType]: del g_config.outfitCache[nationName][vehicleName][season][itemType] if not g_config.outfitCache[nationName][vehicleName][season]: del g_config.outfitCache[nationName][vehicleName][season] if not g_config.outfitCache[nationName][vehicleName]: del g_config.outfitCache[nationName][vehicleName] if not g_config.outfitCache[nationName]: del g_config.outfitCache[nationName] loadJson(g_config.ID, 'outfitCache', g_config.outfitCache, g_config.configPath, True) if cart.totalPrice != ITEM_PRICE_EMPTY: msgCtx = {'money': formatPrice(cart.totalPrice.price), 'count': cart.numSelected} SystemMessages.pushMessage(g_config.i18n['UI_flashCol_applied_money'] % msgCtx, type=CURRENCY_TO_SM_TYPE.get(cart.totalPrice.getCurrency(byWeight=True), SM_TYPE.PurchaseForGold)) else: SystemMessages.pushI18nMessage(MESSENGER.SERVICECHANNELMESSAGES_SYSMSG_CONVERTER_CUSTOMIZATIONS, type=SM_TYPE.Information) self.__onCacheResync() self.itemsCache.onSyncCompleted += self.__onCacheResync
def new_showDamageFromShot(self, attackerID, points, effectsIndex, damageFactor, *a, **k): if LOG_EVENTS and attackerID > 0: player = BigWorld.player() #Initial info points_count = len(points) if points else 0 timeLeft, timeLeftSec = getTimeLeft() eventInfo = [ '%s' % player.arenaUniqueID, timeLeft, timeLeftSec, '"Vehicle.showDamageFromShot"', '%s' % player.arena.vehicles[self.id].get('accountDBID', '-'), '%s' % player.arena.vehicles[attackerID].get('accountDBID', '-'), json.dumps({ 'points': points_count, 'effectsIndex': effectsIndex, 'damageFactor': damageFactor }) ] #Decode info shellInfo = {} for shot in player.arena.vehicles[attackerID][ 'vehicleType'].gun.shots: if effectsIndex == shot.shell.effectsIndex: shellInfo['name'] = shot.shell.name shellInfo['kind'] = shellTypeAbb(shot.shell.kind) shellInfo['damage'] = str(shot.shell.damage) shellInfo['caliber'] = shot.shell.caliber shellInfo['piercingPower'] = str(shot.piercingPower) shellInfo['speed'] = round(shot.speed / 0.8, 3) shellInfo['gravity'] = round(shot.gravity / 0.64, 3) shellInfo['maxDistance'] = shot.maxDistance if shot.shell.kind == 'HIGH_EXPLOSIVE': shellInfo[ 'explosionRadius'] = shot.shell.type.explosionRadius break eventInfo.append(json.dumps(shellInfo) if shellInfo else '') maxHitEffectCode, decodedPoints, maxDamagedComponent = DamageFromShotDecoder.decodeHitPoints( points, self.appearance.collisions) hasPiercedHit = DamageFromShotDecoder.hasDamaged(maxHitEffectCode) attacker = BigWorld.entities.get(attackerID, None) attackerPos = attacker.position if isinstance( attacker, Vehicle ) and attacker.inWorld and attacker.isStarted else player.arena.positions.get( attackerID) eventInfo.append( json.dumps({ 'maxHitEffectCode': VEHICLE_HIT_EFFECT_NAMES.get(maxHitEffectCode), 'maxDamagedComponent': maxDamagedComponent, 'hasPiercedHit': hasPiercedHit, 'distance': round(self.position.distTo(attackerPos), 3) if attackerPos else None, 'hitPoints': [{ 'componentName': point.componentName, 'hitEffectGroup': point.hitEffectGroup } for point in decodedPoints] if decodedPoints else None })) for num, encodedPoint in enumerate(points, 1): hitsInfo = [] #[[Dir1-Layer1, ...], [Dir2-Layer1, ...], ...] hitsScheme = None compIdx, hitEffectCode, startPoint, endPoint = DamageFromShotDecoder.decodeSegment( encodedPoint, self.appearance.collisions, TankPartIndexes.ALL[-1]) if compIdx >= 0 and startPoint != endPoint: convertedCompIdx = DamageFromShotDecoder.convertComponentIndex( compIdx) bbox = self.appearance.collisions.getBoundingBox( convertedCompIdx) width, height, depth = (bbox[1] - bbox[0]) / 256.0 if COLLIDE_MULTI: if COLLIDE_SCHEME == 'hexahedron': hitsScheme = _CSHexahedron(width, height, depth, COLLIDE_SCALE) elif COLLIDE_SCHEME == 'cross': hitsScheme = _CSCross(width, height, depth, COLLIDE_SCALE) else: hitsScheme = _CSCenter() else: hitsScheme = _CSCenter() compMatrix = Matrix( self.appearance.compoundModel.node( TankPartIndexes.getName(convertedCompIdx))) firstHitDir = endPoint - startPoint firstHitDir.normalise() firstHitDir = compMatrix.applyVector(firstHitDir) firstHitPos = compMatrix.applyPoint(startPoint) for direction in hitsScheme.directions: hitInfo = [] collisions = self.appearance.collisions.collideAllWorld( firstHitPos - firstHitDir.scale(COLLIDE_INDENT) + direction, firstHitPos + firstHitDir.scale(COLLIDE_LENGTH) + direction) if collisions: base = None testPointAdded = collidePointAdded = False for collision in collisions: if collision[3] in TankPartIndexes.ALL: if base is None: base = collision[0] if not testPointAdded: if collision[0] > COLLIDE_INDENT: hitInfo.append( 'TestPoint%s(distance=%s, tankPart=%s)' % (num if points_count > 1 else '', round(COLLIDE_INDENT - base, 4), TankPartIndexes.getName( convertedCompIdx))) testPointAdded = True material = self.getMatinfo( collision[3], collision[2]) hitInfo.append({ 'distance': round(collision[0] - base, 4), 'angleCos': round(collision[1], 4), 'tankPart': TankPartIndexes.getName(collision[3]), 'armor': round(material.armor, 4) if material else None }) if not collidePointAdded: collidePointAdded = True if material and material.vehicleDamageFactor > 0 and collision[ 3] in (TankPartIndexes.HULL, TankPartIndexes.TURRET): break if collidePointAdded: if not testPointAdded and base is not None: hitInfo.append( 'TestPoint%s(distance=%s, tankPart=%s)' % (num if points_count > 1 else '', round(COLLIDE_INDENT - base, 4), TankPartIndexes.getName( convertedCompIdx))) hitsInfo.append(hitInfo) eventInfo.append(json.dumps('%s: %s' % ('TestPoint%d' % num if points_count > 1 else 'layers' if hitsScheme.NAME == 'center' else 'TestPoint', \ hitsScheme.format(hitsInfo[0] if hitsScheme.NAME == 'center' else hitsInfo) if hitsScheme else '[]'))) printStrings(LOG_EVENTS_FILENAME, eventInfo)