Example #1
0
        public void FightDirty(WorldObject target)
        {
            // Skill description:
            // Your melee and missile attacks have a chance to weaken your opponent.
            // - Low attacks can reduce the defense skills of the opponent.
            // - Medium attacks can cause small amounts of bleeding damage.
            // - High attacks can reduce opponents' attack and healing skills

            // Effects:
            // Low: reduces the defense skills of the opponent by -10
            // Medium: bleed ticks for 60 damage per 20 seconds
            // High: reduces the attack skills of the opponent by -10, and
            //       the healing effects of the opponent by -15 rating
            //
            // these damage #s are doubled for dirty fighting specialized.

            // Notes:
            // - Dirty fighting works for melee and missile attacks.
            // - Has a 25% chance to activate on any melee of missile attack.
            //   - This activation is reduced proportionally if Dirty Fighting is lower
            //     than your active weapon skill as determined by your equipped weapon.
            // - All activate effects last 20 seconds.
            // - Although a specific effect won't stack with itself,
            //   you can stack all 3 effects on the opponent at the same time. This means
            //   when a skill activates at one attack height, you can move to another attack height
            //   to try to land an additional effect.
            // - Successfully landing a Dirty Fighting effect is mentioned in chat. Additionally,
            //   the medium height effect results in 'floating glyphs' around the target:

            //   "Dirty Fighting! <Player> delivers a Bleeding Assault to <target>!"
            //   "Dirty Fighting! <Player> delivers a Traumatic Assault to <target>!"

            // dirty fighting skill must be at least trained
            var dirtySkill = GetCreatureSkill(Skill.DirtyFighting);

            if (dirtySkill.AdvancementClass < SkillAdvancementClass.Trained)
            {
                return;
            }

            // ensure creature target
            var creatureTarget = target as Creature;

            if (creatureTarget == null)
            {
                return;
            }

            var chance = 0.25f;

            var attackSkill = GetCreatureSkill(GetCurrentWeaponSkill());

            if (dirtySkill.Current < attackSkill.Current)
            {
                chance *= (float)dirtySkill.Current / attackSkill.Current;
            }

            var rng = ThreadSafeRandom.Next(0.0f, 1.0f);

            if (rng > chance)
            {
                return;
            }

            switch (AttackHeight)
            {
            case ACE.Entity.Enum.AttackHeight.Low:
                FightDirty_ApplyLowAttack(creatureTarget);
                break;

            case ACE.Entity.Enum.AttackHeight.Medium:
                FightDirty_ApplyMediumAttack(creatureTarget);
                break;

            case ACE.Entity.Enum.AttackHeight.High:
                FightDirty_ApplyHighAttack(creatureTarget);
                break;
            }
        }
        private async Task CommandExecutedAsync(Optional <CommandInfo> command, ICommandContext context, IResult result)
        {
            // Null is success, because some modules returns null after success and library always returns ExecuteResult.
            if (result == null)
            {
                result = ExecuteResult.FromSuccess();
            }

            if (!result.IsSuccess && result.Error != null)
            {
                string reply = "";

                string moreInfo = "";
                if (command.IsSpecified)
                {
                    moreInfo = $"\n*Pro vice informací zadej `{Configuration["Prefix"]}help {command.Value.Aliases.First().Split(' ', 2)[0]}`*";
                }

                switch (result.Error.Value)
                {
                case CommandError.Unsuccessful when result is CommandRedirectResult crr && !string.IsNullOrEmpty(crr.NewCommand):
                    await CommandService.ExecuteAsync(context, crr.NewCommand, Provider);

                    break;

                case CommandError.UnmetPrecondition:
                case CommandError.Unsuccessful:
                    reply = result.ErrorReason;
                    break;

                case CommandError.ObjectNotFound when result is ParseResult parseResult && typeof(IUser).IsAssignableFrom(parseResult.ErrorParameter.Type):
                    ParameterInfo param = ((ParseResult)result).ErrorParameter;
                    var           pos   = param.Command.Parameters.ToList().IndexOf(param);

                    reply = $"Nemohl jsem najít uživatele zadaného v {pos + 1}. argumentu.\n> {command.Value.GetCommandFormat(Configuration["Prefix"], param)}{moreInfo}";
                    break;

                case CommandError.ParseFailed:
                    param = ((ParseResult)result).ErrorParameter;
                    pos   = param.Command.Parameters.ToList().IndexOf(param);

                    var typeName = param.Type.Name;

                    if (typeName == "Int32")
                    {
                        typeName = "číslo";
                    }
                    if (typeName == "String")
                    {
                        typeName = "řetězec";
                    }

                    reply = $"V {pos + 1}. argumentu má být **{typeName}**\n> {command.Value.GetCommandFormat(Configuration["Prefix"], param)}{moreInfo}";
                    break;

                case CommandError.BadArgCount:
                    var firstLine = Configuration.GetSection("BadArgumentFirstLine").AsEnumerable().Where(o => o.Value != null).ToArray();

                    reply = $"{firstLine[ThreadSafeRandom.Next(firstLine.Length)].Value}\n> {command.Value.GetCommandFormat(Configuration["Prefix"])}{moreInfo}";
                    break;

                case CommandError.Exception:
                    await context.Message.AddReactionAsync(new Emoji("❌"));

                    break;
                }

                // Reply to command message without mentioning any user
                if (!string.IsNullOrEmpty(reply))
                {
                    await context.Message.ReplyAsync(reply, allowedMentions : new AllowedMentions {
                        MentionRepliedUser = false
                    });
                }
            }
        }
        /// <summary>
        /// Rolls for the ManaConversionMod for casters
        /// </summary>
        private static double RollManaConversionMod(int tier)
        {
            int magicMod = 0;

            int chance = 0;

            switch (tier)
            {
            case 1:
            case 2:
                magicMod = 0;
                break;

            case 3:
                chance = ThreadSafeRandom.Next(1, 1000);
                if (chance > 900)
                {
                    magicMod = 5;
                }
                else if (chance > 800)
                {
                    magicMod = 4;
                }
                else if (chance > 700)
                {
                    magicMod = 3;
                }
                else if (chance > 600)
                {
                    magicMod = 2;
                }
                else if (chance > 500)
                {
                    magicMod = 1;
                }
                break;

            case 4:
                chance = ThreadSafeRandom.Next(1, 1000);
                if (chance > 900)
                {
                    magicMod = 10;
                }
                else if (chance > 800)
                {
                    magicMod = 9;
                }
                else if (chance > 700)
                {
                    magicMod = 8;
                }
                else if (chance > 600)
                {
                    magicMod = 7;
                }
                else if (chance > 500)
                {
                    magicMod = 6;
                }
                else
                {
                    magicMod = 5;
                }
                break;

            case 5:
                chance = ThreadSafeRandom.Next(1, 1000);
                if (chance > 900)
                {
                    magicMod = 10;
                }
                else if (chance > 800)
                {
                    magicMod = 9;
                }
                else if (chance > 700)
                {
                    magicMod = 8;
                }
                else if (chance > 600)
                {
                    magicMod = 7;
                }
                else if (chance > 500)
                {
                    magicMod = 6;
                }
                else
                {
                    magicMod = 5;
                }
                break;

            case 6:
                chance = ThreadSafeRandom.Next(1, 1000);
                if (chance > 900)
                {
                    magicMod = 10;
                }
                else if (chance > 800)
                {
                    magicMod = 9;
                }
                else if (chance > 700)
                {
                    magicMod = 8;
                }
                else if (chance > 600)
                {
                    magicMod = 7;
                }
                else if (chance > 500)
                {
                    magicMod = 6;
                }
                else
                {
                    magicMod = 5;
                }
                break;

            case 7:
                chance = ThreadSafeRandom.Next(1, 1000);
                if (chance > 900)
                {
                    magicMod = 10;
                }
                else if (chance > 800)
                {
                    magicMod = 9;
                }
                else if (chance > 700)
                {
                    magicMod = 8;
                }
                else if (chance > 600)
                {
                    magicMod = 7;
                }
                else if (chance > 500)
                {
                    magicMod = 6;
                }
                else
                {
                    magicMod = 5;
                }
                break;

            default:
                chance = ThreadSafeRandom.Next(1, 1000);
                if (chance > 900)
                {
                    magicMod = 10;
                }
                else if (chance > 800)
                {
                    magicMod = 9;
                }
                else if (chance > 700)
                {
                    magicMod = 8;
                }
                else if (chance > 600)
                {
                    magicMod = 7;
                }
                else if (chance > 500)
                {
                    magicMod = 6;
                }
                else
                {
                    magicMod = 5;
                }
                break;
            }

            double manaDMod = magicMod / 100.0;

            return(manaDMod);
        }
        private static void MutateCaster(WorldObject wo, TreasureDeath profile, bool isMagical, int?wieldDifficulty = null, TreasureRoll roll = null)
        {
            if (wieldDifficulty != null)
            {
                // previous method

                var wieldRequirement = WieldRequirement.RawSkill;
                var wieldSkillType   = Skill.None;

                double elementalDamageMod = 0;

                if (wieldDifficulty == 0)
                {
                    if (profile.Tier > 6)
                    {
                        wieldRequirement = WieldRequirement.Level;
                        wieldSkillType   = Skill.Axe; // Set by examples from PCAP data

                        wieldDifficulty = profile.Tier switch
                        {
                            7 => 150, // In this instance, used for indicating player level, rather than skill level
                            _ => 180, // In this instance, used for indicating player level, rather than skill level
                        };
                    }
                }
                else
                {
                    elementalDamageMod = RollElementalDamageMod(wieldDifficulty.Value);

                    if (wo.W_DamageType == DamageType.Nether)
                    {
                        wieldSkillType = Skill.VoidMagic;
                    }
                    else
                    {
                        wieldSkillType = Skill.WarMagic;
                    }
                }

                // ManaConversionMod
                var manaConversionMod = RollManaConversionMod(profile.Tier);
                if (manaConversionMod > 0.0f)
                {
                    wo.ManaConversionMod = manaConversionMod;
                }

                // ElementalDamageMod
                if (elementalDamageMod > 1.0f)
                {
                    wo.ElementalDamageMod = elementalDamageMod;
                }

                // WieldRequirements
                if (wieldDifficulty > 0 || wieldRequirement == WieldRequirement.Level)
                {
                    wo.WieldRequirements = wieldRequirement;
                    wo.WieldSkillType    = (int)wieldSkillType;
                    wo.WieldDifficulty   = wieldDifficulty;
                }
                else
                {
                    wo.WieldRequirements = WieldRequirement.Invalid;
                    wo.WieldSkillType    = null;
                    wo.WieldDifficulty   = null;
                }

                // WeaponDefense
                wo.WeaponDefense = RollWeaponDefense(wieldDifficulty.Value, profile);
            }
            else
            {
                // new method - mutation scripts

                // mutate ManaConversionMod
                var mutationFilter = MutationCache.GetMutation("Casters.caster.txt");
                mutationFilter.TryMutate(wo, profile.Tier);

                // mutate ElementalDamageMod / WieldRequirements
                var isElemental = wo.W_DamageType != DamageType.Undef;
                var scriptName  = GetCasterScript(isElemental);

                mutationFilter = MutationCache.GetMutation(scriptName);
                mutationFilter.TryMutate(wo, profile.Tier);

                // this part was not handled by mutation filter
                if (wo.WieldRequirements == WieldRequirement.RawSkill)
                {
                    if (wo.W_DamageType == DamageType.Nether)
                    {
                        wo.WieldSkillType = (int)Skill.VoidMagic;
                    }
                    else
                    {
                        wo.WieldSkillType = (int)Skill.WarMagic;
                    }
                }

                // mutate WeaponDefense
                mutationFilter = MutationCache.GetMutation("Casters.weapon_defense.txt");
                mutationFilter.TryMutate(wo, profile.Tier);
            }

            // material type
            int materialType = GetMaterialType(wo, profile.Tier);

            if (materialType > 0)
            {
                wo.MaterialType = (MaterialType)materialType;
            }

            // item color
            MutateColor(wo);

            // gem count / gem material
            if (wo.GemCode != null)
            {
                wo.GemCount = GemCountChance.Roll(wo.GemCode.Value, profile.Tier);
            }
            else
            {
                wo.GemCount = ThreadSafeRandom.Next(1, 5);
            }

            wo.GemType = RollGemType(profile.Tier);

            // workmanship
            wo.ItemWorkmanship = WorkmanshipChance.Roll(profile.Tier);

            // burden?

            // item value
            wo.Value = Roll_ItemValue(wo, profile.Tier);

            // missile defense / magic defense
            wo.WeaponMissileDefense = RollWeapon_MissileMagicDefense(profile.Tier);
            wo.WeaponMagicDefense   = RollWeapon_MissileMagicDefense(profile.Tier);

            // spells
            if (!isMagical)
            {
                wo.ItemManaCost   = null;
                wo.ItemMaxMana    = null;
                wo.ItemCurMana    = null;
                wo.ItemSpellcraft = null;
                wo.ItemDifficulty = null;
            }
            else
            {
                // if a caster was from a MagicItem profile, it always had a SpellDID
                MutateCaster_SpellDID(wo, profile);

                AssignMagic(wo, profile, roll);
            }

            // long description
            wo.LongDesc = GetLongDesc(wo);
        }
