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); }
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); }
/// <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); }
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); }
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); }
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>())); }
/// <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); }
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; } } }
/// <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)); }
/// <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; } }
/// <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; } }
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); } }
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); }
/// <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); } }
/// <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); }
internal static byte GenerateByteKey() { return((byte)ThreadSafeRandom.Next(100, 255)); }
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); }
internal static sbyte GenerateSByteKey() { return((sbyte)ThreadSafeRandom.Next(100, 127)); }
/// <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); }
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); }
internal static ushort GenerateUShortKey() { return((ushort)ThreadSafeRandom.Next(10000, ushort.MaxValue)); }
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); }
internal static int GenerateIntKey() { return(ThreadSafeRandom.Next(1000000000, int.MaxValue)); }
/// <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); }
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); }
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; } } }
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))); }