CalculCriticalHitRate() public method

public CalculCriticalHitRate ( int &cHitRate ) : void
cHitRate int
return void
コード例 #1
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="fighter"></param>
        /// <param name="cellId"></param>
        public void TryUseWeapon(AbstractFighter fighter, int cellId, int actionTime = 5000)
        {
            AddMessage(() =>
                {
                    if (LoopState == FightLoopStateEnum.STATE_WAIT_END || LoopState == FightLoopStateEnum.STATE_ENDED)
                    {
                        fighter.Dispatch(WorldMessage.BASIC_NO_OPERATION());
                        return;
                    }

                    if(State != FightStateEnum.STATE_FIGHTING)
                    {
                        Logger.Debug("Fight::TryUseWeapon fight is not in fighting state : " + fighter.Name);
                        fighter.Dispatch(WorldMessage.BASIC_NO_OPERATION());
                        return;
                    }

                    if (m_currentApCost != -1)
                    {
                        Logger.Debug("Fight::TryUseWeapon fight already processing spell launch and not finished : " + fighter.Name);
                        fighter.Dispatch(WorldMessage.BASIC_NO_OPERATION());
                        return;
                    }

                    var weapon = fighter.Inventory.Items.Find(item => item.Slot == ItemSlotEnum.SLOT_WEAPON);

                    if(weapon == null)
                    {
                        TryLaunchSpell(fighter, 0, cellId);
                        return;
                    }

                    if(!CanUseWeapon(fighter, weapon, cellId))
                    {
                        Logger.Debug("Fight::TryUseWeapon unable to use weapon : " + fighter.Name);
                        fighter.Dispatch(WorldMessage.BASIC_NO_OPERATION());
                        return;
                    }

                    var weaponTemplate = weapon.Template;

                    CurrentFighter.Team.CheckWeapon(fighter, weaponTemplate);

                    var isMelee = Pathfinding.GoalDistance(Map, fighter.Cell.Id, cellId) == 1;

                    fighter.UsedAP += weaponTemplate.APCost;

                    Dispatch(WorldMessage.FIGHT_ACTION_START(CurrentFighter.Id));

                    var failure = false;
                    if (weaponTemplate.CFRate != 0)
                    {
                        var criticalFailureRate = weaponTemplate.CFRate - fighter.Statistics.GetTotal(EffectEnum.AddEchecCritic);

                        if (criticalFailureRate < 2)
                            criticalFailureRate = 2;

                        if (Util.Next(0, criticalFailureRate) == 0)
                            failure = true;
                    }

                    if(failure)
                    {
                        CachedBuffer = true;
                        Dispatch(WorldMessage.GAME_ACTION(GameActionTypeEnum.FIGHT_WEAPON_FAILURE, fighter.Id, weaponTemplate.Id.ToString()));
                        Dispatch(WorldMessage.GAME_ACTION(GameActionTypeEnum.FIGHT_PA_LOST, fighter.Id, fighter.Id + ",-" + weaponTemplate.APCost));
                        Dispatch(WorldMessage.FIGHT_ACTION_FINISHED(CurrentFighter.Id));
                        CachedBuffer = false;

                        CurrentFighter.TurnPass = true;
                        return;
                    }

                    var criticalHit = false;
                    if (weaponTemplate.CSRate != 0)
                    {
                        var criticalHitRate = weaponTemplate.CSRate - fighter.Statistics.GetTotal(EffectEnum.AddDamageCritic);

                        fighter.CalculCriticalHitRate(ref criticalHitRate);

                        if (criticalHitRate < 2)
                            criticalHitRate = 2;

                        if (Util.Next(0, criticalHitRate) == 0)
                            criticalHit = true;
                    }

                    if(criticalHit)
                        Dispatch(WorldMessage.GAME_ACTION(GameActionTypeEnum.FIGHT_CRITICAL_HIT, fighter.Id, "0"));

                    var effects = weapon.Statistics.WeaponEffects;
                    var targetLists = new List<Tuple<GenericEffect, List<AbstractFighter>>>();

                    foreach (var effect in effects)
                    {
                        var targetList = new List<AbstractFighter>();
                        foreach (var currentCellId in CellZone.GetCells(Map, cellId, fighter.Cell.Id, weaponTemplate.RangeType))
                        {
                            var fightCell = GetCell(currentCellId);
                            if (fightCell != null)
                            {
                                foreach(var fighterObject in fightCell.FightObjects.OfType<AbstractFighter>())
                                {
                                    if (fighter == fighterObject)
                                        continue;

                                    targetList.Add(fighterObject);
                                }
                            }
                        }
                        targetLists.Add(Tuple.Create(effect.Value, targetList));
                    }

                    LoopState = FightLoopStateEnum.STATE_WAIT_ACTION;

                    fighter.UseWeapon(cellId, actionTime, () =>
                    {
                        if (LoopState == FightLoopStateEnum.STATE_WAIT_END || LoopState == FightLoopStateEnum.STATE_ENDED)
                        {
                            fighter.Dispatch(WorldMessage.BASIC_NO_OPERATION());
                            return;
                        }

                        foreach (var targetsByEffect in targetLists)
                        {
                            targetsByEffect.Item2.RemoveAll(affectedTarget => affectedTarget.IsFighterDead);

                            if (targetsByEffect.Item2.Count == 0)
                            {
                                AddProcessingTarget(
                                        new CastInfos(
                                                        targetsByEffect.Item1.EffectType,
                                                        -1,
                                                        cellId,
                                                        criticalHit && CastInfos.IsDamageEffect(targetsByEffect.Item1.EffectType) ? targetsByEffect.Item1.Value1 + weaponTemplate.CSBonus : targetsByEffect.Item1.Value1,
                                                        criticalHit && CastInfos.IsDamageEffect(targetsByEffect.Item1.EffectType) ? targetsByEffect.Item1.Value2 + weaponTemplate.CSBonus : targetsByEffect.Item1.Value2,
                                                        -1,
                                                        -1,
                                                        0,
                                                        fighter,
                                                        null,
                                                        weaponTemplate.RangeType,
                                                        0,
                                                        -1,
                                                        isMelee)
                                                     );
                            }
                            else
                            {
                                foreach (var target in targetsByEffect.Item2)
                                {
                                    AddProcessingTarget(new CastInfos(
                                                        targetsByEffect.Item1.EffectType,
                                                        -1,
                                                        cellId,
                                                        criticalHit && CastInfos.IsDamageEffect(targetsByEffect.Item1.EffectType) ? targetsByEffect.Item1.Value1 + weaponTemplate.CSBonus : targetsByEffect.Item1.Value1,
                                                        criticalHit && CastInfos.IsDamageEffect(targetsByEffect.Item1.EffectType) ? targetsByEffect.Item1.Value2 + weaponTemplate.CSBonus : targetsByEffect.Item1.Value2,
                                                        -1,
                                                        -1,
                                                        0,
                                                        fighter,
                                                        target,
                                                        weaponTemplate.RangeType,
                                                        target.Cell.Id,
                                                        -1,
                                                        isMelee));
                                }
                            }

                        }

                        m_currentApCost = weaponTemplate.APCost;
                    });
                });
        }
