//----------------------------------------------------------------------------- // Monster.cs // // Microsoft XNA Community Game Platform // Copyright (C) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- using System; using System.Collections.Generic; using System.IO; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; namespace RolePlaying.Data { /// /// An enemy NPC that fights you in combat. /// /// /// Any combat many have many of the same monster, and they don't exist beyond /// combat. Therefore, current statistics are tracked in the runtime combat engine. /// public class Monster : FightingCharacter { /// /// The chance that this monster will defend instead of attack. /// private int defendPercentage; /// /// The chance that this monster will defend instead of attack. /// public int DefendPercentage { get { return defendPercentage; } set { defendPercentage = (value > 100 ? 100 : (value < 0 ? 0 : value)); } } /// /// The possible gear drops from this monster. /// private List gearDrops = new List(); /// /// The possible gear drops from this monster. /// public List GearDrops { get { return gearDrops; } set { gearDrops = value; } } public int CalculateGoldReward(Random random) { return CharacterClass.BaseGoldValue * CharacterLevel; } public int CalculateExperienceReward(Random random) { return CharacterClass.BaseExperienceValue * CharacterLevel; } public List CalculateGearDrop(Random random) { List gearRewards = new List(); Random useRandom = random; if (useRandom == null) { useRandom = new Random(); } foreach (GearDrop gearDrop in GearDrops) { if (random.Next(100) < gearDrop.DropPercentage) { gearRewards.Add(gearDrop.GearName); } } return gearRewards; } internal static Monster Load(string monsterContentName, ContentManager contentManager) { var asset = XmlHelper.GetAssetElementFromXML(monsterContentName); var monster = new Monster { AssetName = monsterContentName, Name = asset.Element("Name").Value, Direction = Enum.TryParse((string)asset.Element("Direction"), out var dir) ? dir : default, CharacterClassContentName = (string)asset.Element("CharacterClassContentName"), CharacterLevel = (int)asset.Element("CharacterLevel"), InitialEquipmentContentNames = asset.Element("InitialEquipmentContentNames") .Elements("Item").Select(x => (string)x).ToList(), CombatSprite = AnimatingSprite.Load(asset.Element("CombatSprite"), contentManager), MapSprite = AnimatingSprite.Load(asset.Element("MapSprite"), contentManager), GearDrops = asset.Element("GearDrops")?.Elements("Item") .Select(item => new GearDrop { GearName = (string)item.Element("GearName"), DropPercentage = (int)item.Element("DropPercentage") }).ToList() }; monster.CharacterClass = CharacterClass.Load(Path.Combine("CharacterClasses", monster.CharacterClassContentName), contentManager); monster.ShadowTexture = contentManager.Load(Path.Combine("Textures", "Characters", "CharacterShadow")); monster.AddStandardCharacterCombatAnimations(); monster.AddStandardCharacterIdleAnimations(); monster.AddStandardCharacterWalkingAnimations(); monster.ResetAnimation(false); return monster; } /// /// Reads a Monster object from the content pipeline. /// public class MonsterReader : ContentTypeReader { protected override Monster Read(ContentReader input, Monster existingInstance) { Monster monster = existingInstance; if (monster == null) { monster = new Monster(); } input.ReadRawObject(monster as FightingCharacter); monster.DefendPercentage = input.ReadInt32(); monster.GearDrops.AddRange(input.ReadObject>()); return monster; } } } }