public CharacterSheetComponent(int x, int y, Actor actor)
        {
            this.locationX = x;
            this.locationY = y;
            this.actor = actor;

            PerformDrag(0, 0);
        }
        /// <summary>
        /// Creates a new HealthDisplayComponent for a particular actor at a particular position
        /// </summary>
        /// <param name="locationX"></param>
        /// <param name="locationY"></param>
        /// <param name="actor"></param>
        public HealthDisplayComponent(int locationX, int locationY, Actor actor)
        {
            this.locationX = locationX;
            this.locationY = locationY;
            this.actor = actor;
            this.visible = true;

            PerformDrag(0, 0);
        }
Пример #3
0
        public ThrowItemComponent(int x, int y, MapCoordinate targetCoordinate, Actor actor)
        {
            this.locationX = x;
            this.locationY = y;
            this.targetCoordinate = targetCoordinate;
            this.Actor = actor;

            PerformDrag(0, 0);
        }
        //Drawing stuff
        public InventoryDisplayComponent(int locationX, int locationY, Actor currentActor)
        {
            this.locationX = locationX;
            this.locationY = locationY;
            this.CurrentActor = currentActor;
            ChosenCategory = 0;

            PerformDrag(locationX, locationY);
        }
Пример #5
0
        public static ActionFeedback[] HuntDownMission(HuntDownMission mission, Actor actor)
        {
            if (actor.UsesRanged)
            {
                //Are we within range?
                if (actor.MapCharacter.Coordinate - mission.Target.MapCharacter.Coordinate <= actor.LineOfSight)
                {
                    //Attack!
                    actor.CurrentMission = new AttackMission(mission.Target);
                    return new ActionFeedback[] { };
                }
            }
            else
            {
                //Are we near the mission point?
                if (Math.Abs(actor.MapCharacter.Coordinate - mission.Target.MapCharacter.Coordinate) <= 1)
                {
                    //MIssion is done. Attack!
                    actor.CurrentMission = new AttackMission(mission.Target);
                }
            }

            if (Math.Abs(mission.Target.MapCharacter.Coordinate - actor.MapCharacter.Coordinate) > actor.LineOfSight)
            {
                //Ran away - cancel the mission
                actor.CurrentMission = null;
            }

            //Otherwise, check whether the target is still where he was before, and whether we have anywhere to go to
            if (mission.Coordinates == null || mission.Target.MapCharacter.Coordinate != mission.TargetCoordinate)
            {
                //Regenerate the path
                mission.TargetCoordinate = mission.Target.MapCharacter.Coordinate;
                mission.Coordinates = PathfinderInterface.GetPath(actor.MapCharacter.Coordinate, mission.TargetCoordinate);
            }

            //Okay, now...advance
            if (mission.Coordinates == null || mission.Coordinates.Count == 0)
            {
                //Where did he go? Take a turn to figure it out
                mission.Coordinates = null;
                return new ActionFeedback[] { };
            }

            MapCoordinate nextStep = mission.Coordinates.Pop();

            //Do it
            if (GameState.LocalMap.GetBlockAtCoordinate(nextStep).MayContainItems)
            {
                GameState.LocalMap.GetBlockAtCoordinate(nextStep).PutItemOnBlock(actor.MapCharacter);
                actor.MapCharacter.Coordinate = nextStep;
            }
            //And that's done

            return new ActionFeedback[] { };
        }
        //Drawing stuff
        public TradeDisplayComponent(int locationX, int locationY, Actor currentActor, Actor vendorActor)
        {
            this.locationX = locationX;
            this.locationY = locationY;
            this.VendorActor = vendorActor;
            this.PlayerActor = currentActor;
            ChosenCategory = 0;

            PerformDrag(locationX, locationY);

            Buy = true;
        }
Пример #7
0
        public static ActionFeedback[] AttackMission(AttackMission mission, Actor actor)
        {
            List<ActionFeedback> feedback = new List<ActionFeedback>();

            if (Math.Abs(mission.AttackTarget.MapCharacter.Coordinate - actor.MapCharacter.Coordinate) > actor.LineOfSight)
            {
                //Ran away - cancel the mission
                actor.CurrentMission = null;
            }
            else
            {
                if (actor.UsesRanged)
                {
                    //Attack!
                    return CombatManager.Attack(actor, mission.AttackTarget, CombatManager.GetRandomAttackLocation(actor, mission.AttackTarget).Value);
                }
                else
                {
                    if (Math.Abs(mission.AttackTarget.MapCharacter.Coordinate - actor.MapCharacter.Coordinate) > 1)
                    {
                        //Hunt him down!
                        actor.CurrentMission = new HuntDownMission()
                        {
                            Target = mission.AttackTarget,
                            TargetCoordinate = mission.AttackTarget.MapCharacter.Coordinate
                        };
                    }
                    else
                    {
                        if (actor.IsAggressive && CombatManager.GetRandomAttackLocation(actor, mission.AttackTarget).HasValue) //we can hit them
                        {
                            //Attack!
                            return CombatManager.Attack(actor, mission.AttackTarget, CombatManager.GetRandomAttackLocation(actor, mission.AttackTarget).Value);

                        }
                        else
                        {
                            //TODO: Run away!
                        }

                    }
                }
            }

            return new ActionFeedback[] { };
        }
Пример #8
0
        /// <summary>
        /// Performs the effect on this actor. This includes assigning it to the effects list of the GameState
        /// </summary>
        /// <param name="actor"></param>
        /// <param name="effect"></param>
        public static void PerformEffect(Actor actor,Effect effect)
        {
            switch(effect.Name)
            {
                case EffectName.AGIL: actor.Attributes.TempAgil = actor.Attributes.TempAgil ?? 0 + effect.EffectAmount; break;
                case EffectName.BRAWN: actor.Attributes.TempBrawn = actor.Attributes.TempBrawn ?? 0 + effect.EffectAmount; break;
                case EffectName.CHAR: actor.Attributes.TempChar = actor.Attributes.TempChar ?? 0 + effect.EffectAmount; break;
                case EffectName.INTEL: actor.Attributes.TempIntel = actor.Attributes.TempIntel ?? 0 + effect.EffectAmount; break;
                case EffectName.PERC: actor.Attributes.TempPerc = actor.Attributes.TempPerc ?? 0 + effect.EffectAmount; break;
                case EffectName.BLIND: actor.Attributes.TempPerc = (actor.Attributes.TempPerc ?? 0) - effect.EffectAmount; break;
                case EffectName.HEAL: HealthCheckManager.HealCharacter(actor, 5); break;
            }

            effect.Actor = actor;

            GameState.LocalMap.ActiveEffects.Add(effect);
        }
Пример #9
0
        /// <summary>
        /// Kills the current character
        /// </summary>
        /// <param name="actor"></param>
        public static void KillCharacter(Actor actor)
        {
            actor.IsAlive = false;

            //Drop any stuff they have
            foreach (InventoryItem item in actor.Inventory.Inventory.GetAllObjects())
            {
                //Always drop loot & supplies,  10% chance of dropping something else
                if (item.Category == InventoryCategory.LOOT || item.Category == InventoryCategory.SUPPLY || GameState.Random.Next(10) == 5)
                {
                    //Drop them
                    item.InInventory = false;
                    item.IsEquipped = false;
                    GameState.LocalMap.GetBlockAtCoordinate(actor.MapCharacter.Coordinate).PutItemUnderneathOnBlock(item);
                }
            }
        }
Пример #10
0
        /// <summary>
        /// Calculates the chance of hitting a particular body part.
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="defender"></param>
        /// <param name="location"></param>
        /// <returns></returns>
        public static int CalculateHitPercentage(Actor attacker, Actor defender, AttackLocation location)
        {
            //If the bodypart is destroyed, give a percentage of -1 so we can filter it out later
            switch (location)
            {
                case AttackLocation.CHEST:
                    if (defender.Anatomy.Chest <= -5)
                    {
                        return -1;
                    }
                    break;
                case AttackLocation.HEAD:
                    if (defender.Anatomy.Head <= -5)
                    {
                        return -1;
                    }
                    break;
                case AttackLocation.LEFT_ARM:
                    if (defender.Anatomy.LeftArm <= -5)
                    {
                        return -1;
                    }
                    break;
                case AttackLocation.LEGS:
                    if (defender.Anatomy.Legs <= -5)
                    {
                        return -1;
                    }
                    break;
                case AttackLocation.RIGHT_ARM:
                    if (defender.Anatomy.RightArm <= -5)
                    {
                        return -1;
                    }
                    break;
            }

            int atk = 0;
            int def = 0;

            GetStanceEffect(out atk, out def, attacker.CombatStance);

            //Chance to hit -
            // Attacker Skill + Brawn - 5 + location penalty + stance effect  VS Defender Skill + Agil + stance effect
            int hitChance = attacker.Attributes.HandToHand + attacker.TotalBrawn - 5 + penaltyDict[location] + atk;

            GetStanceEffect(out atk, out def, defender.CombatStance);

            //Does the defender have a shield?
            int shieldBonus = 0;

            if (defender.Inventory.EquippedItems.ContainsKey(EquipmentLocation.SHIELD) && defender.Anatomy.LeftArm != 0)
            {
                shieldBonus = defender.Inventory.EquippedItems[EquipmentLocation.SHIELD].ArmourRating;
            }

            //Don't forget the shield if it's there
            int defendChance = defender.Attributes.Dodge + def + shieldBonus;

            //See what the difference is
            int difference = 20 + (hitChance - defendChance);

            return difference > 20 ? 100 : difference < 0 ? 0 : difference / 2 * 10;
        }
Пример #11
0
        /// <summary>
        /// Gets a random attack location to attack. Will prefer attack locations which have more chance of hitting, and will never return any locations which have a 0 chance to hit.
        /// If this is not possible, return null
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="defender"></param>
        /// <returns></returns>
        public static AttackLocation? GetRandomAttackLocation(Actor attacker, Actor defender)
        {
            List<AttackLocation> attackLocations = new List<AttackLocation>();

            foreach (AttackLocation loc in Enum.GetValues(typeof(AttackLocation)).Cast<AttackLocation>())
            {
                //Avoid hitting parts which have been disabled already
                switch (loc)
                {
                    case AttackLocation.CHEST:
                        if (defender.Anatomy.Chest < 0)
                        {
                            continue; //No use
                        }
                        break;
                    case AttackLocation.HEAD:
                        if (defender.Anatomy.Head < 0)
                        {
                            continue;
                        }
                        break;
                    case AttackLocation.LEFT_ARM:
                        if (defender.Anatomy.LeftArm < 0)
                        {
                            continue;
                        }
                        break;
                    case AttackLocation.LEGS:
                        if (defender.Anatomy.Legs < 0)
                        {
                            continue;
                        }
                        break;
                    case AttackLocation.RIGHT_ARM:
                        if (defender.Anatomy.RightArm < 0)
                        {
                            continue;
                        }
                        break;
                }

                for (int i = 0; i < CalculateHitPercentage(attacker, defender, loc); i++)
                {
                    attackLocations.Add(loc);
                }
            }

            //Now pick one at random
            return attackLocations.OrderBy(o => random.Next(100)).FirstOrDefault();
        }
Пример #12
0
        /// <summary>
        /// Generates a map with a particular biome
        /// </summary>
        /// <param name="herdAmount">The total amount of herds to generate</param>
        /// <param name="BanditAmount">The total amount of bandits to generate.</param>
        /// <param name="actors"></param>
        /// <returns></returns>
        public static MapBlock[,] GenerateMap(GlobalBiome biome, int herdAmount, int banditAmount, out Actor[] actors, out MapCoordinate startPoint)
        {
            MapBlock[,] map = new MapBlock[MAP_EDGE, MAP_EDGE];

            Random random = new Random();

            ItemFactory.ItemFactory factory = new ItemFactory.ItemFactory();

            int tileID = 0;

            factory.CreateItem(Archetype.TILES, details[biome].BaseTileTag, out tileID);

            //Create a new map which is edge X edge in dimensions and made of the base tile
            for (int x = 0; x < MAP_EDGE; x++)
            {
                for (int y = 0; y < MAP_EDGE; y++)
                {
                    MapBlock block = new MapBlock();
                    map[x, y] = block;
                    block.Tile = factory.CreateItem("tile", tileID);
                    block.Tile.Coordinate = new MapCoordinate(x, y, 0, MapType.LOCAL);
                }
            }

            #region Leave Town Item

            //Now select all the border tiles and put in a "Exit here" border
            for (int x = 0; x < map.GetLength(0); x++)
            {
                MapCoordinate coo = new MapCoordinate(x, 0, 0, MapType.LOCAL);

                LeaveTownItem lti = new LeaveTownItem();
                lti.Coordinate = coo;
                lti.Description = "continue on your journey";
                lti.Name = "Leave Area";

                lti.Coordinate = coo;

                map[x, 0].ForcePutItemOnBlock(lti);

                coo = new MapCoordinate(x, map.GetLength(1) - 1, 0, MapType.LOCAL);

                lti = new LeaveTownItem();
                lti.Coordinate = coo;
                lti.Description = "continue on your journey";
                lti.Name = "Leave Area";

                lti.Coordinate = coo;

                map[x, map.GetLength(1) - 1].ForcePutItemOnBlock(lti);

            }

            for (int y = 0; y < map.GetLength(1); y++)
            {
                MapCoordinate coo = new MapCoordinate(0, y, 0, MapType.LOCAL);

                LeaveTownItem lti = new LeaveTownItem();
                lti.Coordinate = coo;
                lti.Description = "continue on your journey";
                lti.Name = "Leave Area";

                lti.Coordinate = coo;

                map[0, y].ForcePutItemOnBlock(lti);

                coo = new MapCoordinate(map.GetLength(0) - 1, y, 0, MapType.LOCAL);

                lti = new LeaveTownItem();
                lti.Coordinate = coo;
                lti.Description = "continue on your journey";
                lti.Name = "Leave Area";

                lti.Coordinate = coo;

                map[map.GetLength(0) - 1, y].ForcePutItemOnBlock(lti);
            }

            #endregion

            #region Desert Oasis
            if (biome == GlobalBiome.ARID_DESERT)
            {
                //Let's create a pool of water towards one of the corners.
                int randomNumber = random.Next(2);

                int rXCoord = 0;

                if (randomNumber == 1)
                {
                    //Lower
                    rXCoord = random.Next(0, MAP_EDGE / 3);
                }
                else
                {
                    rXCoord = random.Next(2 * MAP_EDGE / 3, MAP_EDGE);
                }

                randomNumber = random.Next(2);

                int rYCoord = 0;

                if (randomNumber == 1)
                {
                    //Lower
                    rYCoord = random.Next(0, MAP_EDGE / 3);
                }
                else
                {
                    rYCoord = random.Next(2 * MAP_EDGE / 3, MAP_EDGE);
                }

                //The pool will have a radius of 3

                MapCoordinate coo = new MapCoordinate(rXCoord, rYCoord, 0, MapType.LOCAL);

                //Go through the blocks with a radius of 3
                var oasisBlocks = map.Cast<MapBlock>().ToArray().Where(b => Math.Abs(b.Tile.Coordinate - coo) <= 3).ToArray();

                int waterTile = -1;

                factory.CreateItem(Archetype.TILES, "water", out waterTile);

                foreach (var block in oasisBlocks)
                {
                    var coord = block.Tile.Coordinate;
                    block.Tile = factory.CreateItem("tile", waterTile);
                    block.Tile.Coordinate = coord;
                }

                var aroundOasis = map.Cast<MapBlock>().ToArray().Where(b => Math.Abs(b.Tile.Coordinate - coo) <= 4 && Math.Abs(b.Tile.Coordinate - coo) > 3).ToArray();

                int dummy;

                int grassTile = 0;

                factory.CreateItem(Archetype.TILES, "grass", out grassTile);

                foreach (var block in aroundOasis)
                {
                    var coord = block.Tile.Coordinate;
                    block.Tile = factory.CreateItem("tile", grassTile);
                    block.Tile.Coordinate = coord;
                }

                //Put in some trees around the pool
                for (int i = 0; i < 3; i++)
                {
                    MapItem tree = factory.CreateItem(Archetype.MUNDANEITEMS, "jungle tree", out dummy);

                    var block = aroundOasis[random.Next(aroundOasis.Length)];

                    if (block.MayContainItems)
                    {
                        //Drop it
                        block.ForcePutItemOnBlock(tree);
                    }
                }

            }
            #endregion

            #region Wetland Splotches

            if (biome == GlobalBiome.WETLAND)
            {
                int waterTile = -1;

                factory.CreateItem(Archetype.TILES, "water", out waterTile);

                for (int i=0; i < 7; i++)
                {
                    MapBlock rBlock = map[random.Next(map.GetLength(0)), random.Next(map.GetLength(1))];

                    Rectangle safeRect = new Rectangle( MAP_EDGE/2 - 5,MAP_EDGE/2 -5,10,10);

                    if (safeRect.Contains(rBlock.Tile.Coordinate.X,rBlock.Tile.Coordinate.Y))
                    {
                        continue; //Not here!
                    }

                    int size = random.Next(1, 3);

                    //Get all the tiles around the block for a particular size
                    var pool = map.Cast<MapBlock>().ToArray().Where(b => Math.Abs(b.Tile.Coordinate - rBlock.Tile.Coordinate) <= size).ToArray();

                    foreach(var block in pool)
                    {
                        MapCoordinate coo = block.Tile.Coordinate;
                        block.Tile = factory.CreateItem("tiles", waterTile);
                        block.Tile.Coordinate = coo;
                    }
                }
            }

            #endregion

            for (int i = 0; i < details[biome].TreeCount; i++)
            {
                int treeID = 0;
                MapItem item = null;

                item = factory.CreateItem(Archetype.MUNDANEITEMS, details[biome].TreeTag, out treeID);

                //try 50 times to put it somewhere
                int tries = 0;

                while (tries < 50)
                {
                    MapBlock randomBlock = map[random.Next(map.GetLength(0)), random.Next(map.GetLength(1))];

                    if (randomBlock.MayContainItems)
                    {
                        randomBlock.ForcePutItemOnBlock(item);
                        break;
                    }

                    tries++;
                }
            }

            List<Actor> actorList = new List<Actor>();

            //There, now that's done, lets generate some animals
            if (herdAmount + banditAmount > 0)
            {
                var herds = ActorGeneration.CreateAnimalHerds(biome, false, null, herdAmount);
                var bandits = CampGenerator.CreateBandits(banditAmount);

                var actorGroups = herds.Union(bandits);

                //Each actor group will be placed in a random 3 radius circle

                foreach (var actorGroup in actorGroups)
                {
                    MapBlock randomBlock = map[random.Next(map.GetLength(0)), random.Next(map.GetLength(1))];

                    Rectangle wanderRect = new Rectangle(randomBlock.Tile.Coordinate.X - 2, randomBlock.Tile.Coordinate.Y - 2, 4, 4);

                    //Put the actor groups somewhere around that block
                    var blocks = map.Cast<MapBlock>().ToArray().Where(b => Math.Abs(b.Tile.Coordinate - randomBlock.Tile.Coordinate) < 4).ToArray();

                    //Pick a number of random blocks

                    foreach (var newActor in actorGroup)
                    {
                        int tries = 0;

                        while (tries < 50)
                        {
                            var actorBlock = blocks[random.Next(blocks.Length)];

                            if (actorBlock.MayContainItems)
                            {
                                //Put it there
                                newActor.MapCharacter.Coordinate = actorBlock.Tile.Coordinate;
                                actorBlock.ForcePutItemOnBlock(newActor.MapCharacter);

                                //Make them wander
                                newActor.MissionStack.Push(new WanderMission() { LoiterPercentage = 50, WanderPoint = actorBlock.Tile.Coordinate, WanderRectangle = wanderRect });

                                actorList.Add(newActor);

                                break;
                            }

                            tries++;
                        }
                    }
                }

            }

            //Drop the player in the thick of it
            MapBlock center = map[map.GetLength(0) / 2, map.GetLength(1) / 2];

            center.RemoveTopItem(); //Remove it if someone else wanted it

            startPoint = center.Tile.Coordinate;

            actors = actorList.ToArray();

            return map;
        }
