public CombatManualComponent(int x, int y,CombatManual manual)
        {
            this.cm = manual;

            this.newAttack = cm.SpecialAttack;

            this.locationX = x;
            this.locationY = y;

            this.PerformDrag(0, 0);

            this.clickedNumber = 0;
        }
        public void HandleMouseOver(int x, int y)
        {
            //Are we mousing over a particular special attack?

            selectedAttack = null;

            for (int i = 0; i < saRects.Length; i++)
            {
                Rectangle rect = saRects[i];

                if (rect.Contains(x, y))
                {
                    //Yep!
                    selectedAttack = attacker.SpecialAttacks[i];
                }
            }

            if (selectedAttack != null)
            {
                //Display the details
                int locationX = x + 5;
                int locationY = y;

                int bufferX = 10;
                int bufferY = 40;

                saDetailsRect = new Rectangle(locationX, locationY, 200, 140);

                saNameRect = new Rectangle(locationX, locationY+10, 200, 30);

                sadBleedIcon = new Rectangle(locationX + bufferX, locationY + bufferY, 30, 30);
                sadBleedValue = new Rectangle(locationX + bufferX + 30, locationY + bufferY, 30, 30);

                sadAccuracyIcon = new Rectangle(locationX + bufferX + 60, locationY + bufferY, 30, 30);
                sadAccuracyValue = new Rectangle(locationX + bufferX + 90, locationY + bufferY, 30, 30);

                sadStunIcon = new Rectangle(locationX + bufferX + 120, locationY + bufferY, 30, 30);
                sadStunValue = new Rectangle(locationX + bufferX + 150, locationY + bufferY, 30, 30);

                //--
                sadDamageIcon = new Rectangle(locationX + bufferX + 0, locationY + 30 + bufferY, 30, 30);
                sadDamageValue = new Rectangle(locationX + bufferX + 30, locationY + 30 + bufferY, 30, 30); ;

                sadAttacksIcon = new Rectangle(locationX + bufferX + 60, locationY + 30 + bufferY, 30, 30);
                sadAttacksValue = new Rectangle(locationX + bufferX + 90, locationY + 30 + bufferY, 30, 30);

                sadPiercingIcon = new Rectangle(locationX + bufferX + 120, locationY + 30 + bufferY, 30, 30);
                sadPiercingValue = new Rectangle(locationX + bufferX + 150, locationY + 30 + bufferY, 30, 30);
                //---
                sadSunderIcon = new Rectangle(locationX + bufferX, locationY + 60 + bufferY , 30, 30);
                sadSunderValue = new Rectangle(locationX + bufferX + 30, locationY + 60 + bufferY, 30, 30);

                sadPushIcon = new Rectangle(locationX + bufferX + 60, locationY + 60 + bufferY, 30, 30);
                sadPushValue = new Rectangle(locationX + bufferX + 90, locationY + 60 + bufferY, 30, 30);

                sadTargetsIcon = new Rectangle(locationX + bufferX + 120, locationY + 60 + bufferY, 30, 30);
                sadTargetsValue = new Rectangle(locationX + bufferX + 150, locationY + 60 + bufferY, 30, 30);

            }
        }
Example #3
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();
        }
