コード例 #1
0
    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)
コード例 #2
0
 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
コード例 #3
0
 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
コード例 #4
0
 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)
コード例 #5
0
 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)
コード例 #6
0
    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
コード例 #8
0
    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))
コード例 #9
0
 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)
コード例 #10
0
 def __getAnchorLocationWS(self, anchorLocation, partIdx):
     partMatrix = Math.Matrix(
         self.__vEntity.model.node(TankPartIndexes.getName(partIdx)))
     return self.__applyToAnchorLocation(anchorLocation, partMatrix)
コード例 #11
0
 def checkNode(entity, nodeID):
     node = entity.model.node(TankPartIndexes.getName(nodeID))
     print node.local
コード例 #12
0
def getCustomizationTankPartName(areaId, regionIdx):
    return CustomizationTankPartNames.MASK if areaId == TankPartIndexes.GUN and regionIdx == C11N_MASK_REGION else TankPartIndexes.getName(areaId)
コード例 #13
0
    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
コード例 #14
0
 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
コード例 #15
0
 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)