Пример #13
0
        /// <summary>
        /// Performs an attack on a character. Will also give an amount of feedback. Also reduces the health of the defender if the attack hits
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="defender"></param>
        /// <param name="location"></param>
        /// <param name="special">Special attack modifications to make. THIS DOES NOT CONSIDER TARGETS OR ATTACKS </param>
        /// <returns></returns>
        public static ActionFeedback[] Attack(Actor attacker, Actor defender, AttackLocation location, SpecialAttack special = null)
        {
            List<ActionFeedback> feedback = new List<ActionFeedback>();

            if (defender.MapCharacter == null)
            {
                return new ActionFeedback[] { }; //What on earth are you doing?
            }

            int distance = attacker.MapCharacter.Coordinate - defender.MapCharacter.Coordinate; //This will later be used for ranged attacks

            if (distance >= 2)
            {
                //If the defender is not the character, get thhe defender to walk to the attacked location
                if (!defender.IsPlayerCharacter)
                {
                    defender.MissionStack.Push(defender.CurrentMission);
                    //It's not retainable, so if it's preempted by another mission he won't walk back to the attacked location for nothing
                    defender.CurrentMission = new WalkToMission() { isRetainable = false, TargetCoordinate = attacker.MapCharacter.Coordinate };
                }
            }

            //Do we succeed in the attack?
            int atk = 0;
            int def = 0;

            //The type of dice we roll 3 of to determine weapon damage
            int weaponDiceRolls = attacker.UnarmedDamageDice; //Default damage
            int weaponWoundPotential = 0;
            int weaponStunAmount = 0;

            if (distance < 2)
            {
                if (attacker.Inventory.EquippedItems.ContainsKey(EquipmentLocation.WEAPON) && attacker.Anatomy.RightArm > 0)
                {
                    //Do we have a weapon and an arm to use it?
                    weaponDiceRolls = attacker.Inventory.EquippedItems[EquipmentLocation.WEAPON].DamageDice;
                    weaponWoundPotential = attacker.Inventory.EquippedItems[EquipmentLocation.WEAPON].WoundPotential;
                    weaponStunAmount = attacker.Inventory.EquippedItems[EquipmentLocation.WEAPON].StunAmount;
                }
            }
            else
            {
                //Grab the weapon from the BOW slot
                if (attacker.Inventory.EquippedItems.ContainsKey(EquipmentLocation.BOW) && attacker.Anatomy.RightArm > 0 && attacker.Anatomy.LeftArm > 0)
                {
                    weaponDiceRolls = attacker.Inventory.EquippedItems[EquipmentLocation.BOW].DamageDice;
                    weaponWoundPotential = attacker.Inventory.EquippedItems[EquipmentLocation.BOW].WoundPotential;
                    weaponStunAmount = attacker.Inventory.EquippedItems[EquipmentLocation.BOW].StunAmount;
                }
                else
                {
                    //Firing with a destroyed upper body? For shame
                    feedback.Add(new LogFeedback(null, Color.Red, "You are unable to use a ranged weapon under these conditions"));
                }
            }

            DamageType damageType = DamageType.SLASH;
            if (distance >= 2)
            {
                //Ranged
                damageType = DamageType.PIERCE;
            }

            GetStanceEffect(out atk, out def, attacker.CombatStance);

            //Does the defender have a shield?
            int shieldBonus = 0;

            if (defender.Inventory.EquippedItems.ContainsKey(EquipmentLocation.SHIELD) && defender.Anatomy.LeftArm != 0)
            {
                shieldBonus = defender.Inventory.EquippedItems[EquipmentLocation.SHIELD].ArmourRating;
            }

            int hitChance = 0;

            if (distance < 2)
            {
                //Chance to hit  for hand to hand-
                // Attacker Skill + Brawn - 5 + location penalty + stance effect  VS Defender Skill + Agil + stance effect + shield bonus
                hitChance = attacker.Attributes.HandToHand + attacker.TotalBrawn - 5 + penaltyDict[location] + atk;
            }
            else
            {
                //Chance to hit  for ranged-
                // Attacker Skill + perc - 5 + location penalty + stance effect - distance*2  VS Defender Skill + Agil + stance effect + shield bonus
                hitChance = attacker.Attributes.Ranged + attacker.TotalPerc - 5 - distance * 2 + penaltyDict[location] + atk;
            }

            if (special != null)
            {
                hitChance += special.Effects.FirstOrDefault(e => e.EffectType == SpecialAttackType.ACCURACY) == null ? 0 : special.Effects.FirstOrDefault(e => e.EffectType == SpecialAttackType.ACCURACY).EffectValue;
            }

            GetStanceEffect(out atk, out def, defender.CombatStance);

            int defendChance = defender.Attributes.Dodge + def + shieldBonus;

            //See what the difference is
            int difference = hitChance - defendChance;

            //Now roll a d20 and see whether we hit
            int diceRoll = random.Next(20) + 1;

            if (difference + diceRoll > 0)
            {
                //We have a hit

                //The defender will learn something
                defender.Attributes.IncreaseSkill(SkillName.DODGER);

                //Are they wearing armour ?
                if (defender.Inventory.EquippedItems.ContainsKey(EquipmentLocation.BODY))
                {
                    defender.Attributes.IncreaseSkill(SkillName.ARMOUR_USER);
                }

                //Are they using a shield?
                if (defender.Inventory.EquippedItems.ContainsKey(EquipmentLocation.SHIELD))
                {
                    defender.Attributes.IncreaseSkill(SkillName.BLOCKER);
                }

                feedback.Add(LogAction(attacker, defender, location, damageType, LogMessageStatus.HIT, diceRoll));

                //Calculate the amount of damage we're going to do. Roll 3 dice of a particular kind

                int weaponDamage = random.Next(weaponDiceRolls + 1) + random.Next(weaponDiceRolls + 1) + random.Next(weaponDiceRolls + 1);

                Console.WriteLine("Damage Roll : " + weaponDamage);

                int damage = weaponDamage;

                if (special != null)
                {
                    damage += special.Effects.FirstOrDefault(e => e.EffectType == SpecialAttackType.DAMAGE) == null ? 0 : special.Effects.FirstOrDefault(e => e.EffectType == SpecialAttackType.DAMAGE).EffectValue;
                }

                if (damage > 1)
                {
                    //Do we have any defences?
                    if (defender.IsPlayerCharacter && defender.CurrentDefences > 0)
                    {
                        //Break one instead
                        defender.CurrentDefences--;

                        feedback.Add(LogAction(attacker, defender, location, damageType, LogMessageStatus.DEFENDED, diceRoll));

                        //And mark it
                        GameState.LocalMap.TemporaryGraphics.Add(new TemporaryGraphic()
                        {
                            Coord = new MapCoordinate(defender.MapCharacter.Coordinate),
                            Graphic = SpriteManager.GetSprite(distance < 2 ? InterfaceSpriteName.SWORD_BLOCKED : InterfaceSpriteName.BOW_BLOCKED),
                            LifeTime = attacker.IsPlayerCharacter ? 2 : 2
                        });

                        return feedback.ToArray();

                    }
                }

                //Apply the damage
                //Is the user wearing any armour?
                if (location == AttackLocation.CHEST || location == AttackLocation.LEFT_ARM || location == AttackLocation.RIGHT_ARM)
                {
                    //Determine how much damage we can get through due to pierce
                    int piercing = 0;

                    if (special != null)
                    {
                        piercing = special.Effects.FirstOrDefault(e => e.EffectType == SpecialAttackType.PIERCING) == null ? 0 : special.Effects.FirstOrDefault(e => e.EffectType == SpecialAttackType.PIERCING).EffectValue;
                    }

                    //Use the chest armour
                    if (defender.Inventory.EquippedItems.ContainsKey(EquipmentLocation.BODY))
                    {
                        int block = defender.Inventory.EquippedItems[EquipmentLocation.BODY].ArmourRating - piercing;

                        damage -= (block > 0 ? block : 0);

                        //Do we damage the armour?
                        int sunder = 0;

                        if (special != null)
                        {
                            sunder = special.Effects.FirstOrDefault(e => e.EffectType == SpecialAttackType.SUNDER) == null ? 0 : special.Effects.FirstOrDefault(e => e.EffectType == SpecialAttackType.SUNDER).EffectValue;
                        }

                        if (sunder > 0 && defender.Inventory.EquippedItems[EquipmentLocation.BODY].ArmourRating > 0)
                        {
                            defender.Inventory.EquippedItems[EquipmentLocation.BODY].ArmourRating -= sunder;

                            if (defender.Inventory.EquippedItems[EquipmentLocation.BODY].ArmourRating < 0) //no negative block
                            {
                                defender.Inventory.EquippedItems[EquipmentLocation.BODY].ArmourRating = 0;
                            }

                        }

                    }
                }

                //Other location ?
                if (location == AttackLocation.HEAD)
                {
                    //Use the head armour
                    if (defender.Inventory.EquippedItems.ContainsKey(EquipmentLocation.HEAD))
                    {
                        damage -= defender.Inventory.EquippedItems[EquipmentLocation.HEAD].ArmourRating;
                    }
                }

                if (location == AttackLocation.LEGS)
                {
                    //Use the head armour
                    if (defender.Inventory.EquippedItems.ContainsKey(EquipmentLocation.LEGS))
                    {
                        damage -= defender.Inventory.EquippedItems[EquipmentLocation.LEGS].ArmourRating;
                    }
                }

                if (damage <= 0)
                {
                    //Bounced off the armour
                    feedback.Add(LogAction(attacker, defender, location, damageType, LogMessageStatus.BOUNCE, diceRoll));

                    GameState.LocalMap.TemporaryGraphics.Add(new TemporaryGraphic()
                    {
                        Coord = new MapCoordinate(defender.MapCharacter.Coordinate),
                        Graphic = SpriteManager.GetSprite(distance < 2 ? InterfaceSpriteName.SWORD_ARMOUR : InterfaceSpriteName.BOW_ARMOUR),
                        LifeTime = attacker.IsPlayerCharacter ? 2 : 2
                    });

                    return feedback.ToArray();
                }

                //Do we wound the character?
                diceRoll = random.Next(10) + 1;

                int woundRoll = diceRoll + (defender.Attributes.WoundResist - weaponWoundPotential) - 5;

                int woundBonus = 0;

                if (special != null)
                {
                    woundBonus = special.Effects.FirstOrDefault(e => e.EffectType == SpecialAttackType.BLEED) == null ? 0 : special.Effects.FirstOrDefault(e => e.EffectType == SpecialAttackType.BLEED).EffectValue;

                }
                woundRoll += woundBonus;

                if (woundRoll <= 0)
                {
                    //Yes - open a wound
                    defender.Anatomy.BloodLoss++;
                    defender.Anatomy.BloodLoss += woundBonus; //Yeah, bleed makes you bleed more AND increases chance of bleed. Not entirely sure this won't be overpowered

                    Console.WriteLine("Wounded " + woundRoll);

                    //Log it
                    feedback.Add(LogAction(attacker, defender, location, damageType, LogMessageStatus.BLEED, woundRoll));
                }

                //Roll again
                diceRoll = random.Next(10) + 1;
                int stunRoll = diceRoll + (defender.Attributes.WoundResist - weaponStunAmount) - 5;

                int stunBonus = 0;

                if (special != null)
                {
                    stunBonus = special.Effects.FirstOrDefault(e => e.EffectType == SpecialAttackType.STUN) == null ? 0 : special.Effects.FirstOrDefault(e => e.EffectType == SpecialAttackType.STUN).EffectValue;
                }

                stunRoll += stunBonus;

                if (stunRoll <= 0)
                {
                    //Stun him
                    defender.Anatomy.StunAmount++;
                    defender.Anatomy.StunAmount += stunRoll; //Yeah stun makes you more likely to get stunned and makes you stun longer. Not entirely sure this won't be as overpowered as ell

                    Console.WriteLine("Stunned " + stunRoll);
                }

                //Any damage bonus ?
                if (special != null)
                {
                    damage += special.Effects.FirstOrDefault(e => e.EffectType == SpecialAttackType.DAMAGE) == null ? 0 : special.Effects.FirstOrDefault(e => e.EffectType == SpecialAttackType.DAMAGE).EffectValue;
                }

                #region Push
                if (special != null)
                {
                    //Do we have a push?
                    int pushAmount = special.Effects.FirstOrDefault(e => e.EffectType == SpecialAttackType.PUSH) == null ? 0 : special.Effects.First(e => e.EffectType == SpecialAttackType.PUSH).EffectValue;

                    if (distance >= 2)
                    {
                        pushAmount = 0; //No push!
                    }

                    if (pushAmount > 0)
                    {
                        //Shove the target back by the total amount of push. Or try to at least

                        //Let's determine the direction
                        int pushX = 0;
                        int pushY = 0;

                        pushX = attacker.MapCharacter.Coordinate.X - defender.MapCharacter.Coordinate.X ;
                        pushY = attacker.MapCharacter.Coordinate.Y - defender.MapCharacter.Coordinate.Y;

                        for (int i = 0; i < pushAmount; i++)
                        {
                            //PUSH!
                            //Is the tile free?
                            if (GameState.LocalMap.GetBlockAtCoordinate(new MapCoordinate(defender.MapCharacter.Coordinate.X, defender.MapCharacter.Coordinate.Y, 0, MapType.LOCAL)).MayContainItems)
                            {
                                //Yeah push em
                                GameState.LocalMap.GetBlockAtCoordinate(new MapCoordinate(defender.MapCharacter.Coordinate.X + pushX, defender.MapCharacter.Coordinate.Y + pushY, 0, MapType.LOCAL)).ForcePutItemOnBlock(defender.MapCharacter);
                            }
                            else
                            {
                                //Is there an obstacle in the way?
                                if (GameState.LocalMap.GetBlockAtCoordinate(new MapCoordinate(defender.MapCharacter.Coordinate.X, defender.MapCharacter.Coordinate.Y, 0, MapType.LOCAL)).IsSeeThrough)
                                {
                                    //No, stop there
                                    break;
                                }
                                else
                                {
                                    //Ouch! Stop there anyway

                                    //Do damage equal to push left
                                    damage += pushAmount - i;

                                    feedback.Add(new LogFeedback(null, Color.Red, defender.Name + " hits an obstacle"));
                                    break;
                                }
                            }
                        }
                    }
                }
                #endregion

                //Apply the damage
                switch (location)
                {
                    case AttackLocation.CHEST:
                        defender.Anatomy.Chest -= damage;
                        break;
                    case AttackLocation.HEAD:
                        defender.Anatomy.Head -= damage;
                        break;
                    case AttackLocation.LEFT_ARM:
                        defender.Anatomy.LeftArm -= damage;
                        break;
                    case AttackLocation.LEGS:
                        defender.Anatomy.Legs -= damage;
                        break;
                    case AttackLocation.RIGHT_ARM:
                        defender.Anatomy.RightArm -= damage;
                        break;
                    default:
                        throw new NotImplementedException(location + " has no code prepared for damage");
                }

                GameState.LocalMap.TemporaryGraphics.Add(new TemporaryGraphic()
                {
                    Coord = new MapCoordinate(defender.MapCharacter.Coordinate),
                    Graphic = SpriteManager.GetSprite(distance < 2 ? InterfaceSpriteName.SWORD_HIT : InterfaceSpriteName.BOW_HIT),
                    LifeTime = attacker.IsPlayerCharacter ? 2 : 2
                });

                //Damage assessment - Do this properly later
                switch (location)
                {
                    case AttackLocation.HEAD:
                        if (defender.Anatomy.Head < 0)
                        {
                            if (defender.Anatomy.Head <= -5)
                            {
                                //Destroyed
                                feedback.Add(LogAction(attacker, defender, location, damageType, LogMessageStatus.DESTROY, diceRoll));
                            }
                            else
                            {
                                //Disabled
                                feedback.Add(LogAction(attacker, defender, location, damageType, LogMessageStatus.DISABLE, diceRoll));
                            }

                            //Dead
                            feedback.Add(LogAction(attacker, defender, location, damageType, LogMessageStatus.KILL, diceRoll));
                            //Close the interface
                            feedback.Add(new InterfaceToggleFeedback(InternalActionEnum.OPEN_ATTACK, false, defender));
                            KillCharacter(defender);
                        }
                        break;

                    case AttackLocation.CHEST:
                        if (defender.Anatomy.Chest < 0)
                        {
                            if (defender.Anatomy.Chest <= -5)
                            {
                                //Destroyed
                                feedback.Add(LogAction(attacker, defender, location, damageType, LogMessageStatus.DESTROY, diceRoll));
                            }
                            else
                            {
                                //Disabled
                                feedback.Add(LogAction(attacker, defender, location, damageType, LogMessageStatus.DISABLE, diceRoll));
                            }

                            //Dead
                            feedback.Add(LogAction(attacker, defender, location, damageType, LogMessageStatus.KILL, diceRoll));
                            feedback.Add(new InterfaceToggleFeedback(InternalActionEnum.OPEN_ATTACK, false, defender));
                            KillCharacter(defender);
                        }
                        break;

                    case AttackLocation.LEFT_ARM:
                        if (defender.Anatomy.LeftArm < 0)
                        {
                            if (defender.Anatomy.LeftArm <= -5)
                            {
                                //Destroyed
                                feedback.Add(LogAction(attacker, defender, location, damageType, LogMessageStatus.DESTROY, diceRoll));
                            }
                            else
                            {
                                //Disabled
                                feedback.Add(LogAction(attacker, defender, location, damageType, LogMessageStatus.DISABLE, diceRoll));
                            }
                        }
                        break;

                    case AttackLocation.LEGS:
                        if (defender.Anatomy.Legs < 0)
                        {
                            if (defender.Anatomy.Legs <= -5)
                            {
                                //Destroyed
                                feedback.Add(LogAction(attacker, defender, location, damageType, LogMessageStatus.DESTROY, diceRoll));
                            }
                            else
                            {
                                //Disabled
                                feedback.Add(LogAction(attacker, defender, location, damageType, LogMessageStatus.DISABLE, diceRoll));
                            }
                        }
                        break;

                    case AttackLocation.RIGHT_ARM:
                        if (defender.Anatomy.RightArm < 0)
                        {
                            if (defender.Anatomy.RightArm <= -5)
                            {
                                //Destroyed
                                feedback.Add(LogAction(attacker, defender, location, damageType, LogMessageStatus.DESTROY, diceRoll));
                            }
                            else
                            {
                                //Disabled
                                feedback.Add(LogAction(attacker, defender, location, damageType, LogMessageStatus.DISABLE, diceRoll));
                            }

                        }
                        break;

                    default:
                        throw new NotImplementedException("You've injured an unknown body part " + location);
                }

            }
            else
            {
                //We have a miss

                //The attacker learned something
                attacker.Attributes.IncreaseSkill(SkillName.FIGHTER);

                if (distance > 2)
                {
                    attacker.Attributes.IncreaseSkill(SkillName.ARCHER);
                }
                else
                    //Are they armed?
                    if (attacker.Inventory.EquippedItems.ContainsKey(EquipmentLocation.WEAPON))
                    {
                        switch (attacker.Inventory.EquippedItems[EquipmentLocation.WEAPON].WeaponType.ToUpper())
                        {
                            case "SWORD": attacker.Attributes.IncreaseSkill(SkillName.SWORDFIGHTER); break;
                            case "AXE": attacker.Attributes.IncreaseSkill(SkillName.AXEFIGHTER); break;
                            case "BOW": attacker.Attributes.IncreaseSkill(SkillName.ARCHER); break;
                            default: throw new NotImplementedException("No skill pertains to the weapon type " + attacker.Inventory.EquippedItems[EquipmentLocation.WEAPON].WeaponType);
                        }
                    }
                    else
                    {
                        //Unarmed then
                        attacker.Attributes.IncreaseSkill(SkillName.BRAWLER);
                    }

                feedback.Add(LogAction(attacker, defender, location, damageType, LogMessageStatus.MISS, diceRoll));

                GameState.LocalMap.TemporaryGraphics.Add(new TemporaryGraphic()
                {
                    Coord = new MapCoordinate(defender.MapCharacter.Coordinate),
                    Graphic = SpriteManager.GetSprite(distance < 2 ? InterfaceSpriteName.SWORD_BLOCKED : InterfaceSpriteName.BOW_BLOCKED),
                    LifeTime = (attacker.IsPlayerCharacter ? 2 : 2)
                });
            }

            //We're done

            return feedback.ToArray();
        }
