Пример #1
0
        public static IList <(Location, ITile)> ReadSector(ILogger logger, IItemFactory itemFactory, string fileName, string sectorFileContents, ushort xOffset, ushort yOffset, sbyte z)
        {
            itemFactory.ThrowIfNull(nameof(itemFactory));

            var loadedTilesList = new List <(Location, ITile)>();

            var lines = sectorFileContents.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

            foreach (var readLine in lines)
            {
                var inLine = readLine?.Split(new[] { CommentSymbol }, 2).FirstOrDefault();

                // ignore comments and empty lines.
                if (string.IsNullOrWhiteSpace(inLine))
                {
                    continue;
                }

                var data = inLine.Split(new[] { SectorSeparator }, 2);

                if (data.Length != 2)
                {
                    throw new InvalidDataException($"Malformed line [{inLine}] in sector file: [{fileName}]");
                }

                var tileInfo = data[0].Split(new[] { PositionSeparator }, 2);
                var tileData = data[1];

                var location = new Location
                {
                    X = (ushort)(xOffset + Convert.ToUInt16(tileInfo[0])),
                    Y = (ushort)(yOffset + Convert.ToUInt16(tileInfo[1])),
                    Z = z,
                };

                // start off with a tile that has no ground in it.
                ITile newTile = new Tile(location, null);

                newTile.AddContent(logger, itemFactory, CipFileParser.Parse(tileData));

                loadedTilesList.Add((location, newTile));
            }

            // TODO: proper logging.
            // Console.WriteLine($"Sector file {sectorFileContents.Name}: {loadedTilesList.Count} tiles loaded.");
            return(loadedTilesList);
        }
Пример #2
0
        private IList <ITile> ReadSector(string fileName, string sectorFileContents, ushort xOffset, ushort yOffset, sbyte z)
        {
            var loadedTilesList = new List <ITile>();

            var lines = sectorFileContents.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

            foreach (var readLine in lines)
            {
                var inLine = readLine?.Split(new[] { CommentSymbol }, 2).FirstOrDefault();

                // ignore comments and empty lines.
                if (string.IsNullOrWhiteSpace(inLine))
                {
                    continue;
                }

                var data = inLine.Split(new[] { SectorSeparator }, 2);

                if (data.Length != 2)
                {
                    throw new InvalidDataException($"Malformed line [{inLine}] in sector file: [{fileName}]");
                }

                var tileInfo = data[0].Split(new[] { PositionSeparator }, 2);
                var tileData = data[1];

                var location = new Location
                {
                    X = (ushort)(xOffset + Convert.ToUInt16(tileInfo[0])),
                    Y = (ushort)(yOffset + Convert.ToUInt16(tileInfo[1])),
                    Z = z,
                };

                // start off with a tile that has no ground in it.
                ITile newTile = this.tileFactory.CreateTile(location);

                this.AddContent(newTile, CipFileParser.Parse(tileData));

                loadedTilesList.Add(newTile);
            }

            this.logger.LogTrace($"Sector file {fileName}: {loadedTilesList.Count} tiles loaded.");

            return(loadedTilesList);
        }
