public override BattleActionResult execute(BattleCreature source, List <BattleCreature> targets, double amp, double hitChanceMultiplier, double alteredChanceForSecondary)
    {
        bool interactableTargets  = false;
        int  damageDealt          = 0;
        List <BattleCreature> hit = new List <BattleCreature>();

        foreach (BattleCreature target in targets)
        {
            if (target.isInteractable())
            {
                interactableTargets = true;
                if (RandomUtils.checkOdds(chanceToHit * (1 + hitChanceMultiplier)))
                {
                    double typeMultiplier = damageType.getDamageMultiplierVs(target.creature.getCreatureTypes());

                    int damage = DamageUtils.calculateDamage(basePower * typeMultiplier,
                                                             source.creature.getStats(),
                                                             target.creature.getStats());
                    damageDealt += damage;
                    target.changeHealth(damage);
                    hit.Add(target);
                }
            }
        }

        return(new DamageBattleActionResult(interactableTargets, targets.Count > 0, damageDealt, damageType, source, targets, hit));
    }
예제 #2
0
    public virtual void Awake()
    {
        hittedObjects = new List <GameObject>();
        GameObject gameManager = GameObject.FindGameObjectWithTag("GameController");

        commonUtils = gameManager.GetComponentInChildren <CommonUtils>();
        damageUtils = gameManager.GetComponentInChildren <DamageUtils>();
    }
예제 #3
0
        public bool Attack(BattleUnitsStack target)
        {
            if (_state != BattleState.InGame)
            {
                return(false);
            }

            var source = GetCurrentStack();

            if (source.GetArmy() == target.GetArmy())
            {
                return(false);
            }

            var hitPoints = DamageUtils.CalcDamageHitPoints(source, target);

            // Fire before attack event
            var beforeAttackEventArgs = new BeforeAttackEventArgs(source, target, hitPoints);

            EventBus.OnBeforeAttack(this, beforeAttackEventArgs);
            if (beforeAttackEventArgs.Cancel)
            {
                return(false);
            }

            hitPoints = beforeAttackEventArgs.HitPoints;

            target.Damage(hitPoints);

            // Fire after attack event
            EventBus.OnAfterAttack(this, new AfterAttackEventArgs(source, target, hitPoints));

            if (target.IsAlive() && !target.IsAnswered())
            {
                var answerHitPoints = DamageUtils.CalcDamageHitPoints(target, source);

                // Fire before answer event
                var beforeAnswerEventArgs = new BeforeAnswerEventArgs(source, target, answerHitPoints);
                EventBus.OnBeforeAnswer(this, beforeAnswerEventArgs);

                if (!beforeAnswerEventArgs.Cancel)
                {
                    answerHitPoints = beforeAnswerEventArgs.HitPoints;

                    source.Damage(answerHitPoints);
                    target.SetAnswered(beforeAnswerEventArgs.IsAnswered);

                    // Fire after answer event
                    EventBus.OnAfterAnswer(this,
                                           new AfterAnswerEventArgs(source, target, hitPoints, beforeAnswerEventArgs.IsAnswered));
                }
            }

            NextTurn();

            return(true);
        }
예제 #4
0
    /// <summary>
    /// 预先判断该武将是否会被打死
    /// </summary>
    /// <param name="attackHero">进攻方数据</param>
    /// <param name="hurtHero">被攻击方数据</param>
    /// <returns></returns>
    public static bool checkRoleDead(HeroVo attackHero, HeroVo hurtHero)
    {
        int damage = DamageUtils.mathDamage(attackHero, hurtHero);

        hurtHero.tempHp -= damage;
        if (hurtHero.tempHp < 0)
        {
            hurtHero.tempHp = 0;
        }
        return((bool)(hurtHero.tempHp <= 0));
    }
예제 #5
0
    /// <summary>
    /// 攻击动作结束
    /// </summary>
    private void attackCompleteHandler()
    {
        int damage = DamageUtils.mathDamage(this.heroVo, this.targetBr.heroVo);

        //范围伤害
        this.rangeHurt(damage);
        //目标受伤
        this.targetBr.hurt(damage);
        //移动回原位
        this.moveAct(this.startPos, true, moveToTargetComplete);
    }
예제 #6
0
    Projectile InstantiateProjectile()
    {
        Contract.Assert(ProjectileTemplate != null);
        Projectile instantiatedProjectile = Instantiate(ProjectileTemplate, ComputeMuzzleWorldPosition3D(), transform.rotation);

        if (!instantiatedProjectile)
        {
            Debug.LogError($"Failed to instantiate projectile of class \"{ProjectileTemplate?.GetType()}\"");
            return(null);
        }
        DamageUtils.SetInstigatorForDamageSubsystemComponents(instantiatedProjectile.gameObject, instigator);
        return(instantiatedProjectile);
    }
