Exemplo n.º 1
0
    def SetTolerance(self, for_whom, who, tolerance):
        invalid_belongs = []
        min_id = self.minID
        max_id = self.maxID
        for_whom = [int(belong) for belong in for_whom.split()]
        invalid_belongs.extend(
            [bel for bel in for_whom if bel > self.maxID or bel < self.minID])
        who = [int(belong) for belong in who.split()]
        invalid_belongs.extend(
            [bel for bel in who if bel > self.maxID or bel < self.minID])
        if invalid_belongs:
            for belong in invalid_belongs:
                logger.warning(
                    f"Invalid belong {belong} listed in relationship map! "
                    f"Belong should be between {self.minID} and {self.maxID}")

        for who_belong in who:
            for whom_belong in for_whom:
                if whom_belong != who_belong:
                    # strange native way to store belong to belong tolerance mappings
                    self.pTolerance[whom_belong + (who_belong - min_id) *
                                    (max_id - min_id + 1) - min_id] = tolerance
                    self.pTolerance[who_belong + (whom_belong - min_id) *
                                    (max_id - min_id + 1) - min_id] = tolerance
                else:
                    logger.warning(
                        f"Belong {who_belong} is in both 'forwhom' and 'who' attribs of set!"
                    )
Exemplo n.º 2
0
 def _LoadVehiclePartTypeToResourceXmlFile(self, some_other_int, fileName):
     vehiclePartTypesXmlNode = xml_to_objfy(fileName)
     if vehiclePartTypesXmlNode.tag == "VehiclePartTypes":
         if len(vehiclePartTypesXmlNode.getchildren()) > 0:
             check_mono_xml_node(vehiclePartTypesXmlNode, "VehiclePart")
             for vehicle_part in vehiclePartTypesXmlNode["VehiclePart"]:
                 vehiclePartName = read_from_xml_node(
                     vehicle_part, "PartName")
                 resourceName = read_from_xml_node(vehicle_part,
                                                   "ResourceName")
                 if self.GetResourceId(resourceName) == -1:
                     logger.warning(
                         f"ResourceManager: warning - invalid resource name '{resourceName}' "
                         f"is matched to vehicle part type '{vehiclePartName}'"
                     )
                 else:
                     if self.vehiclePart2Resource.get(
                             vehiclePartName) is None:
                         self.vehiclePart2Resource[
                             vehiclePartName] = resourceName
                     else:
                         raise NameError(
                             f"ResourceManager: Can't add vehicle part with name {vehiclePartName} "
                             f"to vehiclePart2Resource map. Already exist mapping with this name."
                         )
     else:
         raise FileNotFoundError("Can't load VehiclePartTypes from XML!")
Exemplo n.º 3
0
    def _ReadResourceFromXml(self, xmlFile, xmlNode, parent=0):
        resource = Resource(parent)
        resource.id = -1
        resource.parentId = -1
        resource.name = ''
        resource.geomSize_x = -1
        resource.geomSize_y = -1
        has_parent = parent != 0

        if has_parent:
            resource.geomSize_x = parent.geomSize_x
            resource.geomSize_y = parent.geomSize_y
            resource.parentId = parent.id

        resource.LoadFromXML(xmlFile, xmlNode)
        if self.resourceMap.get(resource.name) is None:
            self.resourceMap[resource.name] = resource
        else:
            logger.warning(f"Error: duplicate resource name: {resource.name}")

        resourceVectorSize = len(self.resourceVector)
        resource.id = resourceVectorSize
        self.resourceVector.append(resource)

        if len(xmlNode.getchildren()) > 0:
            check_mono_xml_node(xmlNode, "Type")
            for child in xmlNode["Type"]:
                self._ReadResourceFromXml(xmlFile, child, resource)