Example #5
0
        public float?CalculateDamage(WorldObject target, WorldObject damageSource, ref bool criticalHit, ref bool sneakAttack)
        {
            var creature = target as Creature;

            // evasion chance
            var evadeChance = GetEvadeChance(target);

            if (ThreadSafeRandom.Next(0.0f, 1.0f) < evadeChance)
            {
                return(null);
            }

            // get weapon base damage
            var baseDamageRange = GetBaseDamage();
            var baseDamage      = ThreadSafeRandom.Next(baseDamageRange.Min, baseDamageRange.Max);

            // get damage mods
            var attackType       = GetAttackType();
            var attributeMod     = GetAttributeMod(attackType);
            var powerAccuracyMod = GetPowerAccuracyMod();
            var recklessnessMod  = GetRecklessnessMod(this, creature);
            var sneakAttackMod   = GetSneakAttackMod(target);

            sneakAttack = sneakAttackMod > 1.0f;

            var damageRatingMod = AdditiveCombine(recklessnessMod, sneakAttackMod, GetRatingMod(EnchantmentManager.GetDamageRating()));
            //Console.WriteLine("Damage rating: " + ModToRating(damageRatingMod));

            var damage = baseDamage * attributeMod * powerAccuracyMod * damageRatingMod;

            // critical hit
            var critical = GetWeaponPhysicalCritFrequencyModifier(this);

            if (ThreadSafeRandom.Next(0.0f, 1.0f) < critical)
            {
                damage      = baseDamageRange.Max * attributeMod * powerAccuracyMod * sneakAttackMod * (2.0f + GetWeaponCritMultiplierModifier(this));
                criticalHit = true;
            }

            // get random body part @ attack height
            var bodyPart = BodyParts.GetBodyPart(target, AttackHeight.Value);

            if (bodyPart == null)
            {
                return(null);
            }

            var creaturePart = new Creature_BodyPart(creature, bodyPart, damageSource != null ? damageSource.IgnoreMagicArmor : false, damageSource != null ? damageSource.IgnoreMagicResist : false);

            // get target armor
            var armor = creaturePart.BaseArmorMod;

            // get target resistance
            DamageType damageType;

            if (damageSource?.ItemType == ItemType.MissileWeapon)
            {
                damageType = (DamageType)damageSource.GetProperty(PropertyInt.DamageType);
            }
            else
            {
                damageType = GetDamageType();
            }

            creaturePart.WeaponResistanceMod = GetWeaponResistanceModifier(this, damageType);
            var resistance = GetResistance(creaturePart, damageType);

            // ratings
            var damageResistRatingMod = GetNegativeRatingMod(creature.EnchantmentManager.GetDamageResistRating());
            //Console.WriteLine("Damage resistance rating: " + NegativeModToRating(damageResistRatingMod));

            // scale damage for armor and shield
            var armorMod  = SkillFormula.CalcArmorMod(resistance);
            var shieldMod = creature.GetShieldMod(this, damageType);

            var slayerMod          = GetWeaponCreatureSlayerModifier(this, target as Creature);
            var elementalDamageMod = GetMissileElementalDamageModifier(this, target as Creature, damageType);

            return((damage + elementalDamageMod) * armorMod * shieldMod * slayerMod * damageResistRatingMod);
        }
Example #6
0
        /// <summary>
        /// Calculates the creature damage for a physical monster attack
        /// </summary>
        /// <param name="bodyPart">The creature body part the monster is targeting</param>
        /// <param name="criticalHit">Is TRUE if monster rolls a critical hit</param>
        public float?CalculateDamage(ref DamageType damageType, CombatManeuver maneuver, BodyPart bodyPart, ref bool criticalHit, ref float shieldMod)
        {
            // check lifestone protection
            var player = AttackTarget as Player;

            if (player != null && player.UnderLifestoneProtection)
            {
                player.HandleLifestoneProtection();
                return(null);
            }

            // evasion chance
            var evadeChance = GetEvadeChance();

            if (ThreadSafeRandom.Next(0.0f, 1.0f) < evadeChance)
            {
                return(null);
            }

            // get base damage
            var attackPart = GetAttackPart(maneuver);

            if (attackPart == null)
            {
                return(0.0f);
            }

            damageType = GetDamageType(attackPart);
            var damageRange = GetBaseDamage(attackPart);
            var baseDamage  = ThreadSafeRandom.Next(damageRange.Min, damageRange.Max);

            var damageRatingMod = GetPositiveRatingMod(GetDamageRating());
            //Console.WriteLine("Damage Rating: " + damageRatingMod);

            var recklessnessMod = player != null?player.GetRecklessnessMod() : 1.0f;

            var target    = AttackTarget as Creature;
            var targetPet = AttackTarget as CombatPet;

            // handle pet damage type
            var pet = this as CombatPet;

            if (pet != null)
            {
                damageType = pet.DamageType;
            }

            // monster weapon / attributes
            var weapon = GetEquippedWeapon();

            // critical hit
            var critical = 0.1f;

            if (ThreadSafeRandom.Next(0.0f, 1.0f) < critical)
            {
                if (player != null && player.AugmentationCriticalDefense > 0)
                {
                    var protChance = player.AugmentationCriticalDefense * 0.25f;
                    if (ThreadSafeRandom.Next(0.0f, 1.0f) > protChance)
                    {
                        criticalHit = true;
                    }
                }
                else
                {
                    criticalHit = true;
                }
            }

            // attribute damage modifier (verify)
            var attributeMod = GetAttributeMod(weapon);

            // get armor piece
            var armorLayers = GetArmorLayers(bodyPart);

            // get armor modifiers
            var armorMod = GetArmorMod(damageType, armorLayers, weapon);

            // get resistance modifiers (protect/vuln)
            var resistanceMod = AttackTarget.EnchantmentManager.GetResistanceMod(damageType);

            var attackTarget          = AttackTarget as Creature;
            var damageResistRatingMod = GetNegativeRatingMod(attackTarget.GetDamageResistRating());

            // get shield modifier
            shieldMod = attackTarget.GetShieldMod(this, damageType);

            // scale damage by modifiers
            var damage = baseDamage * damageRatingMod * attributeMod * armorMod * shieldMod * resistanceMod * damageResistRatingMod;

            if (!criticalHit)
            {
                damage *= recklessnessMod;
            }
            else
            {
                damage *= 2;    // fixme: target recklessness mod still in effect?
            }
            return(damage);
        }
Example #7
0
        public async Task ActivationSched_WhenAny_Busy_Timeout()
        {
            TaskScheduler scheduler = this.masterScheduler.GetWorkItemGroup(this.context).TaskScheduler;

            var        pause1  = new TaskCompletionSource <bool>();
            var        pause2  = new TaskCompletionSource <bool>();
            var        finish  = new TaskCompletionSource <bool>();
            Task <int> task1   = null;
            Task <int> task2   = null;
            Task       join    = null;
            Task       wrapper = new Task(() =>
            {
                task1 = Task <int> .Factory.StartNew(() =>
                {
                    this.output.WriteLine("Task-1 Started");
                    Assert.Equal(scheduler, TaskScheduler.Current);
                    int num1 = 1;
                    while (!pause1.Task.Result) // Infinite busy loop
                    {
                        num1 = ThreadSafeRandom.Next();
                    }
                    this.output.WriteLine("Task-1 Done");
                    return(num1);
                });
                task2 = Task <int> .Factory.StartNew(() =>
                {
                    this.output.WriteLine("Task-2 Started");
                    Assert.Equal(scheduler, TaskScheduler.Current);
                    int num2 = 2;
                    while (!pause2.Task.Result) // Infinite busy loop
                    {
                        num2 = ThreadSafeRandom.Next();
                    }
                    this.output.WriteLine("Task-2 Done");
                    return(num2);
                });

                join = Task.WhenAny(task1, task2, Task.Delay(TimeSpan.FromSeconds(2)));

                finish.SetResult(true);
            });

            wrapper.Start(scheduler);

            var timeoutLimit = TimeSpan.FromSeconds(1);

            try
            {
                await finish.Task.WithTimeout(timeoutLimit);
            }
            catch (TimeoutException)
            {
                Assert.True(false, "Result did not arrive before timeout " + timeoutLimit);
            }

            Assert.NotNull(join); // Joined promise assigned
            await join;

            Assert.True(join.IsCompleted && !join.IsFaulted, "Join Status " + join.Status);
            Assert.False(task1.IsFaulted, "Task-1 Faulted " + task1.Exception);
            Assert.False(task1.IsCompleted, "Task-1 Status " + task1.Status);
            Assert.False(task2.IsFaulted, "Task-2 Faulted " + task2.Exception);
            Assert.False(task2.IsCompleted, "Task-2 Status " + task2.Status);
        }