Пример #14
0
        public AttackActorComponent(int locationX, int locationY, Actor attacker, Actor target)
        {
            this.locationX = locationX;
            this.locationY = locationY;
            this.attacker = attacker;
            this.TargetActor = target;
            this.currentAttackLocation = AttackLocation.CHEST;

            //Force a move
            this.PerformDrag(locationX, locationY);
        }
Пример #15
0
        /// <summary>
        /// Creates an Enemy of a paticular type (optional), having a particular tag (optional) and having a particular intelligence (optional).
        /// Will return the enemy ID so that you can get the actual item from the crea
        /// </summary>
        /// <param name="enemyType"></param>
        /// <param name="enemyTag"></param>
        /// <param name="intelligent"></param>
        /// <param name="level">The skill level of this enemy</param>
        /// <param name="gearCost">The total cost of this unit's equipped items</param>
        /// <param name="?"></param>
        /// <returns></returns>
        public static Actor CreateActor(string enemyType, string enemyTag, bool? intelligent, int level, int gearCost, Gender? gender, out int enemyID, ActorProfession? profession = null)
        {
            //Get all the data from the database and we'll make our own filtering
            var dictionary = DatabaseHandling.GetDatabase(Archetype.ENEMIES);

            var possibleMatches = dictionary.Values.AsQueryable();

            if (!String.IsNullOrEmpty(enemyType))
            {
                possibleMatches = possibleMatches.Where(v => v[4].Equals(enemyType));
            }

            if (!String.IsNullOrEmpty(enemyTag))
            {
                possibleMatches = possibleMatches.Where(v => v[5].Equals(enemyTag));
            }

            if (intelligent.HasValue)
            {
                possibleMatches = possibleMatches.Where(v => Boolean.Parse(v[7]).Equals(intelligent.Value));
            }

            if (gender.HasValue)
            {
                possibleMatches = possibleMatches.Where(v => (v[12]).Equals(gender.Value.ToString()));
            }

            //Put the possible matches and pick one at random
            if (possibleMatches.Count() == 0)
            {
                enemyID = -1;
                return null; //No match
            }

            //Pick one at random
            var selected = possibleMatches.ToArray()[random.Next(possibleMatches.Count())];

            int aggressivity = Int32.Parse(selected[10]);

            //Create the details
            enemyID = Int32.Parse(selected[0]);
            EnemyData data = GetEnemyData(enemyID);

            DRObjects.Actor actor = new DRObjects.Actor();
            actor.EnemyData = data;
            actor.IsPlayerCharacter = false;
            // actor.LineOfSight = data.EnemyLineOfSight;
            actor.UniqueId = Guid.NewGuid();
            actor.IsAggressive = aggressivity > 0;
            actor.Gender = (Gender)Enum.Parse(typeof(Gender), selected[12]);

            actor.Name = ActorNameGenerator.GenerateName(enemyType, actor.Gender);

            //Give him attributes
            actor.Attributes = GenerateAttributes(data.EnemyType, data.Profession, level, actor);

            //Set his anatomy too
            actor.Anatomy = GenerateAnatomy(data.EnemyType);

            //link one to another
            actor.Attributes.Health = actor.Anatomy;

            //Create the equipped item inventory
            actor.Inventory.EquippedItems = GenerateEquippedItems(gearCost);

            //And create the inventory
            foreach (var item in actor.Inventory.EquippedItems.Values)
            {
                actor.Inventory.Inventory.Add(item.Category, item);
            }

            return actor;
        }
Пример #16
0
        /// <summary>
        /// Updates the Vendor's stock to brand new stock
        /// </summary>
        /// <param name="actor"></param>
        public void UpdateVendorStock(Actor actor)
        {
            //First see how much money they have to buy stuff with.
            //Money to buy stuff = SUM (Base Values of old stock Inventory Items) + Money on Hand - 1000

            int totalMoney = actor.VendorDetails.Stock.GetAllObjects().Sum(s => s.BaseValue) + actor.VendorDetails.Money - 1000;

            //Generate the stuff
            InventoryItemManager iim = new InventoryItemManager();

            actor.VendorDetails.Stock = new GroupedList<InventoryItem>();
            actor.VendorDetails.GenerationTime = new DivineRightDateTime(GameState.UniverseTime);

            switch (actor.VendorDetails.VendorType)
            {
                case VendorType.GENERAL:
                    foreach (InventoryItem inv in iim.GetItemsWithAMaxValue(InventoryCategory.ARMOUR.ToString(), totalMoney / 4))
                    {
                        inv.InInventory = true;
                        actor.VendorDetails.Stock.Add(inv.Category, inv);
                    }
                    foreach (InventoryItem inv in iim.GetItemsWithAMaxValue(InventoryCategory.LOOT.ToString(), totalMoney / 4))
                    {
                        inv.InInventory = true;
                        actor.VendorDetails.Stock.Add(inv.Category, inv);
                    }
                    foreach (InventoryItem inv in iim.GetItemsWithAMaxValue(InventoryCategory.WEAPON.ToString(), totalMoney / 4))
                    {
                        inv.InInventory = true;
                        actor.VendorDetails.Stock.Add(inv.Category, inv);
                    }
                    foreach (InventoryItem inv in iim.GetItemsWithAMaxValue(InventoryCategory.SUPPLY.ToString(), totalMoney / 4))
                    {
                        inv.InInventory = true;
                        actor.VendorDetails.Stock.Add(inv.Category, inv);
                    }
                    break;
                case VendorType.SMITH:
                    foreach (InventoryItem inv in iim.GetItemsWithAMaxValue(InventoryCategory.ARMOUR.ToString(), totalMoney / 2))
                    {
                        inv.InInventory = true;
                        actor.VendorDetails.Stock.Add(inv.Category, inv);
                    }
                    foreach (InventoryItem inv in iim.GetItemsWithAMaxValue(InventoryCategory.WEAPON.ToString(), totalMoney / 2))
                    {
                        inv.InInventory = true;
                        actor.VendorDetails.Stock.Add(inv.Category, inv);
                    }
                    break;
                case VendorType.TRADER:
                    foreach (InventoryItem inv in iim.GetItemsWithAMaxValue(InventoryCategory.LOOT.ToString(), totalMoney))
                    {
                        inv.InInventory = true;
                        actor.VendorDetails.Stock.Add(inv.Category, inv);
                    }
                    break;
                case VendorType.TAVERN:
                    foreach (InventoryItem inv in iim.GetItemsWithAMaxValue(InventoryCategory.SUPPLY.ToString(), totalMoney))
                    {
                        inv.InInventory = true;
                        actor.VendorDetails.Stock.Add(inv.Category, inv);
                    }
                    break;
            }

            actor.VendorDetails.Money = 1000;
        }
Пример #17
0
        /// <summary>
        /// Generates a vendor, adds the vendor details to the actor being created
        /// </summary>
        /// <param name="newActor"></param>
        /// <param name="actor"></param>
        public void GenerateVendor(Actor newActor, MapletActor actor)
        {
            newActor.VendorDetails = new VendorDetails();
            newActor.VendorDetails.VendorType = actor.VendorType.Value;
            newActor.VendorDetails.VendorLevel = actor.VendorLevel ?? 1;
            newActor.VendorDetails.GenerationTime = new DivineRightDateTime(GameState.UniverseTime);

            //Generate the stuff
            InventoryItemManager iim = new InventoryItemManager();

            int maxCategorySize = 1000 * newActor.VendorDetails.VendorLevel;

            newActor.VendorDetails.Stock = new GroupedList<InventoryItem>();

            switch (newActor.VendorDetails.VendorType)
            {
                case VendorType.GENERAL:
                    foreach (InventoryItem inv in iim.GetItemsWithAMaxValue(InventoryCategory.SUPPLY.ToString(), (int)(maxCategorySize * 0.75)))
                    {
                        inv.InInventory = true;
                        newActor.VendorDetails.Stock.Add(inv.Category, inv);
                    }
                    foreach (InventoryItem inv in iim.GetItemsWithAMaxValue(InventoryCategory.LOOT.ToString(), (int)(maxCategorySize * 0.75)))
                    {
                        inv.InInventory = true;
                        newActor.VendorDetails.Stock.Add(inv.Category, inv);
                    }
                    foreach (InventoryItem inv in iim.GetItemsWithAMaxValue(InventoryCategory.ARMOUR.ToString(), (int)(maxCategorySize * 0.75)))
                    {
                        inv.InInventory = true;
                        newActor.VendorDetails.Stock.Add(inv.Category, inv);
                    }
                    foreach (InventoryItem inv in iim.GetItemsWithAMaxValue(InventoryCategory.WEAPON.ToString(), (int)(maxCategorySize * 0.75)))
                    {
                        inv.InInventory = true;
                        newActor.VendorDetails.Stock.Add(inv.Category, inv);
                    }
                    break;
                case VendorType.SMITH:
                    foreach (InventoryItem inv in iim.GetItemsWithAMaxValue(InventoryCategory.ARMOUR.ToString(), (int)(maxCategorySize * 1.5)))
                    {
                        inv.InInventory = true;
                        newActor.VendorDetails.Stock.Add(inv.Category, inv);
                    }
                    foreach (InventoryItem inv in iim.GetItemsWithAMaxValue(InventoryCategory.WEAPON.ToString(), (int)(maxCategorySize * 1.5)))
                    {
                        inv.InInventory = true;
                        newActor.VendorDetails.Stock.Add(inv.Category, inv);
                    }
                    break;
                case VendorType.TRADER:
                    foreach (InventoryItem inv in iim.GetItemsWithAMaxValue(InventoryCategory.LOOT.ToString(), maxCategorySize * 3))
                    {
                        inv.InInventory = true;
                        newActor.VendorDetails.Stock.Add(inv.Category, inv);
                    }
                    break;
                case VendorType.TAVERN:
                    foreach (InventoryItem inv in iim.GetItemsWithAMaxValue(InventoryCategory.SUPPLY.ToString(), maxCategorySize))
                    {
                        inv.InInventory = true;
                        newActor.VendorDetails.Stock.Add(inv.Category, inv);
                    }
                    break;
            }

            newActor.VendorDetails.Money = 1000;
        }
Пример #18
0
        /// <summary>
        /// Regenerates the stats of an orc such that it retains any missions it has, however will be of a particular level with a particular gear cost
        /// Will also pick the correct orc icon depending on level
        /// </summary>
        /// <param name="level"></param>
        /// <param name="gearCost"></param>
        /// <param name="enemyID"></param>
        /// <returns></returns>
        public static void RegenerateOrc(Actor actor, int level, int gearCost)
        {
            Random random = new Random();

            //This should give us a random from 0.75 to 1.25
            double multiplier = (random.NextDouble() / 2) - 0.25 + 1;

            //Start by regenerating the actor's stats and gear
            actor.Attributes = GenerateAttributes("orc", level == 5 ? ActorProfession.WORKER : ActorProfession.WARRIOR, (int)(level * multiplier), actor);

            multiplier = (random.NextDouble() / 2) - 0.25 + 1;

            //And the gear
            actor.Inventory.EquippedItems = GenerateEquippedItems((int)(gearCost * multiplier));

            foreach (var item in actor.Inventory.EquippedItems.Values)
            {
                actor.Inventory.Inventory.Add(item.Category, item);
            }

            //And finally, we need to pick the right graphic
            string graphic = String.Empty;

            if (level <= 5)
            {
                actor.MapCharacter.Graphic = SpriteManager.GetSprite(LocalSpriteName.ENEMY_ORC_CIV);
            }
            else if (level <= 10)
            {
                actor.MapCharacter.Graphic = SpriteManager.GetSprite(LocalSpriteName.ENEMY_ORC_LIGHT);
            }
            else
            {
                actor.MapCharacter.Graphic = SpriteManager.GetSprite(LocalSpriteName.ENEMY_ORC_HEAVY);
            }

            //Done
        }
