Пример #1
0
        public CombatEventResult Attack(string attackerName, string defenderName, double easeOfAttack, double easeOfDodging = World.Mean, bool dodge = true, bool block = true, bool parry = true)
        {
            if (Defender.Has <ControllerComponent>())
            {
                Defender.Get <ControllerComponent>().Disturb();
            }

            double atkRoll = World.SkillRoll();

            if (atkRoll > easeOfAttack)
            {
                Logger.InfoFormat("{0} misses {1} (needs:{2:0.00}, rolled:{3:0.00}, difficulty: {4:0.00}%)", attackerName, defenderName, easeOfAttack, atkRoll,
                                  World.ChanceOfSuccess(easeOfAttack));
                return(CombatEventResult.Miss);
            }

            Logger.InfoFormat("{0} attacks {1} (needs:{2:0.00}, rolled:{3:0.00}, difficulty: {4:0.00}%)", attackerName, defenderName, easeOfAttack, atkRoll,
                              World.ChanceOfSuccess(easeOfAttack));

            if (dodge)
            {
                double defRoll = World.SkillRoll();

                Logger.InfoFormat("{1} attempts to dodge {0}'s attack (needs:{2:0.00}, rolled:{3:0.00}, difficulty: {4:0.00}%)", attackerName, defenderName, easeOfDodging, defRoll,
                                  World.ChanceOfSuccess(easeOfDodging));
                if (defRoll < easeOfDodging)
                {
                    return(CombatEventResult.Dodge);
                }
            }

            // todo defenses, parries, etc

            return(CombatEventResult.Hit);
        }
Пример #2
0
        public void Damage(int damage, double penetration, DamageType type, out int damageResistance, out int damageDealt)
        {
            Contract.Ensures(Contract.ValueAtReturn(out damageDealt) >= 0);
            Contract.Ensures(Contract.ValueAtReturn(out damageResistance) >= 0);

            damageDealt      = damage;
            damageResistance = 0;

            if (Defender.Has <EquipmentComponent>())
            {
                var equipment = Defender.Get <EquipmentComponent>();

                if (equipment.ContainSlot(BodyPartTargetted.Name) && equipment.IsSlotEquipped(BodyPartTargetted.Name))
                {
                    var armorEntity = equipment.GetEquippedItemAt(BodyPartTargetted.Name);

                    if (armorEntity.Has <ArmorComponent>())
                    {
                        var armor = armorEntity.Get <ArmorComponent>();

                        if (armor.Defenses.ContainsKey(BodyPartTargetted.Name))
                        {
                            if (Rng.Chance(armor.Defenses[BodyPartTargetted.Name].Coverage / 100.0))
                            {
                                damageResistance = (int)Math.Floor(armor.Defenses[BodyPartTargetted.Name].Resistances[type] / penetration);
                                damageDealt      = Math.Max(damage - damageResistance, 0);
                                Logger.InfoFormat("Damage: {3} reduced to {0} because of {1} [DR: {2}]", damageDealt, armor.OwnerUId, damageResistance, damage);
                            }
                            else
                            {
                                // we hit a chink in the armor
                                damageResistance = 0;
                                Logger.InfoFormat("Hit a chink in the armor, DR = 0");
                            }
                        }
                    }
                }
            }

            if (Defender.Has <ActorComponent>())
            {
                Defender.Get <ActorComponent>().Disturb();
            }

            if (damageDealt > BodyPartTargetted.MaxHealth)
            {
                damageDealt = Math.Min(damage, BodyPartTargetted.MaxHealth);
                Logger.DebugFormat("Damage reduced to {0} because of {1}'s max health", damageDealt, BodyPartTargetted.Name);
            }

            BodyPartTargetted.Health       -= damageDealt;
            BodyPartTargetted.Owner.Health -= damageDealt;

            Logger.InfoFormat("{0}'s {1} was hurt ({2} damage)", Identifier.GetNameOrId(Defender), BodyPartTargetted.Name, damageDealt);
        }
