Exemple #1
0
        //IsAdditional is needed because additional actions may be required for some actions' effects
        //For instance, Goring Blade's bleed effect requires another action so the first action can still show damage numbers
        //Sentinel doesn't require an additional action because it doesn't need to show those numbers
        //this is stupid
        public static void TryStatus(Character caster, Character target, BattleCommand skill, CommandResult action, CommandResultContainer results, bool isAdditional = true)
        {
            double rand = Program.Random.NextDouble();

            //Statuses only land for non-resisted attacks and attacks that hit
            if (skill != null && skill.statusId != 0 && (action.hitType > HitType.Evade && action.hitType != HitType.Resist) && rand < skill.statusChance)
            {
                StatusEffect effect = Server.GetWorldManager().GetStatusEffect(skill.statusId);
                //Because combos might change duration or tier
                if (effect != null)
                {
                    effect.SetDuration(skill.statusDuration);
                    effect.SetTier(skill.statusTier);
                    effect.SetMagnitude(skill.statusMagnitude);
                    effect.SetOwner(target);
                    effect.SetSource(caster);

                    if (target.statusEffects.AddStatusEffect(effect, caster))
                    {
                        //If we need an extra action to show the status text
                        if (isAdditional)
                        {
                            results.AddAction(target.actorId, 30328, skill.statusId | (uint)HitEffect.StatusEffectType);
                        }
                    }
                    else
                    {
                        action.worldMasterTextId = 32002;//Is this right?
                    }
                }
                else
                {
                    //until all effects are scripted and added to db just doing this
                    if (target.statusEffects.AddStatusEffect(skill.statusId, skill.statusTier, skill.statusMagnitude, skill.statusDuration, 3000))
                    {
                        //If we need an extra action to show the status text
                        if (isAdditional)
                        {
                            results.AddAction(target.actorId, 30328, skill.statusId | (uint)HitEffect.StatusEffectType);
                        }
                    }
                    else
                    {
                        action.worldMasterTextId = 32002;//Is this right?
                    }
                }
            }
        }
Exemple #2
0
        public static void FinishActionSpell(Character attacker, Character defender, BattleCommand skill, CommandResult action, CommandResultContainer actionContainer = null)
        {
            //Determine the hit type of the action
            if (!TryMiss(attacker, defender, skill, action))
            {
                HandleStoneskin(defender, action);
                if (!TryCrit(attacker, defender, skill, action))
                {
                    if (!TryResist(attacker, defender, skill, action))
                    {
                        action.hitType = HitType.Hit;
                    }
                }
            }

            //There are no multi-hit spells
            action.worldMasterTextId = SingleHitTypeTextIds[action.hitType];

            //Set the hit effect
            SetHitEffectSpell(attacker, defender, skill, action);

            HandleStoneskin(defender, action);

            CalculateSpellDamageTaken(attacker, defender, skill, action);

            actionContainer.AddAction(action);

            DamageTarget(attacker, defender, action, actionContainer);
        }
Exemple #3
0
        /*
         * Hit Effecthelpers. Different types of hit effects hits use some flags for different things, so they're split into physical, magical, heal, and status
         */
        public static void DoAction(Character caster, Character target, BattleCommand skill, CommandResult action, CommandResultContainer actionContainer = null)
        {
            switch (action.actionType)
            {
            case (ActionType.Physical):
                FinishActionPhysical(caster, target, skill, action, actionContainer);
                break;

            case (ActionType.Magic):
                FinishActionSpell(caster, target, skill, action, actionContainer);
                break;

            case (ActionType.Heal):
                FinishActionHeal(caster, target, skill, action, actionContainer);
                break;

            case (ActionType.Status):
                FinishActionStatus(caster, target, skill, action, actionContainer);
                break;

            default:
                actionContainer.AddAction(action);
                break;
            }
        }
Exemple #4
0
        public static void FinishActionStatus(Character attacker, Character defender, BattleCommand skill, CommandResult action, CommandResultContainer actionContainer = null)
        {
            //Set the hit effect
            SetHitEffectStatus(attacker, defender, skill, action);

            TryStatus(attacker, defender, skill, action, actionContainer, false);

            actionContainer.AddAction(action);
        }
Exemple #5
0
        public static void FinishActionHeal(Character attacker, Character defender, BattleCommand skill, CommandResult action, CommandResultContainer actionContainer = null)
        {
            //Set the hit effect
            SetHitEffectHeal(attacker, defender, skill, action);

            actionContainer.AddAction(action);

            HealTarget(attacker, defender, action, actionContainer);
        }