Example #8
0
        public float?DamageTarget(Creature target, WorldObject damageSource)
        {
            if (target.Health.Current <= 0)
            {
                return(0.0f);
            }

            var critical    = false;
            var sneakAttack = false;

            // check PK status
            var targetPlayer = target as Player;

            if (targetPlayer != null)
            {
                var pkStatus = CheckPKStatusVsTarget(this, targetPlayer, null);
                if (pkStatus != null && pkStatus == false)
                {
                    Session.Network.EnqueueSend(new GameMessageSystemChat($"You fail to affect {targetPlayer.Name} because you are not a player killer!", ChatMessageType.Magic));
                    return(0.0f);
                }
            }
            var bodyPart   = BodyPart.Chest;
            var damageType = GetDamageType();

            float?damage = null;

            if (targetPlayer != null)
            {
                damage = CalculateDamagePVP(target, damageSource, damageType, ref critical, ref sneakAttack, ref bodyPart);

                // TODO: level up shield mod?
                if (targetPlayer.Invincible ?? false)
                {
                    damage = 0.0f;
                }
            }
            else
            {
                damage = CalculateDamage(target, damageSource, ref critical, ref sneakAttack);
            }

            if (damage != null)
            {
                var attackType = GetAttackType();
                OnDamageTarget(target, attackType);

                if (targetPlayer != null)
                {
                    targetPlayer.TakeDamage(this, damageType, damage.Value, bodyPart, critical);
                }
                else
                {
                    target.TakeDamage(this, damageType, damage.Value, critical);
                }
            }
            else
            {
                if (targetPlayer != null && targetPlayer.UnderLifestoneProtection)
                {
                    Session.Network.EnqueueSend(new GameMessageSystemChat($"The Lifestone's magic protects {target.Name} from the attack!", ChatMessageType.Magic));
                }
                else
                {
                    Session.Network.EnqueueSend(new GameMessageSystemChat($"{target.Name} evaded your attack.", ChatMessageType.CombatSelf));
                }
            }

            if (damage != null && target.Health.Current > 0)
            {
                var recklessnessMod = critical ? 1.0f : GetRecklessnessMod();

                var attackConditions = new AttackConditions();
                if (recklessnessMod > 1.0f)
                {
                    attackConditions |= AttackConditions.Recklessness;
                }
                if (sneakAttack)
                {
                    attackConditions |= AttackConditions.SneakAttack;
                }

                // notify attacker
                var intDamage = (uint)Math.Round(damage.Value);
                if (damageSource?.ItemType == ItemType.MissileWeapon)
                {
                    Session.Network.EnqueueSend(new GameEventAttackerNotification(Session, target.Name, damageType, (float)intDamage / target.Health.MaxValue, intDamage, critical, attackConditions));
                }
                else
                {
                    Session.Network.EnqueueSend(new GameEventAttackerNotification(Session, target.Name, GetDamageType(), (float)intDamage / target.Health.MaxValue, intDamage, critical, attackConditions));
                }

                // splatter effects
                if (targetPlayer == null)
                {
                    Session.Network.EnqueueSend(new GameMessageSound(target.Guid, Sound.HitFlesh1, 0.5f));
                    if (damage >= target.Health.MaxValue * 0.25f)
                    {
                        var painSound = (Sound)Enum.Parse(typeof(Sound), "Wound" + ThreadSafeRandom.Next(1, 3), true);
                        Session.Network.EnqueueSend(new GameMessageSound(target.Guid, painSound, 1.0f));
                    }
                    var splatter = (PlayScript)Enum.Parse(typeof(PlayScript), "Splatter" + GetSplatterHeight() + GetSplatterDir(target));
                    Session.Network.EnqueueSend(new GameMessageScript(target.Guid, splatter));
                }

                // handle Dirty Fighting
                if (GetCreatureSkill(Skill.DirtyFighting).AdvancementClass >= SkillAdvancementClass.Trained)
                {
                    FightDirty(target);
                }
            }

            if (damage != null && damage > 0.0f)
            {
                Session.Network.EnqueueSend(new GameEventUpdateHealth(Session, target.Guid.Full, (float)target.Health.Current / target.Health.MaxValue));
            }

            if (targetPlayer == null)
            {
                OnAttackMonster(target);
            }

            return(damage);
        }
Example #9
0
        public TypeDummyFactory()
        {
            AutoFixtureBackedDummyFactory.ConstrainDummyToExclude(CultureKind.Unknown);
            AutoFixtureBackedDummyFactory.ConstrainDummyToExclude(DateTimeFormatKind.Unknown);
            AutoFixtureBackedDummyFactory.ConstrainDummyToExclude(MissingProtocolStrategy.Unknown);
            AutoFixtureBackedDummyFactory.ConstrainDummyToExclude(StandardTimeZone.Unknown);

            // UtcDateTimeRangeInclusive
            AutoFixtureBackedDummyFactory.AddDummyCreator(
                () =>
            {
                var startDateTime = A.Dummy <DateTime>();

                var endDateTime = A.Dummy <DateTime>().ThatIs(_ => _ >= startDateTime);

                var result = new UtcDateTimeRangeInclusive(startDateTime.ToUniversalTime(), endDateTime.ToUniversalTime());

                return(result);
            });

            // Type
            AutoFixtureBackedDummyFactory.AddDummyCreator(
                () =>
            {
                Type result;

                if (ThreadSafeRandom.Next(0, 2) == 0)
                {
                    result = GetRandomClosedTypeInAppDomain();
                }
                else
                {
                    while (true)
                    {
                        var genericTypeDefinition = GetRandomGenericTypeDefinitionInAppDomain();

                        var typeArguments = Enumerable.Range(0, genericTypeDefinition.GetGenericArguments().Length).Select(_ => GetRandomClosedTypeInAppDomain()).ToArray();

                        try
                        {
                            result = genericTypeDefinition.MakeGenericType(typeArguments);

                            break;
                        }
                        catch (Exception)
                        {
                        }
                    }
                }

                return(result);
            });

            // IOperation
            AutoFixtureBackedDummyFactory.AddDummyCreator(
                () =>
            {
                var result = (IOperation)A.Dummy <OperationBase>();

                return(result);
            });

            // IReturningOperation<Version>
            AutoFixtureBackedDummyFactory.AddDummyCreator(
                () =>
            {
                var result = (IReturningOperation <Version>)A.Dummy <ReturningOperationBase <Version> >();

                return(result);
            });

            // IVoidOperation
            AutoFixtureBackedDummyFactory.AddDummyCreator(
                () =>
            {
                var result = (IVoidOperation)A.Dummy <VoidOperationBase>();

                return(result);
            });

            // NullEvent
            AutoFixtureBackedDummyFactory.AddDummyCreator(
                () => new NullEvent(
                    A.Dummy <DateTime>().ToUniversalTime()));

            // NullEvent<Version>
            AutoFixtureBackedDummyFactory.AddDummyCreator(
                () => new NullEvent <Version>(
                    A.Dummy <Version>(),
                    A.Dummy <DateTime>().ToUniversalTime()));

            // ExecuteOpRequestedEvent<GetProtocolOp>
            AutoFixtureBackedDummyFactory.AddDummyCreator(
                () => new ExecuteOpRequestedEvent <GetProtocolOp>(
                    A.Dummy <GetProtocolOp>(),
                    A.Dummy <DateTime>().ToUniversalTime(),
                    A.Dummy <string>()));

            // ExecuteOpRequestedEvent<Version, GetProtocolOp>
            AutoFixtureBackedDummyFactory.AddDummyCreator(
                () => new ExecuteOpRequestedEvent <Version, GetProtocolOp>(
                    A.Dummy <Version>(),
                    A.Dummy <GetProtocolOp>(),
                    A.Dummy <DateTime>().ToUniversalTime(),
                    A.Dummy <string>()));
        }
Example #10
0
        /// <summary>
        /// Selects a random combat maneuver for a monster's next attack
        /// </summary>
        public MotionCommand?GetCombatManeuver()
        {
            // similar to Player.GetSwingAnimation(), more logging

            if (CombatTable == null)
            {
                log.Error($"{Name} ({Guid}).GetCombatManeuver() - CombatTable is null");
                return(null);
            }

            //ShowCombatTable();

            var motionTable = DatManager.PortalDat.ReadFromDat <DatLoader.FileTypes.MotionTable>(MotionTableId);

            if (motionTable == null)
            {
                log.Error($"{Name} ({Guid}).GetCombatManeuver() - motionTable is null");
                return(null);
            }

            if (!CombatTable.Stances.TryGetValue(CurrentMotionState.Stance, out var stanceManeuvers))
            {
                log.Error($"{Name} ({Guid}).GetCombatManeuver() - couldn't find stance {CurrentMotionState.Stance} in CMT {CombatTableDID:X8}");
                return(null);
            }

            var stanceKey = (uint)CurrentMotionState.Stance << 16 | ((uint)MotionCommand.Ready & 0xFFFFF);

            motionTable.Links.TryGetValue(stanceKey, out var motions);
            if (motions == null)
            {
                log.Error($"{Name} ({Guid}).GetCombatManeuver() - couldn't find stance {CurrentMotionState.Stance} in MotionTable {MotionTableId:X8}");
                return(null);
            }

            // choose a random attack height?
            // apparently this might have been based on monster Z vs. player Z?

            // 28659 - Uber Penguin (CMT 30000040) doesn't have High attack height
            // do a more thorough investigation for this...
            var startHeight = stanceManeuvers.Table.Count == 3 ? 1 : 2;

            AttackHeight = (AttackHeight)ThreadSafeRandom.Next(startHeight, 3);

            if (!stanceManeuvers.Table.TryGetValue(AttackHeight.Value, out var attackTypes))
            {
                log.Error($"{Name} ({Guid}).GetCombatManeuver() - couldn't find attack height {AttackHeight} for stance {CurrentMotionState.Stance} in CMT {CombatTableDID:X8}");
                return(null);
            }

            if (IsDualWieldAttack)
            {
                DualWieldAlternate = !DualWieldAlternate;
            }

            var offhand = IsDualWieldAttack && !DualWieldAlternate;

            var weapon = GetEquippedMeleeWeapon();

            // monsters supposedly always used 0.5 PowerLevel according to anon docs,
            // which translates into a 1.0 PowerMod

            if (weapon != null)
            {
                AttackType = weapon.GetAttackType(CurrentMotionState.Stance, 0.5f, offhand);
            }
            else
            {
                if (AttackHeight != ACE.Entity.Enum.AttackHeight.Low)
                {
                    AttackType = AttackType.Punch;
                }
                else
                {
                    AttackType = AttackType.Kick;
                }
            }

            if (!attackTypes.Table.TryGetValue(AttackType, out var maneuvers) || maneuvers.Count == 0)
            {
                if (AttackType == AttackType.Kick)
                {
                    AttackType = AttackType.Punch;

                    if (!attackTypes.Table.TryGetValue(AttackType, out maneuvers) || maneuvers.Count == 0)
                    {
                        log.Error($"{Name} ({Guid}).GetCombatManeuver() - couldn't find attack type Kick or Punch for attack height {AttackHeight} and stance {CurrentMotionState.Stance} in CMT {CombatTableDID:X8}");
                        return(null);
                    }
                }
                else if (AttackType.IsMultiStrike())
                {
                    var reduced = AttackType.ReduceMultiStrike();

                    if (!attackTypes.Table.TryGetValue(reduced, out maneuvers) || maneuvers.Count == 0)
                    {
                        log.Error($"{Name} ({Guid}).GetCombatManeuver() - couldn't find attack type {reduced} for attack height {AttackHeight} and stance {CurrentMotionState.Stance} in CMT {CombatTableDID:X8}");
                        return(null);
                    }
                    //else
                    //log.Info($"{Name} ({Guid}).GetCombatManeuver() - successfully reduced attack type {AttackType} to {reduced} for attack height {AttackHeight} and stance {CurrentMotionState.Stance} in CMT {CombatTableDID:X8}");
                }
                else
                {
                    log.Error($"{Name} ({Guid}).GetCombatManeuver() - couldn't find attack type {AttackType} for attack height {AttackHeight} and stance {CurrentMotionState.Stance} in CMT {CombatTableDID:X8}");
                    return(null);
                }
            }

            var motionCommand = maneuvers[0];

            if (maneuvers.Count > 1)
            {
                // only used for special attacks?

                // note that with rolling for AttackHeight first,
                // for a CMT with high, med, med-special, and low
                // the chance of rolling the special attack is reduced from 1/4 to 1/6 -- investigate

                var rng = ThreadSafeRandom.Next(0, maneuvers.Count - 1);
                motionCommand = maneuvers[rng];
            }

            // ensure this motionCommand exists in monster's motion table
            if (!motions.ContainsKey((uint)motionCommand))
            {
                // for some reason, the combat maneuvers table can return stance motions that don't exist in the motion table
                // ie. skeletons (combat maneuvers table 0x30000000, motion table 0x09000025)
                // for sword combat, they have double and triple strikes (dagger / two-handed only?)
                if (motionCommand.IsMultiStrike())
                {
                    var singleStrike = motionCommand.ReduceMultiStrike();

                    if (motions.ContainsKey((uint)singleStrike))
                    {
                        //log.Info($"{Name} ({Guid}).GetCombatManeuver() - successfully reduced {motionCommand} to {singleStrike}");
                        return(singleStrike);
                    }
                }
                else if (motionCommand.IsSubsequent())
                {
                    var firstCommand = motionCommand.ReduceSubsequent();

                    if (motions.ContainsKey((uint)firstCommand))
                    {
                        //log.Info($"{Name} ({Guid}).GetCombatManeuver() - successfully reduced {motionCommand} to {firstCommand}");
                        return(firstCommand);
                    }
                }
                log.Error($"{Name} ({Guid}).GetCombatManeuver() - couldn't find {motionCommand} in MotionTable {MotionTableId:X8}");
                return(null);
            }

            //Console.WriteLine(motionCommand);

            return(motionCommand);
        }