Пример #3
0
        public override ActionResult OnProcess()
        {
            var hitBonus         = 0;
            var weapon           = Weapon.Get <RangeComponent>();
            var attackerName     = Identifier.GetNameOrId(Attacker);
            var defenderName     = Identifier.GetNameOrId(Defender);
            var attackerLocation = Attacker.Get <Location>();
            var defenderLocation = Defender.Get <Location>();


            //apply skill
            if (Attacker.Has <ActorComponent>())
            {
                hitBonus += Attacker.Get <Person>().GetSkill(weapon.Skill).Rank;
            }
            else
            {
                hitBonus += World.MEAN;
            }

            if (weapon.ShotsRemaining <= 0)
            {
                World.Log.Normal(String.Format("{0} attempts to use the only to realize the weapon is not loaded",
                                               attackerName));
                Attacker.Get <ActorComponent>().AP.ActionPoints -= weapon.APToAttack;
                return(ActionResult.Failed);
            }

            weapon.ShotsRemaining--;

            IEnumerable <Entity> entitiesOnPath;

            if (attackerLocation.Point == defenderLocation.Point)
            {
                // suicide?
                entitiesOnPath = attackerLocation.Level.GetEntitiesAt(defenderLocation.Point).Where(e => e.Has <DefendComponent>()).ToList();
            }
            else
            {
                entitiesOnPath = GetTargetsOnPath(attackerLocation.Level, attackerLocation.Point, defenderLocation.Point).ToList();
            }

            int targetsInTheWay = 0;

            foreach (var currentEntity in entitiesOnPath)
            {
                var targetLocation = currentEntity.Get <Location>();

                double range        = targetLocation.DistanceTo(attackerLocation) * World.TILE_LENGTH_IN_METER;
                double rangePenalty = Math.Min(0, -World.STANDARD_DEVIATION * RANGE_PENALTY_STD_DEV_MULT * Math.Log(range) + World.STANDARD_DEVIATION * 2 / 3);
                Logger.InfoFormat("Target: {2}, range to target: {0}, penalty: {1}", range, rangePenalty, defenderName);

                // not being targetted gives a sigma (std dev) penalty
                rangePenalty -= Defender.Id == currentEntity.Id ? 0 : World.STANDARD_DEVIATION;

                int difficultyOfShot = (int)Math.Round(hitBonus + rangePenalty + (targetsInTheWay * RANGE_PENALTY_TILE_OCCUPIED) - (TargettingPenalty ? BodyPartTargetted.TargettingPenalty : 0));
                Logger.InfoFormat("Shot difficulty: {0}, targetting penalty: {1}, weapon bonus: {2}, is target: {3}",
                                  difficultyOfShot, BodyPartTargetted.TargettingPenalty, hitBonus,
                                  Defender.Id == currentEntity.Id);

                var result = Attack(attackerName, defenderName, difficultyOfShot);

                if (result == CombatEventResult.Hit)
                {
                    var damage = Math.Max(weapon.Damage.Roll(), 1);
                    int damageResistance, realDamage;

                    Damage(weapon.Damage.Roll(), weapon.Penetration, weapon.DamageType, out damageResistance, out realDamage);

                    World.Log.Normal(String.Format("{0} {1} {2}'s {3}.... and inflict {4} wounds.",
                                                   attackerName, weapon.ActionDescriptionPlural, defenderName, BodyPartTargetted.Name, "todo-description"));

                    Logger.Info(new CombatEventArgs(Attacker, Defender, Weapon, BodyPartTargetted, CombatEventResult.Hit, damage,
                                                    damageResistance, realDamage));
                    return(ActionResult.Success);
                }
                else if (result == CombatEventResult.Miss)
                {
                    if (Defender.Id == currentEntity.Id)                     // if this is where the actor targetted
                    {
                        World.Log.Normal(String.Format("{0} {1} {2}'s {3}.... and misses.",
                                                       attackerName, weapon.ActionDescriptionPlural, defenderName, BodyPartTargetted.Name));
                    }

                    Logger.Info(new CombatEventArgs(Attacker, Defender, Weapon, BodyPartTargetted));
                    return(ActionResult.Failed);
                }
                else if (result == CombatEventResult.Dodge)
                {
                    if (Defender.Id == currentEntity.Id)                     // if this is where the actor targetted
                    {
                        World.Log.Normal(String.Format("{0} {1} {2}'s {3}.... and {2} dodges.",
                                                       attackerName, weapon.ActionDescriptionPlural, defenderName, BodyPartTargetted.Name));
                    }

                    Logger.Info(new CombatEventArgs(Attacker, Defender, Weapon, BodyPartTargetted, CombatEventResult.Dodge));
                    return(ActionResult.Failed);
                }
                targetsInTheWay++;
            }

            // todo drop ammo casing

            World.Log.Normal(String.Format("{0} {1} and hits nothing", attackerName, weapon.ActionDescriptionPlural));
            return(ActionResult.Failed);
        }