Exemplo n.º 4
0
 def LoadFromXML(self, xmlFile, xmlNode):
     self.name = read_from_xml_node(xmlNode, "Name")
     self.damageCoeffForPlayerFromEnemies = float(read_from_xml_node(xmlNode, "EnemyWeaponCoeff"))
     self.enemiesShootingDelay = float(read_from_xml_node(xmlNode, "EnemyShootingDelay"))
     if self.damageCoeffForPlayerFromEnemies < 0.0:
         logger.warning("Invalid EnemyWeaponCoeff! Should be a positive float number!")
     if self.enemiesShootingDelay < 0.0 or self.enemiesShootingDelay > 3.0:
         logger.warning("Invalid EnemyShootingDelay! Should be a positive float number between 0.0 and 3.0")
Exemplo n.º 5
0
def child_from_xml_node(xml_node: objectify.ObjectifiedElement, child_name: str, do_not_warn: bool = False):
    '''Get child from ObjectifiedElement by name'''
    try:
        return xml_node[child_name]
    except AttributeError:
        if not do_not_warn:
            logger.warning(f"There is no child with name {child_name} for xml node {xml_node.tag} in {xml_node.base}")
        return None
Exemplo n.º 6
0
 def AddAffix(self, affix: Affix):
     if self.GetAffixIdByNameAndResource(
             affix.name, affix.affixGroup.targetResourceId) != -1:
         logger.warning(f"Affix {affix.name} already exists for resource!")
     else:
         affix.affixId = len(self.affixes)
         self.affixes.append(affix)
         self.affix_map[affix.name] = affix
Exemplo n.º 7
0
 def GetResourceNameByVehiclePartName(
         self,
         vehiclePartName):  # (self, *result, vehiclePartName) in original
     res_name = self.vehiclePart2Resource.get(vehiclePartName)
     if res_name is not None:
         return res_name
     else:
         logger.warning(
             f"ResourceManager: can't find ResourceName for given VehiclePartName : {vehiclePartName}"
         )
Exemplo n.º 8
0
 def ParseProto(string_in: str, paramsPos):
     if len(string_in) < 3:
         logger.warning(f"No protocol found for '{string_in}'")
     paramsPos = string_in.find(":")
     if paramsPos == -1:
         logger.warning(f"No protocol found for '{string_in}'")
     elif string_in.find("new") == 0:
         return 2
     elif string_in.find("file") == 0:
         return 1
Exemplo n.º 9
0
 def LoadFormat(self, xmlFile, xmlNode, format_type: int = 0):
     for rel in xmlNode.iterchildren():
         if rel.tag != "set":
             logger.warning(
                 f"Invalid tag {rel.tag} in Relationship map {xmlNode.base}"
             )
         else:
             tolerance = self.GetToleranceByName(
                 read_from_xml_node(rel, "tolerance"))
             for_whom = read_from_xml_node(rel, "forwhom")
             who = read_from_xml_node(rel, "who")
             self.SetTolerance(for_whom, who, tolerance)
Exemplo n.º 10
0
    def LoadFromXML(self, fileName):
        xmlFile = xml_to_objfy(fileName)
        if xmlFile.tag == "Affixes":
            check_mono_xml_node(xmlFile, "ForResource")
            for resource_node in xmlFile["ForResource"]:
                resource_name = read_from_xml_node(resource_node, "Name")
                resource_id = self.theResourceManager.GetResourceId(
                    resource_name)
                if resource_id == -1:
                    logger.warning(
                        f"Error loading affixes: invalid resource name: {resource_name}"
                    )
                else:
                    prefixes = child_from_xml_node(resource_node,
                                                   "Prefixes",
                                                   do_not_warn=True)
                    suffixes = child_from_xml_node(resource_node,
                                                   "Suffixes",
                                                   do_not_warn=True)

                    if prefixes is not None:
                        check_mono_xml_node(prefixes, "AffixGroup")
                        for affix_group_node in child_from_xml_node(
                                prefixes, "AffixGroup"):
                            affix_group = AffixGroup(self)
                            affix_group.affixType = 0
                            affix_group.LoadFromXML(xmlFile, affix_group_node)

                            affix_groups_list_size = len(self.affixGroups)
                            affix_group.affixGroupId = affix_groups_list_size
                            affix_group.targetResourceId = resource_id

                            self.affixGroups.append(affix_group)
                    if suffixes is not None:
                        check_mono_xml_node(suffixes, "AffixGroup")
                        for affix_group_node in child_from_xml_node(
                                suffixes, "AffixGroup"):
                            affix_group = AffixGroup(self)
                            affix_group.affixType = 1
                            affix_group.LoadFromXML(xmlFile, affix_group_node)

                            affix_groups_list_size = len(self.affixGroups)
                            affix_group.affixGroupId = affix_groups_list_size
                            affix_group.targetResourceId = resource_id

                            self.affixGroups.append(affix_group)
                    if suffixes is None and prefixes is None:
                        logger.warning(
                            f"Affixes node for resource {resource_name} has no Prefixes and no Suffixes!"
                        )
        else:
            raise NameError("Affixes file should contain root Affixes tag")