Example #11
0
        private static void GenerateWieldedTreasureSets(List <TreasureWielded> items, ref List <WorldObject> results, ref int curIdx, bool skip = false)
        {
            var rng         = ThreadSafeRandom.Next(0.0f, 1.0f);
            var probability = 0.0f;
            var rolled      = false;
            var continued   = false;

            for ( ; curIdx < items.Count; curIdx++)
            {
                var item = items[curIdx];

                if (item.ContinuesPreviousSet)
                {
                    if (!continued)
                    {
                        curIdx--;
                        return;
                    }
                    else
                    {
                        continued = false;
                    }
                }

                var skipNext = true;

                if (!skip)
                {
                    if (item.SetStart || probability >= 1.0f)
                    {
                        rng         = ThreadSafeRandom.Next(0.0f, 1.0f);
                        probability = 0.0f;
                        rolled      = false;
                    }

                    probability += item.Probability;

                    if (rng < probability && !rolled)
                    {
                        rolled   = true;
                        skipNext = false;

                        // item roll successful, add to generated list
                        var wo = CreateWieldedTreasure(item);

                        if (wo != null)
                        {
                            if (results == null)
                            {
                                results = new List <WorldObject>();
                            }

                            results.Add(wo);
                        }
                    }
                }

                if (item.HasSubSet)
                {
                    curIdx++;
                    GenerateWieldedTreasureSets(items, ref results, ref curIdx, skipNext);
                    continued = true;
                }
            }
        }
Example #12
0
 /// <summary>
 /// Mutation operator.
 /// </summary>
 ///
 /// <remarks><para>The method performs chromosome's mutation, changing randomly
 /// one of its bits.</para></remarks>
 ///
 public override void Mutate( )
 {
     val ^= ((ulong)1 << rand.Next(length));
 }
Example #13
0
        /// <summary>
        /// Mutation operator.
        /// </summary>
        ///
        /// <remarks><para>The method performs chromosome's mutation by calling on of the methods
        /// randomly: <see cref="MutateGene"/>, <see cref="TransposeIS"/>, <see cref="TransposeRoot"/>.
        /// </para></remarks>
        ///
        public override void Mutate()
        {
            // randomly choose mutation method
            switch (rand.Next(3))
            {
            case 0:                         // ordinary gene mutation
                MutateGene();
                break;

            case 1:                         // IS transposition
                TransposeIS();
                break;

            case 2:                         // root transposition
                TransposeRoot();
                break;
            }
        }
Example #14
0
        /// <summary>
        /// Registers the policies in the container
        /// </summary>
        /// <param name="container">The container.</param>
        public static void Register(IContainer container)
        {
            var policies = container.GetInstance <IPolicies>();
            var tracer   = container.GetInstance <ITracer>();
            var log      = container.GetInstance <ILogFactory>().Create();

            var chaosPolicy      = CreateRetryChaos(policies);
            var chaosPolicyAsync = CreateRetryChaosAsync(policies);

            var retrySql = Policy
                           .Handle <PostgresException>(ex => ex.IsTransient)
                           .WaitAndRetry(
                RetryConstants.RetryCount,
                retryAttempt => TimeSpan.FromMilliseconds(ThreadSafeRandom.Next(RetryConstants.MinWait, RetryConstants.MaxWait)),
                (exception, timeSpan, retryCount, context) =>
            {
                log.WarnException($"An error has occurred; we will try to re-run the transaction in {timeSpan.TotalMilliseconds} ms. An error has occured {retryCount} times", exception);
                if (tracer.ActiveSpan != null)
                {
                    IScope scope = tracer.BuildSpan("RetrySqlPolicy").StartActive(finishSpanOnDispose: false);
                    try
                    {
                        scope.Span.SetTag("RetryTime", timeSpan.ToString());
                        scope.Span.Log(exception.ToString());
                    }
                    finally
                    {
                        scope.Span.Finish(DateTimeOffset.UtcNow.Add(timeSpan));
                    }
                }
            });

            var retrySqlAsync = Policy
                                .Handle <PostgresException>(ex => ex.IsTransient)
                                .WaitAndRetryAsync(
                RetryConstants.RetryCount,
                retryAttempt => TimeSpan.FromMilliseconds(ThreadSafeRandom.Next(RetryConstants.MinWait, RetryConstants.MaxWait)),
                (exception, timeSpan, retryCount, context) =>
            {
                log.WarnException($"An error has occurred; we will try to re-run the transaction in {timeSpan.TotalMilliseconds} ms. An error has occured {retryCount} times", exception);
                if (tracer.ActiveSpan != null)
                {
                    IScope scope = tracer.BuildSpan("RetrySqlPolicy").StartActive(finishSpanOnDispose: false);
                    try
                    {
                        scope.Span.SetTag("RetryTime", timeSpan.ToString());
                        scope.Span.Log(exception.ToString());
                    }
                    finally
                    {
                        scope.Span.Finish(DateTimeOffset.UtcNow.Add(timeSpan));
                    }
                }
            });

            //RetryCommandHandler
            policies.TransportDefinition.TryAdd(TransportPolicyDefinitions.RetryCommandHandler,
                                                new TransportPolicyDefinition(
                                                    TransportPolicyDefinitions.RetryCommandHandler,
                                                    "A policy for retrying a failed command. This checks specific" +
                                                    "PostGres server errors, such as deadlocks, and retries the command" +
                                                    "after a short pause"));
            if (chaosPolicy != null)
            {
                policies.Registry[TransportPolicyDefinitions.RetryCommandHandler] = retrySql.Wrap(chaosPolicy);
            }
            else
            {
                policies.Registry[TransportPolicyDefinitions.RetryCommandHandler] = retrySql;
            }


            //RetryCommandHandlerAsync
            policies.TransportDefinition.TryAdd(TransportPolicyDefinitions.RetryCommandHandlerAsync,
                                                new TransportPolicyDefinition(
                                                    TransportPolicyDefinitions.RetryCommandHandler,
                                                    "A policy for retrying a failed command. This checks specific" +
                                                    "PostGres server errors, such as deadlocks, and retries the command" +
                                                    "after a short pause"));
            if (chaosPolicyAsync != null)
            {
                policies.Registry[TransportPolicyDefinitions.RetryCommandHandlerAsync] = retrySqlAsync.WrapAsync(chaosPolicyAsync);
            }
            else
            {
                policies.Registry[TransportPolicyDefinitions.RetryCommandHandlerAsync] = retrySqlAsync;
            }

            //RetryQueryHandler
            policies.TransportDefinition.TryAdd(TransportPolicyDefinitions.RetryQueryHandler,
                                                new TransportPolicyDefinition(
                                                    TransportPolicyDefinitions.RetryQueryHandler,
                                                    "A policy for retrying a failed query. This checks specific" +
                                                    "PostGres server errors, such as deadlocks, and retries the query" +
                                                    "after a short pause"));
            if (chaosPolicy != null)
            {
                policies.Registry[TransportPolicyDefinitions.RetryQueryHandler] = retrySql.Wrap(chaosPolicy);
            }
            else
            {
                policies.Registry[TransportPolicyDefinitions.RetryQueryHandler] = retrySql;
            }
        }
Example #15
0
        public async Task ActivationSched_Turn_Execution_Order_Loop()
        {
            TaskScheduler scheduler = this.masterScheduler.GetWorkItemGroup(this.context).TaskScheduler;

            const int NumChains   = 100;
            const int ChainLength = 3;
            // Can we add a unit test that basicaly checks that any turn is indeed run till completion before any other turn?
            // For example, you have a long running main turn and in the middle it spawns a lot of short CWs (on Done promise) and StartNew.
            // You test that no CW/StartNew runs until the main turn is fully done. And run in stress.

            var resultHandles = new TaskCompletionSource <bool> [NumChains];

            Task[] taskChains      = new Task[NumChains];
            Task[] taskChainEnds   = new Task[NumChains];
            bool[] executingChain  = new bool[NumChains];
            int[]  stageComplete   = new int[NumChains];
            int    executingGlobal = -1;

            for (int i = 0; i < NumChains; i++)
            {
                int chainNum  = i; // Capture
                int sleepTime = ThreadSafeRandom.Next(100);
                resultHandles[i] = new TaskCompletionSource <bool>();
                taskChains[i]    = new Task(() =>
                {
                    const int taskNum = 0;
                    try
                    {
                        Assert.Equal(-1, executingGlobal);  // "Detected unexpected other execution in chain " + chainNum + " Task " + taskNum
                        Assert.False(executingChain[chainNum], "Detected unexpected other execution on chain " + chainNum + " Task " + taskNum);

                        executingGlobal          = chainNum;
                        executingChain[chainNum] = true;

                        Thread.Sleep(sleepTime);
                    }
                    finally
                    {
                        stageComplete[chainNum]  = taskNum;
                        executingChain[chainNum] = false;
                        executingGlobal          = -1;
                    }
                });
                Task task = taskChains[i];
                for (int j = 1; j < ChainLength; j++)
                {
                    int taskNum = j; // Capture
                    task = task.ContinueWith(t =>
                    {
                        if (t.IsFaulted)
                        {
                            throw t.Exception;
                        }
                        this.output.WriteLine("Inside Chain {0} Task {1}", chainNum, taskNum);
                        try
                        {
                            Assert.Equal(-1, executingGlobal);                  // "Detected unexpected other execution in chain " + chainNum + " Task " + taskNum
                            Assert.False(executingChain[chainNum], "Detected unexpected other execution on chain " + chainNum + " Task " + taskNum);
                            Assert.Equal(taskNum - 1, stageComplete[chainNum]); // "Detected unexpected execution stage on chain " + chainNum + " Task " + taskNum

                            executingGlobal          = chainNum;
                            executingChain[chainNum] = true;

                            Thread.Sleep(sleepTime);
                        }
                        finally
                        {
                            stageComplete[chainNum]  = taskNum;
                            executingChain[chainNum] = false;
                            executingGlobal          = -1;
                        }
                    }, scheduler);
                }
                taskChainEnds[chainNum] = task.ContinueWith(t =>
                {
                    if (t.IsFaulted)
                    {
                        throw t.Exception;
                    }
                    this.output.WriteLine("Inside Chain {0} Final Task", chainNum);
                    resultHandles[chainNum].SetResult(true);
                }, scheduler);
            }

            for (int i = 0; i < NumChains; i++)
            {
                taskChains[i].Start(scheduler);
            }

            for (int i = 0; i < NumChains; i++)
            {
                TimeSpan waitCheckTime = TimeSpan.FromMilliseconds(150 * ChainLength * NumChains * WaitFactor);

                try
                {
                    await resultHandles[i].Task.WithTimeout(waitCheckTime);
                }
                catch (TimeoutException)
                {
                    Assert.True(false, "Result did not arrive before timeout " + waitCheckTime);
                }

                bool ok = resultHandles[i].Task.Result;

                try
                {
                    // since resultHandle being complete doesn't directly imply that the final chain was completed (there's a chance for a race condition), give a small chance for it to complete.
                    await taskChainEnds[i].WithTimeout(TimeSpan.FromMilliseconds(10));
                }
                catch (TimeoutException)
                {
                    Assert.True(false, $"Task chain end {i} should complete very shortly after after its resultHandle");
                }

                Assert.True(taskChainEnds[i].IsCompleted, "Task chain " + i + " should be completed");
                Assert.False(taskChainEnds[i].IsFaulted, "Task chain " + i + " should not be Faulted: " + taskChainEnds[i].Exception);
                Assert.Equal(ChainLength - 1, stageComplete[i]);  // "Task chain " + i + " should have completed all stages"
                Assert.True(ok, "Successfully waited for ResultHandle for Task chain " + i);
            }
        }
