示例#1
0
 public void OnLeftClick(IMouseTargetable target, Vector3 exactClickPosition)
 {
     if (target is IDamageable)
     {
         var targetObject = target as IDamageable;
         if (attack.CanAttack(targetObject))
         {
             Networking.instance.SendCommandToStartAttack(this, targetObject);
             statistics.numberOfAttacks--;
         }
     }
     if (target is Unit)
     {
         var targetUnit = target as Unit;
         if (targetUnit == this)
         {
             targetUnit.GetMyOwner().DeselectUnit();
         }
         else if (targetUnit.GetMyOwner().team == owner.team)
         {
             targetUnit.GetMyOwner().SelectUnit(targetUnit);
         }
     }
     else if (target is Tile)
     {
         MultiTile destination = (target as Tile).PositionRelatedToMouse(currentPosition.size, exactClickPosition);
         if (CanMoveTo(destination))
         {
             Networking.instance.SendCommandToMove(this, destination);
         }
     }
 }
示例#2
0
        public override IEnumerator MoveTo(MultiTile destination)
        {
            PlayMovementAnimation();
            //this is what can be called retarded movement, but i cannot into realistic movement as much as Poland cannot into space ;<\
            // it flies up, then forwards, then down, in straight lines. I know it is bad!

            //turns in one frame currently
            TurnTowards(destination.center);

            //while not up enough, rise
            while (myUnit.transform.position.y < flyHeight)
            {
                FlyUp();
                yield return(null);
            }
            //once we have broke out of the first loop, we will not get back to it (we use yield return, not yield break)

            //while not above the target, fly towards it
            while (!IsAbove(destination.center))
            {
                FlyForward();
                yield return(null);
            }
            while (myUnit.transform.position.y > 0)
            {
                Land();
                yield return(null);
            }
            StopMovementAnimation();
            //HERE we need to pathfind, actually, to get distance etc. to know how many points we lost - I THINK. Or maybe fliers cannot move more that once per turn xD?
            myUnit.statistics.movementPoints = 0;
            myUnit.OnMove(myUnit.currentPosition, destination);
            destination.SetMyObjectTo(myUnit);
            PlayerInput.instance.isInputBlocked = false;
        }
示例#3
0
        void SpawnObstacle()
        {
            Tile     targetTile = target as Tile;
            Obstacle obstacle   = Instantiate(obstaclePrefab, targetTile.transform.position, obstaclePrefab.transform.rotation).GetComponent <Obstacle>();

            obstacle.OnSpawn(MultiTile.Create(targetTile, obstacle.currentPosition.size));
        }
示例#4
0
        public override IEnumerator MoveTo(MultiTile newPosition)
        {
            finalPosition = newPosition;
            Queue <MultiTile> path = Pathfinder.instance.GetPathFromTo(myUnit, newPosition);

            if (myUnit.IsExittingCombat(newPosition))
            {
                myUnit.ExitCombat();
                int health = myUnit.statistics.healthPoints;
                foreach (Tile neighbour in myUnit.currentPosition.closeNeighbours)
                {
                    if (myUnit.IsAlive() && neighbour.GetMyObject <Unit>() != null && myUnit.IsEnemyOf(neighbour.GetMyObject <Unit>()))
                    {
                        int damage = DamageCalculator.CalculateDamage(neighbour.GetMyObject <Unit>(), myUnit, 1.5f);
                        neighbour.GetMyObject <Unit>().Backstab(myUnit, damage);
                        health -= damage;
                    }
                }
                if (health > 0)
                {
                    //THe attacks will not kill us, cause calculated :P
                }
                else
                {
                    //rip, abort.
                    yield break;
                }
            }

            BattlescapeGraphics.ColouringTool.UncolourAllTiles();
            PlayMovementAnimation();
            int tileCount = path.Count;

            for (int i = 0; i < tileCount; ++i)
            {
                MultiTile temporaryGoal = path.Dequeue();
                myUnit.OnMove(myUnit.currentPosition, temporaryGoal);
                myUnit.TryToSetMyPositionTo(temporaryGoal);
                //I am aware, that for now we are still just turning into a direction in one frame. If we ever want it any other way, it needs a bit of work to set it otherwise so im not doing it now :D.
                //if we want to slowly turn, we need to ask if we already turned, and if not we turn and if yes we move here.
                TurnTowards(temporaryGoal.center);
                while (Vector3.Distance(myUnit.transform.position, temporaryGoal.center) > 0.0001f)
                {
                    myUnit.transform.position = Vector3.MoveTowards(myUnit.transform.position, temporaryGoal.center, visualSpeed * Time.deltaTime);
                    yield return(null);
                }
                temporaryGoal.SetMyObjectTo(myUnit);
            }
            StopMovementAnimation();
            PlayerInput.instance.isInputBlocked = false;
            if (newPosition.IsProtectedByEnemyOf(myUnit))
            {
                myUnit.statistics.movementPoints = 0;
            }
            else
            {
                myUnit.statistics.movementPoints -= tileCount - 1;
            }
            BattlescapeGraphics.ColouringTool.ColourLegalTilesFor(myUnit);
        }
        // this class is supposed to make an army "randomly" position itself in the begining of a fight. I want it also to be an option for PLAYER's army - so that a "casual" player, who does not want to
        // have to think about it - can also click it and not think about positioning army before the battle.


        public void RepositionUnits()
        {
            foreach (Unit unit in GameRound.instance.currentPlayer.playerUnits)
            {
                MultiTile newPosition = ChooseThePosition(unit.currentPosition.size);
                DropZone.instance.SendCommandToSetUnitPosition(unit, newPosition);
            }
        }
 bool HasExtraSpace(MultiTile position)
 {
     foreach (Tile neighbour in position.closeNeighbours)
     {
         if (neighbour.IsEmpty() == false)
         {
             return(false);
         }
     }
     return(true);
 }
