Пример #1
0
    void fallBack(unitScript unit)
    {
        pathFinder.getMovementPaths(unit.GetComponent <GridItem>().getPos(), unit.getMovementDistance(), false);
        //run away from enemy
        //Calculate vector



        //if has shield switch to it and deploy
        if (swapTo(unit, WeaponType.shield))
        {
            activateShield(unit, unit.GetComponent <GridItem>());
        }
    }
Пример #2
0
    protected float getCoverPenalty(unitScript unit, unitScript clickedUnit, float distance)
    {
        Vector2 unitPosition  = unit.GetComponent <GridItem>().getPos();
        Vector2 enemyPosition = clickedUnit.GetComponent <GridItem>().getPos();

        return(getCoverPenalty(new Vector3(unitPosition.x, 1, unitPosition.y), new Vector3(enemyPosition.x, 1.0f, enemyPosition.y)));
    }
Пример #3
0
    protected float meleeChanceToHit(unitScript unit, unitScript clickedUnit)
    {
        if (unit.getCurrentWeapon().type == WeaponType.ranged)
        {
            return(0);
        }

        // Check outflank bonus
        int     flankBonus    = 0;  // Flank Check
        Vector2 enemyPosition = clickedUnit.GetComponent <GridItem>().getPos();

        foreach (unitScript u in playerUnitList)
        {
            if (u != null)
            {
                Vector2 unitPosition = u.GetComponent <GridItem>().getPos();
                if (u.getOwner() == controllerID && u != unit && Vector2.Distance(unitPosition, enemyPosition) < 2)
                {
                    flankBonus = 2;
                    print("Flanked Bitches");
                }
            }
        }


        // return chance to hit
        return((5.0f + (unit.getSkill() + flankBonus) - clickedUnit.getSkill()) / 10.0f);
    }
Пример #4
0
    protected bool activateShield(unitScript unit, GridItem position)
    {
        if (!(unit.getCurrentWeapon().type == WeaponType.shield))
        {
            return(false);
        }
        Shield currentShield = (Shield)unit.getCurrentWeapon();

        if (currentShield.isBroken(unit.GetInstanceID()))
        {
            return(false);
        }

        if (currentShield.getShield(unit.GetInstanceID()) != null)
        {
            Destroy(currentShield.getShield(unit.GetInstanceID()));
        }

        //Check position is within range
        if (currentShield == null || Vector2.Distance(unit.GetComponent <GridItem>().getPos(), position.getPos()) > currentShield.range)
        {
            return(false);
        }
        //Create the game object
        //TODO- Fix the roation and shape of shields to be frontal not surround
        Vector3 toPosition = position.getVectorPostion() - unit.GetComponent <GridItem>().getVectorPostion();
        float   rotation   = Vector3.Angle(new Vector3(0, 0, 1), Vector3.Cross(toPosition, new Vector3(0, 1, 0)));

        print(rotation);
        GameObject newShield = Instantiate <GameObject>(Resources.Load <GameObject>("Units/Shield"), position.getVectorPostion(), Quaternion.Euler(0, rotation, 0));

        currentShield.setShield(unit.GetInstanceID(), newShield);

        newShield.GetComponent <shieldScript>().setStats(controllerID, unit.getSmarts() * 3);
        //Check it's collisions with other shields
        currentShield.shieldBreakCheck();


        unit.activateAttack();

        print("ACTIVATE SHIELD");
        map.UnHilightMap();



        return(true);
    }
Пример #5
0
    //Assisting functions
    unitScript targetPrioritisation(unitScript unit, List <unitScript> enemyList)
    {
        AIUnitController unitControl = unit.GetComponent <AIUnitController>();

        List <float> priorites = new List <float>();

        foreach (unitScript otherUnit in enemyList)
        {
            //Add factors
            float priority = 0;

            if (otherUnit == null || otherUnit.getOwner() == controllerID || otherUnit.getHealth() <= 0)
            {
                priorites.Add(-1000000);
                break;
            }
            //distance - wrecklessness (negative if over wrecklessness
            priority -= Mathf.Max(0, Vector2.Distance(unit.GetComponent <GridItem>().getPos(), otherUnit.GetComponent <GridItem>().getPos()) - unitControl.wrecklessness);
            //deuling preference
            bool weaponsMatch = unit.getCurrentWeapon().type == otherUnit.getCurrentWeapon().type;
            if ((weaponsMatch && unitControl.deulingPreference) || (!weaponsMatch && !unitControl.deulingPreference))
            {
                priority += 2;
            }
            //Agro multiplied by anger
            if (unitControl.agroTarget == otherUnit)
            {
                priority += 10 * unitControl.anger;
            }
            priorites.Add(priority);
        }
        priorites.ForEach(e => print("Inlist" + e));
        int maxIndex = priorites.IndexOf(priorites.Max());

        unitControl.target = enemyList[maxIndex];
        print("Selected : " + enemyList[maxIndex]);
        return(enemyList[maxIndex]);
    }
