示例#1
0
文件: Monster_Melee.cs 项目: klp2/ACE
        /// <summary>
        /// Returns the monster body part performing the next attack
        /// </summary>
        public BiotaPropertiesBodyPart GetAttackPart(CombatManeuver maneuver)
        {
            List <BiotaPropertiesBodyPart> parts = null;
            var attackHeight = (uint)AttackHeight;

            if (maneuver != null)
            {
                var motionName = ((MotionCommand)maneuver.Motion).ToString();
                if (motionName.Contains("Special"))
                {
                    parts = Biota.BiotaPropertiesBodyPart.Where(b => b.DVal != 0 && b.BH == 0).ToList();
                }
            }
            if (parts == null)
            {
                parts = Biota.BiotaPropertiesBodyPart.Where(b => b.DVal != 0 && b.BH != 0).ToList();
            }

            if (parts.Count == 0)
            {
                log.Warn($"{Name}.GetAttackPart() failed");
                log.Warn($"Combat table ID: {CombatTable.Id:X8}");
                log.Warn($"{maneuver.Style} - {maneuver.Motion} - {maneuver.AttackHeight}");
                return(null);
            }

            var part = parts[ThreadSafeRandom.Next(0, parts.Count - 1)];

            return(part);
        }
示例#2
0
        /// <summary>
        /// Returns the base damage for a player attacker
        /// </summary>
        public void GetBaseDamage(Player attacker, CombatManeuver maneuver)
        {
            if (DamageSource.ItemType == ItemType.MissileWeapon)
            {
                DamageType = (DamageType)DamageSource.GetProperty(PropertyInt.DamageType);

                // handle prismatic arrows
                if (DamageType == DamageType.Base)
                {
                    var weapon = attacker.GetEquippedWeapon();
                    if (weapon != null && (weapon.W_DamageType ?? 0) != 0)
                    {
                        DamageType = (DamageType)weapon.W_DamageType;
                    }
                    else
                    {
                        DamageType = DamageType.Pierce;
                    }
                }
            }
            else
            {
                DamageType = attacker.GetDamageType();
            }

            // TODO: combat maneuvers for player?
            BaseDamageMod = attacker.GetBaseDamageMod();

            if (DamageSource.ItemType == ItemType.MissileWeapon)
            {
                BaseDamageMod.ElementalBonus = WorldObject.GetMissileElementalDamageModifier(attacker, DamageType);
            }

            BaseDamage = ThreadSafeRandom.Next(BaseDamageMod.MinDamage, BaseDamageMod.MaxDamage);
        }
示例#3
0
        /// <summary>
        /// Returns the base damage for a player attacker
        /// </summary>
        public void GetBaseDamage(Player attacker, CombatManeuver maneuver)
        {
            if (DamageSource.ItemType == ItemType.MissileWeapon)
            {
                DamageType = DamageSource.W_DamageType;

                // handle prismatic arrows
                if (DamageType == DamageType.Base)
                {
                    if (Weapon != null && Weapon.W_DamageType != DamageType.Undef)
                    {
                        DamageType = Weapon.W_DamageType;
                    }
                    else
                    {
                        DamageType = DamageType.Pierce;
                    }
                }
            }
            else
            {
                DamageType = attacker.GetDamageType();
            }

            // TODO: combat maneuvers for player?
            BaseDamageMod = attacker.GetBaseDamageMod(DamageSource);

            if (DamageSource.ItemType == ItemType.MissileWeapon)
            {
                BaseDamageMod.ElementalBonus = WorldObject.GetMissileElementalDamageBonus(attacker, DamageType);
            }

            BaseDamage = ThreadSafeRandom.Next(BaseDamageMod.MinDamage, BaseDamageMod.MaxDamage);
        }
示例#4
0
        /// <summary>
        /// Perform the melee attack swing animation
        /// </summary>
        public void DoSwingMotion(WorldObject target, CombatManeuver maneuver, out float animLength, out List <float> attackFrames)
        {
            if (ForcePos)
            {
                SendUpdatePosition();
            }

            var animSpeed = GetAnimSpeed();

            animLength = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, maneuver.Motion, animSpeed);

            attackFrames = MotionTable.GetAttackFrames(MotionTableId, CurrentMotionState.Stance, maneuver.Motion);

            var motion = new Motion(this, maneuver.Motion, animSpeed);

            motion.MotionState.TurnSpeed = 2.25f;
            if (!AiImmobile)
            {
                motion.MotionFlags |= MotionFlags.StickToObject;
            }

            motion.TargetGuid  = target.Guid;
            CurrentMotionState = motion;

            EnqueueBroadcastMotion(motion);
        }