Пример #19
0
        /// <summary>
        /// Gets the actions which can be performed on this Block
        /// </summary>
        /// <param name="actor"></param>
        /// <returns></returns>
        public ActionType[] GetActions(Actor actor)
        {
            MapItem item = GetTopItem();
            List<ActionType> actions = item.GetPossibleActions(actor).ToList();

            if (this.Tile.GetType().Equals(typeof(GlobalTile)))
            {
                //We can also throw something - if we have line of sight - we'll worry about this later
                actions.Add(ActionType.THROW);
            }
            if (this.MayContainItems)
            {
                actions.Add(ActionType.MOVE);
            }

            return actions.ToArray();
        }
Пример #20
0
        public static SkillsAndAttributes GenerateAttributes(string race, ActorProfession profession, int level, Actor actor)
        {
            //Roll 6 3d3s and put the results in an array
            int[] results = new int[6];

            //We'll throw away the smallest one

            for (int i = 0; i < results.Length; i++)
            {
                results[i] = random.Next(3) + 1 + random.Next(3) + 1 + random.Next(3) + 1;
            }

            //sort the array by size so top one goes first
            results = results.OrderByDescending(r => r).ToArray();

            //Create a new ActorAttribute
            SkillsAndAttributes att = new SkillsAndAttributes();

            if (profession == ActorProfession.WARRIOR)
            {
                //Prefer Brawn, Agil, Perc, Intel then char
                att.Brawn = results[0];
                att.Agil = results[1];
                att.Perc = results[2];
                att.Intel = results[3];
                att.Char = results[4];

                //Combat skills - give him evasion and attack in an amount equal to level
                att.Evasion = level;
                att.HandToHand = level;

            }
            else if (profession == ActorProfession.BRUTE)
            {
                //Prefer Brawn, Agil, perc, Intel then char.
                att.Brawn = results[0];
                att.Agil = results[1];
                att.Perc = results[2];
                att.Intel = results[3];
                att.Char = results[4];

                //Combat skills - give him evasion and attack in an amount equal to level. More hand to hand, less evasion
                att.Evasion = level - 2;
                att.HandToHand = level + 2;
            }
            else if (profession == ActorProfession.RANGED)
            {
                //Prefer Perc, Agil, Brawn, Intel then char
                att.Perc = results[0];
                att.Agil = results[1];
                att.Brawn = results[2];
                att.Intel = results[3];
                att.Char = results[4];

                //Combat skills - give him evasion and attack in an amount equal to level.
                att.Evasion = level;
                att.HandToHand = level;

                actor.UsesRanged = true;

            }
            else if (profession == ActorProfession.DEFENDER)
            {
                //Prefer agil, brawn, perc, intel than char
                att.Agil = results[0];
                att.Brawn = results[1];
                att.Perc = results[2];
                att.Intel = results[3];
                att.Char = results[4];

                //Combat skills - give him evasion and attack in an amount equal to level. +2 to evasion -2 to H2H
                att.Evasion = level + 2;
                att.HandToHand = level - 2;
            }
            else if (profession == ActorProfession.WORKER || profession == ActorProfession.MERCHANT || profession == ActorProfession.RICH)
            {
                //Prefer things randomly
                results = results.OrderByDescending(r => random.Next(10)).ToArray();

                att.Brawn = results[0];
                att.Agil = results[1];
                att.Perc = results[2];
                att.Intel = results[3];
                att.Char = results[4];

                att.HandToHand = level;
                att.Evasion = level;
            }
            else
            {
                throw new NotImplementedException("No code for profession " + profession);
            }

            //Add the racial bonuses
            RaceData data = ReadRaceData(race);

            att.Agil = att.BaseAgil + data.AgilModifier;
            att.Brawn = att.BaseBrawn + data.BrawnModifier;
            att.Char = att.BaseChar + data.DexModifier;
            att.Intel = att.BaseIntel + data.IntelModifier;
            att.Perc = att.BasePerc + data.PercModifier;

            //Make sure all attributes are larger than 0
            att.Agil = att.BaseAgil > 0 ? att.BaseAgil : 0;
            att.Brawn = att.BaseBrawn > 0 ? att.BaseBrawn : 0;
            att.Char = att.BaseChar > 0 ? att.BaseChar : 0;
            att.Intel = att.BaseIntel > 0 ? att.BaseIntel : 0;
            att.Perc = att.BasePerc > 0 ? att.BasePerc : 0;

            att.Actor = actor;
            att.Health = actor.Anatomy;

            return att;
        }
Пример #21
0
        /// <summary>
        /// Creates an actor owned by a particular faction having a level +- 25% of the level passed.
        /// The actual actor will be chosen according to the actual level
        /// The worth of the equipment the actor is as described in the database for the chosen actor
        /// Actors chosen will be of the warrior profession
        /// </summary>
        /// <param name="owner"></param>
        /// <param name="level"></param>
        /// <returns></returns>
        public static Actor CreateActor(OwningFactions owner, int skillLevel)
        {
            int levelToCreate = GameState.Random.Next((int)(skillLevel * 0.75) > 0 ? (int)(skillLevel * 0.75) : 0, (int)(skillLevel * 1.25));

            //Get all the data from the database and we'll make our own filtering
            var dictionary = DatabaseHandling.GetDatabase(Archetype.ACTORS);

            var possibleMatches = dictionary.Values.AsQueryable();

            //Correct owner
            possibleMatches = possibleMatches.Where(v => v[4].ToUpper().Equals(owner.ToString()));

            //The closest one w.r.t skill level
            possibleMatches = possibleMatches.Where(v => Int32.Parse(v[11]) < levelToCreate).OrderBy(v => Int32.Parse(v[11]));

            //Have we got at least one?
            if (possibleMatches.Count() == 0)
            {
                //Nope sorry
                return null;
            }
            else
            {
                //Copy pasted from CreateActors - rule of 3s
                var chosen = possibleMatches.First();

                //Now we can generate the actor itself
                Actor actor = new Actor();
                actor.Anatomy = GenerateAnatomy(chosen[5]);

                actor.EnemyData = new EnemyData()
                {
                    EnemyID = Int32.Parse(chosen[0]),
                    EnemyLineOfSight = Int32.Parse(chosen[9]),
                    EnemyName = chosen[1],
                    EnemyType = chosen[5],
                    Intelligent = true,
                    Profession = ActorProfession.WARRIOR
                };

                //Pick a profession from warrior, rogue, brute or ranged
                int professionRandom = GameState.Random.Next(4);

                switch (professionRandom)
                {
                    case 0:
                        actor.EnemyData.Profession = ActorProfession.BRUTE; break;
                    case 1:
                        actor.EnemyData.Profession = ActorProfession.RANGED; break;
                    case 2:
                        actor.EnemyData.Profession = ActorProfession.WARRIOR; break;
                    case 3:
                        actor.EnemyData.Profession = ActorProfession.RANGED; break;
                }

                actor.Attributes = GenerateAttributes(chosen[5], actor.EnemyData.Profession, levelToCreate, actor);
                actor.Attributes.Actor = actor;

                actor.FeedingLevel = FeedingLevel.FULL;

                actor.Gender = (Gender)Enum.Parse(typeof(Gender), chosen[13]);

                actor.Inventory = new ActorInventory();

                actor.Inventory.EquippedItems = GenerateEquippedItems(Int32.Parse(chosen[12]),actor.EnemyData.Profession);

                //Add all of those into the inventory
                foreach (var item in actor.Inventory.EquippedItems.Values)
                {
                    actor.Inventory.Inventory.Add(item.Category, item);
                }

                actor.IsActive = true;
                actor.IsAggressive = chosen[8] == "1";
                actor.IsAlive = true;
                actor.IsAnimal = false;
                actor.IsDomesticatedAnimal = false;
                actor.IsPlayerCharacter = false;
                actor.IsStunned = false;

                //For fixing LoS
                actor.Attributes.Perc = Int32.Parse(chosen[9]) - 2;

                actor.Name = ActorNameGenerator.CanGenerateName(chosen[5]) ? ActorNameGenerator.GenerateName(chosen[5], actor.Gender) : chosen[1];

                actor.Owners = owner;
                actor.UniqueId = Guid.NewGuid();

                actor.MapCharacter = new LocalCharacter();

                LocalCharacter mc = actor.MapCharacter as LocalCharacter;

                mc.Actor = actor;
                mc.Coordinate = new MapCoordinate();
                mc.Description = chosen[10];
                mc.EnemyThought = EnemyThought.WAIT;

                string chosenGraphic = string.Empty;

                if (!String.IsNullOrWhiteSpace(chosen[3]))
                {
                    string setChoice = String.Empty;
                    //Does graphicset contain multiple choices?
                    if (chosen[3].Contains(","))
                    {
                        //Yes, lets split it
                        var possibleSets = chosen[3].Split(',');

                        setChoice = possibleSets[GameState.Random.Next(possibleSets.Length)];
                    }
                    else
                    {
                        setChoice = chosen[3];
                    }

                    //Instead of a single graphic, use a graphical set
                    mc.Graphics = GraphicSetManager.GetSprites((GraphicSetName)Enum.Parse(typeof(GraphicSetName), setChoice.ToUpper()));

                }
                else
                {
                    //Does graphic contain multiple choices?
                    if (chosen[2].Contains(","))
                    {
                        //yes, lets split it
                        var graphics = chosen[2].Split(',');

                        //use random to determine which one we want
                        chosenGraphic = graphics[GameState.Random.Next(graphics.Length)];

                        mc.Graphic = SpriteManager.GetSprite((LocalSpriteName)Enum.Parse(typeof(LocalSpriteName), chosenGraphic));
                    }
                    else
                    {
                        //nope
                        mc.Graphic = SpriteManager.GetSprite((LocalSpriteName)Enum.Parse(typeof(LocalSpriteName), chosen[2]));
                    }
                }

                mc.InternalName = chosen[2];
                mc.IsActive = true;
                mc.IsStunned = false;
                mc.MayContainItems = false;
                mc.Name = actor.Name;
                mc.OwnedBy = owner;

                return actor;
            }
        }
Пример #22
0
        /// <summary>
        /// Creates a number of actors for a particular owner and profession. It will also balance the level and difficulty of acctors, and will create a hierarchy of warriors.
        /// Do not use this for animals
        /// If there are no actors of that particular type for that profession, will not create anything
        /// </summary>
        public static Actor[] CreateActors(OwningFactions owner, ActorProfession profession, int total)
        {
            List<Actor> actors = new List<Actor>();

            //Get all the data from the database and we'll make our own filtering
            var dictionary = DatabaseHandling.GetDatabase(Archetype.ACTORS);

            var possibleMatches = dictionary.Values.AsQueryable();

            //Correct owner
            possibleMatches = possibleMatches.Where(v => v[4].ToUpper().Equals(owner.ToString()));

            //Correct profession
            possibleMatches = possibleMatches.Where(v => v[6].ToUpper().Equals(profession.ToString()));

            //Have we got at least one ?
            if (possibleMatches.Count() == 0)
            {
                return new Actor[] { }; //Nope - return nothing
            }

            //For use with warriors
            int level1 = 0;
            int level2 = 0;

            for (int i = 0; i < total; i++)
            {
                var possibles = possibleMatches;

                //Are we generating warriors?
                if (profession == ActorProfession.WARRIOR)
                {
                    int warriorGenerationLevel = 1;

                    if (level2 == 3)
                    {
                        //hard
                        warriorGenerationLevel = 3;
                        level2 = 0;
                    }
                    else if (level1 == 3)
                    {
                        //Generate a medium
                        warriorGenerationLevel = 2;
                        level1 = 0;
                        level2++;
                    }
                    else
                    {
                        //Generate an easy
                        warriorGenerationLevel = 1;
                        level1++;
                    }

                    possibles = possibles.Where(p => p[7].ToString().Equals(warriorGenerationLevel.ToString()));
                }

                //Pick a random one from the possibilities - this'll crash if we have no possibles, but that's going to be a problem anyway

                var chosen = possibles.ToArray()[(GameState.Random.Next(possibles.Count()))];

                //Now we can generate the actors themselves
                Actor actor = new Actor();
                actor.Anatomy = GenerateAnatomy(chosen[5]);
                actor.Attributes = GenerateAttributes(chosen[5], (ActorProfession)Enum.Parse(typeof(ActorProfession), chosen[6], true), Int32.Parse(chosen[11]), actor);

                actor.Attributes.Actor = actor;
                actor.EnemyData = new EnemyData()
                {
                    EnemyID = Int32.Parse(chosen[0]),
                    EnemyLineOfSight = Int32.Parse(chosen[9]),
                    EnemyName = chosen[1],
                    EnemyType = chosen[5],
                    Intelligent = true,
                    Profession = profession
                };

                actor.FeedingLevel = FeedingLevel.FULL;
                actor.Gender = (Gender)Enum.Parse(typeof(Gender), chosen[13]);

                actor.Inventory = new ActorInventory();

                if (profession == ActorProfession.WARRIOR)
                {
                    actor.Inventory.EquippedItems = GenerateEquippedItems(Int32.Parse(chosen[12]));

                    //Add all of those into the inventory
                    foreach (var item in actor.Inventory.EquippedItems.Values)
                    {
                        actor.Inventory.Inventory.Add(item.Category, item);
                    }
                }

                actor.IsActive = true;
                actor.IsAggressive = chosen[8] == "1";
                actor.IsAlive = true;
                actor.IsAnimal = false;
                actor.IsDomesticatedAnimal = false;
                actor.IsPlayerCharacter = false;
                actor.IsStunned = false;
                actor.Attributes.Perc = Int32.Parse(chosen[9]) - 2;

                actor.Name = ActorNameGenerator.CanGenerateName(chosen[5]) ? ActorNameGenerator.GenerateName(chosen[5], actor.Gender) : chosen[1];

                actor.Owners = owner;
                actor.UniqueId = Guid.NewGuid();

                actor.MapCharacter = new LocalCharacter();

                LocalCharacter mc = actor.MapCharacter as LocalCharacter;

                mc.Actor = actor;
                mc.Coordinate = new MapCoordinate();
                mc.Description = chosen[10];
                mc.EnemyThought = EnemyThought.WAIT;

                string chosenGraphic = string.Empty;

                if (!String.IsNullOrWhiteSpace(chosen[3]))
                {
                    string setChoice = String.Empty;
                    //Does graphicset contain multiple choices?
                    if (chosen[3].Contains(","))
                    {
                        //Yes, lets split it
                        var possibleSets = chosen[3].Split(',');

                        setChoice = possibleSets[GameState.Random.Next(possibleSets.Length)];
                    }
                    else
                    {
                        setChoice = chosen[3];
                    }

                    //Instead of a single graphic, use a graphical set
                    mc.Graphics = GraphicSetManager.GetSprites((GraphicSetName)Enum.Parse(typeof(GraphicSetName), setChoice.ToUpper()));

                }
                else
                {
                    //Does graphic contain multiple choices?
                    if (chosen[2].Contains(","))
                    {
                        //yes, lets split it
                        var graphics = chosen[2].Split(',');

                        //use random to determine which one we want
                        chosenGraphic = graphics[GameState.Random.Next(graphics.Length)];

                        mc.Graphic = SpriteManager.GetSprite((LocalSpriteName)Enum.Parse(typeof(LocalSpriteName), chosenGraphic));
                    }
                    else
                    {
                        //nope
                        mc.Graphic = SpriteManager.GetSprite((LocalSpriteName)Enum.Parse(typeof(LocalSpriteName), chosen[2]));
                    }
                }

                mc.InternalName = chosen[2];
                mc.IsActive = true;
                mc.IsStunned = false;
                //mc.LineOfSightRange = actor.LineOfSight.Value;
                mc.MayContainItems = false;
                mc.Name = actor.Name;
                mc.OwnedBy = owner;

                actors.Add(actor);
            }

            return actors.ToArray();
        }
Пример #23
0
        /// <summary>
        /// Attack a particular target using this special attack
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="target"></param>
        /// <param name="attack"></param>
        /// <returns></returns>
        public static ActionFeedback[] PerformSpecialAttack(Actor attacker, Actor target, SpecialAttack attack)
        {
            List<ActionFeedback> feedback = new List<ActionFeedback>();

            feedback.Add(new LogFeedback(InterfaceSpriteName.SA1, Color.Blue, "You strike using " + attack.AttackName));

            if (target.MapCharacter == null)
            {
                return new ActionFeedback[] { }; //Huh ?
            }

            //So, first we need to determine how many targets we're going to attack, and how many times
            List<Actor> targets = new List<Actor>();

            targets.Add(target);

            for (int i = 1; i < attack.Effects.Where(e => e.EffectType == SpecialAttackType.TARGETS).Select(e => e.EffectValue).FirstOrDefault(); i++)
            {
                //Go around the attacker and add another target - later we'll need to check if they're hostile
                foreach (var block in GameState.LocalMap.GetBlocksAroundPoint(attacker.MapCharacter.Coordinate, 1))
                {
                    foreach (var character in block.GetItems().Where(gi => gi.IsActive && gi.GetType() == typeof(LocalCharacter)))
                    {
                        Actor newTarget = (character as LocalCharacter).Actor;

                        if (!targets.Contains(newTarget))
                        {
                            //Add it!
                            targets.Add(newTarget);
                            continue;
                        }
                    }
                }

                break; //No more actors
            }

            int attacksToMake = attack.Effects.FirstOrDefault(e => e.EffectType == SpecialAttackType.ATTACKS) == null ? 1 : attack.Effects.FirstOrDefault(e => e.EffectType == SpecialAttackType.ATTACKS).EffectValue;

            for (int i = 0; i < attacksToMake; i++)
            {
                foreach (var defender in targets)
                {
                    //Are we alive?
                    if (!defender.IsAlive)
                    {
                        continue; //yeah he's dead jim
                    }
                    else
                    {
                        //Attack!
                        feedback.AddRange(Attack(attacker, defender, AttackLocation.CHEST, attack));
                    }
                }
            }

            //Phew, now let's set the timeout
            attack.TimeOutLeft = attack.TimeOut;

            //Done
            return feedback.ToArray();
        }
