Пример #1
0
    public void Reset()
    {
        _movesToNextPipe    = Consts.TURNS_TO_NEXT_PIPE;
        _allTurns           = 0; // for leveled too
        _pipesAdded         = 0;
        _pipesToNextBlocker = Consts.PIPES_TO_NEXT_BLOCKER;
        _pointsForSequences = 0;
        for (int i = 0; i < _resources.Count; ++i)
        {
            _resources[i] = 0;
        }
        GameState  = EGameState.Pause;
        TimePlayed = 0;
        DragSlot   = null;
        AddsViewed = false;

//		// leveled
//		StarsGained = 0;
//		MovesLeft = 0;
//		//

//        // powerups
//        EventData eventData = new EventData("OnPowerUpsResetNeededEvent");
//        //eventData.Data["isforce"] = true;
//        GameManager.Instance.EventManager.CallOnPowerUpsResetNeededEvent(eventData);
    }
Пример #2
0
    private float CreateAttack(GameBoard board, SSlot slot, int pipeColor, int attackPower) // attack after each match to opposite enemy slot
    {
        // find enemies slot in front of slot
        EnemySlot enemySlot = board.AEnemies.Slots[slot.X];
        Enemy     enemy     = enemySlot.GetEnemy();

        if (!enemy)
        {
            OnEndAttack();
            return(0);
        }
        // instantiate attack beam
        Vector3 pos = slot.transform.position;

        pos.z = -7;
        GameObject attackObject = board.GetPool().InstantiateObject("simple_attack_" + pipeColor.ToString(), board.AAttacks.ObjectsContainer, pos);
        // fly to slot
        Vector3 finalPos = enemySlot.transform.position;

        finalPos.z = -7;
        float distance = Mathf.Abs(finalPos.y - pos.y);
        float speed    = 0.02f; // per unit
        float flyTime  = distance * speed;

        LeanTween.move(attackObject, finalPos, flyTime)
        .setEaseOutSine()
        .setOnComplete(() => {
            GameObject.Destroy(attackObject);
            ApplyAttack(board, enemy, pipeColor, attackPower);
        });
        return(flyTime);
    }
Пример #3
0
    //

    public GameBoardData()
    {
        _movesToNextPipe = 0;
        if (GameBoard.AddingType != EAddingType.OnNoMatch)
        {
            _movesToNextPipe = Consts.TURNS_TO_NEXT_PIPE;
        }
        _allTurns           = 0;
        _pipesAdded         = 0;
        _pipesToNextBlocker = Consts.PIPES_TO_NEXT_BLOCKER;
        _pointsForSequences = 0;
        _resources          = new List <long>();
        for (int i = 0; i < Consts.CLASSIC_GAME_COLORS; ++i)
        {
            _resources.Add(0);
            //SetResourceForce(0, i);
        }
        AddsViewed = false;
        GameState  = EGameState.Pause;
        TimePlayed = 0;
        DragSlot   = null;
        PowerUps   = new Dictionary <GameData.PowerUpType, int>();
        foreach (GameData.PowerUpType powerUp in Enum.GetValues(typeof(GameData.PowerUpType)))
        {
            PowerUps.Add(powerUp, 0);
        }
    }
Пример #4
0
 public int AddManaForBump(SSlot slot, SPipe pipe, int mana, int color)
 {
     for (int i = 0; i < _buttons.Count; ++i)
     {
         int addedMana = _buttons[i].AddMana(mana, color);
         if (addedMana > 0)
         {
             mana -= addedMana;
             Vector3    startPos = transform.parent.transform.InverseTransformPoint(slot.transform.position);
             Vector3    endPos   = transform.parent.transform.parent.InverseTransformPoint(_buttons[i].transform.position);
             GameObject effect   = GameObject.Instantiate(CollectManaEffect, Vector3.zero, Quaternion.identity) as GameObject;
             effect.transform.SetParent(transform.parent.transform, false);
             effect.transform.localPosition = startPos;
             List <Vector3>   path        = GameManager.Instance.GameData.XMLSplineData[String.Format("chip_get_{0}", UnityEngine.Random.Range(1, 4))];
             MoveSplineAction splineMover = new MoveSplineAction(effect, path, startPos, endPos, Consts.ADD_POINTS_EFFECT_TIME);
             _worker.AddParalelAction(splineMover);
             GameObject.Destroy(effect, Consts.ADD_MANA_EFFECT_TIME + 0.1f);
         }
         if (mana <= 0)
         {
             break;
         }
     }
     return(mana);
 }