示例#7
0
 public bool CanMoveTo(MultiTile destination)
 {
     return
         (destination != null &&
          myUnit.GetMyOwner().IsCurrentLocalPlayer() &&
          myUnit.GetMyOwner() == GameRound.instance.currentPlayer &&
          GameRound.instance.currentPhase == TurnPhases.Movement &&
          myUnit.CanStillMove() &&
          Pathfinder.instance.IsLegalTileForUnit(destination, myUnit) &&
          PlayerInput.instance.isInputBlocked == false);
 }
示例#8
0
 void SetDistancesToMinus(MultiTile start)
 {
     distances = new int[Global.instance.currentMap.mapWidth - start.size.width + 1, Global.instance.currentMap.mapHeight - start.size.height + 1];
     for (int i = 0; i < Global.instance.currentMap.mapWidth - start.size.width + 1; i++)
     {
         for (int j = 0; j < Global.instance.currentMap.mapHeight - start.size.height + 1; j++)
         {
             distances[i, j] = -1;
         }
     }
 }
示例#9
0
        public static void SetNewPosition(int index, int endPosX, int endPosZ)
        {
            Vector3 newPos = Global.instance.currentMap.board[endPosX, endPosZ].transform.position;

            Unit unit = UnitFactory.GetUnitByIndex(index);

            Tile tile = Global.instance.currentMap.board[endPosX, endPosZ];

            unit.TryToSetMyPositionAndMoveTo(MultiTile.Create(tile, unit.currentPosition.size));
            unit.FaceMiddleOfMap();
        }
示例#10
0
        //Played BEFORE the first step in the whole movement. Check for ExitCombat here cause it only makes sense here.
        //Returns true if movement is exiting combat
        public bool IsExittingCombat(MultiTile newPosition)
        {
            if (newPosition.IsProtectedByEnemyOf(this))
            {
                return(false);
            }
            if (currentPosition.IsProtectedByEnemyOf(this))
            {
                return(true);
            }

            return(false);
        }
        void PlaceObject(GameObject objectToPlace, MultiTile position)
        {
            if (position == null)
            {
                GameObject.Destroy(objectToPlace);
                return;
            }
            objectToPlace.GetComponent <IVisuals>().OnSpawn(position);
            Vector3 oldScale = objectToPlace.transform.localScale;

            objectToPlace.transform.SetParent(position.bottomLeftCorner.transform);
            objectToPlace.transform.localScale = oldScale;
        }
示例#12
0
        public bool IsLegalTileForUnit(MultiTile position, Unit unit)
        {
            BFS(unit);
            int legalDistance = 0;

            if (unit.IsInCombat() && unit.statistics.movementPoints > 0)
            {
                legalDistance = 1;
            }
            else if (unit.IsInCombat() == false)
            {
                legalDistance = unit.statistics.movementPoints;
            }
            return(distances[position.bottomLeftCorner.position.x, position.bottomLeftCorner.position.z] <= legalDistance && distances[position.bottomLeftCorner.position.x, position.bottomLeftCorner.position.z] > 0);
        }