Пример #24
0
        /// <summary>
        /// Regenerates a site's actors based on the sitedata. If it is not marked as needing regeneration , will do nothing
        /// </summary>
        /// <param name="sitedata"></param>
        /// <param name="currentMap"></param>
        /// <param name="actors"></param>
        /// <returns></returns>
        public static MapBlock[,] RegenerateSite(SiteData sitedata, MapBlock[,] currentMap, Actor[] currentActors, out Actor[] newActors)
        {
            if (!sitedata.MapRegenerationRequired)
            {
                //Do nothing
                newActors = currentActors;
                return currentMap;
            }

            //So, first go through the actors and remove any of them which shouldn't be there. That is to say all of them which are site members (I realise it's a big ugly but it's a clean check)
            List<Actor> actors = currentActors.ToList();

            var actorsToRemove = currentActors.Where(ca => ca.SiteMember);

            //Remove the map items for these actors
            foreach(var a in actorsToRemove)
            {
                a.IsAlive = false;
            }

            //We'll handle actors soon, first we need to go through all the items and set the ones with the wrong owner to inactive
            foreach (var mapBlock in currentMap)
            {
                foreach (var item in mapBlock.GetItems())
                {
                    if (!item.OwnedBy.HasFlag(sitedata.Owners))
                    {
                        item.IsActive = false;
                    }
                    else
                    {
                        item.IsActive = true;
                    }
                }
            }

            //Now go through the site's actors and create the new ones as required
            foreach (ActorProfession profession in Enum.GetValues(typeof(ActorProfession)))
            {
                //So do we have any wander areas for them ?
                var possibleAreas = sitedata.WanderAreas.Where(wa => wa.Factions.HasFlag(sitedata.Owners) && wa.Profession.Equals(profession));
                var possibleRoutes = sitedata.PatrolRoutes.Where(pr => pr.Owners.HasFlag(sitedata.Owners) && pr.Profession.Equals(profession));

                //Any actors?
                if (sitedata.ActorCounts.ContainsKey(profession))
                {
                    //Yes, how many
                    int total = sitedata.ActorCounts[profession];

                    var a = ActorGeneration.CreateActors(sitedata.Owners, profession, total);

                    foreach (var ac in a)
                    {
                        ac.SiteMember = true;
                    }

                    actors.AddRange(a);

                    foreach (var actor in a)
                    {
                        //So, where we going to drop them off ? Randomly
                        int tries = 0;

                        for (; ; )
                        {
                            int randomX = GameState.Random.Next(currentMap.GetLength(0));
                            int randomY = GameState.Random.Next(currentMap.GetLength(1));

                            if (currentMap[randomX, randomY].MayContainItems)
                            {
                                //Plop it on there
                                actor.MapCharacter.Coordinate = new MapCoordinate(randomX, randomY, 0, MapType.LOCAL);
                                currentMap[randomX, randomY].ForcePutItemOnBlock(actor.MapCharacter);
                                tries = 0;
                                break;
                            }
                            else
                            {
                                tries++;
                            }

                            if (tries >= 150)
                            {
                                //give up
                                break;
                            }
                        }

                        //Go through each actor, and either tell them to wander in the whole map, or within any possible area which matches
                        //Any possible area avaialble?
                        List<object> possibleMissions = new List<object>(); //I know :( But Using an interface or trying to mangle together an inheritance was worse

                        possibleMissions.AddRange(possibleAreas.Where(pa => pa.MaxAmount > pa.CurrentAmount));
                        possibleMissions.AddRange(possibleRoutes);

                        var chosenArea = possibleMissions.OrderBy(pa => GameState.Random.Next(100)).FirstOrDefault();

                        if (chosenArea == null)
                        {
                            //Wander around the whole map
                            actor.CurrentMission = new WanderMission() { LoiterPercentage = 25, WanderPoint = new MapCoordinate(currentMap.GetLength(0) / 2, currentMap.GetLength(1) / 2, 0, MapType.LOCAL), WanderRectangle = new Rectangle(0, 0, currentMap.GetLength(0), currentMap.GetLength(1)) };
                        }
                        else
                        {
                            //Is this a patrol or a wander ?
                            if (chosenArea.GetType().Equals(typeof(PatrolRoute)))
                            {
                                var patrolDetails = chosenArea as PatrolRoute;

                                PatrolRouteMission pm = new PatrolRouteMission();
                                pm.PatrolRoute.AddRange(patrolDetails.Route);

                                actor.CurrentMission = pm;
                            }
                            else if (chosenArea.GetType().Equals(typeof(MapletActorWanderArea)))
                            {
                                var wanderDetails = chosenArea as MapletActorWanderArea;

                                //Wander around in that area
                                actor.CurrentMission = new WanderMission() { LoiterPercentage = 25, WanderPoint = new MapCoordinate(wanderDetails.WanderPoint), WanderRectangle = wanderDetails.WanderRect };
                                wanderDetails.CurrentAmount++;
                            }
                        }

                    }

                }

            }

            newActors = actors.ToArray();
            sitedata.MapRegenerationRequired = false; //We're done

            return currentMap;
        }
Пример #25
0
        /// <summary>
        /// Returns a particular logged action.
        /// </summary>
        /// <returns></returns>
        private static ActionFeedback LogAction(Actor attacker, Actor defender, AttackLocation loc, DamageType type, LogMessageStatus status, int diceroll)
        {
            //Later we'll expand this and put in some randomisation and stuff

            ActionFeedback log = null;

            if (status == LogMessageStatus.BOUNCE)
            {
                //Bounces off the armour
                if (!attacker.IsPlayerCharacter)
                {
                    if (type == DamageType.CRUSH)
                    {
                        log = new LogFeedback(InterfaceSpriteName.DEFENSE, Color.DarkGreen, "The hit bounces off your armour");
                    }
                    else if (type == DamageType.SLASH)
                    {
                        log = new LogFeedback(InterfaceSpriteName.DEFENSE, Color.DarkGreen, "The hit scratches the armour, but doesn't cut through");
                    }
                    else if (type == DamageType.STAB)
                    {
                        log = new LogFeedback(InterfaceSpriteName.DEFENSE, Color.DarkGreen, "The hit fails to punch through your armour");
                    }
                    else if (type == DamageType.THRUST)
                    {
                        log = log = new LogFeedback(InterfaceSpriteName.DEFENSE, Color.DarkGreen, "The hit fails to punch through your armour");
                    }
                    else if (type == DamageType.PIERCE)
                    {
                        log = new LogFeedback(InterfaceSpriteName.DEFENSE, Color.DarkGreen, "The missile fails to punch through your armour");
                    }
                }
                else
                {
                    if (type == DamageType.CRUSH)
                    {
                        log = new LogFeedback(InterfaceSpriteName.DEFENSE, Color.DarkRed, "The hit bounces off your target's armour");
                    }
                    else if (type == DamageType.SLASH)
                    {
                        log = new LogFeedback(InterfaceSpriteName.DEFENSE, Color.DarkRed, "The hit scratches the armour, but doesn't cut through");
                    }
                    else if (type == DamageType.STAB)
                    {
                        log = new LogFeedback(InterfaceSpriteName.DEFENSE, Color.DarkRed, "The hit fails to punch through your target's armour");
                    }
                    else if (type == DamageType.THRUST)
                    {
                        log = log = new LogFeedback(InterfaceSpriteName.DEFENSE, Color.DarkRed, "The hit fails to punch through your target's armour");
                    }
                    else if (type == DamageType.PIERCE)
                    {
                        log = new LogFeedback(InterfaceSpriteName.DEFENSE, Color.DarkRed, "The missile fails to punch through your target's armour");
                    }
                }

                return log;
            }

            if (status == LogMessageStatus.DESTROY)
            {
                if (!attacker.IsPlayerCharacter)
                {
                    if (type == DamageType.CRUSH)
                    {
                        log = new LogFeedback(InterfaceSpriteName.BLOOD, Color.DarkRed, "Your " + loc.ToString().ToLower().Replace("_", " ") + " smashes into pulp under the force of the blow");
                    }
                    else if (type == DamageType.SLASH)
                    {
                        log = new LogFeedback(InterfaceSpriteName.BLOOD, Color.DarkRed, "Your " + loc.ToString().ToLower().Replace("_", " ") + " flies off in an arc");
                    }
                    else if (type == DamageType.STAB)
                    {
                        log = new LogFeedback(InterfaceSpriteName.BLOOD, Color.DarkRed, "Your " + loc.ToString().ToLower().Replace("_", " ") + " dangles off by its skin");
                    }
                    else if (type == DamageType.THRUST)
                    {
                        log = new LogFeedback(InterfaceSpriteName.BLOOD, Color.DarkRed, "Your " + loc.ToString().ToLower().Replace("_", " ") + " dangles off by its skin");
                    }
                    else if (type == DamageType.PIERCE)
                    {
                        log = new LogFeedback(InterfaceSpriteName.BLOOD, Color.DarkRed, "Your perforated " + loc.ToString().ToLower().Replace("_", " ") + " hangs limply off your side");
                    }
                }
                else
                {
                    if (type == DamageType.CRUSH)
                    {
                        log = new LogFeedback(InterfaceSpriteName.BLOOD, Color.DarkRed, "Your opponent's " + loc.ToString().ToLower().Replace("_", " ") + " smashes into pulp under the force of the blow");
                    }
                    else if (type == DamageType.SLASH)
                    {
                        log = new LogFeedback(InterfaceSpriteName.BLOOD, Color.DarkRed, "Your opponent's " + loc.ToString().ToLower().Replace("_", " ") + " flies off in an arc");
                    }
                    else if (type == DamageType.STAB)
                    {
                        log = new LogFeedback(InterfaceSpriteName.BLOOD, Color.DarkRed, "Your opponent's " + loc.ToString().ToLower().Replace("_", " ") + " dangles off by its skin");
                    }
                    else if (type == DamageType.THRUST)
                    {
                        log = new LogFeedback(InterfaceSpriteName.BLOOD, Color.DarkRed, "Your opponent's " + loc.ToString().ToLower().Replace("_", " ") + " dangles off by its skin");
                    }
                    else if (type == DamageType.PIERCE)
                    {
                        log = new LogFeedback(InterfaceSpriteName.BLOOD, Color.DarkRed, "Your opponent's perforated " + loc.ToString().ToLower().Replace("_", " ") + " hangs limply off their side");
                    }
                }

                return log;
            }

            if (status == LogMessageStatus.DISABLE)
            {
                if (!attacker.IsPlayerCharacter)
                {
                    if (type == DamageType.CRUSH)
                    {
                        log = new LogFeedback(InterfaceSpriteName.DEFENSE, Color.DarkRed, "Your " + loc.ToString().ToLower().Replace("_", " ") + " cracks loudly as the bones smash under the blow");
                    }
                    else if (type == DamageType.SLASH)
                    {
                        log = new LogFeedback(InterfaceSpriteName.DEFENSE, Color.DarkRed, "Your " + loc.ToString().ToLower().Replace("_", " ") + " is cut open with the attack");
                    }
                    else if (type == DamageType.STAB)
                    {
                        log = new LogFeedback(InterfaceSpriteName.DEFENSE, Color.DarkRed, "Your " + loc.ToString().ToLower().Replace("_", " ") + " bleeds heavily as the attack goes through");
                    }
                    else if (type == DamageType.THRUST)
                    {
                        log = new LogFeedback(InterfaceSpriteName.DEFENSE, Color.DarkRed, "Your " + loc.ToString().ToLower().Replace("_", " ") + " bleeds heavily as the attack goes through");
                    }
                    else if (type == DamageType.PIERCE)
                    {
                        log = new LogFeedback(InterfaceSpriteName.DEFENSE, Color.DarkRed, "Your " + loc.ToString().ToLower().Replace("_", " ") + " bleeds heavily as the missile pierces through");
                    }
                }
                else
                {
                    if (type == DamageType.CRUSH)
                    {
                        log = new LogFeedback(InterfaceSpriteName.DEFENSE, Color.DarkGreen, "Your opponent's " + loc.ToString().ToLower().Replace("_", " ") + " cracks loudly as the bones smash under the blow");
                    }
                    else if (type == DamageType.SLASH)
                    {
                        log = new LogFeedback(InterfaceSpriteName.DEFENSE, Color.DarkGreen, "Your opponent's " + loc.ToString().ToLower().Replace("_", " ") + " is cut open with the attack");
                    }
                    else if (type == DamageType.STAB)
                    {
                        log = new LogFeedback(InterfaceSpriteName.DEFENSE, Color.DarkGreen, "Your opponent's " + loc.ToString().ToLower().Replace("_", " ") + " bleeds heavily as the attack goes through");
                    }
                    else if (type == DamageType.THRUST)
                    {
                        log = new LogFeedback(InterfaceSpriteName.DEFENSE, Color.DarkGreen, "Your opponent's " + loc.ToString().ToLower().Replace("_", " ") + " bleeds heavily as the attack goes through");
                    }
                    else if (type == DamageType.PIERCE)
                    {
                        log = new LogFeedback(InterfaceSpriteName.DEFENSE, Color.DarkGreen, "Your opponent's " + loc.ToString().ToLower().Replace("_", " ") + " bleeds heavily as the missile pierces through");
                    }
                }

                return log;
            }

            if (status == LogMessageStatus.HIT)
            {
                if (attacker.IsPlayerCharacter)
                {
                    if (type == DamageType.PIERCE)
                    {
                        log = new LogFeedback(InterfaceSpriteName.BOW, Color.DarkGreen, "You loose (" + diceroll + ") at " + defender.EnemyData.EnemyName + " and hit him in the " + loc.ToString().ToLower().Replace("_", " "));
                    }
                    else
                    {
                        log = new LogFeedback(InterfaceSpriteName.SWORD, Color.DarkGreen, "You swing (" + diceroll + ") at " + defender.EnemyData.EnemyName + " and hit him in the " + loc.ToString().ToLower().Replace("_", " "));
                    }
                }
                else
                {
                    if (type == DamageType.PIERCE)
                    {
                        log = new LogFeedback(InterfaceSpriteName.SWORD, Color.DarkRed, attacker.EnemyData.EnemyName + " looses (" + diceroll + ") a projectile at you and hits you in the " + loc.ToString().ToLower().Replace("_", " "));
                    }
                    else
                    {
                        log = new LogFeedback(InterfaceSpriteName.SWORD, Color.DarkRed, attacker.EnemyData.EnemyName + " swings (" + diceroll + ") at you and hits you in the " + loc.ToString().ToLower().Replace("_", " "));
                    }
                }

                return log;
            }

            if (status == LogMessageStatus.KILL)
            {
                if (attacker.IsPlayerCharacter)
                {
                    log = new LogFeedback(InterfaceSpriteName.HEAD, Color.DarkGreen, "You strike your opponent down");
                }
                else
                {
                    //log = new CurrentLogFeedback(InterfaceSpriteName.HEAD, Color.DarkRed, "You die");
                    log = new CreateEventFeedback("Death");
                }

                return log;
            }

            if (status == LogMessageStatus.MISS)
            {
                //We have a miss
                if (attacker.IsPlayerCharacter)
                {
                    if (type == DamageType.PIERCE)
                    {
                        log = new LogFeedback(InterfaceSpriteName.SWORD, Color.DarkRed, "You loose  (" + diceroll + ") your projectile at " + defender.EnemyData.EnemyName + "'s " + loc.ToString().ToLower().Replace("_", " ") + " but miss");
                    }
                    else
                    {
                        log = new LogFeedback(InterfaceSpriteName.SWORD, Color.DarkRed, "You swing (" + diceroll + ") at " + defender.EnemyData.EnemyName + "'s " + loc.ToString().ToLower().Replace("_", " ") + " but miss");
                    }
                }
                else
                {
                    //Player is the defender

                    if (type == DamageType.PIERCE)
                    {
                        log = new LogFeedback(InterfaceSpriteName.SWORD, Color.DarkGreen, "The " + attacker.EnemyData.EnemyName + " looses (" + diceroll + ") their projectile at your " + loc.ToString().ToLower().Replace("_", " ") + ", but misses");
                    }
                    else
                    {
                        log = new LogFeedback(InterfaceSpriteName.SWORD, Color.DarkGreen, "The " + attacker.EnemyData.EnemyName + " swings (" + diceroll + ") at your " + loc.ToString().ToLower().Replace("_", " ") + ", but misses");
                    }
                }

                return log;
            }

            if (status == LogMessageStatus.NO_WOUND)
            {
                //No damage!
                if (attacker.IsPlayerCharacter)
                {
                    log = new LogFeedback(InterfaceSpriteName.BLOOD, Color.DarkRed, "You however fail to wound your opponent");
                }
                else
                {
                    log = new LogFeedback(InterfaceSpriteName.BLOOD, Color.DarkGreen, "It fails to properly wound you, however");
                }

                return log;
            }

            if (status == LogMessageStatus.BLEED)
            {
                if (defender.IsPlayerCharacter)
                {
                    if (defender.Anatomy.BloodLoss == 1)
                    {
                        //Wound opened
                        log = new LogFeedback(InterfaceSpriteName.BLEEDING, Color.DarkRed, "The attack opens a wound");
                    }
                    else
                    {
                        //Wound worsended
                        log = new LogFeedback(InterfaceSpriteName.BLEEDING, Color.DarkRed, "The attack worsens your wound");
                    }
                }

                return log;
            }

            if (status == LogMessageStatus.DEFENDED)
            {
                log = new LogFeedback(InterfaceSpriteName.DEFENSE, Color.DarkBlue, "You dodge the blow at the last moment");

                return log;
            }

            throw new NotImplementedException("No idea what to do here");
        }