Пример #5
0
    protected List <List <SSlot> > GetSlotsWithCharactersInFront(GameBoard board, Enemy enemy, bool justFirst)
    {
        List <List <SSlot> > slots          = new List <List <SSlot> >();
        List <int>           columsToAttack = board.AEnemies.GetSlotsIdsWithEnemy(enemy);

        for (int i = 0; i < columsToAttack.Count; ++i)
        {
            List <SSlot> slotsInColumn  = new List <SSlot>();
            int          col            = columsToAttack[i];
            bool         characterFound = false;
            for (int j = GameBoard.HEIGHT - 1; j >= 0; --j)
            {
                SSlot slot = board.GetSlot(col, j);
                if (!slot.IsEmpty() && slot.Pipe.IsCharacter() && !slot.Pipe.GetComponent <Pipe_Character>().IsDead())
                {
                    characterFound = true;
                    slotsInColumn.Add(slot);
                    if (justFirst)
                    {
                        break;
                    }
                }
            }
            if (!characterFound)
            {
                slotsInColumn.Add(null);
                slotsInColumn.Add(board.GetSlot(col, 0));
            }
            slots.Add(slotsInColumn);
        }
        return(slots);
    }
Пример #6
0
    protected List <List <SSlot> > GetNotEmptySlotsInFront(GameBoard board, Enemy enemy, bool justFirst)
    {
        List <List <SSlot> > slots          = new List <List <SSlot> >();
        List <int>           columsToAttack = board.AEnemies.GetSlotsIdsWithEnemy(enemy);

        for (int i = 0; i < columsToAttack.Count; ++i)
        {
            List <SSlot> slotsInColumn = new List <SSlot>();
            int          col           = columsToAttack[i];
            bool         pipeFound     = false;
            for (int j = GameBoard.HEIGHT - 1; j >= 0; --j)
            {
                SSlot slot = board.GetSlot(col, j);
                if (!slot.IsEmpty())
                {
                    pipeFound = true;
                    slotsInColumn.Add(slot);
                    if (justFirst)
                    {
                        break;
                    }
                }
            }
            if (!pipeFound)
            {
                slotsInColumn.Add(null);
                slotsInColumn.Add(board.GetSlot(col, 0));
            }
            slots.Add(slotsInColumn);
        }
        return(slots);
    }
Пример #7
0
 public bool OnSlotTouched(SSlot slot)
 {
     if (_selectedCharacter)
     {
         if (_selectedCharacter == slot.Pipe)
         {
             _selectedCharacter.Unselect();
             _selectedCharacter = null;
         }
         else
         {
             bool applied = _selectedCharacter.TryApplyPowerup(slot);
             if (applied)
             {
                 _selectedCharacter.Unselect();
                 _selectedCharacter = null;
             }
         }
         return(true); // can't swipe if powerup selected
     }
     else
     {
         return(false);
     }
 }
