コード例 #1
0
        /// <summary>
        /// Возвращает тип обороны, которая может быть использована для отражения указанного наступления.
        /// </summary>
        /// <param name="offenceType"> Тип наступления. </param>
        /// <returns> Возвращает экземпляр типа обороны. </returns>
        public static DefenceType GetDefence(OffenseType offenceType)
        {
            var rawValue    = (int)offenceType;
            var defenceType = (DefenceType)rawValue;

            return(defenceType);
        }
コード例 #2
0
        public void UseOn_ArmorSavePassed_ActEfficientDecrease()
        {
            // ARRANGE
            const OffenseType offenceType           = OffenseType.Tactical;
            const int         fakeToHitDiceRoll     = 2;                        // успех в ToHit 2+
            const int         fakeArmorSaveDiceRoll = 6;                        // успех в ArmorSave 4+ при раных рангах
            const int         fakeActEfficientRoll  = 3;                        // эффективность пробрасывается D3, максимальный бросок
            const int         expectedActEfficient  = fakeActEfficientRoll - 1; // -1 даёт текущая броня

            var actUsageRandomSourceMock = new Mock <ITacticalActUsageRandomSource>();

            actUsageRandomSourceMock.Setup(x => x.RollToHit()).Returns(fakeToHitDiceRoll);
            actUsageRandomSourceMock.Setup(x => x.RollArmorSave()).Returns(fakeArmorSaveDiceRoll);
            actUsageRandomSourceMock.Setup(x => x.RollEfficient(It.IsAny <Roll>())).Returns(fakeActEfficientRoll);
            var actUsageRandomSource = actUsageRandomSourceMock.Object;

            var actUsageService = new TacticalActUsageService(
                actUsageRandomSource,
                _perkResolver,
                _sectorManager);

            var actorMock = new Mock <IActor>();

            actorMock.SetupGet(x => x.Node).Returns(new HexNode(0, 0));
            var actor = actorMock.Object;

            var armors      = new[] { new PersonArmorItem(ImpactType.Kinetic, PersonRuleLevel.Lesser, 10) };
            var monsterMock = CreateMonsterMock(armors: armors);
            var monster     = monsterMock.Object;

            // Настройка дествия
            var actScheme = new TestTacticalActStatsSubScheme
            {
                Offence = new TestTacticalActOffenceSubScheme
                {
                    Type   = offenceType,
                    ApRank = 10,
                    Impact = ImpactType.Kinetic
                }
            };

            var actMock = new Mock <ITacticalAct>();

            actMock.SetupGet(x => x.Stats).Returns(actScheme);
            var act = actMock.Object;



            // ACT
            var usedActs = new UsedTacticalActs(new[] { act });

            actUsageService.UseOn(actor, monster, usedActs);



            // ASSERT
            actUsageRandomSourceMock.Verify(x => x.RollArmorSave(), Times.Once);
            monsterMock.Verify(x => x.TakeDamage(It.Is <int>(damage => damage == expectedActEfficient)), Times.Once);
        }