コード例 #2
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="fighter"></param>
        /// <param name="spellId"></param>
        /// <param name="castCellId"></param>
        public void TryLaunchSpell(AbstractFighter fighter, int spellId, int castCellId, int actionTime = 5000)
        {
            AddMessage(() =>
            {
                if (LoopState == FightLoopStateEnum.STATE_WAIT_END || LoopState == FightLoopStateEnum.STATE_ENDED)
                {
                    fighter.Dispatch(WorldMessage.BASIC_NO_OPERATION());
                    return;
                }

                if (State != FightStateEnum.STATE_FIGHTING)
                {
                    Logger.Debug("Fight::TryLaunchSpell fight is not in fighting state : " + fighter.Name);
                    fighter.Dispatch(WorldMessage.BASIC_NO_OPERATION());
                    return;
                }

                if (m_currentApCost != -1)
                {
                    Logger.Debug("Fight::TryLaunchSpell fight already processing spell launch and not finished : " + fighter.Name);
                    fighter.Dispatch(WorldMessage.BASIC_NO_OPERATION());
                    return;
                }

                if (fighter.SpellBook == null)
                {
                    Logger.Debug("Fight::TryLaunchSpell empty spellbook : " + fighter.Name);
                    fighter.Dispatch(WorldMessage.BASIC_NO_OPERATION());
                    return;
                }

                var spellLevel = fighter.SpellBook.GetSpellLevel(spellId);

                if (spellLevel == null)
                {
                    Logger.Debug("Fight::TryLaunchSpell unnknow spellId : " + fighter.Name);
                    fighter.Dispatch(WorldMessage.BASIC_NO_OPERATION());
                    return;
                }

                var launchResult = CanLaunchSpell(fighter, spellLevel, spellId, fighter.Cell.Id, castCellId);
                if (launchResult != FightSpellLaunchResultEnum.RESULT_OK)
                {
                    Logger.Debug("Fight::TryLaunchSpell unable to launch spell : " + fighter.Name + " reason=" + launchResult);
                    fighter.Dispatch(WorldMessage.BASIC_NO_OPERATION());
                    return;
                }

                var isMelee = Pathfinding.GoalDistance(Map, fighter.Cell.Id, castCellId) == 1;

                fighter.UsedAP += spellLevel.APCost;

                base.Dispatch(WorldMessage.FIGHT_ACTION_START(CurrentFighter.Id));

                var isEchec = false;
                if (spellLevel.ECSRate != 0)
                {
                    var echecRate = spellLevel.ECSRate - fighter.Statistics.GetTotal(EffectEnum.AddEchecCritic);

                    if (echecRate < 2)
                        echecRate = 2;

                    if (Util.Next(0, echecRate) == 0)
                        isEchec = true;

                    if (isEchec)
                    {
                        CachedBuffer = true;
                        Dispatch(WorldMessage.GAME_ACTION(GameActionTypeEnum.FIGHT_CRITICAL_FAILURE, fighter.Id, spellId.ToString()));
                        Dispatch(WorldMessage.GAME_ACTION(GameActionTypeEnum.FIGHT_PA_LOST, fighter.Id, fighter.Id + ",-" + spellLevel.APCost));
                        Dispatch(WorldMessage.FIGHT_ACTION_FINISHED(CurrentFighter.Id));
                        CachedBuffer = false;

                        if (spellLevel.IsECSEndTurn == 1)
                        {
                            CurrentFighter.TurnPass = true;
                        }
                        return;
                    }
                }

                var target = GetFighterOnCell(castCellId);
                if (target != null)
                {
                    fighter.SpellManager.Actualize(spellLevel, spellId, target.Id);
                }

                var isCritic = false;
                if (spellLevel.CSRate != 0 && spellLevel.CriticalEffects.Count > 0)
                {
                    var criticalHitRate = spellLevel.CSRate - fighter.Statistics.GetTotal(EffectEnum.AddDamageCritic);

                    fighter.CalculCriticalHitRate(ref criticalHitRate);

                    if (criticalHitRate < 2)
                        criticalHitRate = 2;

                    if (Util.Next(0, criticalHitRate) == 0)
                        isCritic = true;
                }

                if (isCritic)
                    Dispatch(WorldMessage.GAME_ACTION(GameActionTypeEnum.FIGHT_CRITICAL_HIT, fighter.Id, spellId.ToString()));

                var effects = isCritic ? spellLevel.CriticalEffects : spellLevel.Effects;
                var targetLists = new Dictionary<SpellEffect, List<AbstractFighter>>();
                var effectIndex = 0;

                foreach (var effect in effects)
                {
                    targetLists.Add(effect, new List<AbstractFighter>());

                    var targetType = spellLevel.Template.Targets != null ? spellLevel.Template.Targets.Count > effectIndex ? spellLevel.Template.Targets[effectIndex] : -1 : -1;

                    if (effect.TypeEnum != EffectEnum.UseGlyph && effect.TypeEnum != EffectEnum.UseTrap)
                    {
                        foreach (var currentCellId in CellZone.GetCells(Map, castCellId, fighter.Cell.Id, spellLevel.RangeType))
                        {
                            var fightCell = GetCell(currentCellId);
                            if (fightCell != null)
                            {
                                foreach (var fighterObject in fightCell.FightObjects.OfType<AbstractFighter>())
                                {
                                    if (targetType != -1)
                                    {
                                        // affect caster : 32
                                        if (((((targetType >> 5) & 1) == 1) && (fighter.Id != fighterObject.Id)))
                                        {
                                            if (!targetLists[effect].Contains(fighter))
                                                targetLists[effect].Add(fighter);
                                            continue;
                                        }

                                        // doesnt affect team mates : 1
                                        if (((targetType & 1) == 1) && fighter.Team == fighterObject.Team)
                                            continue;

                                        // doesnt affect the caster : 2
                                        if ((((targetType >> 1) & 1) == 1) && fighter.Id == fighterObject.Id)
                                            continue;

                                        // doesnt affect ennemies : 4
                                        if ((((targetType >> 2) & 1) == 1) && fighter.Team != fighterObject.Team)
                                            continue;

                                        // only invocation : 8
                                        if (((((targetType >> 3) & 1) == 1) && (fighterObject.Invocator == null)))
                                            continue;

                                        // doesnt affect invocs : 16
                                        if (((((targetType >> 4) & 1) == 1) && (fighterObject.Invocator != null)))
                                            continue;
                                    }

                                    if (!targetLists[effect].Contains(fighterObject))
                                        targetLists[effect].Add(fighterObject);
                                }
                            }
                        }
                    }
                    effectIndex++;
                }

                LoopState = FightLoopStateEnum.STATE_WAIT_ACTION;

                var template = SpellManager.Instance.GetTemplate(spellId);

                fighter.LaunchSpell(castCellId, spellId, spellLevel.Level, template.Sprite.ToString(), template.SpriteInfos, actionTime, () =>
                {
                    if (LoopState == FightLoopStateEnum.STATE_WAIT_END || LoopState == FightLoopStateEnum.STATE_ENDED)
                    {
                        fighter.Dispatch(WorldMessage.BASIC_NO_OPERATION());
                        return;
                    }

                    var actualChance = 0;

                    foreach (var effect in effects)
                    {
                        if (effect.Chance > 0)
                        {
                            if (Util.Next(0, 100) > (effect.Chance + actualChance))
                            {
                                actualChance += effect.Chance;
                                continue;
                            }
                            actualChance -= 100;
                        }

                        targetLists[effect].RemoveAll(affectedTarget => affectedTarget.IsFighterDead);

                        if (targetLists[effect].Count == 0)
                        {
                            var castInfos = new CastInfos(
                                                    effect.TypeEnum,
                                                    spellId,
                                                    castCellId,
                                                    effect.Value1,
                                                    effect.Value2,
                                                    effect.Value3,
                                                    effect.Chance,
                                                    effect.Duration,
                                                    fighter,
                                                    null,
                                                    spellLevel.RangeType,
                                                    0,
                                                    spellLevel.Level,
                                                    isMelee);
                            AddProcessingTarget(castInfos);
                            CurrentFighter.Team.CheckSpell(CurrentFighter, castInfos);
                        }
                        else
                        {
                            foreach (var effectTarget in targetLists[effect])
                            {
                                var castInfos = new CastInfos(
                                                    effect.TypeEnum,
                                                    spellId,
                                                    castCellId,
                                                    effect.Value1,
                                                    effect.Value2,
                                                    effect.Value3,
                                                    effect.Chance,
                                                    effect.Duration,
                                                    fighter,
                                                    effectTarget,
                                                    spellLevel.RangeType,
                                                    effectTarget.Cell.Id,
                                                    spellLevel.Level,
                                                    isMelee);
                                AddProcessingTarget(castInfos);
                                CurrentFighter.Team.CheckSpell(CurrentFighter, castInfos);
                            }
                        }

                    }

                    m_currentApCost = spellLevel.APCost;

                });
            });
        }