Example #16
0
        private float DoCalculateDamage(Creature attacker, Creature defender, WorldObject damageSource)
        {
            var playerAttacker = attacker as Player;
            var playerDefender = defender as Player;

            Attacker = attacker;
            Defender = defender;

            CombatType = damageSource.ProjectileSource == null?attacker.GetCombatType() : CombatType.Missile;

            DamageSource = damageSource;

            Weapon = damageSource.ProjectileSource == null?attacker.GetEquippedWeapon() : damageSource.ProjectileLauncher;

            AttackType   = attacker.AttackType;
            AttackHeight = attacker.AttackHeight ?? AttackHeight.Medium;

            // check lifestone protection
            if (playerDefender != null && playerDefender.UnderLifestoneProtection)
            {
                LifestoneProtection = true;
                playerDefender.HandleLifestoneProtection();
                return(0.0f);
            }

            if (defender.Invincible)
            {
                return(0.0f);
            }

            // overpower
            if (attacker.Overpower != null)
            {
                Overpower = Creature.GetOverpower(attacker, defender);
            }

            // evasion chance
            if (!Overpower)
            {
                EvasionChance = GetEvadeChance(attacker, defender);
                if (EvasionChance > ThreadSafeRandom.Next(0.0f, 1.0f))
                {
                    Evaded = true;
                    return(0.0f);
                }
            }

            // get base damage
            if (playerAttacker != null)
            {
                GetBaseDamage(playerAttacker);
            }
            else
            {
                GetBaseDamage(attacker, AttackMotion ?? MotionCommand.Invalid);
            }

            if (DamageType == DamageType.Undef && !AllowDamageTypeUndef.Contains(damageSource.WeenieClassId))
            {
                log.Error($"DamageEvent.DoCalculateDamage({attacker?.Name} ({attacker?.Guid}), {defender?.Name} ({defender?.Guid}), {damageSource?.Name} ({damageSource?.Guid})) - DamageType == DamageType.Undef");
                GeneralFailure = true;
            }

            if (GeneralFailure)
            {
                return(0.0f);
            }

            // get damage modifiers
            PowerMod     = attacker.GetPowerMod(Weapon);
            AttributeMod = attacker.GetAttributeMod(Weapon);
            SlayerMod    = WorldObject.GetWeaponCreatureSlayerModifier(attacker, defender);

            // ratings
            DamageRatingBaseMod = Creature.GetPositiveRatingMod(attacker.GetDamageRating());
            RecklessnessMod     = Creature.GetRecklessnessMod(attacker, defender);
            SneakAttackMod      = attacker.GetSneakAttackMod(defender);
            HeritageMod         = attacker.GetHeritageBonus(Weapon) ? 1.05f : 1.0f;

            DamageRatingMod = Creature.AdditiveCombine(DamageRatingBaseMod, RecklessnessMod, SneakAttackMod, HeritageMod);

            // damage before mitigation
            DamageBeforeMitigation = BaseDamage * AttributeMod * PowerMod * SlayerMod * DamageRatingMod;

            // critical hit?
            var attackSkill = attacker.GetCreatureSkill(attacker.GetCurrentWeaponSkill());

            CriticalChance = WorldObject.GetWeaponCriticalChance(attacker, attackSkill, defender);
            if (CriticalChance > ThreadSafeRandom.Next(0.0f, 1.0f))
            {
                if (playerDefender != null && playerDefender.AugmentationCriticalDefense > 0)
                {
                    var criticalDefenseMod    = playerAttacker != null ? 0.05f : 0.25f;
                    var criticalDefenseChance = playerDefender.AugmentationCriticalDefense * criticalDefenseMod;

                    if (criticalDefenseChance > ThreadSafeRandom.Next(0.0f, 1.0f))
                    {
                        CriticalDefended = true;
                    }
                }

                if (!CriticalDefended)
                {
                    IsCritical = true;

                    CriticalDamageMod = 1.0f + WorldObject.GetWeaponCritDamageMod(attacker, attackSkill, defender);

                    // recklessness excluded from crits
                    RecklessnessMod        = 1.0f;
                    DamageRatingMod        = Creature.AdditiveCombine(DamageRatingBaseMod, SneakAttackMod, HeritageMod);
                    DamageBeforeMitigation = BaseDamageMod.MaxDamage * AttributeMod * PowerMod * SlayerMod * DamageRatingMod * CriticalDamageMod;
                }
            }

            // armor rending and cleaving
            var armorRendingMod = 1.0f;

            if (Weapon != null && Weapon.HasImbuedEffect(ImbuedEffectType.ArmorRending))
            {
                armorRendingMod = WorldObject.GetArmorRendingMod(attackSkill);
            }

            var armorCleavingMod = attacker.GetArmorCleavingMod(Weapon);

            var ignoreArmorMod = Math.Min(armorRendingMod, armorCleavingMod);

            // get body part / armor pieces / armor modifier
            if (playerDefender != null)
            {
                // select random body part @ current attack height
                GetBodyPart(AttackHeight);

                // get player armor pieces
                Armor = attacker.GetArmorLayers(playerDefender, BodyPart);

                // get armor modifiers
                ArmorMod = attacker.GetArmorMod(DamageType, Armor, Weapon, ignoreArmorMod);
            }
            else
            {
                // determine height quadrant
                Quadrant = GetQuadrant(Defender, Attacker, AttackHeight, DamageSource);

                // select random body part @ current attack height
                GetBodyPart(Defender, Quadrant);
                if (Evaded)
                {
                    return(0.0f);
                }

                Armor = CreaturePart.GetArmorLayers((CombatBodyPart)BiotaPropertiesBodyPart.Key);

                // get target armor
                ArmorMod = CreaturePart.GetArmorMod(DamageType, Armor, Weapon, ignoreArmorMod);
            }

            if (Weapon != null && Weapon.HasImbuedEffect(ImbuedEffectType.IgnoreAllArmor))
            {
                ArmorMod = 1.0f;
            }

            // get resistance modifiers
            WeaponResistanceMod = WorldObject.GetWeaponResistanceModifier(attacker, attackSkill, DamageType);

            if (playerDefender != null)
            {
                ResistanceMod = playerDefender.GetResistanceMod(DamageType, Weapon, WeaponResistanceMod);
            }
            else
            {
                var resistanceType = Creature.GetResistanceType(DamageType);
                ResistanceMod = (float)Math.Max(0.0f, defender.GetResistanceMod(resistanceType, Weapon, WeaponResistanceMod));
            }

            // damage resistance rating
            DamageResistanceRatingMod = Creature.GetNegativeRatingMod(defender.GetDamageResistRating(CombatType));

            // get shield modifier
            ShieldMod = defender.GetShieldMod(attacker, DamageType, Weapon);

            // calculate final output damage
            Damage          = DamageBeforeMitigation * ArmorMod * ShieldMod * ResistanceMod * DamageResistanceRatingMod;
            DamageMitigated = DamageBeforeMitigation - Damage;

            return(Damage);
        }
Example #17
0
        /// <summary>
        /// Calculates the damage for a spell projectile
        /// Used by war magic, void magic, and life magic projectiles
        /// </summary>
        public double?CalculateDamage(WorldObject _source, Creature target, ref bool criticalHit)
        {
            var source       = _source as Creature;
            var sourcePlayer = source as Player;
            var targetPlayer = target as Player;

            if (source == null || targetPlayer != null && targetPlayer.Invincible == true)
            {
                return(null);
            }

            // target already dead?
            if (target.Health.Current <= 0)
            {
                return(-1);
            }

            // check lifestone protection
            if (targetPlayer != null && targetPlayer.UnderLifestoneProtection)
            {
                targetPlayer.HandleLifestoneProtection();
                return(null);
            }

            double damageBonus = 0.0f, warSkillBonus = 0.0f, finalDamage = 0.0f;

            var resistanceType = Creature.GetResistanceType(Spell.DamageType);

            var resisted = source.ResistSpell(target, Spell);

            if (resisted != null && resisted == true)
            {
                return(null);
            }

            CreatureSkill attackSkill    = null;
            var           sourceCreature = source as Creature;

            if (sourceCreature != null)
            {
                attackSkill = sourceCreature.GetCreatureSkill(Spell.School);
            }

            // critical hit
            var critical = GetWeaponMagicCritFrequencyModifier(source, attackSkill, target);

            if (ThreadSafeRandom.Next(0.0f, 1.0f) < critical)
            {
                var criticalDefended = false;
                if (targetPlayer != null && targetPlayer.AugmentationCriticalDefense > 0)
                {
                    var criticalDefenseMod    = sourcePlayer != null ? 0.05f : 0.25f;
                    var criticalDefenseChance = targetPlayer.AugmentationCriticalDefense * criticalDefenseMod;

                    if (criticalDefenseChance > ThreadSafeRandom.Next(0.0f, 1.0f))
                    {
                        criticalDefended = true;
                    }
                }

                if (!criticalDefended)
                {
                    criticalHit = true;
                }
            }

            var shieldMod = GetShieldMod(target);

            bool isPVP = sourcePlayer != null && targetPlayer != null;

            var elementalDmgBonus = GetCasterElementalDamageModifier(source, target, Spell.DamageType);

            // Possible 2x + damage bonus for the slayer property
            var slayerBonus = GetWeaponCreatureSlayerModifier(source, target);

            // life magic projectiles: ie., martyr's hecatomb
            if (Spell.School == MagicSchool.LifeMagic)
            {
                var lifeMagicDamage = LifeProjectileDamage * Spell.DamageRatio;

                // could life magic projectiles crit?
                // if so, did they use the same 1.5x formula as war magic, instead of 2.0x?
                if (criticalHit)
                {
                    damageBonus = lifeMagicDamage * 0.5f * GetWeaponCritDamageMod(source, attackSkill, target);
                }

                finalDamage = (lifeMagicDamage + damageBonus) * elementalDmgBonus * slayerBonus * shieldMod;
                return(finalDamage);
            }
            // war magic projectiles (and void currently)
            else
            {
                if (criticalHit)
                {
                    if (isPVP) // PvP: 50% of the MIN damage added to normal damage roll
                    {
                        damageBonus = Spell.MinDamage * 0.5f;
                    }
                    else   // PvE: 50% of the MAX damage added to normal damage roll
                    {
                        damageBonus = Spell.MaxDamage * 0.5f;
                    }

                    var critDamageMod = GetWeaponCritDamageMod(source, attackSkill, target);

                    damageBonus *= critDamageMod;
                }

                /* War Magic skill-based damage bonus
                 * http://acpedia.org/wiki/Announcements_-_2002/08_-_Atonement#Letter_to_the_Players
                 */
                if (sourcePlayer != null && Spell.School == MagicSchool.WarMagic)
                {
                    var warSkill = source.GetCreatureSkill(Spell.School).Current;
                    if (warSkill > Spell.Power)
                    {
                        // Bonus clamped to a maximum of 50%
                        var percentageBonus = Math.Clamp((warSkill - Spell.Power) / 100.0f, 0.0f, 0.5f);
                        warSkillBonus = Spell.MinDamage * percentageBonus;
                    }
                }
                var baseDamage = ThreadSafeRandom.Next(Spell.MinDamage, Spell.MaxDamage);

                var weaponResistanceMod = GetWeaponResistanceModifier(source, attackSkill, Spell.DamageType);

                finalDamage  = baseDamage + damageBonus + warSkillBonus;
                finalDamage *= target.GetResistanceMod(resistanceType, source, weaponResistanceMod)
                               * elementalDmgBonus * slayerBonus * shieldMod;

                return(finalDamage);
            }
        }