Пример #6
0
    protected float rangedChanceToHit(unitScript unit, unitScript clickedUnit)
    {
        if (unit.getCurrentWeapon().type == WeaponType.melee)
        {
            return(0.0f);
        }
        //Calculate range penalty
        float distance = Vector2.Distance(unit.GetComponent <GridItem>().getPos(), clickedUnit.GetComponent <GridItem>().getPos());

        float rangedPenalty = getRangePenalty(unit, distance);

        //Calculate cover penalty
        float coverPenalty = getCoverPenalty(unit, clickedUnit, distance);

        //Get base shooting skill
        float shootingSkill = getBaseHitChance(unit);

        //Return formula
        return(shootingSkill - (rangedPenalty + coverPenalty) / 10);
    }
Пример #7
0
    protected bool MeleeAttack(unitScript unit, unitScript clickedUnit, bool initialAttack = true)
    {
        // Check attack can occur
        if (unit.getCurrentWeapon().type == WeaponType.ranged || unit == null || clickedUnit == null)
        {
            return(false);
        }

        float distance = Vector2.Distance(unit.GetComponent <GridItem>().getPos(), clickedUnit.GetComponent <GridItem>().getPos());

        if (!(unit.getCurrentWeapon().type == WeaponType.melee) || distance > ((MeleeWeapon)unit.getCurrentWeapon()).range)
        {
            return(false);
        }

        // Given it can roll the dice
        float roll = UnityEngine.Random.Range(0.0f, 1.0f);

        float chanceToHit = meleeChanceToHit(unit, clickedUnit);

        print(roll + " " + chanceToHit);
        if (roll < chanceToHit)
        {
            clickedUnit.takeDamage(unit.getStrength() + unit.getCurrentWeapon().damage);
        }
        else
        {
            clickedUnit.displayMiss();
        }
        unit.activateAttack();
        if (initialAttack && clickedUnit.getStrikeback() == false)
        {
            bool result = MeleeAttack(clickedUnit, unit, false);
            if (result)
            {
                clickedUnit.useStrikeback();
            }
        }
        return(true);
    }
Пример #8
0
    void testMove(unitScript unit)
    {
        pathFinder.getMovementPaths(unit.GetComponent <GridItem>().getPos(), unit.getMovementDistance(), false);
        var  locations = pathFinder.getReachableLocations();
        bool f         = true;

        foreach (Vector2 location in locations)
        {
            float chance = Random.Range(0.0f, 1.0f);
            if (!f && chance > 0.5)
            {
                if (!unit.hasMoved())
                {
                    Vector2[] path = pathFinder.drawPath(location, false);
                    unit.setPath(path);
                }
            }
            if (f)
            {
                f = !f;
            }
        }
    }
Пример #9
0
    // Update is called once per frame
    void Update()
    {
        if (map == null)
        {
            initiateController();
        }

        if (isTurn())
        {
            if (currentIndex == playerUnitList.Length)
            {
                endTurn();
                map.clearDisplay();
                currentIndex = 0;
                return;
            }
            if (!(playerUnitList[currentIndex] != null))
            {
                currentIndex++;
                return;
            }
            AIUnitController currentUnitAI = playerUnitList[currentIndex].GetComponent <AIUnitController>();

            if (!(currentUnitAI.moved && currentUnitAI.attacked))
            {
                unitScript unit = playerUnitList[currentIndex];
                // issue commands to current unit
                switch (unit.GetComponent <AIUnitController>().state)
                {
                case AIState.test:
                    testMove(unit);
                    break;

                case AIState.hunt:
                    hunt(unit);
                    break;

                case AIState.fallback:
                    fallBack(unit);
                    break;

                case AIState.groupUp:
                    groupUp(unit);
                    break;

                case AIState.recover:
                    recover(unit);
                    break;

                case AIState.support:
                    support(unit);
                    break;
                }
            }
            else if (playerUnitList[currentIndex].canEndTurn())
            {
                playerUnitList[currentIndex].GetComponent <AIUnitController>().endTurn();
                currentIndex++;
            }
        }
    }