コード例 #3
0
        public void UseOn_ArmorSavePassed_ActEfficientDecrease()
        {
            // ARRANGE
            const OffenseType OFFENCETYPE              = OffenseType.Tactical;
            const int         FAKE_TOHIT_DICE_ROLL     = 2;                          // успех в ToHit 2+
            const int         FAKE_ARMORSAVE_DICE_ROLL = 6;                          // успех в ArmorSave 4+ при раных рангах
            const int         FAKE_ACTEFFICIENT_ROLL   = 3;                          // эффективность пробрасывается D3, максимальный бросок
            const int         EXPECTED_ACTEFFICIENT    = FAKE_ACTEFFICIENT_ROLL - 1; // -1 даёт текущая броня

            var actUsageRandomSourceMock = new Mock <ITacticalActUsageRandomSource>();

            actUsageRandomSourceMock.Setup(x => x.RollToHit(It.IsAny <Roll>())).Returns(FAKE_TOHIT_DICE_ROLL);
            actUsageRandomSourceMock.Setup(x => x.RollArmorSave()).Returns(FAKE_ARMORSAVE_DICE_ROLL);
            actUsageRandomSourceMock.Setup(x => x.RollEfficient(It.IsAny <Roll>())).Returns(FAKE_ACTEFFICIENT_ROLL);
            var actUsageRandomSource = actUsageRandomSourceMock.Object;

            var perkResolverMock = new Mock <IPerkResolver>();
            var perkResolver     = perkResolverMock.Object;

            var actUsageService = new ActorActUsageHandler(perkResolver, actUsageRandomSource);

            var actorMock = new Mock <IActor>();

            actorMock.SetupGet(x => x.Node).Returns(new HexNode(0, 0));
            var actor = actorMock.Object;

            var armors      = new[] { new PersonArmorItem(ImpactType.Kinetic, PersonRuleLevel.Lesser, 10) };
            var monsterMock = CreateMonsterMock(armors: armors);
            var monster     = monsterMock.Object;

            // Настройка дествия
            var actScheme = new TestTacticalActStatsSubScheme
            {
                Offence = new TestTacticalActOffenceSubScheme
                {
                    Type   = OFFENCETYPE,
                    ApRank = 10,
                    Impact = ImpactType.Kinetic
                }
            };

            var actMock = new Mock <ICombatAct>();

            actMock.SetupGet(x => x.Stats).Returns(actScheme);
            var act = actMock.Object;

            var map = Mock.Of <ISectorMap>();

            // ACT
            var usedActs = new CombatActRoll(act, FAKE_ACTEFFICIENT_ROLL);

            actUsageService.ProcessActUsage(actor, monster, usedActs, map);

            // ASSERT
            actUsageRandomSourceMock.Verify(x => x.RollArmorSave(), Times.Once);
            monsterMock.Verify(x => x.TakeDamage(It.Is <int>(damage => damage == EXPECTED_ACTEFFICIENT)), Times.Once);
        }
コード例 #4
0
        /// <summary>
        /// Извлечение всех оборон актёра, способных противостоять указанному типу урона.
        /// Включая DivineDefence, противодействующий всем типам урона.
        /// </summary>
        /// <param name="targetActor"> Целевой актёр. </param>
        /// <param name="offenceType"> Тип урона. </param>
        /// <returns> Возвращает набор оборон. </returns>
        private static IEnumerable <PersonDefenceItem> GetCurrentDefences(IActor targetActor, OffenseType offenceType)
        {
            var defenceType = HitHelper.GetDefence(offenceType);

            return(targetActor.Person.CombatStats.DefenceStats.Defences
                   .Where(x => x.Type == defenceType || x.Type == DefenceType.DivineDefence));
        }