Exemplo n.º 11
0
def parse_str_to_bool(original_value, string: str, is_striped=False):
    if string is None:
        return original_value
    if string.lower() == "true" or string == "1" or string == "yes":
        return True
    elif string.lower() == "false" or string == "0" or string == "no":
        return False
    else:
        if not is_striped:
            logger.warning(f"Invalid str passed to parse to bool: '{string}'")
            return parse_str_to_bool(original_value, string.strip(), True)
        else:
            return False
Exemplo n.º 12
0
def parse_config(xml_file):
    config = {}
    tree = xml_to_objfy(xml_file)
    if tree.tag == 'config':
        config_entries = tree.attrib
        for entry_name in config_entries:
            if config.get(entry_name) is None:
                config[entry_name] = config_entries[entry_name]
            else:
                logger.warning(f"There is a duplicate config value with name: {entry_name}, "
                               f"will be using last available value for the name.")
            config[entry_name] = config_entries[entry_name]
        return config
    else:
        raise NameError("Config should contain config tag with config entries as attributes!")
Exemplo n.º 13
0
 def AddAllItems(self, filepath):
     '''Replacement to read all models from animmodels.xml'''
     xml_file_node = xml_to_objfy(filepath)
     if xml_file_node.tag == "AnimatedModels":
         for model_node in xml_file_node.iterchildren(tag="model"):
             anim_model = self.AnimatedModel()
             anim_model.model_id = safe_check_and_set(
                 anim_model.model_id, model_node, "id")
             anim_model.file_name = safe_check_and_set(
                 anim_model.file_name, model_node, "file")
             # ToDo: deprecate check on duplication if not needed
             if self.models.get(anim_model.model_id) is not None:
                 logger.warning(
                     f"Duplicate model found in animmodels.xml with id: '{anim_model.model_id}'"
                 )
             self.models[anim_model.model_id] = anim_model
Exemplo n.º 14
0
    def GetStringByStringId(self, str_id, localizationIndex: str = ''):
        '''Get localizied string by id, where id is the service name'''
        if len(localizationIndex) > 0:
            if localizationIndex in ["0", "1"]:
                localizationIndex = f"_localizedform_{localizationIndex}"
            else:
                logger.warning(
                    "Invalid localization index, only empty, 0 and 1 available"
                )

        string = self.strings.get(f"{str_id}{localizationIndex}")
        if string is not None:
            return string
        else:
            logger.warning(
                f"String name given is not in String Dictionary: {str_id}")
