예제 #1
0
    def LoadServers(self, file_name):
        anim_models_alias = "AnimatedModelsServer"
        # static_models_alias = "StaticModelsServer",
        # light_alias = "LightsServer"
        # sprite_alias = "SpritesServer"
        # particles_alias = "ParticlesServer"
        # sounds_alias = "SoundsServer"
        # music_alias = "MusicServer"
        # projectors_alias = "ProjectorsServer"
        # decals_alias = "DecalsServer"
        self.servers = {}  # 9 servers total
        animated_models_server = self.ServerContainer(
            AnimatedModelsServer(), anim_models_alias,
            theWndStation.GetStringByStringId(anim_models_alias, "0"))
        self.servers[anim_models_alias] = animated_models_server
        animated_models_server.server.AddAllItems(
            os.path.join(WORKING_DIRECTORY, "data/models/animmodels.xml"))
        logger.info(f"Loading Servers: {file_name}")

        xml_file_node = xml_to_objfy(file_name)
        if xml_file_node is not None:
            for server_node in xml_file_node.iterchildren():
                server_container = self.servers.get(server_node.tag)
                if server_container is not None:
                    logger.info(f"Loading server :{server_container.name}")
                    server_container.server.ReadFromXmlNode(
                        xml_file_node, server_node)

                else:
                    logger.info(
                        f"Skipping loading unsupported server: {server_node.tag}"
                    )
        else:
            logger.error("Load servers: cannot find Servers")
예제 #2
0
 def GetPrototypeId(self, prototypeName):
     prot_id = -1
     prot_id_from_loaded = self.prototypeNamesToIds.get(prototypeName)
     if prot_id_from_loaded is None and prototypeName:
         logger.error(
             f"No prototype with name '{prototypeName}' registred by PrototypeManager!"
         )
     else:
         prot_id = prot_id_from_loaded
     return prot_id
예제 #3
0
def parse_model_group_health(relative_path: str):
    logger.debug(f"Trying to parse ModelGroups from '{relative_path}'")
    group_health = {}
    with open(os.path.join(WORKING_DIRECTORY, relative_path), 'rb') as f:
        str_from_file = f.read()
    if VehicleGamStruct.GROUP_HEALTH_HEADER.value in str_from_file:
        main_header = VehicleGamStruct.GROUP_HEALTH_HEADER.value
    elif VehicleGamStruct.GROUP_HEALTH_HEADER_URAL_CARGO.value in str_from_file:
        main_header = VehicleGamStruct.GROUP_HEALTH_HEADER_URAL_CARGO.value
    else:
        logger.debug(f"Model file '{relative_path}' given doesn't contain known GroupHealth headers!")
        return None
    group_health["Main"] = {"id": None,
                            "variants": None}
    if VehicleGamStruct.BREAKABLE_BSTR.value in str_from_file:
        main_breakable_raw = str_from_file.split(main_header)
        breakables_raw = main_breakable_raw[1][main_breakable_raw[1].index(VehicleGamStruct.BREAKABLE_BSTR.value):]
        current_index = 0
        while True:
            if breakables_raw[current_index:current_index + 3] == b"\x49\x56\x52":  # IVR
                break
            # finding amount of variants for groups which dictates chunk length
            variants = breakables_raw[current_index + 28]
            if variants == 2:
                chunk_size = 60
            elif variants == 3:
                chunk_size = 72
            else:
                logger.error(f"Tried to parse HealthGroups for model containing group with {variants} variants!"
                             "Only 2 and 3 are supported by toolkit!")

            breakable_string = breakables_raw[current_index:current_index + chunk_size]

            if VehicleGamStruct.BREAKABLE_BSTR.value in breakable_string:
                breakable_name = breakable_string[:11].decode('latin-1').replace('\x00', '')
                breakable_id = int(breakable_string[11:][21:22].hex(), 16)
                group_health[breakable_name] = {"id": breakable_id,
                                                "variants": variants}
            current_index += chunk_size

        # for byte_str in breakables_list:
        #     if VehicleGamStruct.BREAKABLE_BSTR.value in byte_str:
        #         breakable_name = byte_str[:11].decode('latin-1').replace('\x00', '')
        #         breakable_id = int(byte_str[11:][21:22].hex(), 16)
        #         group_health[breakable_name] = breakable_id
        return group_health
    else:
        logger.debug(f"Model file '{relative_path}' doesn't contain any breakable health zones.")
        return group_health
예제 #4
0
    def LoadAdditionalServers(self, file_name):
        xml_file_node = xml_to_objfy(file_name)
        if xml_file_node is not None:
            for server_node in xml_file_node.iterchildren():
                server_container = self.servers.get(server_node.tag)
                if server_container is not None:
                    logger.debug(
                        f"Loading additional server :{server_container.name}")
                    server_container.server.ReadFromXmlNode(
                        xml_file_node, server_node, warn_on_duplication=False)

                else:
                    logger.debug(
                        f"Skipping loading unsupported server: {server_node.tag}"
                    )
        else:
            logger.error("Load servers: cannot find Servers")
예제 #5
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}")
예제 #6
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
예제 #7
0
    def ReadNewPrototype(self, xmlFile, xmlNode: objectify.ObjectifiedElement):
        class_name = read_from_xml_node(xmlNode, "Class")
        logger.debug(f"Loading {class_name} prototype from {xmlNode.base}")
        prototype_info = self.theServer.CreatePrototypeInfoByClassName(
            class_name)(self.theServer)
        if prototype_info:
            prototype_info.className.value = class_name
            parent_prot_name = read_from_xml_node(xmlNode,
                                                  "ParentPrototype",
                                                  do_not_warn=True)
            if parent_prot_name is not None:
                parent_prot_info = self.InternalGetPrototypeInfo(
                    parent_prot_name)
                dummy = PrototypeInfo(self.theServer)
                if parent_prot_info is None:
                    logger.error(
                        f"Parent prototype of {class_name} is not loaded! Expected parent: {parent_prot_name}"
                    )
                    parent_prot_info = dummy
                prototype_info.CopyFrom(parent_prot_info)
            prototypes_length = len(self.prototypes)
            prototype_info.prototypeId = prototypes_length
            if prototype_info.LoadFromXML(xmlFile, xmlNode) == STATUS_SUCCESS:
                if self.prototypeNamesToIds.get(
                        prototype_info.prototypeName.value) is not None:
                    logger.critical(
                        f"Duplicate prototype in game objects: {prototype_info.prototypeName.value}"
                    )
                    raise AttributeError(
                        "Duplicate prototype, critical error!")
                else:
                    self.prototypeNamesToIds[
                        prototype_info.prototypeName.
                        value] = prototype_info.prototypeId
                    self.prototypes.append(prototype_info)
                    self.prototypesMap[
                        prototype_info.prototypeName.value] = prototype_info
                    if prototype_info.className.value not in self.prototypeClasses:
                        self.prototypeClasses.append(
                            prototype_info.className.value)

                    return 1
            else:
                logger.error(
                    f"Prototype {prototype_info.prototypeName.value} "
                    f"of class {prototype_info.className.value} was not loaded!"
                )
                return 0
        else:
            logger.error("Invalid class name: <{class_name}>!")
            return 0
예제 #8
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!")