예제 #7
0
    private void effectMoveCompleteHandler(GameObject effectGo)
    {
        this._isAttacking = false;
        this.isMoveBack   = true;
        GameObject.Destroy(effectGo);
        effectGo = null;
        //执行伤害
        int damage = DamageUtils.mathDamage(this.heroVo, this.targetBr.heroVo);

        //范围伤害
        this.rangeHurt(damage);
        //目标受伤
        this.targetBr.hurt(damage);
        this.moveToTargetComplete();
    }
    /// <summary>
    /// 获取被攻击目标(普通攻击)
    /// </summary>
    /// <param name="isMyTeam">是否是我方队伍攻击</param>
    private void getAttackTarget(bool isMyTeam)
    {
        List <BattleRole> targetList;
        List <BattleRole> targetAry;

        if (isMyTeam)
        {
            targetList = this.targetTeam;
            targetAry  = this.targetTeamAry;
        }
        else
        {
            targetList = this.myTeam;
            targetAry  = this.myTeamAry;
        }
        this.initRoleAttackData(isMyTeam);
        int count       = this.attackList.Count;
        int targetCount = targetList.Count;
        //关闭列表 存放一次进攻后血量为0的角色
        List <int> closeList = new List <int>();

        for (int i = 0; i < count; ++i)
        {
            BattleRole attackRole = this.attackList[i];
            float      dis        = float.MaxValue;
            int        index      = -1;
            //查找距离最近的对手
            for (int j = 0; j < targetCount; ++j)
            {
                BattleRole targetBr = targetList[j];
                if (closeList.IndexOf(targetBr.index) != -1)
                {
                    continue;
                }
                float curDis = (attackRole.posIndexVector - targetBr.posIndexVector).sqrMagnitude;
                if (curDis < dis)
                {
                    index = j;
                    dis   = curDis;
                }
            }
            //计算被攻击者剩余血量 如果进攻后血量为0 则放入关闭列表中
            if (index != -1)
            {
                BattleRole chooseBr = targetList[index];
                if (DamageUtils.checkRoleDead(attackRole.heroVo, chooseBr.heroVo))
                {
                    closeList.Add(chooseBr.index);
                }
                //将目标存放进去
                attackRole.setAttackTarget(chooseBr);
                if (attackRole.heroVo.attackRangeType != 0)
                {
                    List <BattleRole> rangeAttackRoleList = new List <BattleRole>();
                    bool   isHorizontal  = attackRole.heroVo.attackRangeType == BattleConstant.ATTACK_RANGE_HORIZONTAL;
                    int [] rangeIndexAry = BattleFormation.getPosIndexByDirection(isHorizontal, chooseBr.index);
                    //遍历posIndexAry 剔除 chooseBr.index 和 closeList中的索引
                    //判断checkRoleDead 将血为空的添加进col
                    int length = rangeIndexAry.Length;
                    for (int j = 0; j < length; j++)
                    {
                        int rangeIndex = rangeIndexAry[j];
                        if (rangeIndex == chooseBr.index ||
                            closeList.IndexOf(rangeIndex) != -1)
                        {
                            continue;
                        }
                        BattleRole rangeAttackRole = targetAry[rangeIndex];
                        if (rangeAttackRole != null && !rangeAttackRole.isDeaded)
                        {
                            if (DamageUtils.checkRoleDead(attackRole.heroVo, rangeAttackRole.heroVo))
                            {
                                closeList.Add(chooseBr.index);
                            }
                            rangeAttackRoleList.Add(rangeAttackRole);
                        }
                    }
                    attackRole.setAttackRangeTarget(rangeAttackRoleList);
                }
                attackRole.isAttacking = true;
            }
        }
    }