Пример #8
0
 private float CreateAttackWithColored(GameBoard board, Enemy enemy)
 {
     List<List<SSlot>> slots = GetNotEmptySlotsInFront(board, enemy, true);
     float maxTime = 0;
     for (int i = 0; i < slots.Count; ++i)
     {
         Vector3 finalPos = Vector3.zero;
         SSlot firstSlot = slots[i][0];
         bool attackPipe = false;
         if (!firstSlot)
         {
             // attack lives panel
             firstSlot = slots[i][1];
             finalPos = firstSlot.transform.position;
             finalPos.y -= 1.5f;
         } else
         {
             // attack character or colored pipes
             attackPipe = true;
             finalPos = firstSlot.transform.position;
         }
         int slotX = firstSlot.X;
         Vector3 startPos = board.AEnemies.Slots[slotX].transform.position;
         // instantiate attack beam
         finalPos.z = -7;
         startPos.z = -7;
         GameObject attackObject = (GameObject)GameObject.Instantiate(AttackPrefab, startPos, Quaternion.identity, board.AAttacks.ObjectsContainer);
         // fly to slot
         finalPos.z = -7;
         float distance = Mathf.Abs(finalPos.y - startPos.y);
         float speed = 0.05f; // per unit
         float flyTime = distance * speed;
         if (maxTime < flyTime)
         {
             maxTime = flyTime;
         }
         LeanTween.move(attackObject, finalPos, flyTime)
             .setEaseOutSine()
             .setOnComplete(() => {
                 GameObject.Destroy(attackObject);
                 if (attackPipe)
                 {
                     if (firstSlot.Pipe.IsCharacter())
                     {
                         ApplyAttackOnCharacter(firstSlot, firstSlot.Pipe.GetComponent<Pipe_Character>(), enemy.Color, Power);
                     } else
                     if (firstSlot.Pipe.IsColored())
                     {
                         ApplyAttackOnColoredPipe(firstSlot, firstSlot.Pipe.GetComponent<Pipe_Colored>(), enemy.Color, Power);
                     }
                 } else
                 {
                     ApplyAttackOnLivesPanel(enemy.Color, Power);
                 }
             });
         // 
     }
     return maxTime;
 }
Пример #9
0
    public void ShowHint(GameBoard.MatchHintData mhData, GameBoard gBoard)
    {
        _hiding = false;
        //if (mhData.XA == mhData.XB && mhData.YA == mhData.YB)
        //{
        //    int r = 0;
        //}
        //Debug.Log(mhData.XA + "/" + mhData.YA + " --- " + mhData.XB + "/" + mhData.YB);
        // rotating
        if (mhData.XA != mhData.XB)
        {
            // horizontal slide
            if (mhData.XA < mhData.XB)
            {
                // slide right
                //Helpers.SetRotationDgr(AGameObject, 0);
            }
            else
            {
                // slide left
                Helpers.SetRotationDgr(AGameObject, 180);
            }
        }
        else
        {
            // vertical slide
            if (mhData.YA < mhData.YB)
            {
                // slide up
                Helpers.SetRotationDgr(AGameObject, 90);
            }
            else
            {
                // slide down
                Helpers.SetRotationDgr(AGameObject, -90);
            }
        }

        // positioning
        SSlot slot = gBoard.GetSlot(mhData.XA, mhData.YA);

        if (slot != null)
        {
            AGameObject.transform.SetParent(slot.transform.parent, false);
            Vector3 pos = slot.transform.position;
            pos.z = -5;
            AGameObject.transform.position = pos;
        }

        //SetColorsWithIndex(0);
        //_timer = 0.0f;
        //_index = 0;
        _startPos = ArrowSprites[0].transform.localPosition;
        _endPos   = ArrowSprites[ArrowSprites.Length - 1].transform.localPosition;
        _endPos   = _endPos + new Vector3(ArrowSprites[ArrowSprites.Length - 1].sprite.rect.width / 100.0f, 0.0f, 0.0f);
    }
Пример #10
0
 public bool TryApplyPowerup(SSlot slot)
 {
     if (!IsCanApply(slot))
     {
         return(false);
     }
     SetAmount(0);
     _powerup.ApplyPowerup(slot);
     return(true);
 }
Пример #11
0
 private void ApplyAttackOnColoredPipe(SSlot slot, Pipe_Colored pipe, int acolor, int power)
 {
     if (pipe.Param == 0)
     {
         GameManager.Instance.Game.BreakePipeInSlot(slot, pipe.GetExplodeEffectPrefab());
     } else
     {
         pipe.SetValueForce(pipe.Param - 1);
     }
 }