Пример #26
0
        /// <summary>
        /// Generates a site
        /// </summary>
        /// <param name="siteType"></param>
        /// <param name="biomeType"></param>
        /// <param name="owner"></param>
        /// <param name="startPoint"></param>
        /// <param name="actors"></param>
        /// <returns></returns>
        public static MapBlock[,] GenerateSite(SiteData siteData, out Actor[] actors)
        {
            MapCoordinate startPoint = null;

            //First we generate some empty wilderness of the right type
            MapBlock[,] map = WildernessGenerator.GenerateMap(siteData.Biome, 0, 0, out actors, out startPoint);

            //Now, clear the tiles from between 5,5 till 25,25
            for (int x = 5; x < 26; x++)
            {
                for (int y = 5; y < 26; y++)
                {
                    MapBlock block = map[x, y];
                    block.RemoveAllItems();
                }
            }

            ItemFactory.ItemFactory itemFactory = new ItemFactory.ItemFactory();

            int waterID = 0;

            MapItem waterTile = itemFactory.CreateItem(Archetype.TILES, "water", out waterID);

            //If it's a fishing village, put some water in
            if (siteData.SiteTypeData.SiteType == SiteType.FISHING_VILLAGE)
            {
                for (int x = 0; x < map.GetLength(0); x++)
                {
                    for (int y = map.GetLength(1) - 10; y < map.GetLength(1); y++)
                    {
                        MapBlock block = map[x, y];
                        block.RemoveAllItems();

                        //Set the tile to water
                        block.Tile = itemFactory.CreateItem("tiles", waterID);
                        block.Tile.Coordinate = new MapCoordinate(x, y, 0, MapType.LOCAL);
                    }
                }
            }

            LocalMapGenerator lmg = new LocalMapGenerator();

            LocalMapXMLParser parser = new LocalMapXMLParser();

            Maplet maplet = parser.ParseMapletFromTag(siteData.SiteTypeData.SiteType.ToString().Replace("_", " ").ToLower(),siteData.Biome);

            var tileID = DatabaseHandling.GetItemIdFromTag(Archetype.TILES, WildernessGenerator.details[siteData.Biome].BaseTileTag);

            MapletActorWanderArea[] wanderAreas = null;
            MapletPatrolPoint[] patrolPoints = null;
            MapletFootpathNode[] footPath = null;

            //Now generate the actual map
            MapBlock[,] siteMap = lmg.GenerateMap(tileID, null, maplet, false, "", siteData.Owners, out actors, out wanderAreas, out patrolPoints, out footPath);

            //Now lets fuse the maps
            map = lmg.JoinMaps(map, siteMap, 5, 5);

            foreach (var actor in actors)
            {
                if (actor.CurrentMission == null)
                {
                    actor.CurrentMission = actor.MissionStack.Count > 0 ? actor.MissionStack.Pop() : null;
                }

                if (actor.CurrentMission != null && actor.CurrentMission.GetType() == typeof(WanderMission))
                {
                    WanderMission wMiss = actor.CurrentMission as WanderMission;

                    wMiss.WanderPoint.X += 5;
                    wMiss.WanderPoint.Y += 5;

                    wMiss.WanderRectangle = new Rectangle(wMiss.WanderRectangle.X + 5, wMiss.WanderRectangle.Y + 5, wMiss.WanderRectangle.Width, wMiss.WanderRectangle.Height);
                }
            }

            //Fix the patrol points

            foreach (var point in patrolPoints)
            {
                point.Point.X += 5;
                point.Point.Y += 5;
            }

            //Let's fix the patrol points, we need to merge them into PatrolRoutes
            var patrolRoutes = PatrolRoute.GetPatrolRoutes(patrolPoints);

            foreach (var area in wanderAreas)
            {
                area.WanderRect = new Rectangle(area.WanderRect.X + 5, area.WanderRect.Y + 5, area.WanderRect.Width, area.WanderRect.Height);
            }

            //And fix the path nodes
            foreach (var pn in footPath)
            {
                pn.Point.X += 5;
                pn.Point.Y += 5;
            }

            //If the map already has any actors in it, make the characters prone
            foreach (var actor in actors)
            {
                actor.IsProne = true;
            }

            //Now generate the pathfinding map
            PathfinderInterface.Nodes = GeneratePathfindingMap(map);

            int pathTileID = -1;

            var dummy = itemFactory.CreateItem(Archetype.TILES, "stone", out pathTileID);

            //Go through each footpath node. Attempt to connect the node with the other primary nodes
            foreach (var fp in footPath)
            {
                foreach (var primary in footPath.Where(p => p.IsPrimary))
                {
                    //Join them up
                    var path = PathfinderInterface.GetPath(fp.Point, primary.Point);
                    if (path != null)
                    {
                        foreach (var coord in path)
                        {
                            MapBlock block = map[coord.X, coord.Y];

                            //Only do this if the tile isn't wood, or stone
                            if (!block.Tile.InternalName.ToUpper().Contains("STONE") && !block.Tile.InternalName.ToUpper().Contains("WOOD"))
                            {
                                block.Tile = itemFactory.CreateItem("tiles", pathTileID);
                                block.Tile.Coordinate = new MapCoordinate(coord);
                            }

                        }
                    }
                }
            }

            List<Actor> actorList = new List<Actor>();

            actorList.AddRange(actors); //And add the actors

            //Let's generate a number of actors then
            foreach (ActorProfession profession in Enum.GetValues(typeof(ActorProfession)))
            {
                //So do we have any wander areas for them ?
                var possibleAreas = wanderAreas.Where(wa => wa.Factions.HasFlag(siteData.Owners) && wa.Profession.Equals(profession));
                var possibleRoutes = patrolRoutes.Where(pr => pr.Owners.HasFlag(siteData.Owners) && pr.Profession.Equals(profession));

                //Any actors?
                if (siteData.ActorCounts.ContainsKey(profession))
                {
                    //Yes, how many
                    int total = siteData.ActorCounts[profession];

                    var a = ActorGeneration.CreateActors(siteData.Owners, profession, total);

                    foreach(var ac in a)
                    {
                        ac.SiteMember = true;
                    }

                    actorList.AddRange(a);

                    foreach (var actor in a)
                    {
                        //So, where we going to drop them off ? Randomly
                        int tries = 0;

                        for (; ; )
                        {
                            int randomX = GameState.Random.Next(map.GetLength(0));
                            int randomY = GameState.Random.Next(map.GetLength(1));

                            if (map[randomX, randomY].MayContainItems)
                            {
                                //Plop it on there
                                actor.MapCharacter.Coordinate = new MapCoordinate(randomX, randomY, 0, MapType.LOCAL);
                                map[randomX, randomY].ForcePutItemOnBlock(actor.MapCharacter);
                                tries = 0;
                                break;
                            }
                            else
                            {
                                tries++;
                            }

                            if (tries >= 150)
                            {
                                //give up
                                break;
                            }
                        }

                        //Go through each actor, and either tell them to wander in the whole map, or within any possible area which matches
                        //Any possible area avaialble?
                        List<object> possibleMissions = new List<object>(); //I know :( But Using an interface or trying to mangle together an inheritance was worse

                        possibleMissions.AddRange(possibleAreas.Where(pa => pa.MaxAmount > pa.CurrentAmount));
                        possibleMissions.AddRange(possibleRoutes);

                        var chosenArea = possibleMissions.OrderBy(pa => GameState.Random.Next(100)).FirstOrDefault();

                        if (chosenArea == null)
                        {
                            //Wander around the whole map
                            actor.CurrentMission = new WanderMission() { LoiterPercentage = 25, WanderPoint = new MapCoordinate(map.GetLength(0) / 2, map.GetLength(1) / 2, 0, MapType.LOCAL), WanderRectangle = new Rectangle(0, 0, map.GetLength(0), map.GetLength(1)) };
                        }
                        else
                        {
                            //Is this a patrol or a wander ?
                            if (chosenArea.GetType().Equals(typeof(PatrolRoute)))
                            {
                                var patrolDetails = chosenArea as PatrolRoute;

                                PatrolRouteMission pm = new PatrolRouteMission();
                                pm.PatrolRoute.AddRange(patrolDetails.Route);

                                actor.CurrentMission = pm;
                            }
                            else if (chosenArea.GetType().Equals(typeof(MapletActorWanderArea)))
                            {
                                var wanderDetails = chosenArea as MapletActorWanderArea;

                                //Wander around in that area
                                actor.CurrentMission = new WanderMission() { LoiterPercentage = 25, WanderPoint = new MapCoordinate(wanderDetails.WanderPoint), WanderRectangle = wanderDetails.WanderRect };
                                wanderDetails.CurrentAmount++;
                            }
                        }

                    }

                }

            }

            actors = actorList.ToArray();

            siteData.PatrolRoutes = patrolRoutes.ToList();
            siteData.WanderAreas = wanderAreas.ToList();

            return map;
        }
Пример #27
0
        /// <summary>
        /// Checks for health and decides whether the character should be dead
        /// Also bleeds the character
        /// Also checks whether the character is stunned or not
        /// </summary>
        /// <param name="actor"></param>
        /// <returns></returns>
        public static ActionFeedback[] CheckHealth(Actor actor)
        {
            if (!actor.IsAlive || !actor.MapCharacter.IsActive)
            {
                //Nothing we can do here
                return new ActionFeedback[] { };
            }

            //Check for body part damage
            if (actor.Anatomy.Head < 0)
            {
                //Character is dead
                actor.IsAlive = false;
                if (actor.IsPlayerCharacter)
                {
                    //Inform the character
                    return new ActionFeedback[] { new CreateEventFeedback("DEATH") };
                }
            }

            if (actor.Anatomy.Chest < 0)
            {
                //Character is dead
                actor.IsAlive = false;
                if (actor.IsPlayerCharacter)
                {
                    //Inform the character
                    return new ActionFeedback[] { new CreateEventFeedback("DEATH") };
                }
            }

            //Bleed a bit
            actor.Anatomy.BloodTotal -= actor.Anatomy.BloodLoss;

            if (actor.Anatomy.BloodLoss <= 0 && actor.Anatomy.BloodTotal < HumanoidAnatomy.BLOODTOTAL)
            {
                //Increase the blood amount
                actor.Anatomy.BloodTotal++;
            }
            else if (actor.Anatomy.BloodLoss > 0)
            {
                //Is it time to reduce the blood level?
                if (actor.Anatomy.BodyTimer++ >= HumanoidAnatomy.BODY_TIMER_FLIP)
                {
                    //Decrease bleeding amount
                    actor.Anatomy.BloodLoss--;
                    actor.Anatomy.BodyTimer = 0;
                }
                else
                {
                    //tick
                    actor.Anatomy.BodyTimer++;
                }
            }

            //Are we low on blood?

            if (actor.Anatomy.BloodTotal < HumanoidAnatomy.BLOOD_STUN_AMOUNT)
            {
                //Increase the stun level
                actor.Anatomy.StunAmount++;
            }

            if (actor.Anatomy.BloodTotal < 0)
            {
                //Death
                CombatManager.KillCharacter(actor); //Drop the stuff

                if (actor.IsPlayerCharacter)
                {
                    return new ActionFeedback[] { new LogFeedback(InterfaceSpriteName.BLEEDING, Color.Red, "You bleed to death"), new CreateEventFeedback("DEATH") };
                }
                else
                {
                    return new ActionFeedback[] { new LogFeedback(InterfaceSpriteName.BLEEDING, Color.Red, actor.Name + " has bled to death") };
                }
            }

            if (actor.IsStunned) //unstun
            {
                actor.IsStunned = false;
                if (actor.MapCharacter as LocalCharacter != null)
                {
                    (actor.MapCharacter as LocalCharacter).IsStunned = false;
                }
            }

            if (actor.Anatomy.StunAmount > 0)
            {
                if (actor.Anatomy.StunAmount > 10)
                {
                    //Reduce it to the max amount. 10
                    actor.Anatomy.StunAmount = 10;
                }

                //Check whether the actor is stunned or not

                if (actor.Anatomy.StunAmount > 0)
                {
                    //Stunned
                    actor.IsStunned = true;

                    if (actor.MapCharacter as LocalCharacter != null)
                    {
                        (actor.MapCharacter as LocalCharacter).IsStunned = true;
                    }

                    //Feel better
                    actor.Anatomy.StunAmount--;

                    if (actor.IsPlayerCharacter)
                    {
                        return new ActionFeedback[] { new LogFeedback(InterfaceSpriteName.SPIRAL, Color.Red, "You black out") };
                    }
                }
            }

            return new ActionFeedback[] { };
        }