Пример #3
0
        /// <summary>
        /// Reads a <see cref="IMonsterTypeEntity"/> out of a monster file.
        /// </summary>
        /// <param name="monsterFileInfo">The information about the monster file.</param>
        /// <returns>The <see cref="IMonsterTypeEntity"/> instance.</returns>
        private IMonsterTypeEntity ReadMonsterFile(FileInfo monsterFileInfo)
        {
            monsterFileInfo.ThrowIfNull(nameof(monsterFileInfo));

            if (!monsterFileInfo.Exists)
            {
                return(null);
            }

            var monsterType = new MonsterTypeEntity();

            foreach ((string name, string value) in this.ReadInDataTuples(File.ReadLines(monsterFileInfo.FullName), monsterFileInfo.FullName))
            {
                switch (name)
                {
                case "racenumber":
                    monsterType.RaceId = Convert.ToUInt16(value);
                    break;

                case "name":
                    monsterType.Name = value;
                    break;

                case "article":
                    monsterType.Article = value;
                    break;

                case "outfit":
                    var(lookTypeId, headColor, bodyColor, legsColor, feetColor) = CipFileParser.ParseMonsterOutfit(value);

                    monsterType.Outfit = new Outfit()
                    {
                        Id   = lookTypeId,
                        Head = headColor,
                        Body = bodyColor,
                        Legs = legsColor,
                        Feet = feetColor,
                    };
                    break;

                case "corpse":
                    monsterType.Corpse = Convert.ToUInt16(value);
                    break;

                case "blood":
                    if (Enum.TryParse(value, out BloodType bloodType))
                    {
                        monsterType.BloodType = bloodType;
                    }

                    break;

                case "experience":
                    monsterType.BaseExperienceYield = Convert.ToUInt32(value);
                    break;

                case "summoncost":
                    monsterType.SummonCost = Convert.ToUInt16(value);
                    break;

                case "fleethreshold":
                    monsterType.HitpointFleeThreshold = Convert.ToUInt16(value);
                    break;

                case "attack":
                    monsterType.BaseAttack = Convert.ToUInt16(value);
                    break;

                case "defend":
                    monsterType.BaseDefense = Convert.ToUInt16(value);
                    break;

                case "armor":
                    monsterType.BaseArmorRating = Convert.ToUInt16(value);
                    break;

                case "poison":
                    monsterType.SetConditionInfect(ConditionFlag.Posion, Convert.ToUInt16(value));
                    break;

                case "losetarget":
                    monsterType.LoseTargetDistance = Convert.ToByte(value);
                    break;

                case "strategy":
                    monsterType.Strategy = CipFileParser.ParseMonsterStrategy(value);
                    break;

                case "flags":
                    var parsedElements = CipFileParser.Parse(value);

                    foreach (var element in parsedElements)
                    {
                        if (!element.IsFlag || element.Attributes == null || !element.Attributes.Any())
                        {
                            continue;
                        }

                        if (Enum.TryParse(element.Attributes.First().Name, out CipCreatureFlag flagMatch))
                        {
                            if (flagMatch.ToCreatureFlag() is CreatureFlag creatureFlag)
                            {
                                monsterType.SetCreatureFlag(creatureFlag);
                            }
                        }
                    }

                    break;

                case "skills":
                    var skillParsed = CipFileParser.ParseMonsterSkills(value);

                    foreach (var skill in skillParsed)
                    {
                        if (!Enum.TryParse(skill.Name, ignoreCase: true, out CipMonsterSkillType mSkill))
                        {
                            continue;
                        }

                        switch (mSkill)
                        {
                        case CipMonsterSkillType.Hitpoints:
                            monsterType.MaxHitpoints = skill.CurrentLevel < 0 ? ushort.MaxValue : (ushort)skill.DefaultLevel;
                            break;

                        case CipMonsterSkillType.GoStrength:
                            monsterType.BaseSpeed = skill.CurrentLevel < 0 ? ushort.MinValue : (ushort)skill.DefaultLevel;
                            break;

                        case CipMonsterSkillType.CarryStrength:
                            monsterType.Capacity = skill.CurrentLevel < 0 ? ushort.MinValue : (ushort)skill.DefaultLevel;
                            break;

                        case CipMonsterSkillType.FistFighting:
                            if (skill.CurrentLevel > 0)
                            {
                                monsterType.SetSkill(SkillType.NoWeapon, skill.CurrentLevel, skill.DefaultLevel, skill.MaximumLevel, skill.TargetCount, skill.CountIncreaseFactor, skill.IncreaserPerLevel);
                            }

                            break;
                        }
                    }

                    break;

                case "spells":
                    monsterType.SetSpells(CipFileParser.ParseMonsterSpells(value));
                    break;

                case "inventory":
                    monsterType.SetInventory(CipFileParser.ParseMonsterInventory(value));
                    break;

                case "talk":
                    monsterType.SetPhrases(CipFileParser.ParsePhrases(value));
                    break;
                }
            }

            monsterType.Lock();

            return(monsterType);
        }