Пример #12
0
 public bool TryApplyPowerup(SSlot slot)
 {
     if (!IsCanApply(slot))
     {
         return(false);
     }
     Mana.SetAmount(0);
     UpdateReadyMark();
     _powerup.ApplyPowerup(slot);
     return(true);
 }
    public override bool IsCanApply(SSlot slot)
    {
        if (!slot || !slot.Pipe)
        {
            return(false);
        }
        EPipeType pipeType = slot.Pipe.PipeType;

        if (pipeType == EPipeType.Colored) // || pipeType == EPipeType.Blocker) //TODO upgrade to breake blockers
        {
            return(true);
        }
        return(false);
    }
Пример #14
0
    private void AddCharacter(string characterId, GameBoard board, List <SSlot> emptySlots)
    {
        if (emptySlots.Count == 0)
        {
            Debug.LogError("NO SLOTS FOR CHARACTER");
            return;
        }
        GameObject     obj       = board.GetPool().GetObjectFromPool(characterId, board.SlotsContainer);
        Pipe_Character character = obj.GetComponent <Pipe_Character>();
        SSlot          slot      = emptySlots[0];

        emptySlots.RemoveAt(0);
        slot.SetPipe(character);
        character.InitCharacter(1);
        character.PlayAddAnimation();
        _characters.Add(character);
    }
Пример #15
0
    public void Collect(SSlot slot, int pipeColor, int toCollect)
    {
        if (IsFull())
        {
            return;
        }
        SetAmount(GetAmount() + toCollect);
        Vector3    startPos = transform.parent.transform.InverseTransformPoint(slot.transform.position);
        Vector3    endPos   = transform.parent.transform.parent.InverseTransformPoint(transform.position);
        GameObject effect   = GameObject.Instantiate(CollectEffect, Vector3.zero, Quaternion.identity) as GameObject;

        effect.transform.SetParent(transform.parent.transform, false);
        effect.transform.localPosition = startPos;
        List <Vector3>   path        = GameManager.Instance.GameData.XMLSplineData[String.Format("chip_get_{0}", UnityEngine.Random.Range(1, 4))];
        MoveSplineAction splineMover = new MoveSplineAction(effect, path, startPos, endPos, Consts.ADD_POINTS_EFFECT_TIME);

        _worker.AddParalelAction(splineMover);
        GameObject.Destroy(effect, Consts.ADD_MANA_EFFECT_TIME + 0.1f);
    }
Пример #16
0
    public override bool IsCanApply()
    {
        GameBoard    board = GameManager.Instance.Game;
        List <SSlot> slots = new List <SSlot>();

        for (int i = 0; i < GameBoard.WIDTH; ++i)
        {
            for (int j = 0; j < GameBoard.HEIGHT; ++j)
            {
                SSlot slot = board.Slots[i, j];
                SPipe pipe = slot.Pipe;
                if (pipe != null)
                {
                    slots.Add(slot);
                }
            }
        }
        return(slots.Count > 0);
    }
    public override void ApplyPowerup(SSlot slot)
    {
        GameBoard board = GameManager.Instance.Game;

        board.SetGameState(EGameState.PlayerUsedPowerup, "PowerUp_DestroyPiece");
        board.BreakePipeInSlot(slot, (slot.Pipe as Pipe_Colored).GetExplodeEffectPrefab());
        //EventData eventData = new EventData("OnPowerUpUsedEvent");
        //eventData.Data["type"] = GameData.PowerUpType.Breake;
        //GameManager.Instance.EventManager.CallOnPowerUpUsedEvent(eventData);
        // if no pipes left - add new pipe on board without move counting
        if (board.GetMovablePipesCount() == 0)
        {
            board.OnTurnWasMade(false, true);
        }
        else
        {
            board.SetGameState(EGameState.PlayersTurn, "DestroyPiece powerup completed");
        }
    }