Exemple #6
0
        //Determine the hit type, set the hit effect, modify damage based on stoneskin and hit type, hit target
        public static void FinishActionPhysical(Character attacker, Character defender, BattleCommand skill, CommandResult action, CommandResultContainer actionContainer = null)
        {
            //Figure out the hit type and change damage depending on hit type
            if (!TryMiss(attacker, defender, skill, action))
            {
                //Handle Stoneskin here because it seems like stoneskin mitigates damage done before taking into consideration crit/block/parry damage reductions.
                //This is based on the fact that a 0 damage attack due to stoneskin will heal for 0 with Aegis Boon, meaning Aegis Boon didn't mitigate any damage
                HandleStoneskin(defender, action);

                //Crits can't be blocked (is this true for Aegis Boon and Divine Veil?) or parried so they are checked first.
                if (!TryCrit(attacker, defender, skill, action))
                {
                    //Block and parry order don't really matter because if you can block you can't parry and vice versa
                    if (!TryBlock(attacker, defender, skill, action))
                    {
                        if (!TryParry(attacker, defender, skill, action))
                        {
                            //Finally if it's none of these, the attack was a hit
                            action.hitType = HitType.Hit;
                        }
                    }
                }
            }

            //Actions have different text ids depending on whether they're a part of a multi-hit ws or not.
            Dictionary <HitType, ushort> textIds = SingleHitTypeTextIds;

            //If this is the first hit of a multi hit command, add the "You use [command] on [target]" action
            //Needs to be done here because certain buff messages appear before it.
            if (skill != null && skill.numHits > 1)
            {
                if (action.hitNum == 1)
                {
                    actionContainer?.AddAction(new CommandResult(attacker.actorId, 30441, 0));
                }

                textIds = MultiHitTypeTextIds;
            }

            //Set the correct textId
            action.worldMasterTextId = textIds[action.hitType];

            //Set the hit effect
            SetHitEffectPhysical(attacker, defender, skill, action, actionContainer);

            //Modify damage based on defender's stats
            CalculatePhysicalDamageTaken(attacker, defender, skill, action);

            actionContainer.AddAction(action);
            action.enmity = (ushort)(action.enmity * (skill != null ? skill.enmityModifier : 1));
            //Damage the target
            DamageTarget(attacker, defender, action, actionContainer);
        }
Exemple #7
0
        //The order of messages that appears after using a command is:

        //1. Cast start messages. (ie "You begin casting... ")
        //2. Messages from buffs that activate before the command actually starts, like Power Surge or Presence of Mind. (This may be wrong and these could be the same as 4.)
        //3. If the command is a multi-hit command, this is where the "You use [command] on [target]" message goes

        //Then, for each hit:
        //4. Buffs that activate before a command hits, like Blindside
        //5. The hit itself. For single hit commands this message is "Your [command] hits [target] for x damage" for multi hits it's "[Target] takes x points of damage"
        //6. Stoneskin falling off
        //6. Buffs that activate after a command hits, like Aegis Boon and Divine Veil

        //After all hits
        //7. If it's a multi-hit command there's a "{numhits]fold attack..." message or if all hits miss an "All attacks missed" message
        //8. Buffs that fall off after the skill ends, like Excruciate

        //For every target defeated:
        //8. Defeat message
        //9. EXP message
        //10. EXP chain message


        //folder is probably temporary until move to cached scripts is complete
        public void DoBattleCommand(BattleCommand command, string folder)
        {
            //List<BattleAction> actions = new List<BattleAction>();
            CommandResultContainer actions = new CommandResultContainer();

            var  targets   = command.targetFind.GetTargets();
            bool hitTarget = false;

            if (targets.Count > 0)
            {
                statusEffects.CallLuaFunctionByFlag((uint)StatusEffectFlags.ActivateOnCommandStart, "onCommandStart", this, command, actions);

                foreach (var chara in targets)
                {
                    ushort hitCount    = 0;
                    ushort totalDamage = 0;
                    for (int hitNum = 1; hitNum <= command.numHits; hitNum++)
                    {
                        var action = new CommandResult(chara.actorId, command, (byte)GetHitDirection(chara), (byte)hitNum);

                        //uncached script
                        lua.LuaEngine.CallLuaBattleCommandFunction(this, command, folder, "onSkillFinish", this, chara, command, action, actions);
                        //cached script
                        //skill.CallLuaFunction(owner, "onSkillFinish", this, chara, command, action, actions);
                        if (action.hitType > HitType.Evade && action.hitType != HitType.Resist)
                        {
                            hitTarget = true;
                            hitCount++;
                            totalDamage += action.amount;
                        }
                    }

                    if (command.numHits > 1)
                    {
                        //30442: [hitCount]fold Attack! [chara] takes a total of totalDamage points of damage.
                        //30450: All attacks miss!
                        ushort textId = (ushort)(hitTarget ? 30442 : 30450);
                        actions.AddAction(new CommandResult(chara.actorId, textId, 0, totalDamage, (byte)hitCount));
                    }
                }

                statusEffects.CallLuaFunctionByFlag((uint)StatusEffectFlags.ActivateOnCommandFinish, "onCommandFinish", this, command, actions);
            }
            else
            {
                actions.AddAction(new CommandResult(actorId, 30202, 0));
            }

            //Now that we know if we hit the target we can check if the combo continues
            if (this is Player)
            {
                if (command.isCombo && hitTarget)
                {
                    ((Player)this).SetCombos(command.comboNextCommandId);
                }
                else
                {
                    ((Player)this).SetCombos();
                }
            }

            CommandResult error = new CommandResult(actorId, 0, 0);

            DelMP(command.CalculateMpCost(this));
            DelTP(command.CalculateTpCost(this));
            actions.CombineLists();
            DoBattleAction(command.id, command.battleAnimation, actions.GetList());
        }