예제 #1
0
        private void _handleResolveActionEvent(IActor source, ITarget target, Action action)
        {
            var a = action.BaseAction;

            ITarget[] targets = getTargetsInRadius(target, a.Radius);
            //EventLog.Add(new CombatLogEvent(CombatLogEventType.CAST, Time, source, action: a));

            foreach (ITarget tar in targets)
            {
                // Calculate and apply damage.
                if (a.Potency > 0)
                {
                    //CombatLogEvent damage = calculateActionDamage(a, source, tar);
                    //EventLog.Add(damage);
                }

                // Apply auras.
                if (a.AurasApplied != null)
                {
                    foreach (BaseAura aura in a.AurasApplied)
                    {
                        if (aura.Targets == AuraTarget.TARGET)
                        {
                            EventQueue.Add(new BattleEvent(
                                               BattleEventType.APPLY_AURA,
                                               Time,
                                               source,
                                               tar,
                                               baseAura: aura));
                        }
                    }
                }
            }

            // Apply self-auras.
            if (a.AurasApplied != null)
            {
                foreach (BaseAura aura in a.AurasApplied)
                {
                    if (aura.Targets == AuraTarget.SOURCE)
                    {
                        EventQueue.Add(new BattleEvent(
                                           BattleEventType.APPLY_AURA,
                                           Time,
                                           source,
                                           source,
                                           baseAura: aura));
                    }
                }
            }

            // Resolve action effects on the source actor, and add any
            // resulting events to the queue.
            var newEvents = source.ExecuteAction(action, Time);

            foreach (BattleEvent ev in newEvents)
            {
                EventQueue.Add(ev);
            }
        }
예제 #2
0
        private void _handleUseActionEvent(IActor source, ITarget target, Action action)
        {
            // Queue next actor availability.
            long t = source.BeginCast(action, Time);

            EventQueue.Add(new BattleEvent(BattleEventType.ACTOR_READY, t, source));

            // Resolves later if it has a cast time, else resolves now.
            if (action.BaseAction.CastTime > 0)
            {
                EventQueue.Add(new BattleEvent(
                                   BattleEventType.RESOLVE_ACTION,
                                   t,
                                   source,
                                   target,
                                   action: action));
            }
            else
            {
                EventQueue.Add(new BattleEvent(
                                   BattleEventType.RESOLVE_ACTION,
                                   Time,
                                   source,
                                   target,
                                   action: action));
            }
        }
예제 #3
0
        /// <summary>
        /// Contextually roll the damage of an action.  The order of operations for ACTION
        /// damage is as follows:
        ///
        /// D = ⌊ f(ptc) * f(wd) * f(ap) * f(det) * f(tnc) * traits ⌋ * f(chr) ⌋
        /// * f(dhr) ⌋ * rand[ 0.95, 1.05 ] ⌋ * buff_1 ⌋ * buff_2 ⌋ * ...
        /// (credit: TheoryJerks)
        ///
        /// Using BattleCalculations functions, this translates to:
        /// 1. Calculate base damage (ptc, wd, ap, det, tnc, traits)
        /// 2. Roll critical hit multiplier (chr)
        /// 3. Roll direct hit multiplier (dhr)
        /// 4. Roll damage variance (5% variance)
        /// 5. Calculate aura multipliers. (buff_1, buff_2, ...)
        ///
        /// </summary>
        /// <param name="source">The source actor performing the action.</param>
        /// <param name="target">The target being affected by the action.</param>
        /// <param name="action">The action being used.</param>
        /// <returns>Final damage value after all considerations.</returns>
        public static int RollActionDamage(IActor source, ITarget target, Action action)
        {
            double damage = _calculateActionBaseDamage(source, target, action);

            // Roll for critical and direct hits, and multiply.
            bool isCrit   = RollConditionalSuccess(_calculateCriticalHitRate(source, target, action));
            bool isDirect = RollConditionalSuccess(_calculateDirectHitRate(source, target));

            if (isCrit)
            {
                damage = Math.Floor(damage * Formulas.calculateCriticalHitMultiplier(source.getStat(CharacterStat.CRITICALHIT)));
            }
            if (isDirect)
            {
                damage = Math.Floor(damage * Constants.DirectHitMultiplier);
            }

            // 5% damage variance.
            damage = _rollDamageVariance(damage);

            // Aura multipliers.
            var modifiers = _getAuraMultipliers(source, target, action.BaseAction.Aspect);

            foreach (double modifier in modifiers)
            {
                damage = Math.Floor(damage * modifier);
            }

            return((int)damage);
        }