Пример #18
0
    public bool CheckSlot(SSlot slot)
    {
        if (!slot || !slot.Pipe || slot.Pipe.PipeType != EPipeType.Colored)
        {
            return(false);
        }
        int pipeColor = slot.Pipe.AColor;

        if (pipeColor < Slots.Count)
        {
            if (Slots[pipeColor].CheckAim(slot.Pipe.Param))
            {
                _creaturesManager.CustomizeCreature(pipeColor, Slots[pipeColor].GetLevel());
                SPipe pipe = slot.TakePipe();
                FlyingEffect(pipe);
                return(true);
            }
        }
        return(false);
    }
Пример #19
0
 public bool OnSlotTouched(SSlot slot)
 {
     if (GameManager.Instance.Game.GetGameState() != EGameState.PlayersTurn)
     {
         return(false);
     }
     if (_selectedButton)
     {
         bool applied = _selectedButton.TryApplyPowerup(slot);
         if (applied)
         {
             _selectedButton.Unselect();
             _selectedButton = null;
         }
         return(true); // can't swipe if powerup selected
     }
     else
     {
         return(false);
     }
 }
Пример #20
0
    public virtual bool DealDamage(SSlot slot, int acolor, int power)
    {
        if (_dead)
        {
            Debug.LogError("DEAD!");
            return(false);
        }
        //TODO paper/scissors/stone!!!
        int lives = Lives.GetAmount() - power;

        Lives.SetAmount(lives);
        _dead = Lives.GetAmount() == 0;
        if (_dead)
        {
            slot.TakePipe();
            GameManager.Instance.Game.ACharacters.OnCharacterDied(this);
            PlayDeathAnimation();
        }
        else
        {
            PlayGainDamageAnimation();
        }
        return(_dead);
    }
Пример #21
0
 public virtual void ApplyPowerup(SSlot slot)
 {
 }
Пример #22
0
    private float CreateAttack(GameBoard board, SSlot slot, int pipeColor, int attackPower)
    {
        EnemySlot enemySlot = board.AEnemies.Slots[slot.X]; // find enemies slot in front of slot
        Enemy     enemy     = enemySlot.GetEnemy();

        if (!enemy)
        {
            board.BreakePipeInSlot(slot, (slot.Pipe as Pipe_Colored).GetExplodeEffectPrefab());
            OnEndAttack();
            return(0);
        }
        SPipe pipe = slot.TakePipe();

        //Time.timeScale = 0.1f;
        Vector3 fromPos = pipe.transform.position;
        Vector3 toPos   = enemySlot.transform.position;

        float distance = Mathf.Abs(fromPos.y - toPos.y);
        float speed    = 0.05f; // per unit
        float flyTime  = distance * speed;

        Vector3[] pathPoints = new Vector3[5];
        // from
        Vector3 p1 = fromPos;

        p1.z                    = -11;
        pathPoints[1]           = p1;
        pipe.transform.position = p1;
        // to
        Vector3 p3 = toPos;

        p3.z          = -11;
        pathPoints[3] = p3;
        // first liverage
        Vector3 p0 = p1;

        p0.x         += UnityEngine.Random.Range(-4.0f, 4.0f);
        p0.y         += UnityEngine.Random.Range(-2.0f, -4.0f);
        pathPoints[0] = p0;
        // second liverage
        Vector3 p4 = p3;

        p4.x         += UnityEngine.Random.Range(-4.0f, 4.0f);
        p4.y         += UnityEngine.Random.Range(2.0f, 4.0f);
        pathPoints[4] = p4;
        // middle point
        Vector3 p2 = (p1 + p3) / 2.0f;

        p2.x         += UnityEngine.Random.Range(-3.0f, 3.0f);
        pathPoints[2] = p2;
        //
        LTSpline spline = new LTSpline(pathPoints);
        //
        //GameObject trailEffect = GameObject.Instantiate(FlyEffectPrefab, Vector3.zero, Quaternion.identity) as GameObject;
        //trailEffect.transform.SetParent(pipe.transform, false);
        //trailEffect.transform.localPosition = Vector3.zero;
        ////trailEffect.transform.position = fromPos;
        ////trailEffect.transform.localScale = new Vector3(0, 0, 1);
        ////LeanTween.scale(trailEffect, Vector3.one, Consts.FINAL_ATTACK_TIME / 2.0f)
        ////    .setEase(LeanTweenType.easeInOutSine)
        ////    .setLoopPingPong(1)
        Vector3 startAngle = pipe.transform.eulerAngles;

        LeanTween.value(pipe.gameObject, 0.0f, 1.0f, flyTime)
        .setOnUpdate((float norm) =>
        {
            Vector3 pos             = spline.point(norm);
            pipe.transform.position = pos;
        })
        .setOnComplete(() =>
        {
            ApplyAttack(board, enemy, pipeColor, attackPower);
            //Destroy(trailEffect, Consts.ADD_POINTS_EFFECT_TIME + 0.2f);
            pipe.transform.localScale = Vector3.one;
            pipe.transform.localScale = Vector3.zero;
            pipe.gameObject.SetActive(false);
            //pipe.PlayHideAnimation();
        })
        .setEaseInOutSine();
        LeanTween.rotateX(pipe.gameObject, startAngle.x + 40, (flyTime - 0.05f) / 2.0f)
        .setLoopPingPong(1)
        .setEase(LeanTweenType.easeInOutSine);
        LeanTween.rotateY(pipe.gameObject, startAngle.y + 40, (flyTime - 0.05f) / 2.0f)
        .setLoopPingPong(1)
        .setEase(LeanTweenType.easeInOutSine);
        float scale = 0.85f;

        LeanTween.scale(pipe.gameObject, new Vector3(scale, scale, scale), flyTime - 0.1f);
        return(flyTime);
    }
