Exemplo n.º 1
0
    void assignViolentWork(Unit_local worker)
    {
        UnitRelativePositionSorter comparer = new UnitRelativePositionSorter(worker.transform.position);

        comparer.DistanceMode();
        remainingToPerish.Sort(comparer);
        List <Unit> inRange        = new List <Unit>();
        Unit        closestHoplite = null;
        Unit        closestDog     = null;
        Unit        closestCourier = null;

        for (int i = 0; i < remainingToPerish.Count && comparer.DistanceOf(remainingToPerish[i]) <= worker.stats.weapon_range; ++i)
        {
            inRange.Add(remainingToPerish[i]);
            if (closestHoplite == null && remainingToPerish[i].name.Contains("hoplite"))
            {
                closestHoplite = remainingToPerish[i];
            }
            else if (closestDog == null && remainingToPerish[i].name.Contains("dog"))
            {
                closestDog = remainingToPerish[i];
            }
            else if (closestCourier == null && remainingToPerish[i].name.Contains("courier"))
            {
                closestCourier = remainingToPerish[i];
            }
        }
        Unit targetUnit;

        if (closestHoplite != null)
        {
            targetUnit = closestHoplite;
        }
        else if (closestDog != null)
        {
            targetUnit = closestDog;
        }
        else if (closestCourier != null)
        {
            targetUnit = closestCourier;
        }
        else
        {
            targetUnit = remainingToPerish[0];
        }
        Task result = new Task(worker, Task.actions.attack, targetUnit.transform.position, targetUnit);

        worker.work(result);
        assignments.Add(result);
    }
Exemplo n.º 2
0
    public void MoveCohort(Vector2 goTo, Unit_local toFollow)
    {
        Stop();
        masterTask = new Task(null, Task.actions.move, goTo, toFollow);
        List <Unit_local> thisIsToSupressWarnings = new List <Unit_local>(members);
        float             weakLinkETA             = 0;

        foreach (Unit_local toMove in thisIsToSupressWarnings)
        {
            if (toMove.stats.isMobile == false)
            {
                throw new InvalidOperationException("Cannot move a cohort that includes immobile members. Units should be sorted out in Gamestate.CombineActiveCohorts.");
            }
            else
            {
                float thisMoversETA = Vector2.Distance(toMove.transform.position, goTo) / toMove.stats.speed;
                if (thisMoversETA > weakLinkETA)
                {
                    weakLinkETA = thisMoversETA;
                }
            }
        }
        UnitRelativePositionSorter vsGoTo = new UnitRelativePositionSorter(goTo);

        vsGoTo.DirectionMode();
        List <Unit_local> unitsByDirection = new List <Unit_local>(members);

// This is a list of units sorted by their compass-direction from the destination point.
        (unitsByDirection).Sort(vsGoTo);
        vsGoTo.DistanceMode();
        List <Unit_local> unitsByDistance = new List <Unit_local>(members);

        unitsByDistance.Sort(vsGoTo);
// Units are removed from unitsByDirection (and unitsByDistance) as they are assigned to groups, so this is a way of saying "while there are unassigned units."
        while (unitsByDirection.Count > 0)
        {
// We take the current closest unit to the distination... (previous cycles of grouping will have removed closer units)
            Unit_local        sliceLeader                   = unitsByDistance[0];
            int               leaderDirectionIndex          = unitsByDirection.IndexOf(sliceLeader);
            float             leaderDistanceFromDestination = vsGoTo.DistanceOf(sliceLeader);
            float             leaderRadius                  = sliceLeader.bodyCircle.radius;
            int               totalUnaccounted              = unitsByDirection.Count;
            List <Unit_local> slice = new List <Unit_local> {
                sliceLeader
            };
// That unit will be the group leader. We check the units clockwise and counter-clockwise from its' position on the imaginary circle of unit positions aronud the destination.
            for (int sign = -1; sign <= 1 && slice.Count < unitsByDirection.Count; sign = sign + 2)
            {
                // this is a loop-breaker variable
                for (int indexOffset = sign; indexOffset < 1000; indexOffset += sign)
                {
                    Unit_local inQuestion = unitsByDirection[(leaderDirectionIndex + indexOffset + totalUnaccounted) % totalUnaccounted];
// These are all in radians...
                    float directionOfLeader       = vsGoTo.DirectionOf(sliceLeader);
                    float directionInQuestion     = vsGoTo.DirectionOf(inQuestion);
                    float circumferencialDistance = Mathf.Abs(directionOfLeader - directionInQuestion);
                    circumferencialDistance = Mathf.Min(circumferencialDistance, 2 * Mathf.PI - circumferencialDistance);
// ...until here, when circumferentialDistance becomes a measure of real distance.
                    circumferencialDistance *= leaderDistanceFromDestination;
// In both directions, we stop checking when the next-closest (by direction) unit doesn't fall within the shadow cast by the leader, if you imagine the destination as a light source.
                    if (circumferencialDistance < leaderRadius && inQuestion != sliceLeader)
                    {
                        slice.Add(inQuestion);
                    }
                    else
                    {
                        break;
                    }
                }
            }
            slice.Sort(vsGoTo);
// This line makes it so that all groups arive at the same time.
// PROBLEM: this will make fast units move slugishly for very short journeys.
            float leaderSpeed = Mathf.Clamp(Vector2.Distance(sliceLeader.transform.position, goTo) / weakLinkETA, 0, sliceLeader.stats.speed);
            sliceLeader.work(new Task(sliceLeader, Task.actions.move, goTo, toFollow, -1, leaderSpeed));
            for (int followerIndex = 1; followerIndex < slice.Count; ++followerIndex)
            {
                slice[followerIndex].work(new Task(slice[followerIndex], Task.actions.move, goTo, sliceLeader));
            }
            foreach (MobileUnit_local sliceMember in slice)
            {
                assignments.Add(sliceMember.task);
                unitsByDirection.Remove(sliceMember);
                unitsByDistance.Remove(sliceMember);
            }
        }
    }