예제 #4
0
        public BattleEvent(BattleEventType type,
                           long time,
                           IActor source,
                           ITarget target    = null,
                           Action action     = null,
                           Aura aura         = null,
                           BaseAura baseAura = null)
        {
            Type   = type;
            Source = source;
            Target = target;
            Time   = time;

            Action   = action;
            Aura     = aura;
            BaseAura = baseAura;
        }
예제 #5
0
        /// <summary>
        /// Contextually calculates the critical hit rate for an action.
        /// This will account for aura effects on the source actor, and the
        /// target if applicable.
        ///
        /// This function will defer to the source actor to determine the
        /// base critical hit rate before auras, as a subclass of actor
        /// may adjust the outgoing critical hit rate contextually.
        /// (e.g. Warrior's beast gauge effects crit rate, Bootshine is a
        /// guaranteed crit when performed from the rear in Opo-opo Form, etc.)
        /// </summary>
        /// <param name="source">Source actor performing the action.</param>
        /// <param name="target">Target the action will affect.</param>
        /// <param name="action">The action being used.</param>
        /// <returns>The current critical hit rate for the action being used.</returns>
        private static double _calculateCriticalHitRate(IActor source, ITarget target, Action action = null, Aura aura = null)
        {
            double rate = source.getCriticalHitRate(action);

            foreach (Aura a in source.Auras)
            {
                rate += a.BaseAura.CriticalHitRateModifier;
            }

            if (target != null)
            {
                foreach (Aura a in target.Auras)
                {
                    rate += a.BaseAura.IncomingCriticalHitRateModifier;
                }
            }

            return(Math.Min(1, rate));
        }
예제 #6
0
        /// <summary>
        /// Contextually calculate the damage of an action before critical or direct hit
        /// calculations and before 5% variance. Requires initialized and active source
        /// actor and target, as well as the action information.
        /// </summary>
        /// <param name="source">The source actor using the action.</param>
        /// <param name="target">The target being affected by the action.</param>
        /// <param name="action">The action being used.</param>
        /// <returns>Damage before RNG effects.</returns>
        private static double _calculateActionBaseDamage(IActor source, ITarget target, Action action)
        {
            var potency = action.BaseAction.Potency;

            if (potency == 0)
            {
                return(0);
            }

            double damage      = 0;
            var    primaryStat = Constants.getDefaultPrimaryStat(source.JobID);

            // Collect relevant stats and multipliers.
            var weaponDamage            = source.getStat(CharacterStat.WEAPONDAMAGE);
            var attackPower             = source.getStat(CharacterStat.ATTACKPOWER);
            var determinationMultiplier = Formulas.calculateDeterminationMultiplier(source.getStat(CharacterStat.DETERMINATION));
            var tenacityMultiplier      = Formulas.calculateTenacityMultiplier(source.getStat(CharacterStat.TENACITY));

            // Base damage, innate actor multipliers (determination, tenacity, traits)
            damage = Formulas.calculateActionDamage(potency, weaponDamage, attackPower, source.JobID, primaryStat);
            damage = damage * determinationMultiplier;
            damage = damage * tenacityMultiplier;
            damage = Math.Floor(damage * Constants.getTraitDamageModifier(source.JobID));

            return(damage);
        }