Exemplo n.º 1
0
        public DamageOutcome Evaluate(BaseCharacter attacker, BaseCharacter defender, Damage attackerDamage)
        {
            var damageDealt   = attackerDamage.DamageDealt;
            var doNotEval     = false;
            var evalWithDummy = false;

            if (attacker == null)
            {
                if (Rm_RPGHandler.Instance.Combat.SkipEvaluatingDmgWithNullAttack)
                {
                    doNotEval = true;
                }
                else
                {
                    attacker = new BaseCharacter();
                    attacker.Init();
                    evalWithDummy = true;
                }
            }

            if (!doNotEval && !evalWithDummy && (attacker.CharacterType == CharacterType.Player || defender.CharacterType == CharacterType.Player))
            {
                var participants = new[] { attacker, defender };
                if (participants.All(p => p != null) && participants.Any(p => p.CharacterType != CharacterType.Player))
                {
                    var player = participants.First(p => p.CharacterType == CharacterType.Player);
                    var other  = participants.First(p => p.CharacterType != CharacterType.Player);

                    var cc = other as CombatCharacter;
                    if (!cc.AttackedOnceByPlayer)
                    {
                        var repDef = Rm_RPGHandler.Instance.Repositories.Quests.AllReputations.FirstOrDefault(r => r.ID == cc.ReputationId);
                        if (repDef != null)
                        {
                            if (repDef.ValueLossForNPCAttack > 0)
                            {
                                var playerRep = GetObject.PlayerSave.QuestLog.AllReputations.FirstOrDefault(r => r.ReputationID == cc.ReputationId);
                                if (playerRep != null)
                                {
                                    playerRep.Value -= repDef.ValueLossForNPCAttack;
                                }
                            }
                        }
                        cc.AttackedOnceByPlayer = true;
                    }
                }
            }

            var combatCalcTree = Rm_RPGHandler.Instance.Nodes.DamageTakenTree;

            if (defender.CharacterType == CharacterType.Player)
            {
                var playerDifficulty = GetObject.PlayerSave.Difficulty;
                var difficultyDef    = Rm_RPGHandler.Instance.Player.Difficulties.FirstOrDefault(d => d.ID == playerDifficulty);
                if (difficultyDef != null)
                {
                    attackerDamage.ApplyMultiplier(difficultyDef.DamageMultiplier);
                }
            }

            if (!doNotEval)
            {
                var nodeChain = new NodeChain(combatCalcTree, typeof(CombatStartNode), "DamageTaken")
                {
                    Attacker    = attacker,
                    Defender    = defender,
                    Damage      = attackerDamage,
                    DamageDealt = damageDealt
                };

                AttackOutcome?outcome = null;
                while (!nodeChain.Done)
                {
                    nodeChain.Evaluate();

                    if (nodeChain.CurrentNode is MissedHitNode)
                    {
                        outcome = AttackOutcome.Missed;
                    }
                    else if (nodeChain.CurrentNode is EvadedHitNode)
                    {
                        outcome = AttackOutcome.Evaded;
                    }
                }

                if (outcome != null && (outcome != AttackOutcome.Success || outcome != AttackOutcome.Critical))
                {
                    return(new DamageOutcome(null, outcome.Value));
                }
                else
                {
                    return(new DamageOutcome(attackerDamage, damageDealt, nodeChain.Damage.IsCritical ? AttackOutcome.Critical : AttackOutcome.Success));
                }
            }
            else
            {
                return(new DamageOutcome(attackerDamage, attackerDamage.DamageDealt, AttackOutcome.Success));
            }
        }