Пример #4
0
        public override ActionResult OnProcess()
        {
            var hitBonus         = 0;
            var weapon           = Weapon.Get <RangeComponent>();
            var attackerName     = Identifier.GetNameOrId(Attacker);
            var defenderName     = Identifier.GetNameOrId(Defender);
            var attackerLocation = Attacker.Get <GameObject>();
            var defenderLocation = Defender.Get <GameObject>();

            //apply skill
            if (Attacker.Has <ControllerComponent>())
            {
                hitBonus += Attacker.Get <Creature>().Skills[weapon.Skill];
            }
            else
            {
                hitBonus += World.Mean;
            }

            if (weapon.ShotsRemaining <= 0)
            {
                Log.NormalFormat("{0} attempts to use the only to realize the weapon is not loaded",
                                 attackerName);
                return(ActionResult.Failed);
            }

            weapon.ShotsRemaining--;

            IEnumerable <Entity> entitiesOnPath;

            if (attackerLocation.Location == defenderLocation.Location)
            {
                // suicide?
                entitiesOnPath = attackerLocation.Level.GetEntitiesAt <BodyComponent>(defenderLocation.Location).ToList();
            }
            else
            {
                entitiesOnPath = GetTargetsOnPath(attackerLocation.Level, attackerLocation.Location, defenderLocation.Location).ToList();
            }

            int targetsInTheWay = 0;

            foreach (var currentEntity in entitiesOnPath)
            {
                var targetLocation = currentEntity.Get <GameObject>();

                double range        = targetLocation.DistanceTo(attackerLocation) * World.TileLengthInMeter;
                double rangePenalty = Math.Min(0, -World.StandardDeviation * RangePenaltyStdDevMultiplier * Math.Log(range) + World.StandardDeviation * 2 / 3);
                Logger.InfoFormat("Target: {2}, range to target: {0}, penalty: {1}", range, rangePenalty, defenderName);

                // not being targetted gives a sigma (std dev) penalty
                rangePenalty -= Defender.Id == currentEntity.Id ? 0 : World.StandardDeviation;

                int easeOfShot = (int)Math.Round(hitBonus + rangePenalty + (targetsInTheWay * RangePenaltyTileOccupied) + (TargettingPenalty ? BodyPartTargetted.TargettingPenalty : 0));
                Logger.InfoFormat("Ease of Shot: {0}, targetting penalty: {1}, weapon bonus: {2}, is original target: {3}",
                                  easeOfShot, BodyPartTargetted.TargettingPenalty, hitBonus,
                                  Defender.Id == currentEntity.Id);

                var result = Attack(attackerName, defenderName, easeOfShot);

                if (result == CombatEventResult.Hit)
                {
                    var damage = Math.Max(weapon.Damage.Roll(), 1);
                    int damageResistance, realDamage;

                    Damage(weapon.Damage.Roll(), weapon.Penetration, weapon.DamageType, out damageResistance, out realDamage);

                    Log.NormalFormat("{0} {1} {2}'s {3}.... and inflict {4} wounds.",
                                     attackerName, weapon.ActionDescriptionPlural, defenderName, BodyPartTargetted.Name, "todo-description");

                    Logger.Info(new CombatEventArgs(Attacker, Defender, Weapon, BodyPartTargetted, CombatEventResult.Hit, damage,
                                                    damageResistance, realDamage));
                    return(ActionResult.Success);
                }
                else if (result == CombatEventResult.Miss)
                {
                    if (Defender.Id == currentEntity.Id)                     // if this is where the actor targetted
                    {
                        Log.NormalFormat("{0} {1} {2}'s {3}.... and misses.",
                                         attackerName, weapon.ActionDescriptionPlural, defenderName, BodyPartTargetted.Name);
                    }

                    Logger.Info(new CombatEventArgs(Attacker, Defender, Weapon, BodyPartTargetted));
                    return(ActionResult.Failed);
                }
                else if (result == CombatEventResult.Dodge)
                {
                    if (Defender.Id == currentEntity.Id)                     // if this is where the actor targetted
                    {
                        Log.NormalFormat("{0} {1} {2}'s {3}.... and {2} dodges.",
                                         attackerName, weapon.ActionDescriptionPlural, defenderName, BodyPartTargetted.Name);
                    }

                    Logger.Info(new CombatEventArgs(Attacker, Defender, Weapon, BodyPartTargetted, CombatEventResult.Dodge));
                    return(ActionResult.Failed);
                }
                targetsInTheWay++;
            }

            // todo drop ammo casing

            Log.NormalFormat("{0} {1} and hits nothing", attackerName, weapon.ActionDescriptionPlural);
            return(ActionResult.Failed);
        }