Пример #23
0
 private void ApplyAttackOnCharacter(SSlot slot, Pipe_Character character, int acolor, int power)
 {
     character.DealDamage(slot, acolor, power);
 }
Пример #24
0
    public void ShowHint(GameBoard.MatchHintData mhData, GameBoard gBoard)
    {
        // rotating
        if (mhData.XA != mhData.XB)
        {
            // horizontal slide
            if (mhData.XA < mhData.XB)
            {
                // slide right
                //Helpers.SetRotationDgr(AGameObject, 0);
            }
            else
            {
                // slide left
                Helpers.SetRotationDgr(AGameObject, 180);
            }
        }
        else
        {
            // vertical slide
            if (mhData.YA < mhData.YB)
            {
                // slide up
                Helpers.SetRotationDgr(AGameObject, 90);
            }
            else
            {
                // slide down
                Helpers.SetRotationDgr(AGameObject, -90);
            }
        }

        // positioning
        SSlot slot = gBoard.GetSlot(mhData.XA, mhData.YA);

        if (slot != null)
        {
            AGameObject.transform.SetParent(slot.transform.parent, false);
            Vector3 pos = slot.transform.position;
            pos.z = -5;
            AGameObject.transform.position = pos;
        }
        // fade in
        Color startColor  = new Color(1, 1, 1, 0);
        Color finishColor = new Color(1, 1, 1, 1);

        for (int i = 0; i < AObjects.Count; ++i)
        {
            GameObject     obj  = AObjects[i];
            SpriteRenderer rend = ARenderers[i];
            LeanTween.cancel(obj);
            rend.color = startColor;
            LeanTween.value(obj, startColor, finishColor, HIDING_SPEED)
            .setOnUpdate(
                (Color val) => {
                rend.color = val;
            }
                )
            .setOnComplete(
                () => {
                AnimateHint();
            }
                );
        }

        //
        float startX  = 0.0f;
        float finishX = 2.0f;

        Helpers.SetXLocal(AObjects[0], startX);
        LeanTween.moveLocalX(AObjects[0], finishX, 0.2f).setLoopPingPong(-1);         //.setEase(LeanTweenType.easeInOutElastic);
    }
Пример #25
0
 public bool IsCanApply(SSlot slot)
 {
     return(_powerup.IsCanApply(slot));
 }
Пример #26
0
 public virtual bool IsCanApply(SSlot slot)
 {
     return(true);
 }