Example #4
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();
        }
        /// <summary>
        /// Generates a special attack having a particular level
        /// </summary>
        /// <param name="level"></param>
        /// <returns></returns>
        public static SpecialAttack GenerateSpecialAttack(int level)
        {
            //Let's see how many points this counts as
            int pointTotal = Settings.PointProgression[level - 1];

            SpecialAttack attack = new SpecialAttack();
            attack.AttackName = GenerateName();
            attack.Level = level;
            attack.PointCost = pointTotal;
            attack.Effects = new List<Effect>();

            Random random = GameState.Random;

            int attempts = 0;

            while(pointTotal > 0 && attempts++ < 100)
            {
                //Spend!
                var randomEffect = Settings.EffectCosts.GetRandom();

                if (randomEffect.PointCost > pointTotal)
                {
                    continue;
                }

                //Do we have it already?
                var current = attack.Effects.FirstOrDefault(e => e.EffectType == randomEffect.Type);

                if (current != null)
                {
                    int index = 0;

                    //Can we progress?
                    for (index = 0; index < randomEffect.Progressions.Length; index++)
                    {
                        if (randomEffect.Progressions[index] == current.EffectValue)
                        {
                            break;
                        }
                    }

                    //Is that the last one?
                    if (index == randomEffect.Progressions.Length -1)
                    {
                        //Yep. Continue
                        continue;
                    }
                    else
                    {
                        //Nope, we can
                        current.EffectValue = randomEffect.Progressions[index + 1];
                        pointTotal -= randomEffect.PointCost;
                    }

                }
                else
                {
                    //Nope, create a new one
                    Effect effect = new Effect();
                    effect.EffectType = randomEffect.Type;
                    effect.EffectValue = randomEffect.Progressions[0];

                    attack.Effects.Add(effect);

                    pointTotal -= randomEffect.PointCost;
                }

            }

            attack.TimeOutLeft = 0;
            var timeOut = attack.Effects.FirstOrDefault(e => e.EffectType == SpecialAttackType.TIMEOUT);

            attack.TimeOut = timeOut == null ? 15 : timeOut.EffectValue;

            return attack;
        }
        public void Draw(Microsoft.Xna.Framework.Content.ContentManager content, Microsoft.Xna.Framework.Graphics.SpriteBatch batch)
        {
            if (font == null)
            {
                font = content.Load<SpriteFont>(@"Fonts/TextFeedbackFont");
            }

            var white = SpriteManager.GetSprite(ColourSpriteName.WHITE);

            batch.Draw(content, white, borderRect, Color.DarkGray);

            //Draw the background
            var scrollBackground = SpriteManager.GetSprite(InterfaceSpriteName.PAPER_TEXTURE);

            batch.Draw(content.Load<Texture2D>(scrollBackground.path), rect, scrollBackground.sourceRectangle, Color.White);

            batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.PAPER_TEXTURE), oldBackground, Color.White);
            batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.PAPER_TEXTURE), newBackground, Color.White);
            batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.PAPER_TEXTURE), slotBackground, Color.White);

            //The text
            batch.DrawString(font, newAttack.AttackName, newName, Alignment.Center, Color.Black);
            batch.DrawString(font, "New Attack", newText, Alignment.Center, Color.White);

            foreach (var icons in newIcons)
            {
                switch (icons.Item1)
                {
                    case SpecialAttackType.ACCURACY:
                        batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.ACCURATE_STRIKE), icons.Item2, Color.Black);
                        break;
                    case SpecialAttackType.ATTACKS:
                        batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.RAPID_STRIKES), icons.Item2, Color.Black);
                        break;
                    case SpecialAttackType.BLEED:
                        batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.BLEEDING_STRIKE), icons.Item2, Color.Black);
                        break;
                    case SpecialAttackType.DAMAGE:
                        batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.POWER_STRIKE), icons.Item2, Color.Black);
                        break;
                    case SpecialAttackType.PIERCING:
                        batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.ARMOUR_PIERCING_STRIKE), icons.Item2, Color.Black);
                        break;
                    case SpecialAttackType.PUSH:
                        batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.PUSHBACK), icons.Item2, Color.Black);
                        break;
                    case SpecialAttackType.STUN:
                        batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.STUNNING_STRIKE), icons.Item2, Color.Black);
                        break;
                    case SpecialAttackType.SUNDER:
                        batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.SUNDER), icons.Item2, Color.Black);
                        break;
                    case SpecialAttackType.TARGETS:
                        batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.WHIRLWIND), icons.Item2, Color.Black);
                        break;
                }
            }

            foreach (var details in newDetails)
            {
                DRObjects.ActorHandling.SpecialAttacks.Effect effect = newAttack.Effects.FirstOrDefault(e => e.EffectType == details.Item1);

                string display = "0";

                if (effect != null)
                {
                    display = effect.EffectValue.ToString();
                }

                Color colour = Color.Black;

                if (oldAttack != null)
                {
                    int newCompare = newAttack.Effects.Where(e => e.EffectType == details.Item1).Select(e => e.EffectValue).FirstOrDefault();
                    int oldCompare = oldAttack.Effects.Where(e => e.EffectType == details.Item1).Select(e => e.EffectValue).FirstOrDefault();

                    if (newCompare > oldCompare)
                    {
                        colour = Color.Green;
                    }
                    else if (newCompare < oldCompare)
                    {
                        colour = Color.Red;
                    }
                }

                batch.DrawString(font, display, details.Item2, Alignment.Center, colour);
            }

            for (int i = 0; i < slotRectangles.Length; i++)
            {
                Rectangle slot = slotRectangles[i];

               // batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.PAPER_TEXTURE), slotRectangles[i], Color.White);

                SpriteData sprite = SpriteManager.GetSprite( (InterfaceSpriteName) Enum.Parse(typeof(InterfaceSpriteName),"SA" + (i+1) ));

                batch.Draw(content,sprite,slotRectangles[i],GameState.PlayerCharacter.SpecialAttacks[i] == null ? Color.Black : Color.White);

                if (clickedNumber == i)
                {
                    //Circle!
                    batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.CIRCLE), new Rectangle(slotRectangles[i].X - 10, slotRectangles[i].Y - 10, slotRectangles[i].Width + 20, slotRectangles[i].Height + 20), Color.White);
                }
            }

            if (this.clickedNumber != null)
            {
                oldAttack = GameState.PlayerCharacter.SpecialAttacks[this.clickedNumber.Value];
            }
            else
            {
                oldAttack = null;
            }

            if (oldAttack != null)
            {
                //Draw the old attack stuff
                batch.DrawString(font, oldAttack.AttackName, oldName, Alignment.Center, Color.Black);
                batch.DrawString(font, "Old Attack", oldText, Alignment.Center, Color.White);

                foreach (var icons in oldIcons)
                {
                    switch (icons.Item1)
                    {
                        case SpecialAttackType.ACCURACY:
                            batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.ACCURATE_STRIKE), icons.Item2, Color.Black);
                            break;
                        case SpecialAttackType.ATTACKS:
                            batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.RAPID_STRIKES), icons.Item2, Color.Black);
                            break;
                        case SpecialAttackType.BLEED:
                            batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.BLEEDING_STRIKE), icons.Item2, Color.Black);
                            break;
                        case SpecialAttackType.DAMAGE:
                            batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.POWER_STRIKE), icons.Item2, Color.Black);
                            break;
                        case SpecialAttackType.PIERCING:
                            batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.ARMOUR_PIERCING_STRIKE), icons.Item2, Color.Black);
                            break;
                        case SpecialAttackType.PUSH:
                            batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.PUSHBACK), icons.Item2, Color.Black);
                            break;
                        case SpecialAttackType.STUN:
                            batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.STUNNING_STRIKE), icons.Item2, Color.Black);
                            break;
                        case SpecialAttackType.SUNDER:
                            batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.SUNDER), icons.Item2, Color.Black);
                            break;
                        case SpecialAttackType.TARGETS:
                            batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.WHIRLWIND), icons.Item2, Color.Black);
                            break;
                    }
                }

                foreach (var details in oldDetails)
                {
                    DRObjects.ActorHandling.SpecialAttacks.Effect effect = oldAttack.Effects.FirstOrDefault(e => e.EffectType == details.Item1);

                    string display = "0";

                    if (effect != null)
                    {
                        display = effect.EffectValue.ToString();
                    }

                    batch.DrawString(font, display, details.Item2, Alignment.Center, Color.Black);
                }

            }
            else if (this.clickedNumber != null)
            {
                //This means a non-selected one is selected
                batch.DrawString(font, "Empty Slot", oldName, Alignment.Center, Color.Black);
                batch.DrawString(font, "Old Attack", oldText, Alignment.Center, Color.White);
            }

            if (this.newAttack.SkillLevelRequired <= GameState.PlayerCharacter.Attributes.GetSkill(SkillName.FIGHTER))
            {
                batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.PAPER_TEXTURE), learnRect, Color.LightGray);
                batch.DrawString(font, "LEARN", learnRect, Alignment.Center, Color.DarkGreen);
            }

            batch.Draw(content, SpriteManager.GetSprite(InterfaceSpriteName.PAPER_TEXTURE), cancelRect, Color.LightGray);
            batch.DrawString(font, "CANCEL", cancelRect, Alignment.Center, Color.DarkRed);
        }
Example #7
0
 public CombatManual(SpecialAttack attack)
 {
     this.SpecialAttack = attack;
 }