示例#13
0
 public void OnTileToMoveHovered(Unit unitToMove, MultiTile targetTile)
 {
     if (targetTile.IsProtectedByEnemyOf(unitToMove))
     {
         SetCursorTo(enterCombatCursor, clickingEnterCombatCursor);
     }
     else if (unitToMove.IsInCombat())
     {
         SetCursorTo(combatExitingMovementCursor, clickingCombatExitingMovementCursor);
     }
     else
     {
         SetCursorTo(walkingCursor, clickingWalkingCursor);
     }
 }
示例#14
0
        public void OnTileHovered(Tile hoveredTile, Vector3 exactMousePosition)
        {
            MultiTile hoveredMultitile = hoveredTile.PositionRelatedToMouse(currentPosition.size, exactMousePosition);

            if (CanMoveTo(hoveredMultitile))
            {
                foreach (Unit otherUnit in Global.instance.GetAllUnits())
                {
                    if (IsEnemyOf(otherUnit) && CouldAttackEnemyFromTile(otherUnit, hoveredMultitile))
                    {
                        BattlescapeGraphics.ColouringTool.ColourObject(otherUnit, Color.red);
                    }
                }
            }
        }
示例#15
0
        void RPCDoMovement(int startX, int startZ, int endX, int endZ)
        {
            Tile bottomLeftCorner = Global.instance.currentMap.board[startX, startZ];
            Unit unit             = bottomLeftCorner.GetMyObject <Unit>();

            if (unit == null)
            {
                Debug.LogError("NoUnit!");
                LogConsole.instance.SpawnLog("NO UNIT TO MOVE!");
                return;
            }
            MultiTile destination = MultiTile.Create(Global.instance.currentMap.board[endX, endZ], unit.currentPosition.size);

            unit.Move(destination);
        }
示例#16
0
        MultiTile CalibrateToFitInBoard(MultiTile position)
        {
            int posX = position.bottomLeftCorner.position.x;
            int posZ = position.bottomLeftCorner.position.z;

            if (posX + position.size.width > Global.instance.currentMap.mapWidth)
            {
                posX = Global.instance.currentMap.mapWidth - position.size.width;
            }
            if (posZ + position.size.height > Global.instance.currentMap.mapHeight)
            {
                posZ = Global.instance.currentMap.mapHeight - position.size.height;
            }
            return(MultiTile.Create(Global.instance.currentMap.board[posX, posZ], position.size));
        }
示例#17
0
        public MultiTile PositionRelatedToMouse(Size size, Vector3 exactClickPosition)
        {
            // this variable is equal to 1 if width or height are even, otherwise 0
            int widthEven  = size.width % 2;
            int heightEven = size.height % 2;

            // check which part of tile player clicked
            int xGt = Convert.ToInt32(exactClickPosition.x > this.transform.position.x);
            int zGt = Convert.ToInt32(exactClickPosition.z > this.transform.position.z);

            // find new bottom left corner of Multitile
            int widthOffset  = (size.width - widthEven) / 2 - xGt * Convert.ToInt32(widthEven == 0);
            int heightOffset = (size.height - heightEven) / 2 - zGt * Convert.ToInt32(heightEven == 0);

            return(MultiTile.Create(ToTile(this.Offset(-widthOffset, -heightOffset).CalibrateTo(size.width, size.height)), size));
        }
示例#18
0
 public void OnMove(MultiTile oldPosition, MultiTile newPosition)
 {
     //played on EVERY change of tile. Two tiles are used here to avoid confusion in using currentPosition - this will work no matter if we use it slightly before or after movement.
     if (oldPosition.IsProtectedByEnemyOf(this) == false && newPosition.IsProtectedByEnemyOf(this))
     {
         //Unit just came from SAFETY to COMBAT, so inform it and all of the enemies around about it.
         OnCombatEnter();
         foreach (Tile neighbour in newPosition.closeNeighbours)
         {
             if (neighbour.GetMyObject <Unit>() != null && IsEnemyOf(neighbour.GetMyObject <Unit>()))
             {
                 neighbour.GetMyObject <Unit>().OnCombatEnter();
             }
         }
     }
 }
示例#19
0
        public int DistanceTo(MultiTile other)
        {
            int currentDistance = Int32.MaxValue;

            foreach (Tile tile in this)
            {
                foreach (Tile otherTile in other)
                {
                    int newDistance = tile.position.DistanceTo(otherTile.position);
                    if (newDistance < currentDistance)
                    {
                        currentDistance = newDistance;
                    }
                }
            }
            return(currentDistance);
        }