Пример #27
0
 // for players attacks
 public virtual IEnumerator AttackCoroutine(GameBoard board, SSlot slot, int pipeColor, int attackPower)
 {
     ResetWeapon();
     yield return(new WaitForSeconds(0.1f));
 }
Пример #28
0
 public override IEnumerator AttackCoroutine(GameBoard board, SSlot slot, int pipeColor, int attackPower)
 {
     OnStartAttack();
     yield return(new WaitForSeconds(CreateAttack(board, slot, pipeColor, attackPower)));
 }
Пример #29
0
    public override void ApplyPowerup()
    {
        GameBoard board = GameManager.Instance.Game;

        board.SetGameState(EGameState.PlayerUsedPowerup, "PowerUp_Reshuffle");
        List <SSlot> slots = new List <SSlot>();

        for (int i = 0; i < GameBoard.WIDTH; ++i)
        {
            for (int j = 0; j < GameBoard.HEIGHT; ++j)
            {
                SSlot slot = board.Slots[i, j];
                SPipe pipe = slot.Pipe;
                if (pipe != null)
                {
                    slots.Add(slot);
                }
            }
        }
        if (slots.Count > 0)
        {
            //int boosterPower = GameManager.Instance.Player.BoosterLevel * Consts.PU__POWER_PER_LEVEL_RESHUFFLE;
            //boosterPower = Mathf.Min(slots.Count, boosterPower);
            int boosterPower = slots.Count;
            // take pipes from slots
            slots = Helpers.ShuffleList(slots);
            List <SPipe> pipes = new List <SPipe>();
            for (int i = 0; i < boosterPower; ++i)
            {
                pipes.Add(slots[i].TakePipe());
            }
            // find free slots
            List <SSlot> freeSlots = board.GetEmptySSlots();
            // randomly move pipes to slots
            float maxTime = 0;
            for (int i = 0; i < boosterPower; ++i)
            {
                // add to new slot
                SPipe pipe  = pipes[i];
                int   randI = UnityEngine.Random.Range(0, freeSlots.Count);
                SSlot slot  = freeSlots[randI];

                if (slot.X == pipe.X && slot.Y == pipe.Y && freeSlots.Count > 1)
                {
                    // we must change slot
                    --i;
                    continue;
                }

                freeSlots.RemoveAt(randI);
                // find distance
                float dx       = pipe.X - slot.X;
                float dy       = pipe.Y - slot.Y;
                float distance = Mathf.Sqrt(dx * dx + dy * dy);
                // find move time, check max time
                float moveTime = distance * Consts.PU__RESHUFFLE_TIME_PER_SLOT;
                if (moveTime > maxTime)
                {
                    maxTime = moveTime;
                }
                //
                slot.SetPipe(pipe, false);
                // move upper
                Vector3 oldPos = pipe.transform.position;
                oldPos.z = GameBoard.PipeZ - 1.0f;
                pipe.transform.position = oldPos;
                // fly to new slot
                GameObject pipeObj = pipe.gameObject;
                LeanTween.cancel(pipeObj);
                Vector3 newPos = slot.transform.position;
                newPos.z = GameBoard.PipeZ;
                LeanTween.move(pipeObj, newPos, moveTime)
                //.setDelay(i * 0.01f)
                .setEase(LeanTweenType.easeInOutSine);
            }
            MusicManager.playSound("reshuffle");
            pipes.Clear();
            freeSlots.Clear();
            ////
            //EventData eventData = new EventData("OnPowerUpUsedEvent");
            //eventData.Data["type"] = GameData.PowerUpType.Reshuffle;
            //GameManager.Instance.EventManager.CallOnPowerUpUsedEvent(eventData);
            ////
            LeanTween.delayedCall(maxTime, () =>
            {
                if (!board.CheckIfOutOfMoves())
                {
                    board.SetGameState(EGameState.PlayersTurn, "Reshuffle powerup completed");
                }
            });
            //Invoke("CheckIfOutOfMoves", maxTime);
        }
        else
        {
            //TODO wrong sound, nothing happens
            board.SetGameState(EGameState.PlayersTurn, "Reshuffle wrong");
        }
    }