Пример #4
0
        /// <summary>
        /// Attempts to load the item catalog.
        /// </summary>
        /// <returns>The catalog, containing a mapping of loaded id to the item types.</returns>
        public IDictionary <ushort, IItemType> LoadTypes()
        {
            var itemDictionary  = new Dictionary <ushort, IItemType>();
            var objectsFilePath = Path.Combine(Environment.CurrentDirectory, this.LoaderOptions.FilePath);

            var current = new ItemType();

            foreach (var readLine in File.ReadLines(objectsFilePath))
            {
                if (readLine == null)
                {
                    continue;
                }

                var inLine = readLine.Split(new[] { CommentSymbol }, 2).FirstOrDefault();

                // ignore comments and empty lines.
                if (string.IsNullOrWhiteSpace(inLine))
                {
                    // wrap up the current ItemType and add it if it has enough properties set:
                    if (current.TypeId == 0 || string.IsNullOrWhiteSpace(current.Name))
                    {
                        continue;
                    }

                    current.LockChanges();
                    itemDictionary.Add(current.TypeId, current);

                    current = new ItemType();
                    continue;
                }

                var data = inLine.Split(new[] { PropertyValueSeparator }, 2);

                if (data.Length != 2)
                {
                    throw new InvalidDataException($"Malformed line [{inLine}] in objects file: [{objectsFilePath}]");
                }

                var propName = data[0].ToLower().Trim();
                var propData = data[1].Trim();

                switch (propName)
                {
                case "typeid":
                    current.SetId(Convert.ToUInt16(propData));
                    break;

                case "name":
                    current.SetName(propData.Substring(Math.Min(1, propData.Length), Math.Max(0, propData.Length - 2)));
                    break;

                case "description":
                    current.SetDescription(propData);
                    break;

                case "flags":
                    foreach (var element in CipFileParser.Parse(propData))
                    {
                        var flagName = element.Attributes.First().Name;

                        if (Enum.TryParse(flagName, out ItemFlag flagMatch))
                        {
                            current.SetFlag(flagMatch);
                            continue;
                        }

                        this.Logger.Warning($"Unknown flag [{flagName}] found on item with TypeID [{current.TypeId}].");
                    }

                    break;

                case "attributes":
                    foreach (var attrStr in propData.Substring(Math.Min(1, propData.Length), Math.Max(0, propData.Length - 2)).Split(','))
                    {
                        var attrPair = attrStr.Split('=');

                        if (attrPair.Length != 2)
                        {
                            this.Logger.Error($"Invalid attribute {attrStr}.");

                            continue;
                        }

                        current.SetAttribute(attrPair[0], Convert.ToInt32(attrPair[1]));
                    }

                    break;
                }
            }

            // wrap up the last ItemType and add it if it has enough properties set:
            if (current.TypeId != 0 && !string.IsNullOrWhiteSpace(current.Name))
            {
                current.LockChanges();
                itemDictionary.Add(current.TypeId, current);
            }

            return(itemDictionary);
        }
Пример #5
0
        /// <summary>
        /// Reads a <see cref="IMonsterType"/> out of a monster file.
        /// </summary>
        /// <param name="monsterFileInfo">The information about the monster file.</param>
        /// <returns>The <see cref="IMonsterType"/> instance.</returns>
        private IMonsterType ReadMonsterFile(FileInfo monsterFileInfo)
        {
            monsterFileInfo.ThrowIfNull(nameof(monsterFileInfo));

            if (!monsterFileInfo.Exists)
            {
                return(null);
            }

            var monsterType = new MonsterType();

            foreach ((string name, string value) in this.ReadInDataTuples(File.ReadLines(monsterFileInfo.FullName), monsterFileInfo.FullName))
            {
                switch (name)
                {
                case "racenumber":
                    monsterType.SetId(Convert.ToUInt16(value));
                    break;

                case "name":
                    monsterType.SetName(value.Trim('\"'));
                    break;

                case "article":
                    monsterType.SetArticle(value.Trim('\"'));
                    break;

                case "outfit":
                    monsterType.SetOutfit(value.Trim('(', ')'));
                    break;

                case "corpse":
                    monsterType.SetCorpse(Convert.ToUInt16(value));
                    break;

                case "blood":
                    monsterType.SetBlood(value);
                    break;

                case "experience":
                    monsterType.SetExperience(Convert.ToUInt32(value));
                    break;

                case "summoncost":
                    monsterType.SetSummonCost(Convert.ToUInt16(value));
                    break;

                case "fleethreshold":
                    monsterType.SetFleeTreshold(Convert.ToUInt16(value));
                    break;

                case "attack":
                    monsterType.SetAttack(Convert.ToUInt16(value));
                    break;

                case "defend":
                    monsterType.SetDefense(Convert.ToUInt16(value));
                    break;

                case "armor":
                    monsterType.SetArmor(Convert.ToUInt16(value));
                    break;

                case "poison":
                    monsterType.SetConditionInfect(ConditionFlag.Posion, Convert.ToUInt16(value));
                    break;

                case "losetarget":
                    monsterType.SetLoseTarget(Convert.ToByte(value));
                    break;

                case "strategy":
                    monsterType.SetStrategy(CipFileParser.ParseMonsterStrategy(value));
                    break;

                case "flags":
                    monsterType.SetFlags(CipFileParser.Parse(value));
                    break;

                case "skills":
                    monsterType.SetSkills(CipFileParser.ParseMonsterSkills(value));
                    break;

                case "spells":
                    monsterType.SetSpells(CipFileParser.ParseMonsterSpells(value));
                    break;

                case "inventory":
                    monsterType.SetInventory(CipFileParser.ParseMonsterInventory(value));
                    break;

                case "talk":
                    monsterType.SetPhrases(CipFileParser.ParsePhrases(value));
                    break;
                }
            }

            monsterType.Lock();

            return(monsterType);
        }