Пример #28
0
        /// <summary>
        /// Generates a map based on the maplet assigned
        /// </summary>
        /// <param name="maplet">The maplet to generate</param>
        /// <param name="parentWallID">The wall that the parent has</param>
        /// <param name="parentTileID">The ID of the tiles used in the parent maplet item</param>
        /// <param name="enemyType">The type of actor which is dominant in this map</param>
        /// <param name="owner">The owner of the map. Any maplet items which don't belong will be hidden</param>
        /// <param name="actors">The actors which we have generated</param>
        /// <param name="actorType">The type of actors to generate</param>
        /// <returns></returns>
        public MapBlock[,] GenerateMap(int parentTileID, int? parentWallID, Maplet maplet, bool preferSides, string actorType, OwningFactions owner,
            out Actor[] actors, out MapletActorWanderArea[] wAreas, out MapletPatrolPoint[] patrolRoutes, out MapletFootpathNode[] footpathNodes)
        {
            List<Actor> actorList = new List<Actor>();
            List<MapletActorWanderArea> wanderAreas = new List<MapletActorWanderArea>();
            List<MapletPatrolPoint> patrolRouteList = new List<MapletPatrolPoint>();
            List<MapletFootpathNode> footpathNodeList = new List<MapletFootpathNode>();

            PlanningMapItemType[,] planningMap = new PlanningMapItemType[maplet.SizeX, maplet.SizeY];

            //Step 1: Plan how the map will look

            //Step 1a: Set all tiles to available, and set the frame to walls if there's a wall
            planningMap = this.CreateBlueprint(maplet);

            //Step 1b: Put in the tiles in the actual map, and the walls if they are present
            MapBlock[,] generatedMap = new MapBlock[maplet.SizeX, maplet.SizeY];
            ItemFactory.ItemFactory factory = new ItemFactory.ItemFactory();

            int tileID = 0;

            if (maplet.Tiled)
            {
                if (maplet.TileID.HasValue)
                {
                    tileID = maplet.TileID.Value;
                }
                else
                {
                    //Load the tileID from the factory
                    factory.CreateItem(Archetype.TILES, maplet.TileTag, out tileID);
                }

            }
            else
            {
                tileID = parentTileID;
            }

            //That's the tiles done
            for (int x = 0; x < generatedMap.GetLength(0); x++)
            {
                for (int y = 0; y < generatedMap.GetLength(1); y++)
                {
                    MapItem tile = factory.CreateItem("tile", tileID);
                    tile.Coordinate = new MapCoordinate(x, y, 0, DRObjects.Enums.MapType.LOCAL);

                    MapBlock block = new MapBlock();
                    block.Tile = tile;

                    generatedMap[x, y] = block;
                }
            }

            //Do the walls now if they are required
            int? wallID = null;
            int tempWallID = -1;

            if (parentWallID.HasValue)
            {
                MapItem wall = factory.CreateItem("MUNDANEITEMS", parentWallID.Value);
                wallID = parentWallID;
            }
            else
            {
                MapItem wall = factory.CreateItem(DRObjects.Enums.Archetype.MUNDANEITEMS, "wall", out tempWallID);
                wallID = tempWallID;
            }

            if (maplet.Walled && wallID.HasValue)
            {
                //wall the edge tiles
                for (int x = 0; x < maplet.SizeX; x++)
                {
                    generatedMap[x, 0].PutItemOnBlock(factory.CreateItem("mundaneitems", wallID.Value));
                    generatedMap[x, maplet.SizeY - 1].PutItemOnBlock(factory.CreateItem("mundaneitems", wallID.Value));

                    if (maplet.WindowProbability.HasValue && maplet.WindowProbability.Value > 0)
                    {
                        if (random.Next(100) < maplet.WindowProbability.Value)
                        {
                            int itemID;
                            //Put a window :)
                            generatedMap[x, 0].ForcePutItemOnBlock(factory.CreateItem(DRObjects.Enums.Archetype.MUNDANEITEMS, "window", out itemID));
                        }
                        else if (random.Next(100) < maplet.WindowProbability.Value)
                        {
                            int itemID;
                            //Put a window :)
                            generatedMap[x, maplet.SizeY - 1].ForcePutItemOnBlock(factory.CreateItem(DRObjects.Enums.Archetype.MUNDANEITEMS, "window", out itemID));
                        }
                    }
                }

                for (int y = 0; y < maplet.SizeY; y++)
                {
                    generatedMap[0, y].PutItemOnBlock(factory.CreateItem("mundaneitems", wallID.Value));
                    generatedMap[maplet.SizeX - 1, y].PutItemOnBlock(factory.CreateItem("mundaneitems", wallID.Value));

                    if (maplet.WindowProbability.HasValue && maplet.WindowProbability.Value > 0)
                    {
                        if (random.Next(100) < maplet.WindowProbability.Value)
                        {
                            int itemID;
                            //Put a window :)
                            generatedMap[0, y].ForcePutItemOnBlock(factory.CreateItem(DRObjects.Enums.Archetype.MUNDANEITEMS, "window", out itemID));
                        }
                        else if (random.Next(100) < maplet.WindowProbability.Value)
                        {
                            int itemID;
                            //Put a window :)
                            generatedMap[maplet.SizeX - 1, y].ForcePutItemOnBlock(factory.CreateItem(DRObjects.Enums.Archetype.MUNDANEITEMS, "window", out itemID));
                        }
                    }
                }

            }

            //Step 1c: Determine where we'll put the maplets
            foreach (MapletContentsMaplet childMaplet in maplet.MapletContents.Where(mc => (mc is MapletContentsMaplet)).OrderByDescending(mc => mc.ProbabilityPercentage).ThenBy(mc => random.Next()))
            {
                //Calculate the probability of putting the item in, and how many items we're putting
                for (int i = 0; i < childMaplet.MaxAmount; i++)
                {
                    if (random.NextDouble() * 100 <= childMaplet.ProbabilityPercentage)
                    {
                        //Does it fit?
                        int x = -1;
                        int y = -1;
                        PlanningMapItemType[,] newMap;

                        //Convert the child maplet into a planning map
                        PlanningMapItemType[,] childMapletBlueprint = this.CreateBlueprint(childMaplet.Maplet);
                        //mark the areas covered by the blueprint as being held by that blueprint

                        if (childMaplet.Position == PositionAffinity.FIXED)
                        {
                            if (Fits(planningMap, childMapletBlueprint, childMaplet.x.Value, childMaplet.y.Value, out newMap))
                            {
                                //it fits, generate it - <3 Recursion
                                Actor[] childActors = null;

                                MapletActorWanderArea[] wanderA = null;
                                MapletPatrolPoint[] patrolPoints = null;
                                MapletFootpathNode[] fpNodes = null;

                                MapBlock[,] childMap = this.GenerateMap(tileID, wallID.Value, childMaplet.Maplet, childMaplet.Position == DRObjects.LocalMapGeneratorObjects.Enums.PositionAffinity.SIDES, actorType, owner, out childActors, out wanderA, out patrolPoints, out fpNodes);

                                //Add the child actors
                                actorList.AddRange(childActors);

                                //Update any actors's locations should they have any
                                foreach (var actor in childActors)
                                {
                                    if (actor.MissionStack.Count() > 0)
                                    {
                                        var wander = actor.MissionStack.Peek() as WanderMission;

                                        if (wander != null)
                                        {
                                            wander.WanderPoint.X += childMaplet.x.Value;
                                            wander.WanderPoint.Y += childMaplet.y.Value;

                                            wander.WanderRectangle = new Rectangle(wander.WanderRectangle.X + childMaplet.x.Value, wander.WanderRectangle.Y + childMaplet.y.Value, wander.WanderRectangle.Width, wander.WanderRectangle.Height);
                                        }

                                    }
                                }

                                //Update any wander areas too
                                foreach (var area in wanderA)
                                {
                                    area.WanderRect = new Rectangle(area.WanderRect.X + childMaplet.x.Value, area.WanderRect.Y + childMaplet.y.Value, area.WanderRect.Width, area.WanderRect.Height);
                                    area.WanderPoint.X += childMaplet.x.Value;
                                    area.WanderPoint.Y += childMaplet.y.Value;
                                }

                                //and patrol points
                                foreach (var point in patrolPoints)
                                {
                                    point.Point.X += childMaplet.x.Value;
                                    point.Point.Y += childMaplet.y.Value;
                                }

                                foreach (var n in fpNodes)
                                {
                                    n.Point.X += childMaplet.x.Value;
                                    n.Point.Y += childMaplet.y.Value;
                                }

                                //And add them
                                wanderAreas.AddRange(wanderA);
                                patrolRouteList.AddRange(patrolPoints);
                                footpathNodeList.AddRange(fpNodes);

                                //Join the two maps together
                                generatedMap = this.JoinMaps(generatedMap, childMap, childMaplet.x.Value, childMaplet.y.Value);
                            }
                        }
                        else
                        {
                            if (Fits(planningMap, childMapletBlueprint, childMaplet.Position == DRObjects.LocalMapGeneratorObjects.Enums.PositionAffinity.SIDES, childMaplet.FirstFit, childMaplet.Padding, out x, out y, out newMap))
                            {
                                //it fits, generate it - <3 Recursion
                                Actor[] childActors = null;
                                MapletActorWanderArea[] wanderA = null;
                                MapletPatrolPoint[] patrolPoints = null;
                                MapletFootpathNode[] fpNodes = null;

                                MapBlock[,] childMap = this.GenerateMap(tileID, wallID.Value, childMaplet.Maplet, childMaplet.Position == DRObjects.LocalMapGeneratorObjects.Enums.PositionAffinity.SIDES, actorType, owner, out childActors, out wanderA, out patrolPoints, out fpNodes);

                                //Add the child actors
                                actorList.AddRange(childActors);

                                //Update any actors's locations should they have any
                                foreach (var actor in childActors)
                                {
                                    if (actor.MissionStack.Count() > 0)
                                    {
                                        var wander = actor.MissionStack.Peek() as WanderMission;

                                        if (wander != null)
                                        {
                                            wander.WanderPoint.X += x;
                                            wander.WanderPoint.Y += y;

                                            wander.WanderRectangle = new Rectangle(wander.WanderRectangle.X + x, wander.WanderRectangle.Y + y, wander.WanderRectangle.Width, wander.WanderRectangle.Height);
                                        }

                                    }
                                }

                                //Update any wander areas too
                                foreach (var area in wanderA)
                                {
                                    area.WanderRect = new Rectangle(area.WanderRect.X + x, area.WanderRect.Y + y, area.WanderRect.Width, area.WanderRect.Height);
                                    area.WanderPoint.X += x;
                                    area.WanderPoint.Y += y;
                                }

                                //and patrol routes
                                foreach (var point in patrolPoints)
                                {
                                    point.Point.X += x;
                                    point.Point.Y += y;
                                }

                                foreach (var n in fpNodes)
                                {
                                    n.Point.X += x;
                                    n.Point.Y += y;
                                }

                                //And add them
                                wanderAreas.AddRange(wanderA);
                                patrolRouteList.AddRange(patrolPoints);
                                footpathNodeList.AddRange(fpNodes);

                                //Join the two maps together
                                generatedMap = this.JoinMaps(generatedMap, childMap, x, y);
                            }
                        }
                    }
                }
            }

            //Step 2: Put the items into the map

            //Lets list places we can put it in
            List<MapBlock> candidateBlocks = new List<MapBlock>();

            for (int x = 0; x < planningMap.GetLength(0); x++)
            {
                for (int y = 0; y < planningMap.GetLength(1); y++)
                {
                    if (planningMap[x, y] == PlanningMapItemType.FREE)
                    {
                        candidateBlocks.Add(generatedMap[x, y]);
                    }

                }
            }
            List<MapBlock> edgeBlocks = new List<MapBlock>();

            //Lets also get the edge mapblocks - for those who prefer being on the edge
            for (int x = 0; x < planningMap.GetLength(0); x++)
            {
                if (!maplet.Walled)
                {
                    if (planningMap[x, 0] == PlanningMapItemType.FREE)
                    {
                        edgeBlocks.Add(generatedMap[x, 0]);
                    }

                    if (planningMap[x, planningMap.GetLength(1) - 1] == PlanningMapItemType.FREE)
                    {
                        edgeBlocks.Add(generatedMap[x, planningMap.GetLength(1) - 1]);
                    }
                }
                else
                {
                    if (planningMap[x, 1] == PlanningMapItemType.FREE)
                    {
                        edgeBlocks.Add(generatedMap[x, 1]);
                    }

                    if (planningMap[x, planningMap.GetLength(1) - 2] == PlanningMapItemType.FREE)
                    {
                        edgeBlocks.Add(generatedMap[x, planningMap.GetLength(1) - 2]);
                    }
                }

            }

            //Doing the y parts
            for (int y = 0; y < planningMap.GetLength(1); y++)
            {
                if (!maplet.Walled)
                {
                    if (planningMap[0, y] == PlanningMapItemType.FREE)
                    {
                        edgeBlocks.Add(generatedMap[0, y]);
                    }

                    if (planningMap[planningMap.GetLength(0) - 1, y] == PlanningMapItemType.FREE)
                    {
                        edgeBlocks.Add(generatedMap[planningMap.GetLength(0) - 1, y]);
                    }
                }
                else
                {
                    if (planningMap[1, y] == PlanningMapItemType.FREE)
                    {
                        edgeBlocks.Add(generatedMap[1, y]);
                    }

                    if (planningMap[planningMap.GetLength(0) - 2, y] == PlanningMapItemType.FREE)
                    {
                        edgeBlocks.Add(generatedMap[planningMap.GetLength(0) - 2, y]);
                    }

                }

            }

            //go through the maplet contents

            //Get the smallest x and y coordinate in the candidate blocks so we can use it for fixed things

            int smallestX = -1;
            int smallestY = -1;

            try
            {
                smallestX = candidateBlocks.Select(b => b.Tile.Coordinate.X).Min();
                smallestY = candidateBlocks.Select(b => b.Tile.Coordinate.Y).Min();
            }
            catch
            {
                //No space :(

            }

            foreach (MapletContents contents in maplet.MapletContents.Where(mc => mc is MapletContentsItem || mc is MapletContentsItemTag || mc is MapletContentsItemSpecial).OrderByDescending(mc => mc.ProbabilityPercentage))
            {
                //We'll see if we even put this at all
                MapItem itemPlaced = null;

                for (int i = 0; i < contents.MaxAmount; i++)
                {
                    //lets see what the probability of putting it in is
                    if ((random.NextDouble() * 100) <= contents.ProbabilityPercentage)
                    {
                        //Put it in
                        if (contents is MapletContentsItem)
                        {
                            MapletContentsItem mapletContent = (MapletContentsItem)contents;
                            itemPlaced = factory.CreateItem(mapletContent.ItemCategory, mapletContent.ItemID);
                        }
                        else
                            if (contents is MapletContentsItemTag)
                            {
                                MapletContentsItemTag mapletContent = (MapletContentsItemTag)contents;
                                int tempInt;
                                itemPlaced = factory.CreateItem(mapletContent.Category, mapletContent.Tag, out tempInt);
                                //I CHANGED THIS
                                itemPlaced.OwnedBy = mapletContent.Factions;
                            }
                            else
                                if (contents is MapletContentsItemSpecial)
                                {
                                    //what type is it
                                    switch ((contents as MapletContentsItemSpecial).Type)
                                    {
                                        case "StairsUp":
                                            itemPlaced = new DungeonStairs(true); break;
                                        case "StairsDown":
                                            itemPlaced = new DungeonStairs(false); break;
                                        case "SummoningCircle":
                                            itemPlaced = new SummoningCircle(); break;
                                        case "TreasureChest":
                                            itemPlaced = new TreasureChest(); break;
                                        case "Altar":
                                            itemPlaced = new Altar(); break;
                                        case "WishingWell":
                                            itemPlaced = new WishingWell(); break;
                                        case "Potion":
                                            var potionType = (PotionType[]) Enum.GetValues(typeof(PotionType));
                                            var potion = potionType.GetRandom();
                                            itemPlaced = new Potion(potion);
                                            break;
                                        default:
                                            throw new NotImplementedException("No code for " + (contents as MapletContentsItemSpecial).Type + " can be found");
                                    }
                                }

                        if (candidateBlocks.Count != 0)
                        {
                            //Lets decide where to put it

                            if (contents.Position == DRObjects.LocalMapGeneratorObjects.Enums.PositionAffinity.SIDES && edgeBlocks.Count != 0)
                            {
                                //pick a place at random and add it to the maplet
                                int position = random.Next(edgeBlocks.Count);

                                edgeBlocks[position].PutItemOnBlock(itemPlaced);

                                if (!contents.AllowItemsOnTop)
                                {
                                    //remove it from both
                                    candidateBlocks.Remove(edgeBlocks[position]);
                                    edgeBlocks.RemoveAt(position);
                                }
                            }

                            if (contents.Position == DRObjects.LocalMapGeneratorObjects.Enums.PositionAffinity.MIDDLE && candidateBlocks.Except(edgeBlocks).Count() != 0)
                            {
                                //pick a place at random and add it to the maplet
                                int position = random.Next(candidateBlocks.Except(edgeBlocks).Count());

                                MapBlock block = candidateBlocks.Except(edgeBlocks).ToArray()[position];

                                block.PutItemOnBlock(itemPlaced);

                                if (!contents.AllowItemsOnTop)
                                {
                                    //remove it from both
                                    candidateBlocks.Remove(block);
                                    edgeBlocks.Remove(block);
                                }
                            }

                            if (contents.Position == DRObjects.LocalMapGeneratorObjects.Enums.PositionAffinity.ANYWHERE)
                            {
                                //pick a place at random and add it to the maplet
                                int position = random.Next(candidateBlocks.Count);

                                candidateBlocks[position].PutItemOnBlock(itemPlaced);

                                if (!contents.AllowItemsOnTop)
                                {
                                    //remove it from both
                                    edgeBlocks.Remove(candidateBlocks[position]);
                                    candidateBlocks.RemoveAt(position);
                                }
                            }

                            if (contents.Position == DRObjects.LocalMapGeneratorObjects.Enums.PositionAffinity.FIXED)
                            {
                                //Fix it in a particular position.
                                MapCoordinate coordinate = new MapCoordinate(smallestX + contents.x.Value, smallestY + contents.y.Value, 0, DRObjects.Enums.MapType.LOCAL);

                                var selectedBlock = candidateBlocks.Where(cb => cb.Tile.Coordinate.Equals(coordinate)).FirstOrDefault();

                                if (selectedBlock != null)
                                { //maybe someone put something there already
                                    selectedBlock.PutItemOnBlock(itemPlaced);
                                }

                                if (!contents.AllowItemsOnTop)
                                {
                                    //and remoev it from both
                                    candidateBlocks.Remove(selectedBlock);
                                    edgeBlocks.Remove(selectedBlock);
                                }
                            }
                        }
                    }
                }

            }

            //Step 3: Stripe through the map except for the current maplet's walls - work out where the walls are, and for each wall segment, put a door in
            #region Wall Segments
            List<Line> wallSegments = new List<Line>();

            for (int x = 1; x < planningMap.GetLength(0) - 1; x++)
            {
                //lets see if we find a wall Segment
                Line wallSegment = null;

                for (int y = 1; y < planningMap.GetLength(1) - 1; y++)
                {
                    if (planningMap[x, y] == PlanningMapItemType.WALL)
                    {
                        //Three possibilities exist. Either this is the start of a wall segment
                        //Or this is a continuation of a wall segment
                        //Or this is the end of a wall segment
                        // -> Because there is an intersection
                        // -> Because there was an active wall segment and there is no wall in this one
                        if (wallSegment == null)
                        {
                            //Its a start
                            wallSegment = new Line(new MapCoordinate(x, y, 0, DRObjects.Enums.MapType.LOCAL), null);
                        }
                        else
                        {
                            //Continuation or end
                            //Check if there's an interesection
                            //Go up one and down one. If there is the maplet's walls there won't be a door - but then there'll be a double wall anyway which makes no sense
                            if (planningMap[x + 1, y] == PlanningMapItemType.WALL || planningMap[x - 1, y] == PlanningMapItemType.WALL)
                            {
                                //terminate the wall - and start a new one
                                wallSegment.End = new MapCoordinate(x, y, 0, DRObjects.Enums.MapType.LOCAL);
                                wallSegments.Add(wallSegment);

                                wallSegment = new Line(new MapCoordinate(x, y, 0, DRObjects.Enums.MapType.LOCAL), null);
                            }
                            else
                            {
                                //do nothing, its a continuation
                            }
                        }

                    }
                    else
                    {
                        //Mayhaps a line has stopped?
                        if (wallSegment != null)
                        {
                            //It has - lets terminate it
                            wallSegment.End = new MapCoordinate(x, y - 1, 0, DRObjects.Enums.MapType.LOCAL);
                            wallSegments.Add(wallSegment);

                            wallSegment = null;
                        }

                    }

                }

                //Check if there's an active line - maybe it reaches till the end of the maplet
                if (wallSegment != null)
                {
                    wallSegment.End = new MapCoordinate(x, (planningMap.GetLength(1) - 1), 0, DRObjects.Enums.MapType.LOCAL);
                    wallSegments.Add(wallSegment);
                    wallSegment = null;
                }
            }

            //Now stripe in the other direction
            for (int y = 1; y < planningMap.GetLength(1) - 1; y++)
            {
                //lets see if we find a wall Segment
                Line wallSegment = null;

                for (int x = 1; x < planningMap.GetLength(0) - 1; x++)
                {
                    if (planningMap[x, y] == PlanningMapItemType.WALL)
                    {
                        //Three possibilities exist. Either this is the start of a wall segment
                        //Or this is a continuation of a wall segment
                        //Or this is the end of a wall segment
                        // -> Because there is an intersection
                        // -> Because there was an active wall segment and there is no wall in this one
                        if (wallSegment == null)
                        {
                            //Its a start
                            wallSegment = new Line(new MapCoordinate(x, y, 0, DRObjects.Enums.MapType.LOCAL), null);
                        }
                        else
                        {
                            //Continuation or end
                            //Check if there's an interesection
                            //Go up one and down one. If there is the maplet's walls there won't be a door - but then there'll be a double wall anyway which makes no sense
                            if (planningMap[x, y + 1] == PlanningMapItemType.WALL || planningMap[x, y - 1] == PlanningMapItemType.WALL)
                            {
                                //terminate the wall - and start a new one
                                wallSegment.End = new MapCoordinate(x, y, 0, DRObjects.Enums.MapType.LOCAL);
                                wallSegments.Add(wallSegment);

                                wallSegment = new Line(new MapCoordinate(x, y, 0, DRObjects.Enums.MapType.LOCAL), null);
                            }
                            else
                            {
                                //do nothing, its a continuation
                            }
                        }

                    }
                    else
                    {
                        //Mayhaps a line has stopped?
                        if (wallSegment != null)
                        {
                            //It has - lets terminate it
                            wallSegment.End = new MapCoordinate(x - 1, y, 0, DRObjects.Enums.MapType.LOCAL);
                            wallSegments.Add(wallSegment);

                            wallSegment = null;
                        }

                    }

                }

                //Check if there's an active line - maybe it reaches till the end of the maplet
                if (wallSegment != null)
                {
                    wallSegment.End = new MapCoordinate(planningMap.GetLength(0) - 1, y, 0, DRObjects.Enums.MapType.LOCAL);
                    wallSegments.Add(wallSegment);
                    wallSegment = null;
                }
            }

            #endregion Wall Segments

            #region Doors

            //Get all wall segments larger than 0, and we can put a door there

            foreach (Line segment in wallSegments.Where(ws => ws.Length() > 1))
            {
                //Put a door somewhere, as long as its not the start or end
                //Oh and remove the wall

                MapBlock block = null;

                if (segment.Start.X == segment.End.X)
                {
                    //Get the entirety of the segment
                    List<int> possibleYs = new List<int>();

                    int smallerY = Math.Min(segment.Start.Y, segment.End.Y);
                    int largerY = Math.Max(segment.Start.Y, segment.End.Y);

                    //Check in the real map whether the tile next to it is free for walking in
                    for (int y = smallerY + 1; y <= largerY; y++)
                    {
                        if (generatedMap[segment.Start.X - 1, y].MayContainItems && generatedMap[segment.Start.X + 1, y].MayContainItems)
                        {
                            possibleYs.Add(y);
                        }
                    }

                    //Now check whether there's a possible y, and pick a random one from it
                    if (possibleYs.Count != 0)
                    {
                        block = generatedMap[segment.Start.X, possibleYs[random.Next(possibleYs.Count - 1)]];
                    }
                    else
                    {
                        //nothing to do - take smallest
                        block = generatedMap[segment.Start.X, segment.Start.Y + 1];
                    }
                }
                else
                {
                    List<int> possibleXs = new List<int>();

                    int smallerX = Math.Min(segment.Start.X, segment.End.X);
                    int largerX = Math.Max(segment.Start.X, segment.End.X);

                    //Check in the real map whether the tile next to it is free for walking in
                    for (int x = smallerX + 1; x <= largerX; x++)
                    {
                        if (generatedMap[x, segment.Start.Y - 1].MayContainItems && generatedMap[x, segment.Start.Y + 1].MayContainItems)
                        {
                            possibleXs.Add(x);
                        }
                    }

                    //Now check whether there's a possible x, and pick a random one from it
                    if (possibleXs.Count != 0)
                    {
                        block = generatedMap[possibleXs[random.Next(possibleXs.Count - 1)], segment.Start.Y];
                    }
                    else
                    {
                        //nothing to do - take the smallest one
                        block = generatedMap[segment.Start.X + 1, segment.Start.Y];
                    }

                }

                try
                {
                    if (block != null)
                    {
                        block.RemoveTopItem();
                        int doorID = -1;
                        block.PutItemOnBlock(factory.CreateItem(DRObjects.Enums.Archetype.MUNDANEITEMS, "door", out doorID));
                    }
                }
                catch { }
            }

            #endregion

            #region Enemies

            //Now lets create enemies :)
            foreach (var mc in maplet.MapletContents.Where(mc => mc.GetType().Equals(typeof(MapletActor))).OrderByDescending(o => o.ProbabilityPercentage))
            {
                var actor = mc as MapletActor;

                for (int i = 0; i < actor.MaxAmount; i++)
                {
                    //Check the random
                    if (random.Next(100) < actor.ProbabilityPercentage)
                    {
                        int actorID = 0;

                        string enemyType = actor.UseLocalType ? actorType : actor.EnemyType;

                        //For now set gear cost to 0
                        Actor newActor = ActorGeneration.CreateActor(enemyType, actor.EnemyTag, null, 10, 0, null, out actorID);

                        if (actor.VendorType.HasValue)
                        {
                            GenerateVendor(newActor, actor);
                        }

                        //Generate the map character
                        var mapCharacter = factory.CreateItem("enemies", actorID);

                        newActor.MapCharacter = mapCharacter;

                        if (!actor.Factions.HasFlag(owner))
                        {
                            //inactive character
                            newActor.MapCharacter.IsActive = false;
                        }

                        (mapCharacter as LocalCharacter).Actor = newActor;

                        //Lets position them randomly
                        for (int attempt = 0; attempt < 150; attempt++)
                        {
                            //Try 150 times
                            int x = random.Next(maplet.SizeX);
                            int y = random.Next(maplet.SizeY);

                            if (generatedMap[x, y].MayContainItems)
                            {
                                //Put it there
                                mapCharacter.Coordinate = new MapCoordinate(x, y, 0, MapType.LOCAL);
                                generatedMap[x, y].ForcePutItemOnBlock(mapCharacter);
                                actorList.Add(newActor);

                                //What mission does he have?
                                if (actor.EnemyMission == ActorMissionType.WANDER)
                                {
                                    newActor.MissionStack.Push(new WanderMission()
                                        {
                                            LoiterPercentage = 80,
                                            WanderPoint = new MapCoordinate(mapCharacter.Coordinate),
                                            WanderRectangle = new Rectangle(0, 0, generatedMap.GetLength(0), generatedMap.GetLength(1))
                                        });
                                }

                                break;
                            }
                        }
                    }
                }
            }

            #endregion

            #region Wander Areas

            foreach (var mc in maplet.MapletContents.Where(mc => mc.GetType().Equals(typeof(MapletActorWanderArea))))
            {
                var wander = mc as MapletActorWanderArea;

                //The area of this is going to be the entire maplet (so if we're in a submaplet, they'll wander in there - Awesome no ?)
                wander.WanderRect = new Rectangle(0, 0, generatedMap.GetLength(0), generatedMap.GetLength(1));

                //Pick the wander point to be the middle of the rectangle. If the point isn't valid we might have a problem
                wander.WanderPoint = new MapCoordinate(generatedMap.GetLength(0) / 2, generatedMap.GetLength(1) / 2, 0, MapType.LOCAL);

                MapletActorWanderArea clone = new MapletActorWanderArea();
                clone.WanderPoint = new MapCoordinate(wander.WanderPoint);
                clone.WanderRect = new Rectangle(wander.WanderRect.X, wander.WanderRect.Y, wander.WanderRect.Width, wander.WanderRect.Height);
                clone.Profession = wander.Profession;
                clone.OwnerFactions = wander.OwnerFactions;

                wanderAreas.Add(clone);
            }

            wAreas = wanderAreas.ToArray();

            #endregion

            #region Patrol Points & Paths

            foreach (var mc in maplet.MapletContents.Where(mc => mc.GetType().Equals(typeof(MapletPatrolPoint))))
            {
                var point = mc as MapletPatrolPoint;

                //The point is going to be in the middle of the entire maplet
                point.Point = new MapCoordinate(generatedMap.GetLength(0) / 2, generatedMap.GetLength(1) / 2, 0, MapType.LOCAL);

                MapletPatrolPoint clone = new MapletPatrolPoint();
                clone.Point = new MapCoordinate(point.Point);
                clone.OwnerFactions = point.OwnerFactions;
                clone.Profession = point.Profession;
                clone.PointRadius = point.PointRadius;

                patrolRouteList.Add(clone);
            }

            patrolRoutes = patrolRouteList.ToArray();

            foreach (var n in maplet.MapletContents.Where(mc => mc.GetType().Equals(typeof(MapletFootpathNode))))
            {
                var node = n as MapletFootpathNode;

                //Point is going to be in the middle of the entire maplet
                node.Point = new MapCoordinate(generatedMap.GetLength(0) / 2, generatedMap.GetLength(1) / 2, 0, MapType.LOCAL);

                //Better create a new one
                MapletFootpathNode clone = new MapletFootpathNode();
                clone.Point = new MapCoordinate(node.Point);
                clone.IsPrimary = node.IsPrimary;

                footpathNodeList.Add(clone);
            }

            footpathNodes = footpathNodeList.ToArray();

            #endregion

            #region Aniamls

            //Now lets create enemies :)
            foreach (var mc in maplet.MapletContents.Where(mc => mc.GetType().Equals(typeof(MapletHerd))).OrderByDescending(o => o.ProbabilityPercentage))
            {
                var herd = mc as MapletHerd;

                for (int i = 0; i < herd.MaxAmount; i++)
                {
                    //Check the random
                    if (random.Next(100) < herd.ProbabilityPercentage)
                    {
                        var herds = ActorGeneration.CreateAnimalHerds(herd.Biome, herd.Domesticated, herd.HerdTag, 1);

                        foreach (var animalHerd in herds)
                        {
                            foreach (var animal in animalHerd)
                            {
                                //Position them on the map
                                for (int attempt = 0; attempt < 150; attempt++)
                                {
                                    //Try 150 times
                                    int x = random.Next(maplet.SizeX);
                                    int y = random.Next(maplet.SizeY);

                                    if (generatedMap[x, y].MayContainItems)
                                    {
                                        //Put it there
                                        animal.MapCharacter.Coordinate = new MapCoordinate(x, y, 0, MapType.LOCAL);
                                        generatedMap[x, y].ForcePutItemOnBlock(animal.MapCharacter);
                                        actorList.Add(animal);

                                        //Wander around does he have?
                                        animal.MissionStack.Push(new WanderMission()
                                        {
                                            LoiterPercentage = 80,
                                            WanderPoint = new MapCoordinate(animal.MapCharacter.Coordinate),
                                            WanderRectangle = new Rectangle(0, 0, generatedMap.GetLength(0), generatedMap.GetLength(1))
                                        });

                                        break;
                                    }
                                }
                            }
                        }

                    }
                }
            }

            #endregion

            actors = actorList.ToArray();

            #region Ownership

            //Go through all map items - If they're not valid for this particular owner, make them inactive.
            foreach (var mapBlock in generatedMap)
            {
                foreach (var item in mapBlock.GetItems())
                {
                    if (!item.OwnedBy.HasFlag(owner))
                    {
                        item.IsActive = false;
                    }
                }
            }

            #endregion

            //we're done
            return generatedMap;
        }