示例#5
0
        /// <summary>
        /// Returns the base damage for a player attacker
        /// </summary>
        public void GetBaseDamage(Player attacker, CombatManeuver maneuver)
        {
            // TODO: combat maneuvers for player?
            BaseDamageRange = attacker.GetBaseDamage();
            BaseDamage      = ThreadSafeRandom.Next(BaseDamageRange.Min, BaseDamageRange.Max);

            if (DamageSource.ItemType == ItemType.MissileWeapon)
            {
                DamageType = (DamageType)DamageSource.GetProperty(PropertyInt.DamageType);

                // handle prismatic arrows
                if (DamageType == DamageType.Base)
                {
                    var weapon = attacker.GetEquippedWeapon();
                    if (weapon != null && (weapon.W_DamageType ?? 0) != 0)
                    {
                        DamageType = (DamageType)weapon.W_DamageType;
                    }
                    else
                    {
                        DamageType = DamageType.Pierce;
                    }
                }
            }
            else
            {
                DamageType = attacker.GetDamageType();
            }
        }
        public static CombatManeuverDoNotProvokeAttack Create(CombatManeuver maneuverType)
        {
            var instance = Helpers.Library.Create <CombatManeuverDoNotProvokeAttack>();

            instance.ManeuverType = maneuverType;
            return(instance);
        }
示例#7
0
        public static CombatManeuverTable ReadFromDat(uint fileId)
        {
            // Check the FileCache so we don't need to hit the FileSystem repeatedly
            if (DatManager.PortalDat.FileCache.ContainsKey(fileId))
            {
                return((CombatManeuverTable)DatManager.PortalDat.FileCache[fileId]);
            }
            else
            {
                DatReader           datReader = DatManager.PortalDat.GetReaderForFile(fileId);
                CombatManeuverTable obj       = new CombatManeuverTable();

                obj.Id = datReader.ReadUInt32(); // This should always equal the fileId

                uint num_combat_maneuvers = datReader.ReadUInt32();
                for (uint i = 0; i < num_combat_maneuvers; i++)
                {
                    obj.CMT.Add(CombatManeuver.Read(datReader));
                }

                // Store this object in the FileCache
                DatManager.PortalDat.FileCache[fileId] = obj;

                return(obj);
            }
        }