Example #18
0
        /// <summary>
        /// Calculates the creature damage for a physical monster attack
        /// </summary>
        public float?CalculateDamagePVP(WorldObject target, WorldObject damageSource, DamageType damageType, ref bool criticalHit, ref bool sneakAttack, ref BodyPart bodyPart)
        {
            // verify target player killer
            var targetPlayer = target as Player;

            if (targetPlayer == null)
            {
                return(null);
            }

            // check lifestone protection
            if (targetPlayer.UnderLifestoneProtection)
            {
                targetPlayer.HandleLifestoneProtection();
                return(null);
            }

            // evasion chance
            var evadeChance = GetEvadeChance(target);

            if (ThreadSafeRandom.Next(0.0f, 1.0f) < evadeChance)
            {
                return(null);
            }

            // get base damage
            var baseDamageRange = GetBaseDamage();
            var baseDamage      = ThreadSafeRandom.Next(baseDamageRange.Min, baseDamageRange.Max);

            // get damage mods
            var attackType       = GetAttackType();
            var attributeMod     = GetAttributeMod(attackType);
            var powerAccuracyMod = GetPowerAccuracyMod();
            var recklessnessMod  = GetRecklessnessMod(this, targetPlayer);
            var sneakAttackMod   = GetSneakAttackMod(target);

            sneakAttack = sneakAttackMod > 1.0f;

            var damageRatingMod = AdditiveCombine(recklessnessMod, sneakAttackMod, GetRatingMod(EnchantmentManager.GetDamageRating()));
            //Console.WriteLine("Damage rating: " + ModToRating(damageRatingMod));

            var damage = baseDamage * attributeMod * powerAccuracyMod * damageRatingMod;

            // critical hit
            var critical = GetWeaponPhysicalCritFrequencyModifier(this);

            if (ThreadSafeRandom.Next(0.0f, 1.0f) < critical)
            {
                damage      = baseDamageRange.Max * attributeMod * powerAccuracyMod * sneakAttackMod * (2.0f + GetWeaponCritMultiplierModifier(this));
                criticalHit = true;
            }

            // select random body part @ current attack height
            bodyPart = BodyParts.GetBodyPart(AttackHeight.Value);

            // get armor piece
            var armor = GetArmor(bodyPart);

            // get armor modifiers
            var armorMod = GetArmorMod(armor, damageSource, damageType);

            // get resistance modifiers (protect/vuln)
            var resistanceMod = damageSource != null && damageSource.IgnoreMagicResist ? 1.0f : AttackTarget.EnchantmentManager.GetResistanceMod(damageType);

            // weapon resistance mod?
            var damageResistRatingMod = GetNegativeRatingMod(AttackTarget.EnchantmentManager.GetDamageResistRating());

            // get shield modifier
            var attackTarget = AttackTarget as Creature;
            var shieldMod    = attackTarget.GetShieldMod(this, damageType);

            var slayerMod          = GetWeaponCreatureSlayerModifier(this, target as Creature);
            var elementalDamageMod = GetMissileElementalDamageModifier(this, target as Creature, damageType);

            // scale damage by modifiers
            var outDamage = (damage + elementalDamageMod) * armorMod * shieldMod * slayerMod * resistanceMod * damageResistRatingMod;

            return(outDamage);
        }
Example #19
0
 internal static byte GenerateByteKey()
 {
     return((byte)ThreadSafeRandom.Next(100, 255));
 }
Example #20
0
        private static void MutateCaster(WorldObject wo, TreasureDeath profile, bool isMagical, int wield, int element)
        {
            WieldRequirement wieldRequirement = WieldRequirement.RawSkill;
            Skill            wieldSkillType   = Skill.None;

            double elementalDamageMod = 0;

            if (wield == 0)
            {
                if (profile.Tier > 6)
                {
                    wieldRequirement = WieldRequirement.Level;
                    wieldSkillType   = Skill.Axe; // Set by examples from PCAP data

                    wield = profile.Tier switch
                    {
                        7 => 150, // In this instance, used for indicating player level, rather than skill level
                        _ => 180, // In this instance, used for indicating player level, rather than skill level
                    };
                }
            }
            else
            {
                // Determine the Elemental Damage Mod amount
                elementalDamageMod = DetermineElementMod(wield);

                // If element is Nether, Void Magic is required, else War Magic is required for all other elements
                if (element == 7)
                {
                    wieldSkillType = Skill.VoidMagic;
                }
                else
                {
                    wieldSkillType = Skill.WarMagic;
                }
            }

            // Setting MagicD and MissileD Bonuses to null (some weenies have a value)
            wo.WeaponMagicDefense   = null;
            wo.WeaponMissileDefense = null;
            // Not sure why this is here, guessing some wienies have it by default
            wo.ItemSkillLevelLimit = null;

            // Setting general traits of weapon
            wo.ItemWorkmanship = GetWorkmanship(profile.Tier);

            int materialType = GetMaterialType(wo, profile.Tier);

            if (materialType > 0)
            {
                wo.MaterialType = (MaterialType)materialType;
            }
            wo.GemCount = ThreadSafeRandom.Next(1, 5);
            wo.GemType  = (MaterialType)ThreadSafeRandom.Next(10, 50);
            wo.Value    = GetValue(profile.Tier, wo.ItemWorkmanship.Value, LootTables.getMaterialValueModifier(wo), LootTables.getGemMaterialValueModifier(wo));
            // Is this right??
            wo.LongDesc = wo.Name;

            // Setting Weapon defensive mods
            wo.WeaponDefense        = GetWieldReqMeleeDMod(wield);
            wo.WeaponMagicDefense   = GetMagicMissileDMod(profile.Tier);
            wo.WeaponMissileDefense = GetMagicMissileDMod(profile.Tier);

            // Setting weapon Offensive Mods
            if (elementalDamageMod > 1.0f)
            {
                wo.ElementalDamageMod = elementalDamageMod;
            }

            // Setting Wield Reqs for weapon
            if (wield > 0 || wieldRequirement == WieldRequirement.Level)
            {
                wo.WieldRequirements = wieldRequirement;
                wo.WieldSkillType    = (int)wieldSkillType;
                wo.WieldDifficulty   = wield;
            }
            else
            {
                wo.WieldRequirements = WieldRequirement.Invalid;
                wo.WieldSkillType    = null;
                wo.WieldDifficulty   = null;
            }

            // Adjusting Properties if weapon has magic (spells)
            double manaConMod = GetManaCMod(profile.Tier);

            if (manaConMod > 0.0f)
            {
                wo.ManaConversionMod = manaConMod;
            }

            if (isMagical)
            {
                wo = AssignMagic(wo, profile);
            }
            else
            {
                wo.ItemManaCost   = null;
                wo.ItemMaxMana    = null;
                wo.ItemCurMana    = null;
                wo.ItemSpellcraft = null;
                wo.ItemDifficulty = null;
            }

            RandomizeColor(wo);
        }
Example #21
0
 internal static sbyte GenerateSByteKey()
 {
     return((sbyte)ThreadSafeRandom.Next(100, 127));
 }
Example #22
0
        /// <summary>
        /// Performs a melee attack for the monster
        /// </summary>
        /// <returns>The length in seconds for the attack animation</returns>
        public float MeleeAttack()
        {
            var target       = AttackTarget as Creature;
            var targetPlayer = AttackTarget as Player;
            var targetPet    = AttackTarget as CombatPet;
            var combatPet    = this as CombatPet;

            if (target == null || !target.IsAlive)
            {
                Sleep();
                return(0.0f);
            }

            if (CurrentMotionState.Stance == MotionStance.NonCombat)
            {
                DoAttackStance();
            }

            // choose a random combat maneuver
            var maneuver = GetCombatManeuver();

            if (maneuver == null)
            {
                Console.WriteLine($"Combat maneuver null! Stance {CurrentMotionState.Stance}, MotionTable {MotionTableId:X8}");
                return(0.0f);
            }

            AttackHeight = maneuver.AttackHeight;

            DoSwingMotion(AttackTarget, maneuver, out float animLength, out var attackFrames);
            PhysicsObj.stick_to_object(AttackTarget.PhysicsObj.ID);

            var numStrikes = attackFrames.Count;

            var actionChain = new ActionChain();

            var prevTime = 0.0f;

            for (var i = 0; i < numStrikes; i++)
            {
                actionChain.AddDelaySeconds(attackFrames[i] * animLength - prevTime);
                prevTime = attackFrames[i] * animLength;

                actionChain.AddAction(this, () =>
                {
                    if (AttackTarget == null || IsDead)
                    {
                        return;
                    }

                    if (WeenieType == WeenieType.GamePiece)
                    {
                        target.TakeDamage(this, DamageType.Slash, target.Health.Current);
                        (this as GamePiece).OnDealtDamage();
                        return;
                    }

                    var weapon      = GetEquippedWeapon();
                    var damageEvent = DamageEvent.CalculateDamage(this, target, weapon, maneuver);

                    //var damage = CalculateDamage(ref damageType, maneuver, bodyPart, ref critical, ref shieldMod);

                    if (damageEvent.HasDamage)
                    {
                        if (combatPet != null || targetPet != null)
                        {
                            // combat pet inflicting or receiving damage
                            //Console.WriteLine($"{target.Name} taking {Math.Round(damage)} {damageType} damage from {Name}");
                            target.TakeDamage(this, damageEvent.DamageType, damageEvent.Damage);
                            EmitSplatter(target, damageEvent.Damage);
                        }
                        else if (targetPlayer != null)
                        {
                            // this is a player taking damage
                            targetPlayer.TakeDamage(this, damageEvent.DamageType, damageEvent.Damage, damageEvent.BodyPart, damageEvent.IsCritical);

                            if (damageEvent.ShieldMod != 1.0f)
                            {
                                var shieldSkill = targetPlayer.GetCreatureSkill(Skill.Shield);
                                Proficiency.OnSuccessUse(targetPlayer, shieldSkill, shieldSkill.Current); // ?
                            }
                        }
                    }
                    else
                    {
                        target.OnEvade(this, CombatType.Melee);
                    }

                    if (combatPet != null)
                    {
                        combatPet.PetOnAttackMonster(target);
                    }
                });
            }
            actionChain.EnqueueChain();

            // TODO: figure out exact speed / delay formula
            var meleeDelay = ThreadSafeRandom.Next(MeleeDelayMin, MeleeDelayMax);

            NextAttackTime = Timers.RunningTime + animLength + meleeDelay;
            return(animLength);
        }