Пример #29
0
        public ActionFeedback[] PerformAction(ActionType actionType, Actor actor, object[] args)
        {
            if (actionType == ActionType.MOVE)
            {
                //the block must handle this
                //TODO: Future - the block can transmit 'moved on' action on the top item or the tile for things like traps

                if (this.MayContainItems)
                {
                    //it is possible to move there

                    //you can only move to a particular block if its only 1 square away

                    int distance = this.Tile.Coordinate - actor.MapCharacter.Coordinate;

                    if (distance > 1)
                    {
                        return new ActionFeedback[] { new TextFeedback("Can't move there") };
                    }

                    actor.MapCharacter.Coordinate = this.Tile.Coordinate;
                    this.mapItems.Add(actor.MapCharacter);

                    //Are we moving the player character on the world map?
                    if (actor.IsPlayerCharacter && this.Tile.GetType() == typeof(GlobalTile))
                    {
                        //So, how about a random encounter?

                        Random random = new Random();

                        int randomValue = random.Next(100);

                        List<ActionFeedback> feedback = new List<ActionFeedback>();

                        //1%
                        if (randomValue > 99)
                        {
                            //Are we next to a bandit camp ?
                            feedback.Add(new LocationChangeFeedback() { RandomEncounter = (this.Tile as GlobalTile).Biome });
                        }

                        //Change the location of the character
                        actor.GlobalCoordinates = new MapCoordinate(this.Tile.Coordinate);
                        actor.GlobalCoordinates.MapType = MapType.GLOBAL;

                        //Make some time pass
                        feedback.Add(new TimePassFeedback() { TimePassInMinutes = (this.Tile as GlobalTile).TraverseTimeInMinutes(actor) });

                        return feedback.ToArray();
                    }

                    if (actor.IsPlayerCharacter)
                    {
                        //Mark all tiles around him as having been visited
                        return new ActionFeedback[1] { new VisitedBlockFeedback { Coordinate = this.Tile.Coordinate } };
                    }

                    return new ActionFeedback[0];
                }
                else
                {
                    //Check whether it's the player character trying to move on a tile upon which there is an enemy
                    if (actor.IsPlayerCharacter)
                    {
                        if (this.GetTopItem().GetType() == typeof(LocalCharacter))
                        {
                            //Attack him instead - randomly
                            LocalCharacter lc = (LocalCharacter)this.GetTopItem();

                            return new ActionFeedback[] { new AttackFeedback() { Attacker = actor, Defender = lc.Actor } };
                        }
                    }

                    //not possible
                    return new ActionFeedback[] { new TextFeedback("Not possible to move there") };
                }
            }
            else if (actionType == ActionType.THROW)
            {
                //Create and open the 'throw item' feedback
                return new ActionFeedback[] { new OpenInterfaceFeedback(new ThrowItemInterface() { Coordinate = this.Tile.Coordinate }) };
            }

            MapItem item = GetTopItem();

            if (item == null)
            {
                return new ActionFeedback[0] { };
            }

            return item.PerformAction(actionType, actor, args);
        }
Пример #30
0
        /// <summary>
        /// Heal this character if they require it
        /// You heal one point each time, +1 for every 5 levels in Healing
        /// Healing happens top down
        /// </summary>
        /// <param name="actor"></param>
        /// <param name="rounds">The amount of rounds we're going to do this for.</param>
        public static void HealCharacter(Actor actor, int rounds)
        {
            //Do we need healing?
            if (actor.Anatomy.Head > -5 && actor.Anatomy.Head == actor.Anatomy.HeadMax
              && actor.Anatomy.Chest > -5 && actor.Anatomy.Chest == actor.Anatomy.ChestMax
              && actor.Anatomy.Legs > -5 && actor.Anatomy.Legs == actor.Anatomy.LegsMax
              && actor.Anatomy.LeftArm > -5 && actor.Anatomy.LeftArm == actor.Anatomy.LeftArmMax
              && actor.Anatomy.RightArm > -5 && actor.Anatomy.RightArm == actor.Anatomy.RightArmMax)
            {
                //Nope, we're fine
                return;
            }

            //Let's determine how much healing we're able to do
            int healing = 1*rounds;

            int skill = 0;

            if (actor.Attributes.Skills.ContainsKey(SkillName.HEALER))
            {
                skill = (int) actor.Attributes.Skills[SkillName.HEALER].SkillLevel;
            }

            healing = (1 + (skill / 5)) * rounds;

            //Go through each body part and incremement as needed

            int headHealing = actor.Anatomy.Head > -5 ? actor.Anatomy.HeadMax - actor.Anatomy.Head : 0;
            int chestHealing = actor.Anatomy.Chest > -5 ? actor.Anatomy.ChestMax - actor.Anatomy.Chest : 0;
            int leftHealing = actor.Anatomy.LeftArm > -5 ? actor.Anatomy.LeftArmMax - actor.Anatomy.LeftArm : 0;
            int rightHealing = actor.Anatomy.RightArm > -5 ? actor.Anatomy.RightArmMax - actor.Anatomy.RightArm : 0;
            int legHealing = actor.Anatomy.Legs > -5 ? actor.Anatomy.LegsMax - actor.Anatomy.Legs : 0;

            if (headHealing > 0)
            {
                //Heal the head
                if (headHealing <= healing)
                {
                    actor.Anatomy.Head += headHealing;
                    healing -= headHealing;
                }
                else
                {
                    actor.Anatomy.Head += healing;
                    healing = 0;
                }
            }

            if (chestHealing > 0 && healing > 0)
            {
                if (chestHealing <= healing)
                {
                    actor.Anatomy.Chest += chestHealing;
                    healing -= chestHealing;
                }
                else
                {
                    actor.Anatomy.Chest += healing;
                    healing = 0;
                }
            }

            if (leftHealing > 0 && healing > 0)
            {
                if (leftHealing<= healing)
                {
                    actor.Anatomy.LeftArm+= leftHealing;
                    healing -= leftHealing;
                }
                else
                {
                    actor.Anatomy.LeftArm += healing;
                    healing = 0;
                }
            }

            if (rightHealing > 0 && healing > 0)
            {
                if (rightHealing <= healing)
                {
                    actor.Anatomy.RightArm+= rightHealing;
                    healing -= rightHealing;
                }
                else
                {
                    actor.Anatomy.RightArm += healing;
                    healing = 0;
                }
            }

            if (legHealing > 0 && healing > 0)
            {
                if (legHealing <= healing)
                {
                    actor.Anatomy.Legs+= legHealing;
                    healing -= legHealing;
                }
                else
                {
                    actor.Anatomy.Legs += healing;
                    healing = 0;
                }
            }

            //And increase some skill!
            for (int i = 0; i < rounds; i++)
            {
                actor.Attributes.IncreaseSkill(SkillName.HEALER);
            }
        }