Exemplo n.º 15
0
    def LoadFromXML(self, xmlFile, copy_to_default: bool = True):
        xmlNode = xml_to_objfy(xmlFile)
        if xmlNode.tag != "relationship":
            raise ValueError(
                "Relationship XML should contain root tag 'relationship'!")
        formatType = 0
        self.minID = int(read_from_xml_node(xmlNode, "MinPlayerID"))
        self.maxID = int(read_from_xml_node(xmlNode, "MaxPlayerID"))
        default_tolerance_name = read_from_xml_node(xmlNode,
                                                    "DefaultTolerance")
        self.defaultTolerance = self.GetToleranceByName(default_tolerance_name)

        if self.minID <= self.maxID:
            if self.maxID - self.minID + 1 > 1000:
                self.maxID = self.minID + 1001
                logger.warning(
                    f"Tolerance range can't be more than 1001, for example 1000-2001 range is valid."
                    f"Reseting max value to be {self.maxID}")
            self.pTolerance = {}
            tolerance_range_len = self.maxID - self.minID
            tolerance_id_range = range(0, tolerance_range_len**2)
            for tolerance_id in tolerance_id_range:
                self.pTolerance[tolerance_id] = self.defaultTolerance
            format_type_read = read_from_xml_node(xmlNode,
                                                  "FormatType",
                                                  do_not_warn=True)
            if format_type_read is not None:
                formatType = int(format_type_read)
            if formatType != 0:
                if formatType == 1:
                    raise NotImplementedError(
                        "Can't work with saves yet, do not load from currentmap.xml"
                    )
                    self.LoadFormat(
                        xmlFile, xmlNode,
                        1)  # ??? do we even need this for format_type 1?
                else:
                    raise ValueError(
                        f"Invalid format type {formatType} for relationship")
            else:
                self.LoadFormat(xmlFile, xmlNode, 0)
        if copy_to_default:
            self.pDefaultTolerance = self.pTolerance
        else:
            raise ValueError(
                "Relationship MinPlayerID should be less than MaxPlayerID")
Exemplo n.º 16
0
def read_from_xml_node(xml_node: objectify.ObjectifiedElement, attrib_name: str, do_not_warn: bool = False):
    attribs = xml_node.attrib
    if attribs:
        prot = attribs.get(attrib_name)
        if prot is not None:
            return prot
        else:
            if not do_not_warn:
                logger.warning(f"There is no attrib with the name: {attrib_name} "
                               f"in a tag {xml_node.tag} of {xml_node.base}")
            return None

    else:
        logger.warning(f"Node {xml_node.tag} of {xml_node.base} is empty!")
        if xml_node.tag == "comment":
            log_comment(xml_node, xml_node.getparent())
        return None
Exemplo n.º 17
0
 def ReadFromXmlNode(self, xmlFile, xmlNode, warn_on_duplication=True):
     if xmlNode is not None:
         check_mono_xml_node(xmlNode, "Item")
         for item_node in xmlNode.iterchildren(tag="Item"):
             item = self.ServerItem()
             item.id = safe_check_and_set(item.id, item_node, "id")
             item.params = safe_check_and_set(item.params, item_node,
                                              "params")
             item.filename = safe_check_and_set(item.filename, item_node,
                                                "file")
             if self.items_map.get(item.id) is None:
                 self.items_list.append(item)
                 self.items_map[item.id] = item
             elif warn_on_duplication:
                 path = unquote(xmlFile.base)
                 logger.warning(
                     f"Duplicate server item with id: '{item.id}' encountered in '{path}'"
                 )
Exemplo n.º 18
0
def check_mono_xml_node(xml_node: objectify.ObjectifiedElement, expected_child_name: str,
                        ignore_comments: bool = False):
    children = xml_node.getchildren()
    if len(children) > 0:
        for child in children:
            if child.tag != expected_child_name:
                if child.tag == "comment" and not ignore_comments:
                    comment = unescape(str(etree.tostring(child))).strip("b'<!-- ").strip(" -->'")
                    path = unquote(xml_node.base).replace(f'file:/{WORKING_DIRECTORY}', '')
                    logger.debug(f"Comment '{comment}' "
                                 f"in tag: '{xml_node.tag}'' "
                                 f"in file: {path}.")
                else:
                    logger.warning(f"Unexpected node with a name {child.tag} found "
                                   f"in xml node: {xml_node.tag} in {xml_node.base}!")
    else:
        logger.error(f"Empty node with a name {xml_node.tag} when expecting to find child "
                     f"nodes with a name {expected_child_name} in {xml_node.base}")
Exemplo n.º 19
0
    def GetAffixGroupsByResourceId(self, resourceId):
        if not self.affixGroups:
            return -1
        else:
            if resourceId != -1:
                valid_afx_gr = [
                    afx_gr for afx_gr in self.affixGroups
                    if self.theResourceManager.ResourceIsKindOf(
                        resourceId, afx_gr.targetResourceId)
                ]
                if len(valid_afx_gr) > 1:
                    logger.warning(
                        f"There is more than one available affixGroup for resource id {resourceId}!"
                    )
                return valid_afx_gr[0]

            else:
                raise ValueError(
                    f"Invalid resourceId given, can't return AffixGroup!")