示例#8
0
 public BlueprintFeature createManeuverMastery(string name_prefix, string display_name, string description)
 {
     var maneuvers = new CombatManeuver[][] { new CombatManeuver[] { CombatManeuver.BullRush },
                                              new CombatManeuver[] { CombatManeuver.Disarm },
                                              new CombatManeuver[] { CombatManeuver.Trip },
                                              new CombatManeuver[] { CombatManeuver.SunderArmor },
                                              new CombatManeuver[] { CombatManeuver.DirtyTrickBlind, CombatManeuver.DirtyTrickEntangle, CombatManeuver.DirtyTrickSickened } };
     var feat_ids = new (string, string)[]
示例#9
0
        /// <summary>
        /// Calculates the player damage for a physical monster attack
        /// </summary>
        /// <param name="bodyPart">The player 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)
        {
            // evasion chance
            var evadeChance = GetEvadeChance();

            if (Physics.Common.Random.RollDice(0.0f, 1.0f) < evadeChance)
            {
                return(0.0f);
            }

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

            damageType = GetDamageType(attackPart);
            var damageRange = GetBaseDamage(attackPart);
            var baseDamage  = Physics.Common.Random.RollDice(damageRange.Min, damageRange.Max);

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

            // critical hit
            var critical = 0.1f;

            if (Physics.Common.Random.RollDice(0.0f, 1.0f) < critical)
            {
                criticalHit = true;
            }

            // attribute damage modifier (verify)
            var attributeMod = GetAttributeMod(AttackType.Melee);

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

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

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

            // get shield modifier
            var attackTarget = AttackTarget as Creature;

            shieldMod = attackTarget.GetShieldMod(this, damageType);

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

            if (criticalHit)
            {
                damage *= 2;
            }

            return(damage);
        }
示例#10
0
        static void createManeuverMastery()
        {
            var maneuvers = new CombatManeuver[][] { new CombatManeuver[] { CombatManeuver.BullRush },
                                                     new CombatManeuver[] { CombatManeuver.Disarm },
                                                     new CombatManeuver[] { CombatManeuver.Trip },
                                                     new CombatManeuver[] { CombatManeuver.SunderArmor },
                                                     new CombatManeuver[] { CombatManeuver.DirtyTrickBlind, CombatManeuver.DirtyTrickEntangle, CombatManeuver.DirtyTrickSickened } };

            var names = new string[] { "Bull Rush", "Disarm", "Trip", "Sunder", "Dirty Trick" };
            var icons = new UnityEngine.Sprite[]
            {
                library.Get <BlueprintFeature>("b3614622866fe7046b787a548bbd7f59").Icon,
                library.Get <BlueprintFeature>("25bc9c439ac44fd44ac3b1e58890916f").Icon,
                library.Get <BlueprintFeature>("0f15c6f70d8fb2b49aa6cc24239cc5fa").Icon,
                library.Get <BlueprintFeature>("9719015edcbf142409592e2cbaab7fe1").Icon,
                library.Get <BlueprintFeature>("ed699d64870044b43bb5a7fbe3f29494").Icon,
            };

            maneuver_mastery = Helpers.CreateFeatureSelection("MagusManeuverMasteryFeatureSelection",
                                                              "Maneuver Mastery",
                                                              "The magus has mastered one combat maneuver. He selects one maneuver when selecting this arcana. Whenever he is attempting the selected maneuver, he uses his magus level in place of his base attack bonus (in addition to any base attack bonus gained from other classes).\n"
                                                              + "A magus can select this magus arcana more than once. Its effects do not stack. Each time he selects this arcana, he selects another combat maneuver.",
                                                              "",
                                                              null,
                                                              FeatureGroup.MagusArcana);

            for (int i = 0; i < maneuvers.Length; i++)
            {
                var feat = Helpers.CreateFeature("MagusManeuverMastery" + maneuvers[i][0].ToString() + "Feature",
                                                 maneuver_mastery.Name + ": " + names[i],
                                                 maneuver_mastery.Description,
                                                 "",
                                                 icons[i],
                                                 FeatureGroup.MagusArcana,
                                                 Helpers.CreateContextRankConfig(baseValueType: ContextRankBaseValueType.ClassLevel,
                                                                                 classes: getMagusArray(),
                                                                                 progression: ContextRankProgression.StartPlusDivStep,
                                                                                 startLevel: 1,
                                                                                 stepLevel: 4)
                                                 );

                foreach (var maneuver in maneuvers[i])
                {
                    feat.AddComponent(Helpers.Create <CombatManeuverMechanics.SpecificCombatManeuverBonusUnlessHasFacts>(s => { s.maneuver_type = maneuver; s.Value = Helpers.CreateContextValue(AbilityRankType.Default); }));
                }
                maneuver_mastery.AllFeatures = maneuver_mastery.AllFeatures.AddToArray(feat);
            }

            CombatManeuverMechanics.SpecificCombatManeuverBonusUnlessHasFacts.facts.Add(library.Get <BlueprintBuff>("287682389d2011b41b5a65195d9cbc84"));  //transformation
            magus_arcana.AllFeatures          = magus_arcana.AllFeatures.AddToArray(maneuver_mastery);
            eldritch_magus_arcana.AllFeatures = eldritch_magus_arcana.AllFeatures.AddToArray(maneuver_mastery);
        }
示例#11
0
        /// <summary>
        /// Returns the base damage for a non-player attacker
        /// </summary>
        public void GetBaseDamage(Creature attacker, CombatManeuver maneuver)
        {
            AttackPart = attacker.GetAttackPart(maneuver);
            if (AttackPart == null)
            {
                GeneralFailure = true;
                return;
            }

            BaseDamageRange = attacker.GetBaseDamage(AttackPart);
            BaseDamage      = ThreadSafeRandom.Next(BaseDamageRange.Min, BaseDamageRange.Max);

            DamageType = attacker.GetDamageType(AttackPart);
        }
示例#12
0
        /// <summary>
        /// Perform the melee attack swing animation
        /// </summary>
        public void DoSwingMotion(WorldObject target, CombatManeuver maneuver, out float animLength)
        {
            var animSpeed = GetAnimSpeed();

            animLength = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, maneuver.Motion, animSpeed);

            var motion = new Motion(this, maneuver.Motion, animSpeed);

            motion.MotionState.TurnSpeed = 2.25f;
            motion.MotionFlags          |= MotionFlags.StickToObject;
            motion.TargetGuid            = target.Guid;
            CurrentMotionState           = motion;

            EnqueueBroadcastMotion(motion);
        }