Example #23
0
 internal static char GenerateCharKey()
 {
     return((char)ThreadSafeRandom.Next(10000, 60000));
 }
        /// <summary>
        /// Rolls for ElementalDamageMod for caster weapons
        /// </summary>
        private static double RollElementalDamageMod(int wield)
        {
            double elementBonus = 0;

            int chance = ThreadSafeRandom.Next(1, 100);

            switch (wield)
            {
            case 290:
                if (chance > 95)
                {
                    elementBonus = 0.03;
                }
                else if (chance > 65)
                {
                    elementBonus = 0.02;
                }
                else
                {
                    elementBonus = 0.01;
                }
                break;

            case 310:
                if (chance > 95)
                {
                    elementBonus = 0.06;
                }
                else if (chance > 65)
                {
                    elementBonus = 0.05;
                }
                else
                {
                    elementBonus = 0.04;
                }
                break;

            case 330:
                if (chance > 95)
                {
                    elementBonus = 0.09;
                }
                else if (chance > 65)
                {
                    elementBonus = 0.08;
                }
                else
                {
                    elementBonus = 0.07;
                }
                break;

            case 355:
                if (chance > 95)
                {
                    elementBonus = 0.13;
                }
                else if (chance > 80)
                {
                    elementBonus = 0.12;
                }
                else if (chance > 55)
                {
                    elementBonus = 0.11;
                }
                else if (chance > 20)
                {
                    elementBonus = 0.10;
                }
                else
                {
                    elementBonus = 0.09;
                }
                break;

            case 375:
                if (chance > 95)
                {
                    elementBonus = 0.16;
                }
                else if (chance > 85)
                {
                    elementBonus = 0.15;
                }
                else if (chance > 60)
                {
                    elementBonus = 0.14;
                }
                else if (chance > 30)
                {
                    elementBonus = 0.13;
                }
                else if (chance > 10)
                {
                    elementBonus = 0.12;
                }
                else
                {
                    elementBonus = 0.11;
                }
                break;

            default:
                // 385
                if (chance > 95)
                {
                    elementBonus = 0.18;
                }
                else if (chance > 65)
                {
                    elementBonus = 0.17;
                }
                else
                {
                    elementBonus = 0.16;
                }
                break;
            }

            elementBonus += 1;

            return(elementBonus);
        }
Example #25
0
 internal static ushort GenerateUShortKey()
 {
     return((ushort)ThreadSafeRandom.Next(10000, ushort.MaxValue));
 }
Example #26
0
        public float GetSneakAttackMod(WorldObject target)
        {
            // ensure trained
            var sneakAttack = GetCreatureSkill(Skill.SneakAttack);

            if (sneakAttack.AdvancementClass < SkillAdvancementClass.Trained)
            {
                return(1.0f);
            }

            // ensure creature target
            var creatureTarget = target as Creature;

            if (creatureTarget == null)
            {
                return(1.0f);
            }

            // Effects:
            // General Sneak Attack effects:
            //   - 100% chance to sneak attack from behind an opponent.
            //   - Deception trained: 10% chance to sneak attack from the front of an opponent
            //   - Deception specialized: 15% chance to sneak attack from the front of an opponent
            var angle  = creatureTarget.GetAngle(this);
            var behind = Math.Abs(angle) > 90.0f;
            var chance = 0.0f;

            if (behind)
            {
                chance = 1.0f;
            }
            else
            {
                var deception = GetCreatureSkill(Skill.Deception);
                if (deception.AdvancementClass == SkillAdvancementClass.Trained)
                {
                    chance = 0.1f;
                }
                else if (deception.AdvancementClass == SkillAdvancementClass.Specialized)
                {
                    chance = 0.15f;
                }

                // if Deception is below 306 skill, these chances are reduced proportionately.
                // this is in addition to proprtional reduction if your Sneak Attack skill is below your attack skill.
                var deceptionCap = 306;
                if (deception.Current < deceptionCap)
                {
                    chance *= Math.Min((float)deception.Current / deceptionCap, 1.0f);
                }
            }
            //Console.WriteLine($"Sneak attack {(behind ? "behind" : "front")}, chance {Math.Round(chance * 100)}%");

            var rng = ThreadSafeRandom.Next(0.0f, 1.0f);

            if (rng > chance)
            {
                return(1.0f);
            }

            // Damage Rating:
            // Sneak Attack Trained:
            //   + 10 Damage Rating when Sneak Attack activates
            // Sneak Attack Specialized:
            //   + 20 Damage Rating when Sneak Attack activates
            var damageRating = sneakAttack.AdvancementClass == SkillAdvancementClass.Specialized ? 20.0f : 10.0f;

            // Sneak Attack works for melee, missile, and magic attacks.

            // if the Sneak Attack skill is lower than your attack skill (as determined by your equipped weapon)
            // then the damage rating is reduced proportionately. Because the damage rating caps at 10 for trained
            // and 20 for specialized, there is no reason to raise the skill above your attack skill
            var attackSkill = GetCreatureSkill(GetCurrentAttackSkill());

            if (sneakAttack.Current < attackSkill.Current)
            {
                if (attackSkill.Current > 0)
                {
                    damageRating *= (float)sneakAttack.Current / attackSkill.Current;
                }
                else
                {
                    damageRating = 0;
                }
            }

            // if the defender has Assess Person, they reduce the extra Sneak Attack damage Deception can add
            // from the front by up to 100%.
            // this percent is reduced proportionately if your buffed Assess Person skill is below the deception cap.
            // this reduction does not apply to attacks from behind.
            if (!behind)
            {
                // compare to assess person or deception??
                // wiki info is confusing here, it says 'your buffed Assess Person'
                // which sounds like its scaling sourceAssess / targetAssess,
                // but i think it should be targetAssess / deceptionCap?
                var targetAssess = creatureTarget.GetCreatureSkill(Skill.AssessPerson).Current;

                var deceptionCap = 306;
                damageRating *= 1.0f - Math.Min((float)targetAssess / deceptionCap, 1.0f);
            }

            var sneakAttackMod = (100 + damageRating) / 100.0f;

            //Console.WriteLine("SneakAttackMod: " + sneakAttackMod);
            return(sneakAttackMod);
        }
Example #27
0
 internal static int GenerateIntKey()
 {
     return(ThreadSafeRandom.Next(1000000000, int.MaxValue));
 }
Example #28
0
        /// <summary>
        /// Calculates the damage for a spell projectile
        /// Used by war magic, void magic, and life magic projectiles
        /// </summary>
        public float?CalculateDamage(WorldObject source, WorldObject caster, Creature target, ref bool criticalHit, ref bool critDefended, ref bool overpower)
        {
            var sourcePlayer = source as Player;
            var targetPlayer = target as Player;

            if (source == null || !target.IsAlive || targetPlayer != null && targetPlayer.Invincible)
            {
                return(null);
            }

            // check lifestone protection
            if (targetPlayer != null && targetPlayer.UnderLifestoneProtection)
            {
                if (sourcePlayer != null)
                {
                    sourcePlayer.Session.Network.EnqueueSend(new GameMessageSystemChat($"The Lifestone's magic protects {targetPlayer.Name} from the attack!", ChatMessageType.Magic));
                }

                targetPlayer.HandleLifestoneProtection();
                return(null);
            }

            var critDamageBonus     = 0.0f;
            var weaponCritDamageMod = 1.0f;
            var weaponResistanceMod = 1.0f;
            var resistanceMod       = 1.0f;

            // life magic
            var lifeMagicDamage = 0.0f;

            // war/void magic
            var baseDamage  = 0;
            var skillBonus  = 0.0f;
            var finalDamage = 0.0f;

            var resistanceType = Creature.GetResistanceType(Spell.DamageType);

            var sourceCreature = source as Creature;

            if (sourceCreature?.Overpower != null)
            {
                overpower = Creature.GetOverpower(sourceCreature, target);
            }

            var resisted = source.TryResistSpell(target, Spell, caster, true);

            if (resisted && !overpower)
            {
                return(null);
            }

            CreatureSkill attackSkill = null;

            if (sourceCreature != null)
            {
                attackSkill = sourceCreature.GetCreatureSkill(Spell.School);
            }

            // critical hit
            var criticalChance = GetWeaponMagicCritFrequency(sourceCreature, attackSkill, target);

            if (ThreadSafeRandom.Next(0.0f, 1.0f) < criticalChance)
            {
                if (targetPlayer != null && targetPlayer.AugmentationCriticalDefense > 0)
                {
                    var criticalDefenseMod    = sourcePlayer != null ? 0.05f : 0.25f;
                    var criticalDefenseChance = targetPlayer.AugmentationCriticalDefense * criticalDefenseMod;

                    if (criticalDefenseChance > ThreadSafeRandom.Next(0.0f, 1.0f))
                    {
                        critDefended = true;
                    }
                }

                if (!critDefended)
                {
                    criticalHit = true;
                }
            }

            var absorbMod = GetAbsorbMod(target);

            bool isPVP = sourcePlayer != null && targetPlayer != null;

            //http://acpedia.org/wiki/Announcements_-_2014/01_-_Forces_of_Nature - Aegis is 72% effective in PvP
            if (isPVP)
            {
                if (isPVP && (target.CombatMode == CombatMode.Melee || target.CombatMode == CombatMode.Missile))
                {
                    absorbMod  = 1 - absorbMod;
                    absorbMod *= 0.72f;
                    absorbMod  = 1 - absorbMod;
                }
            }

            if (isPVP && Spell.IsHarmful)
            {
                Player.UpdatePKTimers(sourcePlayer, targetPlayer);
            }

            var elementalDamageMod = GetCasterElementalDamageModifier(sourceCreature, target, Spell.DamageType);

            // Possible 2x + damage bonus for the slayer property
            var slayerMod = GetWeaponCreatureSlayerModifier(sourceCreature, target);

            // life magic projectiles: ie., martyr's hecatomb
            if (Spell.MetaSpellType == ACE.Entity.Enum.SpellType.LifeProjectile)
            {
                lifeMagicDamage = LifeProjectileDamage * Spell.DamageRatio;

                // could life magic projectiles crit?
                // if so, did they use the same 1.5x formula as war magic, instead of 2.0x?
                if (criticalHit)
                {
                    weaponCritDamageMod = GetWeaponCritDamageMod(sourceCreature, attackSkill, target);
                    critDamageBonus     = lifeMagicDamage * 0.5f * weaponCritDamageMod;
                }

                weaponResistanceMod = GetWeaponResistanceModifier(sourceCreature, attackSkill, Spell.DamageType);

                // if attacker/weapon has IgnoreMagicResist directly, do not transfer to spell projectile
                // only pass if SpellProjectile has it directly, such as 2637 - Invoking Aun Tanua

                resistanceMod = (float)Math.Max(0.0f, target.GetResistanceMod(resistanceType, this, null, weaponResistanceMod));

                finalDamage = (lifeMagicDamage + critDamageBonus) * elementalDamageMod * slayerMod * resistanceMod * absorbMod;
            }
            // war/void magic projectiles
            else
            {
                var minDamage = Spell.MinDamage;
                var maxDamage = Spell.MaxDamage;

                if (isPVP)
                {
                    var modifier = PropertyManager.GetDouble("spell_damage_modifier").Item; // mostly unused

                    if (Spell.School == MagicSchool.WarMagic)
                    {
                        if (SpellType == ProjectileSpellType.Streak)
                        {
                            modifier = PropertyManager.GetDouble("war_streak_spell_damage_modifier").Item; // scales war streak damages
                        }
                    }
                    else if (Spell.School == MagicSchool.VoidMagic)
                    {
                        if (SpellType == ProjectileSpellType.Streak)
                        {
                            modifier = PropertyManager.GetDouble("void_streak_spell_damage_modifier").Item;
                        }
                        else
                        {
                            modifier = PropertyManager.GetDouble("void_projectile_modifier").Item;
                        }
                    }

                    minDamage = (int)Math.Round(minDamage * modifier);
                    maxDamage = (int)Math.Round(maxDamage * modifier);
                }

                if (criticalHit)
                {
                    // Original:
                    // http://acpedia.org/wiki/Announcements_-_2002/08_-_Atonement#Letter_to_the_Players

                    // Critical Strikes: In addition to the skill-based damage bonus, each projectile spell has a 2% chance of causing a critical hit on the target and doing increased damage.
                    // A magical critical hit is similar in some respects to melee critical hits (although the damage calculation is handled differently).
                    // While a melee critical hit automatically does twice the maximum damage of the weapon, a magical critical hit will do an additional half the minimum damage of the spell.
                    // For instance, a magical critical hit from a level 7 spell, which does 110-180 points of damage, would add an additional 55 points of damage to the spell.

                    // Later updated for PvE only:

                    // http://acpedia.org/wiki/Announcements_-_2004/07_-_Treaties_in_Stone#Letter_to_the_Players

                    // Currently when a War Magic spell scores a critical hit, it adds a multiple of the base damage of the spell to a normal damage roll.
                    // Starting in July, War Magic critical hits will instead add a multiple of the maximum damage of the spell.
                    // No more crits that do less damage than non-crits!

                    if (isPVP) // PvP: 50% of the MIN damage added to normal damage roll
                    {
                        critDamageBonus = minDamage * 0.5f;
                    }
                    else   // PvE: 50% of the MAX damage added to normal damage roll
                    {
                        critDamageBonus = maxDamage * 0.5f;
                    }

                    weaponCritDamageMod = GetWeaponCritDamageMod(sourceCreature, attackSkill, target);

                    critDamageBonus *= weaponCritDamageMod;
                }

                /* War Magic skill-based damage bonus
                 * http://acpedia.org/wiki/Announcements_-_2002/08_-_Atonement#Letter_to_the_Players
                 */
                if (sourcePlayer != null)
                {
                    // per retail stats, level 8 difficulty is capped to 350 instead of 400
                    // without this, level 7s have the potential to deal more damage than level 8s
                    var difficulty = Math.Min(Spell.Power, 350);    // was skillMod possibility capped to 1.3x for level 7 spells in retail, instead of level 8 difficulty cap?
                    var magicSkill = sourcePlayer.GetCreatureSkill(Spell.School).Current;

                    if (magicSkill > difficulty)
                    {
                        // Bonus clamped to a maximum of 50%
                        //var percentageBonus = Math.Clamp((magicSkill - Spell.Power) / 100.0f, 0.0f, 0.5f);
                        var percentageBonus = (magicSkill - difficulty) / 1000.0f;

                        skillBonus = minDamage * percentageBonus;
                    }
                }
                baseDamage = ThreadSafeRandom.Next(minDamage, maxDamage);

                weaponResistanceMod = GetWeaponResistanceModifier(sourceCreature, attackSkill, Spell.DamageType);

                // if attacker/weapon has IgnoreMagicResist directly, do not transfer to spell projectile
                // only pass if SpellProjectile has it directly, such as 2637 - Invoking Aun Tanua

                resistanceMod = (float)Math.Max(0.0f, target.GetResistanceMod(resistanceType, this, null, weaponResistanceMod));

                if (sourcePlayer != null && targetPlayer != null && Spell.DamageType == DamageType.Nether)
                {
                    // for direct damage from void spells in pvp,
                    // apply void_pvp_modifier *on top of* the player's natural resistance to nether

                    // this supposedly brings the direct damage from void spells in pvp closer to retail
                    resistanceMod *= (float)PropertyManager.GetDouble("void_pvp_modifier").Item;
                }

                finalDamage = baseDamage + critDamageBonus + skillBonus;

                finalDamage *= elementalDamageMod * slayerMod * resistanceMod * absorbMod;
            }

            // show debug info
            if (sourceCreature != null && sourceCreature.DebugDamage.HasFlag(Creature.DebugDamageType.Attacker))
            {
                ShowInfo(sourceCreature, Spell, attackSkill, criticalChance, criticalHit, critDefended, overpower, weaponCritDamageMod, skillBonus, baseDamage, critDamageBonus, elementalDamageMod, slayerMod, weaponResistanceMod, resistanceMod, absorbMod, LifeProjectileDamage, lifeMagicDamage, finalDamage);
            }
            if (target.DebugDamage.HasFlag(Creature.DebugDamageType.Defender))
            {
                ShowInfo(target, Spell, attackSkill, criticalChance, criticalHit, critDefended, overpower, weaponCritDamageMod, skillBonus, baseDamage, critDamageBonus, elementalDamageMod, slayerMod, weaponResistanceMod, resistanceMod, absorbMod, LifeProjectileDamage, lifeMagicDamage, finalDamage);
            }
            return(finalDamage);
        }