示例#20
0
        public void OnCursorOver(IMouseTargetable target, Vector3 exactMousePosition)
        {
            if (target is Unit)
            {
                var targetUnit = target as Unit;
                if (targetUnit.CanBeSelected())
                {
                    Cursor.instance.OnSelectableHovered();
                    return;
                }
            }
            if (target is IDamageable)
            {
                var targetDamagableObject = target as IDamageable;
                if (attack.CanAttack(targetDamagableObject))
                {
                    Cursor.instance.OnEnemyHovered(this, targetDamagableObject);
                    return;
                }
                else
                {
                    Cursor.instance.ShowInfoCursor();
                }
            }
            if (target is Tile)
            {
                var       targetTile = target as Tile;
                MultiTile position   = targetTile.PositionRelatedToMouse(currentPosition.size, exactMousePosition);

                if (CanMoveTo(position))
                {
                    BattlescapeGraphics.ColouringTool.ColourLegalTilesFor(this);
                    BattlescapeGraphics.ColouringTool.OnPositionHovered(position);
                    Cursor.instance.OnTileToMoveHovered(this, position);
                }
                else
                {
                    Cursor.instance.OnInvalidTargetHovered();
                }
            }
            else
            {
                Cursor.instance.OnInvalidTargetHovered();
            }
        }
示例#21
0
        //This function gives the list of possible tiles a Unit could get to.
        public List <MultiTile> GetAllLegalPositionsFor(Unit unitToMove)
        {
            List <MultiTile> returnList = new List <MultiTile>();

            BFS(unitToMove);
            for (int i = 0; i < Global.instance.currentMap.mapWidth - unitToMove.currentPosition.size.width + 1; i++)
            {
                for (int j = 0; j < Global.instance.currentMap.mapHeight - unitToMove.currentPosition.size.height + 1; j++)
                {
                    MultiTile newPosition = MultiTile.Create(Global.instance.currentMap.board[i, j], unitToMove.currentPosition.size);
                    if (unitToMove.CanMoveTo(newPosition))
                    {
                        returnList.Add(newPosition);
                    }
                }
            }
            return(returnList);
        }
示例#22
0
        //This function populates Distances and Parents arrays with data, using BFS algorithm.
        //Currently it just calculates for whole board (not until reaching destination).
        void BFS(Unit unitToMove)
        {
            //THIS first part is just for optimization
            if (HaveToBFSFor(unitToMove) == false)
            {
                return;
            }
            else
            {
                lastTile = unitToMove.currentPosition.bottomLeftCorner;
                lastUnit = unitToMove;
            }
            MultiTile start = unitToMove.currentPosition;

            parents = new MultiTile[Global.instance.currentMap.mapWidth - start.size.width + 1, Global.instance.currentMap.mapHeight - start.size.height + 1];
            SetDistancesToMinus(start);
            SetProtectedByEnemy(unitToMove);

            Queue <MultiTile> queue = new Queue <MultiTile>();

            distances[start.bottomLeftCorner.position.x, start.bottomLeftCorner.position.z] = 0;
            queue.Enqueue(start);

            while (queue.Count > 0)
            {
                MultiTile current = queue.Peek();
                queue.Dequeue();
                foreach (MultiTile neighbour in current.neighbours)
                {
                    if (distances[neighbour.bottomLeftCorner.position.x, neighbour.bottomLeftCorner.position.z] == -1 && neighbour.IsFreeFor(unitToMove) && IsQuittingCombatIntoCombat(unitToMove, neighbour) == false)
                    {
                        distances[neighbour.bottomLeftCorner.position.x, neighbour.bottomLeftCorner.position.z] = distances[current.bottomLeftCorner.position.x, current.bottomLeftCorner.position.z] + 1;
                        parents[neighbour.bottomLeftCorner.position.x, neighbour.bottomLeftCorner.position.z]   = current;
                        foreach (Tile tile in neighbour)
                        {
                            if (!enemyProtection[tile.position.x, tile.position.z])
                            {
                                queue.Enqueue(neighbour);
                            }
                        }
                    }
                }
            }
        }