Exemplo n.º 20
0
 def IsKindOf(self, theResourceManager, resourceId):
     resourceVector = theResourceManager.resourceVector
     resourceVectorSize = len(resourceVector)
     if self.id == -1:
         return False
     if self.id == resourceId:
         return True
     if resourceVector:
         if self.id < 0 or self.id > resourceVectorSize:
             logger.warning(
                 f"Resource id given is {self.id}, resourceVector size is {resourceVectorSize}"
             )
             return False
         elif self.parentId == -1:
             return False
         elif self.parentId == resourceId:
             return True
         else:
             return False
     else:
         logger.error("theResourceManager doesn't have a resourceVector!")
         return False
Exemplo n.º 21
0
def is_xml_node_contains(xml_node: objectify.ObjectifiedElement, attrib_name: str):
    attribs = xml_node.attrib
    if attribs:
        return attribs.get(attrib_name) is not None
    else:
        logger.warning(f"Asking for attributes of node without attributes: {xml_node.base}")
Exemplo n.º 22
0
    def LoadFromXML(self, xmlFile, xmlNode):
        namedBelongIds = read_from_xml_node(xmlNode["Belongs"], "Values")
        self.namedBelongIds = [int(belong) for belong in namedBelongIds.split()]
        self.namedBelongIdsVector = self.namedBelongIds  # ??? are both needed?

        izvratRepositoryMaxSize = read_from_xml_node(xmlNode["IzvratRepository"], "MaxSize")
        self.izvratRepositoryMaxSize_x = int(izvratRepositoryMaxSize.split()[0])
        self.izvratRepositoryMaxSize_y = int(izvratRepositoryMaxSize.split()[1])

        groundRepositorySize = read_from_xml_node(xmlNode["GroundRepository"], "Size")
        self.groundRepositorySize_x = int(groundRepositorySize.split()[0])
        self.groundRepositorySize_y = int(groundRepositorySize.split()[1])

        self.gameTimeMult = float(read_from_xml_node(xmlNode["Mult"], "GameTimeMult"))
        if self.gameTimeMult <= 0.000099999997:
            logger.warning("GameTimeMult is too low! Set to 0.0001 or higher")
        self.vehicleAiFiringRangeMult = read_from_xml_node(xmlNode["Mult"], "VehicleAIFiringRangeMult")

        self.maxBurstTime = int(read_from_xml_node(xmlNode["BurstParameters"], "MaxBurstTime"))
        self.minBurstTime = int(read_from_xml_node(xmlNode["BurstParameters"], "MinBurstTime"))
        self.timeBetweenBursts = int(read_from_xml_node(xmlNode["BurstParameters"], "TimeBetweenBursts"))

        self.probabilityToGenerateDynamicQuestInTown = \
            float(read_from_xml_node(xmlNode["DynamicQuest"], "ProbabilityToGenerateDynamicQuestInTown"))
        if self.probabilityToGenerateDynamicQuestInTown < 0.0 or self.probabilityToGenerateDynamicQuestInTown > 1.0:
            logger.warning("ProbabilityToGenerateDynamicQuestInTown value is invalid! Set between 0.0 and 1.0")

        self.pathToRelationship = read_from_xml_node(xmlNode["CommonPaths"], "Relationship")
        self.pathToGameObjects = read_from_xml_node(xmlNode["CommonPaths"], "GameObjects")
        self.pathToQuests = read_from_xml_node(xmlNode["CommonPaths"], "Quests")
        self.pathToResourceTypes = read_from_xml_node(xmlNode["CommonPaths"], "ResourceTypes")
        self.pathToAffixes = read_from_xml_node(xmlNode["CommonPaths"], "Affixes")
        self.pathToVehiclePartTypes = read_from_xml_node(xmlNode["CommonPaths"], "VehiclePartTypes")

        self.distToTurnOnPhysics = float(read_from_xml_node(xmlNode["Physics"], "DistToTurnOnPhysics"))
        self.distToTurnOffPhysics = float(read_from_xml_node(xmlNode["Physics"], "DistToTurnOffPhysics"))
        self.physicStepTime = float(read_from_xml_node(xmlNode["Physics"], "PhysicStepTime"))
        if self.distToTurnOffPhysics - 10.0 <= self.distToTurnOnPhysics:
            logger.error(f"Differenece between distToTurnOffPhysics {self.distToTurnOffPhysics} and "
                         f"distToTurnOnPhysics {self.distToTurnOnPhysics} is too low: ! "
                         "Set to be at least 10.0 appart")

        self.barmenModelName = read_from_xml_node(xmlNode["Npc"], "BarmenModelName")

        self.splintersAutoDisableLinearThreshold = \
            float(read_from_xml_node(xmlNode["BreakableObjectSplinters"], "AutoDisableLinearThreshold"))
        self.splintersAutoDisableAngularThreshold = \
            float(read_from_xml_node(xmlNode["BreakableObjectSplinters"], "AutoDisableAngularThreshold"))
        self.splintersAutoDisableNumSteps = \
            int(read_from_xml_node(xmlNode["BreakableObjectSplinters"], "AutoDisableNumSteps"))

        self.vehiclesDropChests = parse_str_to_bool(self.vehiclesDropChests,
                                                    read_from_xml_node(xmlNode["Vehicles"], "VehiclesDropChests"))
        maxSpeedWithNoFuel = float(read_from_xml_node(xmlNode["Vehicles"], "MaxSpeedWithNoFuel"))
        # ??? why? Is this working?
        self.maxSpeedWithNoFuel = maxSpeedWithNoFuel * 0.27777779  # 5/18 = 0.2(7) ???

        self.infoAreaRadius = int(read_from_xml_node(xmlNode["SmartCursor"], "InfoAreaRadius"))
        self.lockTimeout = float(read_from_xml_node(xmlNode["SmartCursor"], "LockTimeout"))
        unlockRegion = read_from_xml_node(xmlNode["SmartCursor"], "UnlockRegion")
        self.unlockRegion_x = float(unlockRegion.split()[0])
        self.unlockRegion_y = float(unlockRegion.split()[1])
        # ??? unused in actual game globalproperties.cfg
        # self.infoObjUpdateTimeout = read_from_xml_node(xmlNode["SmartCursor"], "InfoObjUpdateTimeout")

        self.blastWaveCameraShakeRadiusCoeff = \
            float(read_from_xml_node(xmlNode["CameraController"], "BlastWaveCameraShakeRadiusCoeff"))
        self.shakeDamageToDurationCoeff = \
            float(read_from_xml_node(xmlNode["CameraController"], "ShakeDamageToDurationCoeff"))
        self.maxShakeDamage = float(read_from_xml_node(xmlNode["CameraController"], "MaxShakeDamage"))
        if self.maxShakeDamage <= 1.0:
            logger.warning("maxShakeDamage should be more than 1.0!")

        self.distanceFromPlayerToMoveout = int(read_from_xml_node(xmlNode["Caravans"], "DistanceFromPlayerToMoveout"))

        self.defaultLookBoxLength = float(read_from_xml_node(xmlNode["ObstacleAvoidance"], "DefaultLookBoxLength"))
        self.defaultTargetBoxLength = float(read_from_xml_node(xmlNode["ObstacleAvoidance"], "DefaultTargetBoxLength"))
        self.attractiveCoeff = float(read_from_xml_node(xmlNode["ObstacleAvoidance"], "AttractiveCoeff"))
        self.repulsiveCoeff = float(read_from_xml_node(xmlNode["ObstacleAvoidance"], "RepulsiveCoeff"))
        self.maxDistToAvoid = float(read_from_xml_node(xmlNode["ObstacleAvoidance"], "MaxDistToAvoid"))
        self.predictionTime = float(read_from_xml_node(xmlNode["ObstacleAvoidance"], "PredictionTime"))

        self.throwCoeff = float(read_from_xml_node(xmlNode["DeathProperties"], "ThrowCoeff"))
        self.flowVpVelocity = float(read_from_xml_node(xmlNode["DeathProperties"], "FlowVpVelocity"))
        self.flowWheelVelocity = float(read_from_xml_node(xmlNode["DeathProperties"], "FlowWheelVelocity"))
        self.energyBlowDeltaTime = float(read_from_xml_node(xmlNode["DeathProperties"], "EnergyBlowDeltaTime"))
        self.energyVpBlowProbability = int(read_from_xml_node(xmlNode["DeathProperties"], "EnergyVpBlowProbability"))
        self.energyWheelBlowProbability = \
            int(read_from_xml_node(xmlNode["DeathProperties"], "EnergyWheelBlowProbability"))

        self.healthUnitPrice = float(read_from_xml_node(xmlNode["Repair"], "HealthUnitPrice"))

        self.defaultArticleRegenerationTime = \
            float(read_from_xml_node(xmlNode["Articles"], "DefaultRegenerationTime"))
        self.probabilityToDropArticlesFromDeadVehicles = \
            float(read_from_xml_node(xmlNode["Articles"], "ProbabilityToDropArticlesFromDeadVehicles"))
        self.probabilityToDropGunsFromDeadVehicles = \
            float(read_from_xml_node(xmlNode["Articles"], "ProbabilityToDropGunsFromDeadVehicles"))

        self.zoneRespawnTimeOutIncreaseCoeff = \
            float(read_from_xml_node(xmlNode["InfectionZones"], "ZoneRespawnTimeOutIncreaseCoeff"))
        self.zoneDefaultFirstSpawnTime = \
            float(read_from_xml_node(xmlNode["InfectionZones"], "ZoneDefaultFirstSpawnTime"))

        self.colorFriend = read_from_xml_node(xmlNode["InterfaceStuff"], "ColorFriend")
        self.colorEnemy = read_from_xml_node(xmlNode["InterfaceStuff"], "ColorEnemy")
        self.colorTargetCaptured = read_from_xml_node(xmlNode["InterfaceStuff"], "ColorTargetCaptured")
        self.targetInfoContourWidth = float(read_from_xml_node(xmlNode["InterfaceStuff"], "TargetInfoContourWidth"))
        self.targetCapturedContourWidth = \
            float(read_from_xml_node(xmlNode["InterfaceStuff"], "TargetCapturedContourWidth"))

        self.playerPassMapUnpassableMu = \
            float(read_from_xml_node(xmlNode["PlayerPassmap"], "PlayerPassMapUnpassableMu"))
        self.playerPassMapUnpassableErp = \
            float(read_from_xml_node(xmlNode["PlayerPassmap"], "PlayerPassMapUnpassableErp"))
        self.playerPassMapUnpassableCfm = \
            float(read_from_xml_node(xmlNode["PlayerPassmap"], "PlayerPassMapUnpassableCfm"))

        fullGroupingAngleDegree = float(read_from_xml_node(xmlNode["Weapon"], "MaxGroupingAngle"))
        self.maxGroupingAngle = fullGroupingAngleDegree * 0.017453292 * 0.5  # pi/180 = 0.017453292
        self.timeOutForReAimGuns = float(read_from_xml_node(xmlNode["Weapon"], "TimeOutForReAimGuns"))

        for diffLevel in xmlNode["DifficultyLevels"].iterchildren():
            if diffLevel.tag == "Level":
                coeffs = CoeffsForDifficultyLevel()
                coeffs.LoadFromXML(xmlFile, diffLevel)
                self.difficultyLevelCoeffs.append(coeffs)
            else:
                logger.warning(f"Unexpected tag {diffLevel.tag} in DifficultyLevels enumeration")

        self.property2PriceCoeff = float(read_from_xml_node(xmlNode["Price"], "Property2PriceCoeff"))
        if not self.difficultyLevelCoeffs:
            raise ValueError("No difficulty levels in GlobalProperties!")