Пример #10
0
    void hunt(unitScript unit)
    {
        pathFinder.getMovementPaths(unit.GetComponent <GridItem>().getPos(), 100, false);
        //var locations = pathFinder.getReachableLocations();

        if (unit.getCurrentWeapon().type == WeaponType.melee)
        {
            if (!unit.GetComponent <AIUnitController>().moved)
            {
                //get position of all enemies
                unitScript[]      units      = getAllUnits();
                List <unitScript> targetList = new List <unitScript>(units);
                //Pick target
                unitScript target = targetPrioritisation(unit, targetList);
                if (target == null)
                {
                    unit.GetComponent <AIUnitController>().moved    = true;
                    unit.GetComponent <AIUnitController>().attacked = true;
                    return;
                }

                unit.GetComponent <AIUnitController>().moved = true;
                //Get the positions one short of target

                var oneShort           = target.GetComponent <GridItem>().getPos() - unit.GetComponent <GridItem>().getPos();
                var targetPosXclose    = target.GetComponent <GridItem>().getPos() - new Vector2(Mathf.Sign(oneShort.x), 0);
                var targetPosYclose    = target.GetComponent <GridItem>().getPos() - new Vector2(0, Mathf.Sign(oneShort.y));
                var targetPosXfar      = target.GetComponent <GridItem>().getPos() + new Vector2(Mathf.Sign(oneShort.x), 0);
                var targetPosYfar      = target.GetComponent <GridItem>().getPos() + new Vector2(0, Mathf.Sign(oneShort.y));
                List <Vector2[]> paths = new List <Vector2[]>();
                paths.Add(pathFinder.drawPath(targetPosXclose, false, true));
                paths.Add(pathFinder.drawPath(targetPosYclose, false, true));
                paths.Add(pathFinder.drawPath(targetPosXfar, false, true));
                paths.Add(pathFinder.drawPath(targetPosYfar, false, true));
                //For each potential places try to move there
                foreach (var path in paths)
                {
                    if (path != null)
                    {
                        //if the path is not null attack
                        Vector2[] newPath = new Vector2[Mathf.Min(path.Length, unit.getMovementDistance())];

                        for (int i = 0; i < newPath.Length; i++)
                        {
                            newPath[i] = path[i];
                        }

                        unit.setPath(newPath);
                        break;
                    }
                }
                unit.GetComponent <AIUnitController>().moved = true;
            }
            else if (unit.canEndTurn())
            {
                //Attack target
                MeleeAttack(unit, unit.GetComponent <AIUnitController>().target);
                unit.GetComponent <AIUnitController>().attacked = true;
            }
        }
        else if (unit.getCurrentWeapon().type == WeaponType.ranged)
        {
            if (!unit.GetComponent <AIUnitController>().moved)
            {
                Vector2 initialPosition = unit.GetComponent <GridItem>().getPos();
                //Initialise heursticmap
                var locations = pathFinder.getReachableLocations();
                Dictionary <Vector2, float> heuristicMap = new Dictionary <Vector2, float>();
                RangedWeapon currentGun = (RangedWeapon)unit.getCurrentWeapon();
                var          enemyUnits = getEnemyUnits();
                foreach (Vector2 pos in locations.Where(p => Mathf.Abs(p.x - unit.GetComponent <GridItem>().getPos().x) + Mathf.Abs(p.y - unit.GetComponent <GridItem>().getPos().y) < unit.getMovementDistance()))
                {
                    unit.setPosition((int)pos.x, (int)pos.y);
                    float h = 0.0f;

                    //Get all cover tiles around the current
                    var neighboringTiles = this.map.getAllNeighbours(pos).Where(p => this.map.getTileData(p).coverValue != 0);

                    //How much will this tile hurt?
                    h += enemyUnits.Where(e => getRangePenalty(e, Vector3.Distance(e.GetComponent <GridItem>().getVectorPostion(), unit.GetComponent <GridItem>().getVectorPostion())) == 0)
                         .Aggregate(0, (subHeuristic, enemy) => subHeuristic - 1);

                    //Add back all values from cover
                    foreach (Vector2 cover in neighboringTiles)
                    {
                        //Direction of cover
                        Vector2 vectorToCover = cover - pos;
                        //If the cover is between me and an enemy then increase heurstic
                        h += enemyUnits
                             .Where(
                            e =>   // The enemy is not melee or shield
                            e.getCurrentWeapon().type == WeaponType.ranged
                            &&     //I am within enemy range
                            getRangePenalty(e, Vector3.Distance(e.GetComponent <GridItem>().getVectorPostion(), unit.GetComponent <GridItem>().getVectorPostion())) == 0
                            &&     //And cover is between the enemy and myself
                            (Vector2.Angle(e.GetComponent <GridItem>().getPos() - pos, vectorToCover) < 45)
                            ).Aggregate(0, (subHeurstic, e) => subHeurstic + (this.map.getTileData(cover).coverValue + 2));
                    }

                    // How much damage can I do from this position
                    h += enemyUnits.Select(e => getRangePenalty(unit, Vector3.Distance(e.GetComponent <GridItem>().getVectorPostion(), unit.GetComponent <GridItem>().getVectorPostion())) == 0)
                         .Aggregate(0, (subHeurisitic, e) => subHeurisitic + (e?1:-1));//unit.getCurrentWeapon().damage);

                    heuristicMap[pos] = h;
                    this.map.displayDebugData((int)pos.x, (int)pos.y, h.ToString());
                    unit.setPosition((int)initialPosition.x, (int)initialPosition.y);
                }
                unit.setPosition((int)initialPosition.x, (int)initialPosition.y);

                //Pick location with highest score
                Vector2 moveLocation = heuristicMap.Aggregate((l, r) => l.Value >= r.Value ? l : r).Key;

                print("KEY/Value " + moveLocation + " " + heuristicMap[moveLocation]);
                //Move there
                var path = pathFinder.drawPath(moveLocation, false, true);


                //if the path is not null attack
                Vector2[] newPath = new Vector2[Mathf.Min(path.Length, unit.getMovementDistance())];

                for (int i = 0; i < newPath.Length; i++)
                {
                    newPath[i] = path[i];
                }

                unit.setPath(newPath);

                unit.GetComponent <AIUnitController>().moved = true;

                //If an attack can be made make it
            }
            if (unit.canEndTurn())
            {
                //Find best target
                unitScript target = targetPrioritisation(unit, getEnemyUnits());
                if (target == null)
                {
                    unit.GetComponent <AIUnitController>().attacked = true;
                    return;
                }

                //Attack target
                RangedAttack(unit, unit.GetComponent <AIUnitController>().target);
                unit.GetComponent <AIUnitController>().attacked = true;
            }
        }
        else if (unit.getCurrentWeapon().type == WeaponType.shield)
        {
            if (swapTo(unit, WeaponType.melee))
            {
                print("ready Sword");
            }
            else if (swapTo(unit, WeaponType.ranged))
            {
                print("ready Gun");
            }
        }
    }
    void updateRangefinder(unitScript unit, GridItem position)
    {
        RangedWeapon weapon = (RangedWeapon)unit.getCurrentWeapon();

        // Set line data
        Vector3[] positions = new Vector3[4];
        positions[0] = new Vector3(unit.GetComponent <GridItem>().getX(), 1.0f, unit.GetComponent <GridItem>().getY());
        positions[3] = new Vector3(position.getX(), 1.0f, position.getY());

        float distance = Vector3.Distance(positions[0], positions[3]);

        positions[1] = Vector3.Lerp(positions[0], positions[3], Mathf.Max(0.001f, weapon.minRange / distance));
        positions[2] = Vector3.Lerp(positions[0], positions[3], Mathf.Min(0.9999f, (float)weapon.maxRange / distance));

        rangeRenderer.numPositions = 4;
        rangeRenderer.SetPositions(positions);



        GradientColorKey[] colorKey = new GradientColorKey[4];
        GradientAlphaKey[] alphaKey = new GradientAlphaKey[2];

        //Set ends to red and red
        colorKey[2] = new GradientColorKey(new Color(1, 0, 0), 0.0f);


        Color endColor;

        if (distance < weapon.minRange || distance > weapon.maxRange)
        {
            endColor = new Color(1, 0, 0);
        }
        else
        {
            endColor = new Color(0, 0, 0);
        }

        colorKey[3] = new GradientColorKey(endColor, 1.0f);

        //Set alphaKeys
        alphaKey[0] = new GradientAlphaKey(1.0f, 0.0f);
        alphaKey[1] = new GradientAlphaKey(1.0f, 1.0f);
        //Set color key's two and three according to range

        GradientColorKey minKey, maxKey;

        if (distance > weapon.minRange)
        {
            minKey = new GradientColorKey(new Color(0, 0, 0), (float)weapon.minRange / distance);
        }
        else
        {
            minKey = new GradientColorKey(new Color(1, 0, 0), 0.2f);
        }

        colorKey[0] = minKey;

        if (distance > weapon.minRange)
        {
            maxKey = new GradientColorKey(new Color(0, 0, 0), Mathf.Min(0.99999f, (float)weapon.maxRange / distance));
        }
        else
        {
            maxKey = new GradientColorKey(new Color(1, 0, 0), 0.5f);
        }

        colorKey[1] = maxKey;

        Gradient grad = new Gradient();

        grad.mode = GradientMode.Blend;
        grad.SetKeys(colorKey, alphaKey);

        rangeRenderer.colorGradient = grad;
    }
    void mouseOver()
    {
        //Mouse over tile while unit selected
        if (selected)
        {
            unitScript unit = selected.GetComponent <unitScript>();
            if (unit != null && unit.getOwner() == 0)
            {
                RaycastHit hit;
                var        ray = Camera.main.ScreenPointToRay(Input.mousePosition);

                if (Physics.Raycast(ray, out hit, Mathf.Infinity, (1 << 8)))
                {
                    clickableTile tile = hit.collider.gameObject.GetComponent <clickableTile>();

                    if (tile && !unit.hasMoved() && !attackMode)
                    {
                        GridItem tilePos = tile.GetComponent <GridItem>();
                        //print(tilePos);
                        if (pathFinder != null)
                        {
                            pathFinder.drawPath(tilePos.getPos());
                        }
                        else
                        {
                            print("pathfinder dead");
                        }
                    }

                    unitScript enemyUnit = hit.collider.GetComponent <unitScript>();

                    if (enemyUnit && attackMode == true && enemyUnit.getOwner() != 0)
                    {
                        GridItem playerPos = unit.GetComponent <GridItem>();
                        GridItem enemyPos  = hit.collider.GetComponent <GridItem>();

                        MeleeWeapon currentMeleeWeapon = null;
                        if (unit.getCurrentWeapon().type == WeaponType.melee)
                        {
                            currentMeleeWeapon = (MeleeWeapon)unit.getCurrentWeapon();


                            bool withinMeleeRange = currentMeleeWeapon != null && Vector2.Distance(enemyPos.getPos(), playerPos.getPos()) <= currentMeleeWeapon.range;
                            if (withinMeleeRange || currentMeleeWeapon == null)
                            {
                                GUIController cont = gui.GetComponent <GUIController>();

                                cont.setCombatPanelVisibility(true, unit, enemyUnit, meleeChanceToHit(unit, enemyUnit));
                            }
                        }
                        else if (unit.getCurrentWeapon().type == WeaponType.ranged)
                        {
                            if (canSee(unit, enemyUnit))
                            {
                                rangeRenderer.enabled = true;
                                updateRangefinder(unit, enemyUnit.GetComponent <GridItem>());
                                GUIController cont     = gui.GetComponent <GUIController>();
                                float         distance = Vector2.Distance(unit.GetComponent <GridItem>().getPos(), enemyUnit.GetComponent <GridItem>().getPos());

                                cont.setCombatPanelVisibility(true, unit, enemyUnit, rangedChanceToHit(unit, enemyUnit));
                                cont.loadRangedData(isShielded(unit, enemyUnit), getBaseHitChance(unit), getRangePenalty(unit, distance), getCoverPenalty(unit, enemyUnit, distance));
                            }
                            else if (rangeRenderer.enabled == true)
                            {
                                rangeRenderer.enabled = false;
                            }
                        }
                    }
                    else
                    {
                        GUIController cont = gui.GetComponent <GUIController>();

                        cont.setCombatPanelVisibility(false);
                        rangeRenderer.enabled = false;
                    }
                }
            }
        }

        //We also want to set the enemyStatPanel

        RaycastHit result;
        Ray        line = Camera.main.ScreenPointToRay(Input.mousePosition);

        if (Physics.Raycast(line, out result, Mathf.Infinity, (1 << 8)))
        {
            //set selected to hit
            GameObject enemy = result.collider.gameObject;

            //Select new unit
            if (enemy)
            {
                var        guiCont = gui.GetComponent <GUIController>();
                unitScript unit    = enemy.GetComponent <unitScript>();

                if (unit != null && unit.getOwner() == 1)
                {
                    guiCont.setCharacterPanelVisibility(true, unit, false);
                }
                else
                {
                    guiCont.setCharacterPanelVisibility(false, null, false);
                }
            }
        }
    }