Example #29
0
        private static WorldObject CreateJewels(int tier, bool isMagical)
        {
            uint gemType           = 0;
            int  workmanship       = 0;
            int  rank              = 0;
            int  difficulty        = 0;
            int  spellDID          = 0;
            int  skill_level_limit = 0;

            int gemLootMatrixIndex = tier - 1;

            if (gemLootMatrixIndex > 4)
            {
                gemLootMatrixIndex = 4;
            }
            int upperLimit = LootTables.GemsMatrix[gemLootMatrixIndex].Length - 1;

            uint gemWCID = (uint)LootTables.GemsWCIDsMatrix[gemLootMatrixIndex][ThreadSafeRandom.Next(0, upperLimit)];

            WorldObject wo = WorldObjectFactory.CreateNewWorldObject(gemWCID) as Gem;

            if (wo == null)
            {
                return(null);
            }

            gemType = (uint)wo.MaterialType;

            workmanship = GetWorkmanship(tier);
            wo.SetProperty(PropertyInt.ItemWorkmanship, workmanship);
            int value = LootTables.gemValues[(int)gemType] + ThreadSafeRandom.Next(1, LootTables.gemValues[(int)gemType]);

            wo.SetProperty(PropertyInt.Value, value);

            gemLootMatrixIndex = tier - 1;
            if (isMagical)
            {
                wo.SetProperty(PropertyInt.ItemUseable, 8);
                wo.SetProperty(PropertyInt.UiEffects, (int)UiEffects.Magical);

                int gemSpellIndex;
                int spellChance = 0;

                spellChance = ThreadSafeRandom.Next(0, 3);
                switch (spellChance)
                {
                case 0:
                    gemSpellIndex = LootTables.GemSpellIndexMatrix[gemLootMatrixIndex][0];
                    spellDID      = LootTables.GemCreatureSpellMatrix[gemSpellIndex][ThreadSafeRandom.Next(0, LootTables.GemCreatureSpellMatrix[gemSpellIndex].Length - 1)];
                    break;

                case 1:
                    gemSpellIndex = LootTables.GemSpellIndexMatrix[gemLootMatrixIndex][0];
                    spellDID      = LootTables.GemLifeSpellMatrix[gemSpellIndex][ThreadSafeRandom.Next(0, LootTables.GemLifeSpellMatrix[gemSpellIndex].Length - 1)];
                    break;

                case 2:
                    gemSpellIndex = LootTables.GemSpellIndexMatrix[gemLootMatrixIndex][1];
                    spellDID      = LootTables.GemCreatureSpellMatrix[gemSpellIndex][ThreadSafeRandom.Next(0, LootTables.GemCreatureSpellMatrix[gemSpellIndex].Length - 1)];
                    break;

                default:
                    gemSpellIndex = LootTables.GemSpellIndexMatrix[gemLootMatrixIndex][1];
                    spellDID      = LootTables.GemLifeSpellMatrix[gemSpellIndex][ThreadSafeRandom.Next(0, LootTables.GemLifeSpellMatrix[gemSpellIndex].Length - 1)];
                    break;
                }

                int manaCost   = 50 * gemSpellIndex;
                int spellcraft = 50 * gemSpellIndex;
                int maxMana    = ThreadSafeRandom.Next(manaCost, manaCost + 50);

                wo.SetProperty(PropertyDataId.Spell, (uint)spellDID);
                wo.SetProperty(PropertyInt.ItemAllegianceRankLimit, rank);
                wo.SetProperty(PropertyInt.ItemDifficulty, difficulty);
                wo.SetProperty(PropertyInt.ItemManaCost, manaCost);
                wo.SetProperty(PropertyInt.ItemMaxMana, maxMana);
                wo.SetProperty(PropertyInt.ItemSkillLevelLimit, skill_level_limit);
                wo.SetProperty(PropertyInt.ItemSpellcraft, spellcraft);
            }
            else
            {
                wo.SetProperty(PropertyInt.ItemUseable, 1);

                wo.RemoveProperty(PropertyInt.ItemManaCost);
                wo.RemoveProperty(PropertyInt.ItemMaxMana);
                wo.RemoveProperty(PropertyInt.ItemCurMana);
                wo.RemoveProperty(PropertyInt.ItemSpellcraft);
                wo.RemoveProperty(PropertyInt.ItemDifficulty);
                wo.RemoveProperty(PropertyInt.ItemSkillLevelLimit);
                wo.RemoveProperty(PropertyDataId.Spell);
            }

            wo = RandomizeColor(wo);
            return(wo);
        }
Example #30
0
        public void SetCaptain()
        {
            List<int> list = new List<int>();
            ThreadSafeRandom random = new ThreadSafeRandom();
            GamePlayer[] players = Data.FlagPlayer.ToArray();
            int rand = random.Next(players.Length);
            for (int i = rand; i < players.Length + rand; i++)
            {
                if (Data.Players[players[i % players.Length]].State == TankGameState.LOSE)
                    continue;

                if (players[i % players.Length].CurrentTeamIndex != 0)
                {
                    if (!list.Contains(players[i % players.Length].CurrentTeamIndex))
                    {
                        list.Add(players[i % players.Length].CurrentTeamIndex);
                        Data.Players[players[i % players.Length]].IsCaptain = true;
                    }
                    else
                    {
                        Data.Players[players[i % players.Length]].IsCaptain = false;
                    }
                }
                else
                {
                    list.Add(0);
                    Data.Players[players[i % players.Length]].IsCaptain = true;
                }
            }

            players = Data.Players.Keys.ToArray();
            rand = random.Next(players.Length);
            for (int i = rand; i < players.Length + rand; i++)
            {
                if (Data.Players[players[i % players.Length]].State == TankGameState.LOSE)
                    continue;

                if (!list.Contains(players[i % players.Length].CurrentTeamIndex))
                {
                    list.Add(players[i % players.Length].CurrentTeamIndex);
                    Data.Players[players[i % players.Length]].IsCaptain = true;
                }
            }
        }
Example #31
0
        protected async Task RemindersRange(int iterations = 1000)
        {
            await Task.WhenAll(Enumerable.Range(1, iterations).Select(async i =>
            {
                GrainReference grainRef = MakeTestGrainReference();

                await RetryHelper.RetryOnExceptionAsync(10, RetryOperation.Sigmoid, async() =>
                {
                    await remindersTable.UpsertRow(CreateReminder(grainRef, i.ToString()));
                    return(Task.CompletedTask);
                });
            }));

            var rows = await remindersTable.ReadRows(0, uint.MaxValue);

            Assert.Equal(rows.Reminders.Count, iterations);

            rows = await remindersTable.ReadRows(0, 0);

            Assert.Equal(rows.Reminders.Count, iterations);

            var remindersHashes = rows.Reminders.Select(r => r.GrainRef.GetUniformHashCode()).ToArray();

            await Task.WhenAll(Enumerable.Range(0, iterations).Select(i =>
                                                                      TestRemindersHashInterval(remindersTable, (uint)ThreadSafeRandom.Next(int.MinValue, int.MaxValue), (uint)ThreadSafeRandom.Next(int.MinValue, int.MaxValue),
                                                                                                remindersHashes)));
        }