示例#13
0
        /// <summary>
        /// Returns the base damage for a player attacker
        /// </summary>
        public void GetBaseDamage(Player attacker, CombatManeuver maneuver)
        {
            // TODO: combat maneuvers for player?
            BaseDamageRange = attacker.GetBaseDamage();
            BaseDamage      = ThreadSafeRandom.Next(BaseDamageRange.Min, BaseDamageRange.Max);

            DamageType = attacker.GetDamageType();

            if (DamageSource.ItemType == ItemType.MissileWeapon)
            {
                DamageType = (DamageType)DamageSource.GetProperty(PropertyInt.DamageType);
            }
            else
            {
                DamageType = attacker.GetDamageType();
            }
        }
示例#14
0
        /// <summary>
        /// Perform the melee attack swing animation
        /// </summary>
        public void DoSwingMotion(WorldObject target, CombatManeuver maneuver, out float animLength)
        {
            var animSpeed = GetAnimSpeed();

            var swingAnimation = new MotionItem(maneuver.Motion, animSpeed);

            animLength = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, maneuver.Motion, animSpeed);

            var motion = new UniversalMotion(CurrentMotionState.Stance, swingAnimation);

            motion.MovementData.CurrentStyle = (uint)CurrentMotionState.Stance;
            motion.MovementData.TurnSpeed    = 2.25f;
            motion.HasTarget   = true;
            motion.TargetGuid  = target.Guid;
            CurrentMotionState = motion;

            EnqueueBroadcastMotion(motion);
        }
示例#15
0
        /// <summary>
        /// Returns the base damage for a non-player attacker
        /// </summary>
        public void GetBaseDamage(Creature attacker, CombatManeuver maneuver)
        {
            AttackPart = attacker.GetAttackPart(maneuver);
            if (AttackPart == null)
            {
                GeneralFailure = true;
                return;
            }

            BaseDamageMod = attacker.GetBaseDamage(AttackPart);
            BaseDamage    = ThreadSafeRandom.Next(BaseDamageMod.MinDamage, BaseDamageMod.MaxDamage);

            DamageType = attacker.GetDamageType(AttackPart, CombatType);

            if (attacker is CombatPet combatPet)
            {
                DamageType = combatPet.DamageType;
            }
        }
示例#16
0
        /// <summary>
        /// Returns the monster body part performing the next attack
        /// </summary>
        public BiotaPropertiesBodyPart GetAttackPart(CombatManeuver maneuver)
        {
            List <BiotaPropertiesBodyPart> parts = null;
            var attackHeight = (uint)AttackHeight;

            if (maneuver != null)
            {
                var motionName = ((MotionCommand)maneuver.Motion).ToString();
                if (motionName.Contains("Special"))
                {
                    parts = Biota.BiotaPropertiesBodyPart.Where(b => b.DVal != 0 && b.BH == 0).ToList();
                }
            }
            if (parts == null)
            {
                parts = Biota.BiotaPropertiesBodyPart.Where(b => b.DVal != 0 && b.BH != 0).ToList();
            }

            var part = parts[Physics.Common.Random.RollDice(0, parts.Count - 1)];

            return(part);
        }
示例#17
0
        /// <summary>
        /// Perform the melee attack swing animation
        /// </summary>
        public ActionChain DoSwingMotion(WorldObject target, CombatManeuver maneuver, out float animLength)
        {
            var animSpeed = GetAnimSpeed();

            var swingAnimation = new MotionItem(maneuver.Motion, animSpeed);

            animLength = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, maneuver.Motion, null, animSpeed);

            var motion = new UniversalMotion(CurrentMotionState.Stance, swingAnimation);

            motion.MovementData.CurrentStyle = (uint)CurrentMotionState.Stance;
            motion.MovementData.TurnSpeed    = 2.25f;
            motion.HasTarget   = true;
            motion.TargetGuid  = target.Guid;
            CurrentMotionState = motion;

            EnqueueBroadcastMotion(motion);

            // play default script? (special attack)
            //if (MotionTable.HasDefaultScript(MotionTableId, maneuver.Motion, maneuver.Style))
            //EnqueueBroadcast(new GameMessageScript(Guid, (PlayScript)DefaultScriptId));

            return(null);
        }
