Пример #1
0
    protected override Vector3 CalcAdjDirection(ITargetable targ)
    {
        Unit unit = targ as Unit;         // Only lead target against units

        // How far to aim ahead given how long it would take to reach current position
        // current target position + target velocity * time for projectile to reach current target position
        Vector3 offsetTarget = targ.GetPosition();

        if (unit)
        {
            offsetTarget += unit.GetVelocity() * ((targ.GetPosition() - transform.position).magnitude / projTemplate.GetSpeed());
        }

        // How far to aim ahead given how long it would take to reach predicted position
        // current target position + target velocity * time for projectile to reach predicted target position
        Vector3 offsetTargetAdj = targ.GetPosition();

        if (unit)
        {
            offsetTargetAdj += unit.GetVelocity() * ((offsetTarget - transform.position).magnitude / projTemplate.GetSpeed());
        }

        Vector3 difference = offsetTargetAdj - transform.position;

        // Visuals
        if (parentUnit.printInfo)
        {
            Debug.DrawLine(targ.GetPosition(), transform.position, Color.red);
            Debug.DrawLine(offsetTarget, transform.position, Color.green);
            Debug.DrawLine(offsetTargetAdj, transform.position, Color.blue);
        }

        return(difference.normalized);
    }
Пример #2
0
        public override void Update(float dt)
        {
            if (currentEnemy == null)
            {
                List <ITargetable> targets = map.GetTargetsInRange(position, info.range);
                for (int x = 0; x < targets.Count; x++)
                {
                    if (targets[x] == this)
                    {
                        continue;
                    }
                    if (targets[x].GetTeam() != GetTeam())
                    {
                        currentEnemy = targets[x];
                    }
                }
            }
            else
            {
                if (CanAttack(currentEnemy))
                {
                    atkCooldown = 1.0f / info.attackSpeed;
                    map.Attacks.Add(new Attack(map, DamageType.Physical, info.attack, info.armorPen, position, this, currentEnemy, 60));
                }
                if (currentEnemy.IsDead() || (currentEnemy.GetPosition() - GetPosition()).LengthSquared() < info.range * info.range)
                {
                    currentEnemy = null;
                }
            }
            atkCooldown -= dt;

            base.Update(dt);
        }
Пример #3
0
    float ComparisonWeight(ITargetable x)
    {
        float distanceWeight = Vector3.Distance(transform.position, x.GetPosition()) / range; // distanceWeight is always 0 to 1
        int   typeWeight     = x.GetTargetType() == preferredTargetType ? 0 : 1;              // Move weight out of 0 to 1 range if it is not our preferred type

        return(distanceWeight + typeWeight);                                                  // Always targets the closest preferred target. Only targets a non-preferred target if a preferred target is not present.
    }
Пример #4
0
        public void AddToPartitioning(ITargetable target)
        {
            Vector3 position = target.GetPosition();
            int     x        = (int)(position.X / PartitioningDensity);
            int     y        = (int)(position.Z / PartitioningDensity);

            TargetPartitioning[x, y].Add(target);
        }
Пример #5
0
        public void RemoveFromPartitioning(ITargetable target)
        {
            Vector3 position = target.GetPosition();
            int     x        = (int)(position.X / PartitioningDensity);
            int     y        = (int)(position.Z / PartitioningDensity);

            TargetPartitioning[x, y].Remove(target);
        }
Пример #6
0
        public void AttackUpdate(float dt)
        {
            targetPos = currentEnemy.GetPosition();
            Vector3 diff   = currentEnemy.GetPosition() - champion.GetPosition();
            float   length = diff.Length();

            diff /= length;
            if (champion.InRange(currentEnemy))
            {
                champion.Attack(currentEnemy);
                targetPos = champion.GetPosition();
            }
            if (currentEnemy.IsDead())
            {
                currentEnemy = null;
                state        = TestControllerState.Laning;
            }
        }
Пример #7
0
    bool IsValid(ITargetable potentialTarget)
    {
        // Valid distance
        float sqrDistance = !IsNull(potentialTarget) ? (potentialTarget.GetPosition() - parentUnit.transform.position).sqrMagnitude : 0; // Check distance between us and the target // TODO: Maybe check from the parent unit's position?
        // Valid direction
        Vector3 dir = !IsNull(potentialTarget) ? CalcAdjDirection(potentialTarget) : transform.forward;                                  // direction used elsewhere to check if aimed at target or not

        bool valid = false;

        // Have target, its in range, the look rotation is within limits, it is visible to our team
        if (!IsNull(potentialTarget) && sqrDistance <= range * range && ValidRotationHorizontal(CalcLookRotation(dir)) && potentialTarget.GetVisibleTo(parentUnit.GetTeam()))
        {
            valid = true;
        }
        else
        {
            valid = false;
        }

        return(valid);
    }