コード例 #5
0
    /**比赛中取有效技能 根据当前command*/
    public SkillInstance GetValidSkillInMatch(Command curCommand, bool isAI = false, System.Predicate <SkillInstance> filter = null)
    {
        if (curCommand == Command.None)
        {
            return(null);
        }

        PlayerState curPlayerState = m_player.m_StateMachine.m_curState;

        if (curPlayerState != null && !curPlayerState.IsCommandValid(curCommand))
        {
            return(null);
        }

        List <SkillInstance> skills   = m_cachedSkillList;
        GameMatch            curMatch = GameSystem.Instance.mClient.mCurMatch;

        PlayerState curState      = m_player.m_StateMachine.m_curState;
        bool        bIsSkillState = curState is PlayerState_Skill;

        List <SkillInstance> matchedSkills = new List <SkillInstance>();
        List <SkillInstance> toMatchSkills = new List <SkillInstance>();

        foreach (SkillInstance skillInstance in skills)
        {
            if (isAI && (Command)skillInstance.skill.action_type != curCommand)
            {
                continue;
            }
            if (!_MatchArea(curMatch, skillInstance))
            {
                continue;
            }
            if (!_MatchActionCondition(skillInstance))
            {
                continue;
            }
            if (!_MatchSkillSpecParam(skillInstance))
            {
                continue;
            }
            //has power & has vigour
            if (!_MatchStamina(skillInstance))
            {
                if (curMatch.mainRole == m_player)
                {
                    curMatch.ShowTips((Vector3)m_player.position + Vector3.up, CommonFunction.GetConstString("MATCH_TIPS_NOT_ENOUGH_STAMINA"), GlobalConst.MATCH_TIP_COLOR_RED);
                    if (isAI)
                    {
                        Debug.Log(string.Format("SkillSystem, no enough stamina for skill: {0} {1}", skillInstance.skill.id, skillInstance.skill.name));
                    }
                }
                continue;
            }
            if (isAI && filter != null && !filter(skillInstance))
            {
                continue;
            }
            toMatchSkills.Add(skillInstance);
            //precise matching
            if (!isAI && !_MatchAction(curCommand, skillInstance, false))
            {
                continue;
            }
            matchedSkills.Add(skillInstance);
        }

        if (!isAI && matchedSkills.Count == 0)
        {
            foreach (SkillInstance skillInstance in toMatchSkills)
            {
                //unprecise matching
                if (!_MatchAction(curCommand, skillInstance, true))
                {
                    continue;
                }
                matchedSkills.Add(skillInstance);
            }
        }

        //filter out shoot dunk layup and offense type
        if (!isAI && curCommand == Command.Shoot)
        {
            List <OffenseType> offenses = new List <OffenseType>();
            foreach (SkillInstance skillInstance in matchedSkills)
            {
                if (skillInstance.skill.action_type == 1 && !offenses.Contains(OffenseType.eShot))
                {
                    offenses.Add(OffenseType.eShot);
                }
                else if (skillInstance.skill.action_type == 2 && !offenses.Contains(OffenseType.eLayup))
                {
                    offenses.Add(OffenseType.eLayup);
                }
                else if (skillInstance.skill.action_type == 3 && !offenses.Contains(OffenseType.eDunk))
                {
                    offenses.Add(OffenseType.eDunk);
                }
            }
            if (offenses.Count > 0)
            {
                OffenseType type = _CalcOffenseType(m_player, offenses);
                if (type != OffenseType.eNone)
                {
                    //Debug.Log("OffenseType : " +  type );
                    for (int i = matchedSkills.Count - 1; i >= 0; i--)
                    {
                        SkillInstance skillInstance = matchedSkills[i];
                        if (skillInstance.skill.action_type != (uint)type)
                        {
                            //Debug.Log("Remove action_type : " + skillInstance.skill.action_type + " Type value: " + (uint)skillInstance.skill.action_type);
                            matchedSkills.Remove(skillInstance);
                        }
                    }
                }
            }
        }

        /*
         * if( matchedSkills.Count != 0 )
         * {
         *      Debug.Log("====matched skill===");
         *      foreach( SkillInstance instance in matchedSkills )
         *              Debug.Log("matched skill: " + instance.curAction.action_id);
         *      Debug.Log("====================");
         * }
         */

        //choose highest weight.
        SkillInstance finalSkill = null;

        finalSkill = MatchSkillByWeight(matchedSkills);
        //if( finalSkill != null )
        //	Debug.Log("final skill: " + finalSkill.curAction.action_id);

        //choose a default skill
        if (finalSkill == null && !bIsSkillState && curCommand != Command.CutIn)                //TODO: 临时针对空切特殊处理,以后修改
        {
            foreach (SkillInstance skillInstance in m_basicMatchedSkills)
            {
                if ((Command)skillInstance.skill.action_type != curCommand)
                {
                    continue;
                }
                if (!_MatchArea(curMatch, skillInstance))
                {
                    continue;
                }
                if (!_MatchActionCondition(skillInstance))
                {
                    continue;
                }
                //has power & has vigour
                if (!_MatchStamina(skillInstance))
                {
                    continue;
                }

                finalSkill = skillInstance;
                //Debug.Log("Get basic skill: ");
                break;
            }
        }
        return(finalSkill);
    }