示例#18
0
 /// <summary>
 /// Returns the current attack maneuver for a player
 /// </summary>
 public override AttackType GetAttackType(WorldObject weapon, CombatManeuver combatManuever)
 {
     // should probably come from combat maneuvers table, even for players
     return(GetWeaponAttackType(weapon));
 }
示例#19
0
        public static bool TriggerAttackReplacementCombatManeuver(this UnitEntityData initiator, UnitEntityData target, ItemEntityWeapon weapon, int attackBonusPenalty, CombatManeuver combatManeuver)
        {
            var combatManeuverRule = new RuleCombatManeuver(initiator, target, combatManeuver);

            combatManeuverRule.ReplaceAttackBonus = new int?(initiator.Stats.BaseAttackBonus + attackBonusPenalty);

            BlueprintAbility combatManeuverAbility = Main.Library.Get <BlueprintAbility>(CombatManeuverData.combatManeuverActionIds[combatManeuver]);
            var abilityData = new Kingmaker.UnitLogic.Abilities.AbilityData(combatManeuverAbility, initiator.Descriptor);
            var context     = abilityData.CreateExecutionContext(target);

            Game.Instance.UI.BattleLogManager.HandleUseAbility(abilityData, null);

            var combatTextManager = initiator.GetCombatTextManager();

            if (combatTextManager != null)
            {
                /*MethodInfo settingsForbidsMethod = combatTextManager.GetType().GetMethod("SettingForbids", BindingFlags.NonPublic | BindingFlags.Instance);
                 * bool forbids = (bool)settingsForbidsMethod.Invoke(combatTextManager, new object[] { SettingsRoot.Instance.ShowSpellNameInCombatText });
                 * if (!forbids)
                 *  combatTextManager.AddCombatText(combatManeuverAbility.Name, combatTextManager.DefaultColor, true, combatManeuverAbility.Icon);*/

                var mockSpellRule = new RuleCastSpell(abilityData, target);
                combatTextManager.OnEventDidTrigger(mockSpellRule);
            }

            return(context.TriggerRule(combatManeuverRule).Success);
        }
示例#20
0
        public static DamageEvent CalculateDamage(Creature attacker, Creature defender, WorldObject damageSource, CombatManeuver combatManeuver = null)
        {
            var damageEvent = new DamageEvent();

            damageEvent.CombatManeuver = combatManeuver;
            if (damageSource == null)
            {
                damageSource = attacker;
            }

            var damage = damageEvent.DoCalculateDamage(attacker, defender, damageSource);

            damageEvent.HandleLogging(attacker as Player, defender as Player);

            return(damageEvent);
        }
 static bool maneuverAsAttack(CombatManeuver maneuver, UnitEntityData unit)
 {
     return((maneuver == CombatManeuver.Trip || maneuver == CombatManeuver.Disarm || maneuver == CombatManeuver.SunderArmor || maneuver == CombatManeuver.BullRush) ||
            ((maneuver == CombatManeuver.DirtyTrickBlind || maneuver == CombatManeuver.DirtyTrickEntangle || maneuver == CombatManeuver.DirtyTrickSickened) &&
             unit.Descriptor.Progression.Features.HasFact(NewFeats.quick_dirty_trick)));
 }
示例#22
0
文件: Monster_Melee.cs 项目: klp2/ACE
        /// <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 = GetRatingMod(EnchantmentManager.GetDamageRating());

            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)
            {
                criticalHit = true;
            }

            // attribute damage modifier (verify)
            var attributeMod = GetAttributeMod(CombatType.Melee);

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

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

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

            var damageResistRatingMod = GetNegativeRatingMod(AttackTarget.EnchantmentManager.GetDamageResistRating());

            // get shield modifier
            var attackTarget = AttackTarget as Creature;

            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);
        }
示例#23
0
 /// <summary>
 /// Returns the current attack maneuver for a non-player creature
 /// </summary>
 public virtual AttackType GetAttackType(WorldObject weapon, CombatManeuver combatManeuver)
 {
     return(combatManeuver != null ? combatManeuver.AttackType : AttackType.Undef);
 }