Пример #8
0
        public void Update(float dt)
        {
            if (target != null)
            {
                targetPosition = target.GetPosition();
            }
            Vector3 diff   = targetPosition - position;
            float   length = diff.Length();

            diff     /= length;
            position += diff * dt * Speed;

            if (target != null && target.IsDead())
            {
                map.Attacks.Remove(this);
                return;
            }

            if (target != null && length < 1)
            {
                map.Attacks.Remove(this);
                switch (type)
                {
                case DamageType.Physical: target.TakePhysDmg(damage, pen); break;

                case DamageType.Magical: target.TakeMagDmg(damage, pen); break;
                }
                if (target.IsDead())
                {
                    if (attacker != null)
                    {
                        attacker.ReceiveGold(target.GoldValue);
                        attacker.ReceiveXP(target.ExpValue);
                    }
                }
            }
        }
Пример #9
0
    public void SpawnHitscan(Hitscan temp, Vector3 position, Vector3 direction, Unit from, Status onHit, ITargetable goal)
    {
        Hitscan scan = new Hitscan(temp);

        scan.startPosition = position;
        scan.direction     = direction;
        scan.SetFrom(from);
        scan.SetStatus(onHit);
        //hitscans.Add(scan);
        int index = IndexFromHitscanType(temp.GetHitscanType());

        bool noGoal = IsNull(goal);

        // Raycast or do damage immediately. Use actual distance / hit information to inform visuals
        Vector3 dif    = noGoal ? Vector3.zero : (position - goal.GetPosition());
        float   length = noGoal ? Raycast(scan) : dif.magnitude;

        if (!noGoal)         // Has goal, do damage manually
        {
            goal.Damage(scan.GetDamage(), length, scan.GetDamageType());
            vfx.SpawnEffect(VFXType.Hit_Near, position + direction * length, direction, scan.GetFrom().GetTeam());
        }

        Vector3 size = new Vector3(pS[index].main.startSizeX.constant, length, 1);

        EmitParams param = new EmitParams()
        {
            position    = position,
            velocity    = direction * directionMult,
            startSize3D = size,
            //startColor = Random.value * Color.red + Random.value * Color.green + Random.value * Color.blue,
            startLifetime = scan.GetLifetime()             // 2x just in case. Particles dying prematurely is the worst thing that could happen to this system
        };

        pS[index].Emit(param, 1);
    }
Пример #10
0
    bool CheckFriendlyFire()
    {
        if (IsNull(target))
        {
            return(false);
        }

        // We know how many potential collisions we can have with the parent unit's colliders, so we will cast multiple rays in succession to skip past the collisions that we want to ignore
        // RaycastAll will not work in this case because it will pass through everything, rather than only passing through the parent unit's colliders and stopping on the first collision after them
        Collider[] cols = parentUnit.GetComponentsInChildren <Collider>();

        // First, try to raycast and hope we don't hit ourselves
        Vector3    forward = GetForward();
        RaycastHit hit;
        // If we are targeting a fighter and willing to aim at an ally unit hoping to hit an enemy fighter, we will check for FF in a shorter distance
        float checkDistance = (riskFFAgainstFighters && !target.HasCollision()) ? Vector3.Distance(firePos.position, target.GetPosition()) : range * gameRules.PRJ_friendlyFireCheckRangeMult;
        float offset        = 0.02f;  // How much we move in towards our first raycast hit location to make sure the next raycast is technically inside the collider we hit the first time around

        if (Physics.Raycast(firePos.position, forward, out hit, checkDistance, gameRules.collisionLayerMask))
        {
            if (parentUnit.printInfo)
            {
                Debug.DrawLine(firePos.position, firePos.position + forward * checkDistance, Color.magenta, 2);
            }
            // Is it a unit? This could be either self-detection or hitting a different unit.
            Transform parent = hit.collider.transform.parent;
            Unit      unit   = parent ? parent.GetComponent <Unit>() : null;
            if (unit)
            {
                if (unit.Team == parentUnit.GetTeam())
                {
                    // If we hit a non-parent teammate, immediately return false.
                    if (unit != parentUnit)
                    {
                        return(false);
                    }
                    else
                    {
                        // Here's the fun part. We have to try to brute-force through the parent unit's colliders
                        for (int i = 0; i < cols.Length; i++)
                        {
                            // Start where the last raycast left off, plus moved in a little bit to make sure we dont hit the same collider again
                            if (Physics.Raycast(hit.point + forward * offset, forward, out hit, checkDistance, gameRules.collisionLayerMask))
                            {
                                if (parentUnit.printInfo)
                                {
                                    Debug.DrawLine(firePos.position, firePos.position + forward * checkDistance, Color.magenta, 2);
                                }

                                parent = hit.collider.transform.parent;
                                unit   = parent ? parent.GetComponent <Unit>() : null;
                                if (unit)
                                {
                                    if (unit.Team == parentUnit.GetTeam())
                                    {
                                        // If we hit a non-parent teammate, immediately return false.
                                        if (unit != parentUnit)
                                        {
                                            return(false);
                                        }
                                        // If we hit the parent unit, the hit.point from this raycast will be used by the next raycast as a starting point
                                    }                                     // teammate 2
                                    else                                  // enemy
                                    {                                     // Hit an enemy before an ally unit, no reason to continue checking
                                        return(true);
                                    }
                                }                                 // unit 2
                                else
                                {
                                    return(false);
                                }
                            }     // second raycast
                        }
                    }             // parent
                }                 // teammate
                else              // enemy
                {                 // Hit an enemy before an ally unit, no reason to continue checking
                    return(true);
                }
            }             // unit
            else
            {
                return(false);
            }
        }         // first raycast
        return(true);
    }