예제 #9
0
    public void Update()
    {
        if (projectiles.Count <= 0)         // If nobodys shooting, dont bother getting/setting particles
        {
            return;
        }

        numAlive = pS.GetParticles(particles);

        for (int i = 0; i < projectiles.Count; i++)
        {
            Projectile proj = projectiles[i];

            // TODO: Also do positional hit detection for situations where a projectile slips into a unit without raycast hitting the outer shell (ie rotation)
            // Raycast according to movement path
            RaycastHit hit;
            if (Physics.Raycast(proj.position, proj.direction, out hit, proj.GetSpeed() * Time.deltaTime, mask))
            {
                int  projTeam = proj.GetFrom().Team;
                Unit unit     = null;
                bool hitSelf  = false;
                if (hit.collider.transform.parent)                 // Is this a unit?
                {
                    unit = hit.collider.transform.parent.GetComponent <Unit>();
                    if (unit)                       // Is this a unit?
                    {
                        if (unit != proj.GetFrom()) // If we hit a unit and its not us, damage it
                        {
                            Status status = proj.GetStatus();
                            if (status != null)
                            {
                                if (status.statusType == StatusType.SuperlaserMark)
                                {
                                    status.SetTimeLeft(proj.GetDamage() < gameRules.ABLY_superlaserDmgByStacks[1] ? proj.GetDamage() * SL_turretMult : proj.GetDamage() * SL_superlaserMult);                                     // Store damage in timeLeft field of status
                                }
                                unit.AddStatus(status);
                            }

                            // If we hit an ally, do reduced damage because it was an accidental hit
                            bool doFullDamage = DamageUtils.IgnoresFriendlyFire(proj.GetDamageType()) || unit.Team != projTeam;

                            DamageResult result = unit.Damage(doFullDamage ? proj.GetDamage() : proj.GetDamage() * gameRules.DMG_ffDamageMult, proj.CalcRange(), proj.GetDamageType());

                            if (result.lastHit && proj.GetFrom())
                            {
                                proj.GetFrom().AddKill(unit);
                            }
                        }
                        else
                        {
                            // Ignore this collision
                            hitSelf = true;
                        }
                    }
                }

                // Don't do anything if we are passing through the unit that fired us
                if (!hitSelf)
                {
                    proj.position         = hit.point - proj.direction * gameRules.PRJ_hitOffset;             // Move to contact point
                    particles[i].position = proj.position;

                    particles[i].remainingLifetime = 0;     // Destroy particle
                    toDelete.Add(proj);                     // Destroy projectile

                    Vector3 direction = ((-proj.direction + hit.normal) / 2).normalized;

                    if (unit)
                    {
                        if (unit.GetShields().x > 0)                         // Shielded
                        {
                            vfx.SpawnEffect(VFXType.Hit_Absorbed, proj.position, direction, projTeam);
                        }
                        else                         // Normal hit
                        {
                            vfx.SpawnEffect(VFXType.Hit_Normal, proj.position, direction, projTeam);
                        }
                    }
                    else                     // Terrain
                    {
                        vfx.SpawnEffect(VFXType.Hit_Normal, proj.position, direction, projTeam);
                    }
                    continue;
                }
            }            //if Raycast

            proj.UpdateTimeAlive(Time.deltaTime);
            if (proj.GetTimeAlive() > gameRules.PRJ_maxTimeAlive)
            {
                particles[i].remainingLifetime = 0; // Destroy particle
                toDelete.Add(proj);                 // Destroy projectile
            }

            proj.position += proj.direction * proj.GetSpeed() * Time.deltaTime; // Update projectile position

            particles[i].position = proj.position;                              // Sync particle with projectile
            particles[i].velocity = proj.direction;

            //Debug.DrawRay(proj.position, proj.direction, Color.red);
        }        //for

        for (int i = 0; i < toDelete.Count; i++)
        {
            //Instantiate(test, toDelete[i].position, Quaternion.identity);
            projectiles.Remove(toDelete[i]);
        }
        toDelete.Clear();

        //newProjectilesThisFrame = 0;
        pS.SetParticles(particles, numAlive);
    }     //Update()
예제 #10
0
    // Called immediately after a hitscan is spawned
    float Raycast(Hitscan scan)
    {
        // Raycast according to start position, direction, and range
        RaycastHit hit;

        if (Physics.Raycast(scan.startPosition, scan.direction, out hit, scan.GetRange(), mask))
        {
            int  scanTeam = scan.GetFrom().Team;
            Unit unit     = null;
            bool hitSelf  = false;
            if (hit.collider.transform.parent)             // Is this a unit?
            {
                unit = hit.collider.transform.parent.GetComponent <Unit>();
                if (unit)                       // Is this a unit?
                {
                    if (unit != scan.GetFrom()) // If we hit a unit and its not us, damage it
                    {
                        Status status = scan.GetStatus();
                        if (status != null)
                        {
                            if (status.statusType == StatusType.SuperlaserMark)
                            {
                                status.SetTimeLeft(scan.GetDamage() < gameRules.ABLY_superlaserDmgByStacks[1] ? scan.GetDamage() * SL_turretMult : scan.GetDamage() * SL_superlaserMult);                                 // Store damage in timeLeft field of status
                            }
                            unit.AddStatus(status);
                        }

                        float actualRange = (hit.point - scan.startPosition).magnitude;
                        // If we hit an ally, do reduced damage because it was an accidental hit
                        bool doFullDamage = DamageUtils.IgnoresFriendlyFire(scan.GetDamageType()) || unit.Team != scanTeam;

                        DamageResult result = unit.Damage(doFullDamage ? scan.GetDamage() : scan.GetDamage() * gameRules.DMG_ffDamageMult, actualRange, scan.GetDamageType());

                        if (result.lastHit && scan.GetFrom())
                        {
                            scan.GetFrom().AddKill(unit);
                        }
                    }
                    else
                    {
                        // Ignore this collision
                        hitSelf = true;                         // TODO: Adapt friendly fire code for raycasting here
                    }
                }
            }

            Vector3 endPosition = (hit.point - scan.direction * gameRules.PRJ_hitOffset);

            // Don't do anything if we are passing through the unit that fired us
            if (!hitSelf)
            {
                if (unit)
                {
                    if (unit.GetShields().x > 0)                     // Shielded
                    {
                        vfx.SpawnEffect(VFXType.Hit_Absorbed, endPosition, -scan.direction, scanTeam);
                    }
                    else                     // Normal hit
                    {
                        vfx.SpawnEffect(VFXType.Hit_Normal, endPosition, -scan.direction, scanTeam);
                    }
                }
                else                 // Terrain
                {
                    vfx.SpawnEffect(VFXType.Hit_Normal, endPosition, -scan.direction, scanTeam);
                }
                return((scan.startPosition - endPosition).magnitude); // Return actual length of hitscan
            }
        }                                                             //if Raycast
        return(scan.GetRange());
    }