示例#23
0
        public Queue <MultiTile> GetPathFromTo(Unit unitToMove, MultiTile destination)
        {
            BFS(unitToMove);
            Stack <MultiTile> tileStack = new Stack <MultiTile>();

            tileStack.Push(destination);
            while (!tileStack.Contains(unitToMove.currentPosition))
            {
                MultiTile positionOnTheStack = tileStack.Peek();
                tileStack.Push(parents[positionOnTheStack.bottomLeftCorner.position.x, positionOnTheStack.bottomLeftCorner.position.z]);
            }
            Queue <MultiTile> path = new Queue <MultiTile>();

            while (tileStack.Count > 0)
            {
                path.Enqueue(tileStack.Pop());
            }
            return(path);
        }
        MultiTile GetRandomMultiTile(Size size, MapVisualsSpecification spec)
        {
            int       terminator = 0;
            Tile      tile       = Global.instance.currentMap.board[Random.Range(spec.minDistanceToShortSide, Global.instance.currentMap.mapWidth - spec.minDistanceToShortSide), Random.Range(spec.minDistanceToLongSide, Global.instance.currentMap.mapHeight - spec.minDistanceToLongSide)];
            MultiTile position   = MultiTile.Create(tile, size);

            while (IsMultiTileLegal(position, spec) == false)
            {
                terminator++;
                tile     = Global.instance.currentMap.board[Random.Range(spec.minDistanceToShortSide, Global.instance.currentMap.mapWidth - spec.minDistanceToShortSide), Random.Range(spec.minDistanceToLongSide, Global.instance.currentMap.mapHeight - spec.minDistanceToLongSide)];
                position = MultiTile.Create(tile, size);
                if (terminator == 100)
                {
                    return(null);
                }
            }

            return(position);
        }
示例#25
0
        void OnMouseDrag()
        {
            if (GameRound.instance.gameRoundCount > 0)
            {
                return;
            }
            Ray        cameraRay = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hitInfo;
            int        tileMask = 1 << 9;

            if (Physics.Raycast(cameraRay, out hitInfo, Mathf.Infinity, tileMask))
            {
                Tile      tile     = hitInfo.transform.gameObject.GetComponent <Tile>();
                MultiTile position = tile.PositionRelatedToMouse(myUnit.currentPosition.size, hitInfo.point);
                if (position != null && (position.IsDropzoneOfTeam(GameRound.instance.currentPlayer.team.index)) && position.IsFreeFor(myUnit))
                {
                    DropZone.instance.SendCommandToSetUnitPosition(myUnit, position);
                }
            }
        }
        MultiTile ChooseThePosition(Size size)
        {
            List <MultiTile> possibleTiles = new List <MultiTile>();

            foreach (Tile tile in Global.instance.currentMap.board)
            {
                MultiTile position = MultiTile.Create(tile, size);
                if (position != null && position.IsWalkable() && (position.IsDropzoneOfTeam(GameRound.instance.currentPlayer.team.index)))
                {
                    possibleTiles.Add(position);
                }
            }

            MultiTile chosenTile = Tools.GetRandomElementFromList <MultiTile>(possibleTiles);

            if (chosenTile == null)
            {
                Debug.LogError("Too many units, couldn't put them on battlefield");
                return(null);
            }
            return(chosenTile);
        }
示例#27
0
        /// <summary>
        /// Used to either perform movement in offline modes or send an RPC in online mode.
        /// </summary>
        /// <param name="unit"> Unit to be moved to the last tile in Path made by PathCreator</param>
        public void SendCommandToMove(Unit unit, MultiTile destination)
        {
            PlayerInput.instance.isInputBlocked = true; //this makes sense only on the 'active' PC' that's why I put it here ;)

            if (Global.instance.matchType == MatchTypes.Online)
            {
                int startX = unit.currentPosition.bottomLeftCorner.position.x;
                int startZ = unit.currentPosition.bottomLeftCorner.position.z;
                int endX   = destination.bottomLeftCorner.position.x;
                int endZ   = destination.bottomLeftCorner.position.z;

                photonView.RPC(
                    "RPCDoMovement",
                    RpcTarget.All,
                    startX,
                    startZ,
                    endX,
                    endZ);
            }
            else
            {
                unit.Move(destination);
            }
        }
示例#28
0
 public abstract IEnumerator MoveTo(MultiTile destination);
 bool IsMultiTileLegal(MultiTile position, MapVisualsSpecification spec)
 {
     return(position.IsEmpty() && (spec.needsExtraSpace == false || HasExtraSpace(position)));
 }
示例#30
0
 public void OnSpawn(MultiTile spawningTile)
 {
     TryToSetMyPositionAndMoveTo(spawningTile);
 }