Пример #11
0
        public override void Update(float dt)
        {
            List <ITargetable> targets = map.GetTargetsInRange(GetPosition(), info.viewRadius);

            for (int x = 0; x < targets.Count; x++)
            {
                if (targets[x] == this)
                {
                    continue;
                }
                if (currentEnemy == null && targets[x].GetTeam() != GetTeam() && targets[x].IsTargetable(GetTeam()))
                {
                    currentEnemy = targets[x];
                }
                Vector3 diff   = targets[x].GetPosition() - GetPosition();
                float   length = diff.Length();
                diff /= length;
                if (length < 10 && length != 0)
                {
                    Move(-diff * dt);
                }
            }

            if (currentEnemy == null)
            {
                targetPos = nextTarget;
                Vector3 diff   = nextTarget - GetPosition();
                float   length = diff.Length();
                diff /= length;
                if (length < 5)
                {
                    targetID++;
                    if (targetID >= lane.Waypoints.Length)
                    {
                        targetID = lane.Waypoints.Length - 1;
                    }
                    nextTarget = lane.Waypoints[targetID];
                }
            }
            else
            {
                targetPos = currentEnemy.GetPosition();
                Vector3 diff   = currentEnemy.GetPosition() - GetPosition();
                float   length = diff.Length();
                diff /= length;
                if (length < info.range)
                {
                    Attack(currentEnemy);
                    targetPos = GetPosition();
                }
                else
                {
                    ITargetable test = GetClosestEnemy();
                    if (test != null)
                    {
                        currentEnemy = test;
                    }
                }
                if (currentEnemy.IsDead() || length > info.viewRadius)
                {
                    currentEnemy = null;
                }
            }

            Vector3 tp;

            if (evade)
            {
                tp = evasionTarget;
            }
            else
            {
                tp = targetPos;
            }

            Vector3 tdiff   = tp - GetPosition();
            float   tlength = tdiff.Length();

            tdiff /= tlength;
            if (tlength > 0)
            {
                Vector3 predictedPosition = GetPosition() + tdiff * info.movespeed * 0.5f;

                if (map.InCollision(predictedPosition))
                {
                    evade = true;
                    ICollidable collider = map.GetCollider(predictedPosition);
                    if (collider != null)
                    {
                        Vector3 vertex = collider.Bounds.GetEdgeToCircumvent(GetPosition(), tp);
                        Vector3 dir    = vertex - collider.Bounds.Center;
                        dir          /= dir.Length();
                        evasionTarget = vertex + dir * Size;
                    }
                }

                Move(tdiff * info.movespeed * dt);
            }

            if (evade && tlength < 1)
            {
                evade = false;
            }

            base.Update(dt);
        }
Пример #12
0
 public bool CanAttack(ITargetable target)
 {
     Vector3 diff = target.GetPosition() - GetPosition();
     return atkCooldown < 0 && diff.LengthSquared() < info.range*info.range;
 }
Пример #13
0
        public bool CanAttack(ITargetable target)
        {
            Vector3 diff = target.GetPosition() - GetPosition();

            return(atkCooldown < 0 && diff.LengthSquared() < info.range * info.range);
        }
Пример #14
0
 public void RemoveFromPartitioning(ITargetable target)
 {
     Vector3 position = target.GetPosition();
     int x = (int)(position.X / PartitioningDensity);
     int y = (int)(position.Z / PartitioningDensity);
     TargetPartitioning[x, y].Remove(target);
 }
Пример #15
0
 public void AddToPartitioning(ITargetable target)
 {
     Vector3 position = target.GetPosition();
     int x = (int)(position.X / PartitioningDensity);
     int y = (int)(position.Z / PartitioningDensity);
     TargetPartitioning[x, y].Add(target);
 }
Пример #16
0
 /// <summary>
 /// Takes into account how this turret type deals damage to optimize aiming.
 /// </summary>
 /// <returns></returns>
 protected virtual Vector3 CalcAdjDirection(ITargetable targ)
 {
     return((targ.GetPosition() - transform.position).normalized);
 }
Пример #17
0
 public bool InRange(ITargetable target)
 {
     return (this.position - target.GetPosition()).Length() < info.range + this.GetSize()/2 + target.GetSize()/2;
 }
Пример #18
0
 public bool InRange(ITargetable target)
 {
     return((this.position - target.GetPosition()).Length() < info.range + this.GetSize() / 2 + target.GetSize() / 2);
 }