コード例 #6
0
    OffenseType _CalcOffenseType(Player player, List <OffenseType> offenses)
    {
        GameMatch match  = GameSystem.Instance.mClient.mCurMatch;
        UBasket   basket = match.mCurScene.mBasket;

        if (basket == null)
        {
            return(OffenseType.eNone);
        }

        Dictionary <string, uint> data = player.m_finalAttrs;

        if (data == null)
        {
            Debug.LogError("Can not build player: " + player.m_name + " ,can not fight state by id: " + player.m_id);
            return(OffenseType.eNone);
        }

        PlayGround playGround = match.mCurScene.mGround;

        Debugger.Instance.m_steamer.message = "Attr of offense type: ";
        Dictionary <OffenseType, IM.Number> lstOffenseRates = new Dictionary <OffenseType, IM.Number>();

        foreach (OffenseType type in offenses)
        {
            Area      area        = Area.eInvalid;
            IM.Number offenseRate = IM.Number.zero;

            if (type == OffenseType.eLayup)
            {
                area = playGround.GetLayupArea(player);
            }
            else if (type == OffenseType.eDunk)
            {
                area = playGround.GetDunkArea(player);
            }
            else if (type == OffenseType.eShot)
            {
                area = playGround.GetArea(player);
            }

            if (area == Area.eNear)
            {
                if (type == OffenseType.eLayup)
                {
                    offenseRate = new IM.Number((int)data["layup_near"]);
                }
                else if (type == OffenseType.eDunk)
                {
                    offenseRate = new IM.Number((int)data["dunk_near"]);
                }
                else if (type == OffenseType.eShot)
                {
                    offenseRate = new IM.Number((int)data["shoot_near"]);
                }
            }
            else if (area == Area.eMiddle)
            {
                if (type == OffenseType.eShot)
                {
                    offenseRate = new IM.Number((int)data["shoot_middle"]);
                }
                else if (type == OffenseType.eDunk)
                {
                    offenseRate = new IM.Number((int)data["dunk_middle"]);
                }
                else if (type == OffenseType.eLayup)
                {
                    offenseRate = new IM.Number((int)data["layup_middle"]);
                }
            }
            else if (area == Area.eFar)
            {
                if (type == OffenseType.eShot)
                {
                    offenseRate = new IM.Number((int)data["shoot_far"]);
                }
            }
            lstOffenseRates.Add(type, offenseRate);
            Debugger.Instance.m_steamer.message += type + " " + offenseRate + " ";
        }

        IM.Number totalValue = IM.Number.zero;
        foreach (KeyValuePair <OffenseType, IM.Number> keyvalue in lstOffenseRates)
        {
            totalValue += keyvalue.Value;
        }

        IM.Number rateAdjust = IM.Number.zero;
        if (lstOffenseRates.Count > 1 && lstOffenseRates.ContainsKey(OffenseType.eDunk))
        {
            rateAdjust = GameSystem.Instance.DunkRateConfig.GetRate(m_player.m_position);
        }
        Debugger.Instance.m_steamer.message += "\nDunk adjustment: " + rateAdjust;

        List <OffenseType> keys = new List <OffenseType>(lstOffenseRates.Keys);

        foreach (OffenseType key in keys)
        {
            IM.Number rate = lstOffenseRates[key] / totalValue;
            if (lstOffenseRates.Count > 1)
            {
                if (key == OffenseType.eDunk)
                {
                    rate += rateAdjust;
                }
                else
                {
                    rate -= rateAdjust / (lstOffenseRates.Count - 1);
                }
            }

            lstOffenseRates[key] = rate;
            Debugger.Instance.m_steamer.message += " " + key + ": " + rate;
        }

        IM.Number value = IM.Random.value;
        Debugger.Instance.m_steamer.message += " Random: " + value + "\n";

        OffenseType validType = OffenseType.eShot;

        IM.Number curValue = IM.Number.zero;
        foreach (KeyValuePair <OffenseType, IM.Number> keyvalue in lstOffenseRates)
        {
            IM.Number rate = keyvalue.Value;

            curValue += rate;

            if (value > curValue)
            {
                continue;
            }
            validType = keyvalue.Key;
            break;
        }
        return(validType);
    }