WXMC/.svn/pristine/6e/6e845c47403801e0e51b7dc67f0192f815c7e617.svn-base
2024-12-04 16:18:46 +08:00

4752 lines
149 KiB
Plaintext

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using PuzzleDefine;
public class Board : MonoBehaviour
{
// public
[Header("Nodes")]
public List<Node> nodes = new List<Node>();
[Header("Board variables")]
public int BoardIndex;
public GAME_STATE state;
public bool lockSwap;
public int moveLeft;
public int dropTime;
public int score;
public int star;
public int target1Left;
public int target2Left;
public int target3Left;
public int target4Left;
public int row;
public int column;
public RowAlignmentType rowAlignmentType;
public ColumnAlignmentType columnAlignmentType;
[Header("Booster")]
public BOOSTER_TYPE booster;
public List<Item> boosterItems = new List<Item>();
public Item ovenTouchItem;
[Header("Check")]
public int destroyingItems;
public int droppingItems;
public int flyingItems;
public int matching;
[Header("")]
public bool movingGingerbread;
public bool generatingGingerbread;
public bool skipGenerateGingerbread;
public bool showingInspiringPopup;
public int skipGingerbreadCount;
[Header("Item Lists")]
public List<Item> changingList;
public List<Item> sameColorList;
[Header("Swap")]
public Item touchedItem;
public Item swappedItem;
// UI
[Header("UI")]
public GameObject target1;
public GameObject target2;
public GameObject target3;
public GameObject target4;
public UITarget UITarget;
public UITop UITop;
// Popup
[Header("Popup")]
public PopupOpener targetPopup;
public PopupOpener completedPopup;
public PopupOpener winPopup;
public PopupOpener losePopup;
public PopupOpener noMatchesPopup;
public PopupOpener plus5MovesPopup;
public PopupOpener amazingPopup;
public PopupOpener excellentPopup;
public PopupOpener greatPopup;
// hint
[Header("Hint")]
public int checkHintCall;
public int showHintCall;
public List<Item> hintItems = new List<Item>();
[Header("HeroSkill")]
public bool heroSkillDisplay;
public Vector2Int heroSkillPos;
public Vector2Int heroSkillSize;
// private
Vector3 firstNodePosition;
void Awake()
{
// debug
if (LevelLoader.instance.level == 0)
{
LevelLoader.instance.LoadLevel(true);
}
}
public void Init()
{
state = GAME_STATE.PREPARING_LEVEL;
moveLeft = LevelLoader.instance.moves;
target1Left = LevelLoader.instance.target1Amount;
target2Left = LevelLoader.instance.target2Amount;
target3Left = LevelLoader.instance.target3Amount;
target4Left = LevelLoader.instance.target4Amount;
GenerateBoard();
BeginBooster();
// reset color of the random cookie to make sure there is no match in the original board
//GenerateNoMatches();
// open target popup
// TargetPopup();
}
// float Timer;
// float ClickGap = 0.5f;
void Update()
{
//if (Input.GetKeyDown(KeyCode.Escape))
//{
// Application.Quit();
//}
// if(Timer<ClickGap){
// Timer+= Time.deltaTime;
// }
if (Input.GetMouseButtonDown(0))
{
Collider2D hit = Physics2D.OverlapPoint(Camera.main.ScreenToWorldPoint(Input.mousePosition));
if (hit != null)
{
// if(Timer<ClickGap)return;
// Timer = 0;
var skillDisplayer = hit.gameObject.GetComponent<PuzzleSkillDisplayer>();
var item = hit.gameObject.GetComponent<Item>();
if (skillDisplayer != null && skillDisplayer.currBoard.BoardIndex == BoardIndex)
{
skillDisplayer.TryCastSkill();
}
else if (item != null && item.board.BoardIndex == BoardIndex)
{
PuzzleGameMode.main.PlayerChoosePosition(PuzzleGameMode.main.GetItemPosition(item));
//DestroyBoosterItems(item);
}
}
}
if (state == GAME_STATE.WAITING_USER_SWAP && lockSwap == false && moveLeft > 0)
{
if (Configure.instance.touchIsSwallowed == true && GameObject.Find("Help") != null && GameObject.Find("Help").activeSelf == true)
{
return;
}
// no booster
if (booster == BOOSTER_TYPE.NONE)
{
// // mouse down
//if (Input.GetMouseButtonDown(0))
//{
// // hit the collier
// Collider2D hit = Physics2D.OverlapPoint(Camera.main.ScreenToWorldPoint(Input.mousePosition));
// if (hit != null)
// {
// Item item = hit.gameObject.GetComponent<Item>();
// if (item != null)
// {
// if (item.Movable())
// {
// item.drag = true;
// item.mousePostion = item.GetMousePosition();
// item.deltaPosition = Vector3.zero;
// movingGingerbread = false;
// generatingGingerbread = false;
// skipGenerateGingerbread = false;
// }
// }
// }
}
// mouse up
//else if (Input.GetMouseButtonUp(0))
// {
// Collider2D hit = Physics2D.OverlapPoint(Camera.main.ScreenToWorldPoint(Input.mousePosition));
// if (hit != null)
// {
// var item = hit.gameObject.GetComponent<Item>();
// if (item != null)
// {
// item.drag = false;
// item.swapDirection = Vector3.zero;
// }
// }
// }
//}
// use booster
else
{
//if (Input.GetMouseButtonDown(0))
//{
// Collider2D hit = Physics2D.OverlapPoint(Camera.main.ScreenToWorldPoint(Input.mousePosition));
// if (hit != null)
// {
// var item = hit.gameObject.GetComponent<Item>();
// if (item != null)
// {
// PuzzleGameMode.main.PlayerChoosePosition(PuzzleGameMode.main.GetItemPosition(item));
// //DestroyBoosterItems(item);
// }
// }
//}
}
} // if state is WAITING_USER_SWAP
// fix freezing board
if (state == GAME_STATE.DESTROYING_ITEMS)
{
if (lockSwap == false && destroyingItems == 0 && droppingItems == 0 && flyingItems == 0 && matching == 0)
{
state = GAME_STATE.WAITING_USER_SWAP;
}
}
}
#region Board
void GenerateBoard()
{
row = LevelLoader.instance.row;
column = LevelLoader.instance.column;
if (LevelLoader.instance.currLevelData != null)
{
row = (int)LevelLoader.instance.currLevelData.BoardSizeList[BoardIndex].x;
column = (int)LevelLoader.instance.currLevelData.BoardSizeList[BoardIndex].y;
}
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
{
var order = NodeOrder(i, j);
GameObject node = Instantiate(Resources.Load(Configure.NodePrefab())) as GameObject;
node.transform.SetParent(gameObject.transform, false);
node.name = "Node " + order;
node.GetComponent<Node>().board = this;
node.GetComponent<Node>().i = i;
node.GetComponent<Node>().j = j;
nodes.Add(node.GetComponent<Node>());
} // end for j
} // end for i
GenerateTileLayer();
GenerateTileBorder();
GenerateWaffleLayer();
GenerateItemLayer();
//GenerateCageLayer();
GenerateCollectibleBoxByColumn();
GenerateCollectibleBoxByNode();
}
void GenerateTileLayer()
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
{
var order = NodeOrder(i, j);
// var tileLayerData = LevelLoader.instance.tileLayerData;
//var tileLayerData = LevelLoader.instance.currLevelData.TileTypeList[BoardIndex].tileTypeData;
GameObject tile = null;
TILE_TYPE tileType;
//switch (tileLayerData[order])
//{
// case TILE_TYPE.NONE:
// tile = Instantiate(Resources.Load(Configure.NoneTilePrefab())) as GameObject;
// break;
// case TILE_TYPE.PASS_THROUGH:
// tile = Instantiate(Resources.Load(Configure.NoneTilePrefab())) as GameObject;
// break;
// case TILE_TYPE.LIGHT_TILE:
// tile = Instantiate(Resources.Load(Configure.LightTilePrefab())) as GameObject;
// break;
// case TILE_TYPE.DARD_TILE:
// tile = Instantiate(Resources.Load(Configure.DarkTilePrefab())) as GameObject;
// break;
//}
if (order % 2 == 0)
{
tile = Instantiate(Resources.Load(Configure.LightTilePrefab())) as GameObject;
tileType = TILE_TYPE.LIGHT_TILE;
}
else
{
tile = Instantiate(Resources.Load(Configure.DarkTilePrefab())) as GameObject;
tileType = TILE_TYPE.DARD_TILE;
}
if (tile)
{
tile.transform.SetParent(nodes[order].gameObject.transform);
tile.name = "Tile";
tile.transform.localPosition = NodeLocalPosition(i, j);
tile.GetComponent<Tile>().type = tileType;
tile.GetComponent<Tile>().node = nodes[order];
tile.transform.localScale = PuzzleGameMode.main.GetGemSize();
//if (tile.GetComponent<SpriteRenderer>()) tile.GetComponent<SpriteRenderer>().enabled = false;
nodes[order].tile = tile.GetComponent<Tile>();
}
} // end for j
} // end for i
}
void GenerateTileBorder()
{
// for (int i = 0; i < row; i++)
// {
// for (int j = 0; j < column; j++)
// {
// var order = NodeOrder(i, j);
// nodes[order].tile.SetBorder();
// }
// }
}
// waffle
void GenerateWaffleLayer()
{
if (LevelLoader.instance.currLevelData.WaffleTypeList == null || LevelLoader.instance.currLevelData.WaffleTypeList.Count <= BoardIndex)
{
return;
}
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
{
var order = NodeOrder(i, j);
// var waffleLayerData = LevelLoader.instance.waffleLayerData;
var waffleLayerData = LevelLoader.instance.currLevelData.WaffleTypeList[BoardIndex].waffleTypeData;
GameObject waffle = null;
switch (waffleLayerData[order])
{
case WAFFLE_TYPE.WAFFLE_1:
waffle = Instantiate(Resources.Load(Configure.Waffle1())) as GameObject;
break;
case WAFFLE_TYPE.WAFFLE_2:
waffle = Instantiate(Resources.Load(Configure.Waffle2())) as GameObject;
break;
case WAFFLE_TYPE.WAFFLE_3:
waffle = Instantiate(Resources.Load(Configure.Waffle3())) as GameObject;
break;
}
if (waffle)
{
waffle.transform.SetParent(nodes[order].gameObject.transform);
waffle.name = "Waffle";
waffle.transform.localPosition = NodeLocalPosition(i, j);
waffle.GetComponent<Waffle>().type = waffleLayerData[order];
waffle.GetComponent<Waffle>().node = nodes[order];
nodes[order].waffle = waffle.GetComponent<Waffle>();
}
}
}
}
void GenerateItemLayer()
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
{
var order = NodeOrder(i, j);
// var itemLayerData = LevelLoader.instance.itemLayerData;
//var itemLayerData = LevelLoader.instance.currLevelData.ItemTypeList[BoardIndex].itemTypeData;
if (nodes[order].CanStoreItem())
{
//nodes[order].GenerateItem(itemLayerData[order]);
nodes[order].GenerateItem(ITEM_TYPE.COOKIE_RAMDOM);
// add mask
var mask = Instantiate(Resources.Load(Configure.Mask())) as GameObject;
mask.transform.SetParent(nodes[order].transform);
mask.transform.localPosition = NodeLocalPosition(i, j);
mask.transform.localScale = PuzzleGameMode.main.GetGemSize();
mask.name = "Mask";
}
}
}
DealNoMatchCase(Vector2.one * -1);
}
Vector2 originlaPos = Vector2.one * -1;
void DealNoMatchCase(Vector2 createPos)
{
bool canMatch = false;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
{
var order = NodeOrder(i, j);
Gem gem;
HashSet<Position> connectedGems = new HashSet<Position>();
if (nodes[order].item != null)
{
PuzzleGameMode.main.CalcConnectionMatch(PuzzleGameMode.main.GetItemPosition(nodes[order].item), connectedGems, out gem);
if (connectedGems.Count > 1)
{
canMatch = true;
break;
}
}
}
if (canMatch) break;
}
if (!canMatch)
{
List<Vector2Int> canChangeList = GetCanChangeList();
if (canChangeList.Count <= 0) { return; }
int randomIndex = Random.Range(0, canChangeList.Count);
int randomRow = canChangeList[randomIndex].x;
int randomColumn = canChangeList[randomIndex].y;
if (createPos != Vector2.one * -1)
{
randomRow = (int)createPos.x;
randomColumn = (int)createPos.y;
}
var order = NodeOrder(randomRow, randomColumn);
int sameIndex = GetSameIndex(randomRow, randomColumn);
if (nodes[order].CanStoreItem())
{
if (nodes[order].item != null)
{
nodes[order].item.DestroyItem();
}
if (nodes[sameIndex].item != null)
{
nodes[order].GenerateItem(nodes[sameIndex].item.type);
}
// nodes[order].item.DestroyItem();
// nodes[order].GenerateItem(nodes[sameIndex].item.type);
}
}
}
public List<Vector2Int> GetCanChangeList()
{
List<Vector2Int> changeList = new List<Vector2Int>();
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
{
var CurrNode = GetNode(i, j);
if (CurrNode.CanStoreItem() && GetRoundCanStore(i, j))
{
Vector2Int currVec = new Vector2Int(i, j);
changeList.Add(currVec);
}
}
}
return changeList;
}
public int GetSameIndex(int i, int j)
{
var CurrNode = GetNode(i + 1, j);
if (CurrNode != null && CurrNode.CanStoreItem())
{
return NodeOrder(i + 1, j);
}
CurrNode = GetNode(i, j + 1);
if (CurrNode != null && CurrNode.CanStoreItem())
{
return NodeOrder(i, j + 1);
}
CurrNode = GetNode(i - 1, j);
if (CurrNode != null && CurrNode.CanStoreItem())
{
return NodeOrder(i - 1, j);
}
CurrNode = GetNode(i, j - 1);
if (CurrNode != null && CurrNode.CanStoreItem())
{
return NodeOrder(i, j - 1);
}
return -1;
}
public bool GetRoundCanStore(int i, int j)
{
var CurrNode = GetNode(i + 1, j);
if (CurrNode != null && CurrNode.CanStoreItem())
{
return true;
}
CurrNode = GetNode(i, j + 1);
if (CurrNode != null && CurrNode.CanStoreItem())
{
return true;
}
CurrNode = GetNode(i - 1, j);
if (CurrNode != null && CurrNode.CanStoreItem())
{
return true;
}
CurrNode = GetNode(i, j - 1);
if (CurrNode != null && CurrNode.CanStoreItem())
{
return true;
}
return false;
}
void GenerateCageLayer()
{
if (LevelLoader.instance.currLevelData.CageTypeList == null || LevelLoader.instance.currLevelData.CageTypeList.Count <= BoardIndex)
{
return;
}
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
{
var order = NodeOrder(i, j);
// var cageLayerData = LevelLoader.instance.cageLayerData;
var cageLayerData = LevelLoader.instance.currLevelData.CageTypeList[BoardIndex].cageTypeData;
GameObject cage = null;
switch (cageLayerData[order])
{
case CAGE_TYPE.CAGE_1:
cage = Instantiate(Resources.Load(Configure.Cage1())) as GameObject;
break;
}
if (cage)
{
cage.transform.SetParent(nodes[order].gameObject.transform);
cage.name = "Cage";
cage.transform.localPosition = NodeLocalPosition(i, j);
cage.GetComponent<Cage>().type = cageLayerData[order];
cage.GetComponent<Cage>().node = nodes[order];
nodes[order].cage = cage.GetComponent<Cage>();
}
}
}
}
void GenerateCollectibleBoxByColumn()
{
if (LevelLoader.instance.target1Type != TARGET_TYPE.COLLECTIBLE &&
LevelLoader.instance.target2Type != TARGET_TYPE.COLLECTIBLE &&
LevelLoader.instance.target3Type != TARGET_TYPE.COLLECTIBLE &&
LevelLoader.instance.target4Type != TARGET_TYPE.COLLECTIBLE)
{
return;
}
// foreach (var column in LevelLoader.instance.collectibleCollectColumnMarkers)
foreach (var column in LevelLoader.instance.currLevelData.CollectibleCollectColumnMarkers)
{
var node = GetNode(row - 1, column);
if (node != null && node.CanStoreItem() == true)
{
var box = Instantiate(Resources.Load(Configure.CollectibleBox())) as GameObject;
if (box)
{
box.transform.SetParent(node.gameObject.transform);
box.name = "Box";
box.transform.localPosition = NodeLocalPosition(node.i, node.j) + new Vector3(0, -1 * NodeSize() + 0.2f, 0);
}
}
}
}
void GenerateCollectibleBoxByNode()
{
if (LevelLoader.instance.target1Type != TARGET_TYPE.COLLECTIBLE &&
LevelLoader.instance.target2Type != TARGET_TYPE.COLLECTIBLE &&
LevelLoader.instance.target3Type != TARGET_TYPE.COLLECTIBLE &&
LevelLoader.instance.target4Type != TARGET_TYPE.COLLECTIBLE)
{
return;
}
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
{
var order = NodeOrder(i, j);
// if (LevelLoader.instance.collectibleCollectNodeMarkers.Contains(order))
if (LevelLoader.instance.currLevelData.CollectibleCollectNodeMarkers.Contains(order))
{
var node = GetNode(i, j);
if (node != null)
{
var box = Instantiate(Resources.Load(Configure.CollectibleBox())) as GameObject;
if (box)
{
box.transform.SetParent(node.gameObject.transform);
box.name = "Box";
box.transform.localPosition = NodeLocalPosition(node.i, node.j) + new Vector3(0, -1 * NodeSize() + 0.2f, 0);
}
}
}
}
}
}
#endregion
#region Begin
void BeginBooster()
{
if (Configure.instance.beginFiveMoves == true)
{
//Configure.instance.beginFiveMoves = false;
GameData.instance.SaveBeginFiveMoves(GameData.instance.GetBeginFiveMoves() - 1);
moveLeft += Configure.instance.plusMoves;
}
if (Configure.instance.beginRainbow == true)
{
Configure.instance.beginRainbow = false;
GameData.instance.SaveBeginRainbow(GameData.instance.GetBeginRainbow() - 1);
var items = GetListItems();
var cookies = new List<Item>();
foreach (var item in items)
{
if (item != null && item.IsCookie() && item.Movable())
{
cookies.Add(item);
}
}
var cookie = cookies[Random.Range(0, cookies.Count - 1)];
cookie.ChangeToRainbow();
}
if (Configure.instance.beginBombBreaker == true)
{
Configure.instance.beginBombBreaker = false;
GameData.instance.SaveBeginBombBreaker(GameData.instance.GetBeginBombBreaker() - 1);
var items = GetListItems();
var cookies = new List<Item>();
foreach (var item in items)
{
if (item != null && item.IsCookie() && item.Movable())
{
cookies.Add(item);
}
}
var cookie = cookies[Random.Range(0, cookies.Count - 1)];
cookie.ChangeToBombBreaker();
}
}
#endregion
#region Utility
Vector3 CalculateFirstNodePosition()
{
// var width = NodeSize();
// var height = NodeSize();
// var offset = new Vector3(0, -1, 0);
// return (new Vector3(-((column - 1) * width / 2), (row - 1) * height / 2, 0) + offset);
var width = NodeSize();
var height = NodeSize();
if (columnAlignmentType == ColumnAlignmentType.Upper)
{
if (rowAlignmentType == RowAlignmentType.Left)
{
return new Vector3(width / 2, -height / 2, 0);
}
else if (rowAlignmentType == RowAlignmentType.Center)
{
return (new Vector3(-((column - 1) * width / 2), -height / 2, 0));
}
else
{
return new Vector3(-(column - 1) * width - width / 2, -height / 2, 0);
}
}
else if (columnAlignmentType == ColumnAlignmentType.Middle)
{
if (rowAlignmentType == RowAlignmentType.Left)
{
return new Vector3(width / 2, (row - 1) * height / 2, 0);
}
else if (rowAlignmentType == RowAlignmentType.Center)
{
return new Vector3(-((column - 1) * width / 2),
(row - 1) * height / 2, 0);
}
else
{
return new Vector3(-(column - 1) * width - width / 2,
(row - 1) * height / 2, 0);
}
}
else
{
if (rowAlignmentType == RowAlignmentType.Left)
{
return new Vector3(width / 2, (row - 1) * height + height / 2, 0);
}
else if (rowAlignmentType == RowAlignmentType.Center)
{
return new Vector3(-((column - 1) * width / 2),
(row - 1) * height + height / 2, 0);
}
else
{
return new Vector3(-(column - 1) * width - width / 2, (row - 1) * height + height / 2, 0);
}
}
}
public float NodeSize()
{
// return 0.672f;
return 0.96f * PuzzleGameMode.main.PuzzleUXConfig.GemSize;
}
public Vector3 NodeLocalPosition(int i, int j)
{
var width = NodeSize();
var height = NodeSize();
if (firstNodePosition == Vector3.zero)
{
firstNodePosition = CalculateFirstNodePosition();
}
var x = firstNodePosition.x + j * width;
var y = firstNodePosition.y - i * height;
return new Vector3(x, y, 0);
}
public int NodeOrder(int i, int j)
{
return (i * column + j);
}
public Node GetNode(int currRow, int currColumn)
{
if (currRow < 0 || currRow >= row || currColumn < 0 || currColumn >= column)
{
return null;
}
return nodes[currRow * column + currColumn];
}
Vector3 ColumnFirstItemPosition(int i, int j)
{
Node node = GetNode(i, j);
if (node != null)
{
var item = node.item;
if (item != null)
{
return item.gameObject.transform.position;
}
else
{
return ColumnFirstItemPosition(i + 1, j);
}
}
else
{
return Vector3.zero;
}
}
// return a list of items
public List<Item> GetListItems()
{
var items = new List<Item>();
foreach (var node in nodes)
{
if (node != null)
{
items.Add(node.item);
}
}
return items;
}
#endregion
#region Match
// re-generate the board to make sure there is no "pre-matches"
void GenerateNoMatches()
{
//Debug.Log("Start generating matches");
var combines = GetMatches();
do
{
foreach (var combine in combines)
{
int i = 0;
foreach (var item in combine)
{
if (item != null)
{
// only re-generate color for random item
if (item.OriginCookieType() == ITEM_TYPE.COOKIE_RAMDOM)
{
item.GenerateColor(item.color + i);
i++;
}
}
}
}
combines = GetMatches();
} while (combines.Count > 0);
//Debug.Log("End generating matches");
}
// return the list of matches on the board
public List<List<Item>> GetMatches(FIND_DIRECTION direction = FIND_DIRECTION.NONE, int matches = 3)
{
var combines = new List<List<Item>>();
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
{
if (GetNode(i, j) != null)
{
List<Item> combine = GetNode(i, j).FindMatches(direction, matches);
// combine can be null
if (combine != null)
{
if (combine.Count >= matches)
{
combines.Add(combine);
}
}
}
}
}
return combines;
}
public void FindMatches()
{
//print("find matches");
//StartCoroutine(DestroyMatches());
StartCoroutine(NewDestoryMatches());
}
IEnumerator NewDestoryMatches()
{
//var combines = GetMatches();
//foreach (var combine in combines)
//{
// foreach (var item in combine)
// {
// item.Destroy();
// }
//}
while (destroyingItems > 0)
{
//Debug.Log("Destroying items");
yield return new WaitForSeconds(0.1f);
}
yield return new WaitForEndOfFrame();
Drop();
PuzzleGameMode.main.OnGemFallingFinished();
}
// destroy the matches on the board
IEnumerator DestroyMatches()
{
matching++;
while (true)
{
var combines = GetMatches();
//Debug.Log("Number of combines: " + combines.Count);
foreach (var combine in combines)
{
//Debug.Log("Combine count: " + combine.Count);
if (combine.Count == 3 && combines.Count > 3)
{
// item in match-3 can be a bomb-breaker/x-breaker
SetBombBreakerOrXBreakerCombine(GetMatches(FIND_DIRECTION.ROW));
}
else if (combine.Count == 4)
{
SetColRowBreakerCombine(combine);
}
else if (combine.Count >= 5)
{
SetRainbowCombine(combine);
}
foreach (var item in combine)
{
item.Destroy();
}
} // end foreach combines
// wait until item destroy animation finish
while (destroyingItems > 0)
{
//Debug.Log("Destroying items");
yield return new WaitForSeconds(0.1f);
}
// IMPORTANT: as describe in document Destroy is always delayed (but executed within the same frame).
// So There is case destroyingItems = 0 BUT the item still exist that causes the GenerateNewItems function goes wrong
yield return new WaitForEndOfFrame();
// new items
Drop();
while (droppingItems > 0)
{
//Debug.Log("Dropping items");
yield return new WaitForSeconds(0.1f);
}
yield return new WaitForEndOfFrame();
// check if collect collectible
if (GetMatches().Count <= 0 && CollectCollectible() == false)
{
break;
}
// increase dropTime
dropTime++;
} // end while
// wait until all flying items fly to top bar
while (flyingItems > 0)
{
//Debug.Log("Flying items");
yield return new WaitForSeconds(0.1f);
}
yield return new WaitForEndOfFrame();
if (matching > 1)
{
matching--;
yield break;
}
PuzzleGameMode.main.OnGemFallingFinished();
// check if level complete
//if (state == GAME_STATE.WAITING_USER_SWAP)
//{
// if (moveLeft > 0)
// {
// if (IsLevelCompleted())
// {
// StartCoroutine(PreWinAutoPlay());
// }
// else
// {
// if (MoveGingerbread() == true)
// {
// yield return new WaitForSeconds(Configure.instance.swapTime);
// yield return new WaitForSeconds(0.2f);
// FindMatches();
// }
// if (GenerateGingerbread() == true)
// {
// yield return new WaitForSeconds(0.2f);
// FindMatches();
// }
// if (Help.instance.help == false)
// {
// StartCoroutine(CheckHint());
// }
// else
// {
// Help.instance.Show();
// }
// }
// }
// else if (moveLeft == 0)
// {
// if (IsLevelCompleted())
// {
// SaveLevelInfo();
// // show win popup
// state = GAME_STATE.OPENING_POPUP;
// winPopup.OpenPopup();
// AudioManager.instance.PopupWinAudio();
// }
// else
// {
// // show lose popup
// state = GAME_STATE.OPENING_POPUP;
// losePopup.OpenPopup();
// AudioManager.instance.PopupLoseAudio();
// }
// }
//}
matching--;
// if dropTime >= 3 we should show some text like: grate, amazing, etc.
if (dropTime >= Configure.instance.encouragingPopup && state == GAME_STATE.WAITING_USER_SWAP && showingInspiringPopup == false)
{
ShowInspiringPopup();
}
// when finish function we can swap again
//yield return new WaitForEndOfFrame();
yield return new WaitForSeconds(0.2f);
lockSwap = false;
}
#endregion
#region Drop
void Drop()
{
if (LevelLoader.instance.currLevelData == null || LevelLoader.instance.currLevelData.FillMode == PuzzleGameMode.FillStrategies.Fall)
{
SetDropTargets();
GenerateNewItems(true, Vector3.zero);
Move();
DropItems();
}
else
{
GenerateNewItems(false, Vector3.zero);
}
PuzzleGameMode.main.OnAftermapFilled();
}
// set drop target to the remain items
void SetDropTargets()
{
for (int j = 0; j < column; j++)
{
//need to enumerate rows from bottom to top
for (int i = row - 1; i >= 0; i--)
{
Node node = GetNode(i, j);
if (node != null)
{
Item item = node.item;
if (item != null)
{
// start calculating new target for the node
if (item.Movable())
{
Node target = node.BottomNeighbor();
if (target != null && target.CanGoThrough())
{
if (target.item == null)
{
// check rows below at this time GetNode(i + 1, j) = target
for (int k = i + 2; k < row; k++)
{
if (GetNode(k, j) != null)
{
if (GetNode(k, j).item == null)
{
if (GetNode(k, j).CanStoreItem() == true)
{
target = GetNode(k, j);
}
}
// if a node can not go through we do not need to check bellow
if (GetNode(k, j).CanGoThrough() == false)
{
break;
}
else
{
if (GetNode(k, j).item != null)
{
if (GetNode(k, j).item.Movable() == false)
{
break;
}
}
}
}
}
}
// after have the target we swap items on nodes
if (target.item == null && target.CanStoreItem() == true)
{
target.item = item;
target.item.gameObject.transform.SetParent(target.gameObject.transform);
target.item.node = target;
node.item = null;
}
} // end if target != null
} // end item dropable
} // end item != null
} // end node != null
} // end for i
} // end for j
}
// after destroy and drop items then we generate new items
void GenerateNewItems(bool IsDrop, Vector3 pos)
{
var marshmallowGenerated = false;
Vector2 FinishPos = Vector2.one * -1;
for (int j = 0; j < column; j++)
{
var space = -1;
var itemPos = Vector3.zero;
for (int i = row - 1; i >= 0; i--)
{
if (GetNode(i, j) != null)
{
if (GetNode(i, j).item == null && GetNode(i, j).CanGenerateNewItem() == true)
{
// if target is collectible the new item can be a collectible
var collectible = false;
// collectible is only generated on the highest row
if (i == 0)
{
// check if need to generate new collectible
if (CheckGenerateCollectible() != null &&
CheckGenerateCollectible().Count > 0 &&
(LevelLoader.instance.collectibleGenerateMarkers.Contains(j) || LevelLoader.instance.collectibleGenerateMarkers.Count == 0))
{
collectible = true;
}
}
// check if need to generate a new marshmallow
var marshmallow = false;
if (CheckGenerateMarshmallow() == true)
{
marshmallow = true;
}
if (pos != Vector3.zero)
{
itemPos = pos + Vector3.up * NodeSize();
}
else
{
// calculate position of the new item
if (i > space)
{
space = i;
}
// can pass through node
var pass = 0;
for (int k = 0; k < row; k++)
{
var node = GetNode(k, j);
if (node != null && node.tile != null && node.tile.type == TILE_TYPE.PASS_THROUGH)
{
pass++;
}
else
{
break;
}
}
itemPos = NodeLocalPosition(i, j) + Vector3.up * (space - pass + 1) * NodeSize();
}
//print("COOKIE: Generate new item");
// if target is collectible then generate a new collectible item
if (collectible == true && Random.Range(0, 2) == 1)
{
GetNode(i, j).GenerateItem(CheckGenerateCollectible()[Random.Range(0, CheckGenerateCollectible().Count)]);
}
// generate a marshmallow
else if (marshmallow == true && Random.Range(0, 2) == 1 && marshmallowGenerated == false)
{
marshmallowGenerated = true;
GetNode(i, j).GenerateItem(ITEM_TYPE.MARSHMALLOW);
}
// generate a new random cookie
else
{
FinishPos.x = i;
FinishPos.y = j;
GetNode(i, j).GenerateItem(ITEM_TYPE.COOKIE_RAMDOM);
}
// set position
var newItem = GetNode(i, j).item;
if (newItem != null)
{
if (IsDrop == true)
{
newItem.gameObject.transform.localPosition = itemPos;
}
else
{
newItem.gameObject.transform.localPosition = NodeLocalPosition(i, j);
}
}
}
}
}
}
DealNoMatchCase(FinishPos);
}
// move item to neighbor empty node
void Move()
{
for (int i = row - 1; i >= 0; i--)
{
//need to enumerate rows from bottom to top
for (int j = 0; j < column; j++)
{
Node node = GetNode(i, j);
if (node != null)
{
if (node.item == null && node.CanStoreItem())
{
Node source = node.GetSourceNode();
if (source != null)
{
// Debug.Log("source node: " + source.name);
// new item position
var pos = ColumnFirstItemPosition(0, source.j);
print(pos);
// calculate move path
List<Vector3> path = node.GetMovePath();
if (source.transform.position != NodeLocalPosition(source.i, source.j) + transform.position)
{
// if source item is just generated
path.Add(NodeLocalPosition(source.i, source.j) + transform.position);
}
node.item = source.item;
node.item.gameObject.transform.SetParent(node.gameObject.transform);
node.item.node = node;
source.item = null;
if (path.Count > 1)
{
path.Reverse();
node.item.dropPath = path;
}
SetDropTargets();
GenerateNewItems(true, pos);
} // end if source node != null
}
} // end if node != null
} // for j
} // for i
}
// drop item to new position
void DropItems()
{
//print("COOKIE: Drop items");
for (int j = 0; j < column; j++)
{
for (int i = row - 1; i >= 0; i--)
{
if (GetNode(i, j) != null)
{
if (GetNode(i, j).item != null)
{
GetNode(i, j).item.Drop();
}
}
}
}
}
#endregion
#region Item
// this function check all the items and set them to be bomb-breaker/x-breaker
public void SetBombBreakerOrXBreakerCombine(List<List<Item>> lists)
{
foreach (List<Item> list in lists)
{
foreach (Item item in list)
{
if (item != null && item.node != null)
{
//print(item.node.name);
if (item.node.FindMatches(FIND_DIRECTION.COLUMN).Count > 2)
{
if (item.next == ITEM_TYPE.NONE)
{
var match = item.node.FindMatches(FIND_DIRECTION.COLUMN);
Node top = item.node.TopNeighbor();
Node bottom = item.node.BottomNeighbor();
if (top != null && bottom != null)
{
// - - o -
// o o - o
// - - o -
if (top.item != null && bottom.item != null)
{
if (match.Contains(top.item) && match.Contains(bottom.item))
{
//print("T shape");
item.next = item.GetXBreaker(item.type);
return;
}
}
var topTop = top.TopNeighbor();
var bottomBottom = bottom.BottomNeighbor();
// - - o
// - - o
// o o - o
if (topTop != null)
{
if (top.item != null && topTop.item != null)
{
if (match.Contains(top.item) && match.Contains(topTop.item))
{
var left = item.node.LeftNeighbor();
var right = item.node.RightNeighbor();
if (left != null && right != null)
{
if (left.item != null && right.item != null)
{
if (list.Contains(left.item) && list.Contains(right.item))
{
//print("T shape (top)");
item.next = item.GetXBreaker(item.type);
return;
}
}
}
}
}
}
// o o - o
// - - o
// - - o
if (bottomBottom != null)
{
if (bottom.item != null && bottomBottom.item != null)
{
if (match.Contains(bottom.item) && match.Contains(bottomBottom.item))
{
var left = item.node.LeftNeighbor();
var right = item.node.RightNeighbor();
if (left != null && right != null)
{
if (left.item != null && right.item != null)
{
if (list.Contains(left.item) && list.Contains(right.item))
{
//print("T shape (bottom)");
item.next = item.GetXBreaker(item.type);
return;
}
}
}
}
}
}
} // end check T shape
// L shape = bomb breaker
item.next = item.GetBombBreaker(item.type);
} // item.next = none
} // count > 2
}
}
}
}
public void SetColRowBreakerCombine(List<Item> combine)
{
bool isSwap = false;
foreach (Item item in combine)
{
if (item.next != ITEM_TYPE.NONE)
{
isSwap = true;
break;
}
}
// next type is normal (drop then match) get first item in the combine
if (!isSwap)
{
Item first = null;
foreach (Item item in combine)
{
if (first == null)
{
first = item;
}
else
{
if (item.node.OrderOnBoard() < first.node.OrderOnBoard())
{
first = item;
}
}
}
foreach (Item item in combine)
{
if (first.node.RightNeighbor())
{
if (item.node.OrderOnBoard() == first.node.RightNeighbor().OrderOnBoard())
{
first.next = first.GetColumnBreaker(first.type);
break;
}
}
if (first.node.BottomNeighbor())
{
if (item.node.OrderOnBoard() == first.node.BottomNeighbor().OrderOnBoard())
{
first.next = first.GetRowBreaker(first.type);
break;
}
}
}
} // not swap
}
public void SetRainbowCombine(List<Item> combine)
{
bool isSwap = false;
foreach (Item item in combine)
{
if (item.next != ITEM_TYPE.NONE)
{
isSwap = true;
break;
}
}
if (!isSwap)
{
Item first = null;
foreach (Item item in combine)
{
if (first == null)
{
first = item;
}
else
{
if (item.node.OrderOnBoard() < first.node.OrderOnBoard())
{
first = item;
}
}
}
foreach (Item item in combine)
{
if (first.node.RightNeighbor())
{
if (item.node.OrderOnBoard() == first.node.RightNeighbor().OrderOnBoard())
{
combine[2].next = ITEM_TYPE.COOKIE_RAINBOW;
break;
}
}
if (first.node.BottomNeighbor())
{
if (item.node.OrderOnBoard() == first.node.BottomNeighbor().OrderOnBoard())
{
first.next = ITEM_TYPE.COOKIE_RAINBOW;
break;
}
}
}
}
}
// return 9 items around
public List<Item> ItemAround(Node node)
{
List<Item> items = new List<Item>();
for (int i = node.i - 1; i <= node.i + 1; i++)
{
for (int j = node.j - 1; j <= node.j + 1; j++)
{
if (GetNode(i, j) != null)
{
items.Add(GetNode(i, j).item);
}
}
}
return items;
}
public List<Item> XCrossItems(Node node)
{
var items = new List<Item>();
for (int i = 0; i < row; i++)
{
if (i < node.i)
{
var crossLeft = GetNode(i, node.j - (node.i - i));
var crossRight = GetNode(i, node.j + (node.i - i));
if (crossLeft != null)
{
if (crossLeft.item != null)
{
items.Add(crossLeft.item);
}
}
if (crossRight != null)
{
if (crossRight.item != null)
{
items.Add(crossRight.item);
}
}
}
else if (i == node.i)
{
if (node.item != null)
{
items.Add(node.item);
}
}
else if (i > node.i)
{
var crossLeft = GetNode(i, node.j - (i - node.i));
var crossRight = GetNode(i, node.j + (i - node.i));
if (crossLeft != null)
{
if (crossLeft.item != null)
{
items.Add(crossLeft.item);
}
}
if (crossRight != null)
{
if (crossRight.item != null)
{
items.Add(crossRight.item);
}
}
}
}
return items;
}
// return list of items in a column
public List<Item> ColumnItems(int column)
{
var items = new List<Item>();
for (int i = 0; i < row; i++)
{
if (GetNode(i, column) != null)
{
items.Add(GetNode(i, column).item);
}
}
return items;
}
// return list of items in a row
public List<Item> RowItems(int row)
{
var items = new List<Item>();
for (int j = 0; j < column; j++)
{
if (GetNode(row, j) != null)
{
items.Add(GetNode(row, j).item);
}
}
return items;
}
#endregion
#region Destroy
// destroy the whole board when swap 2 rainbow
public void DoubleRainbowDestroy()
{
StartCoroutine(DestroyWholeBoard());
}
IEnumerator DestroyWholeBoard()
{
for (int i = 0; i < column; i++)
{
List<Item> items = ColumnItems(i);
foreach (var item in items)
{
if (item != null && item.Destroyable() == true)
{
//item.type = item.GetCookie(item.type);
GameObject explosion = CFX_SpawnSystem.GetNextObject(Resources.Load(Configure.RainbowExplosion()) as GameObject);
if (explosion != null) explosion.transform.position = item.transform.position;
item.Destroy();
}
}
yield return new WaitForSeconds(0.2f);
}
FindMatches();
}
// destroy all items of changing list
public void DestroyChangingList()
{
StartCoroutine(StartDestroyChangingList());
}
IEnumerator StartDestroyChangingList()
{
//print("Start destroy items in the list");
var originalState = state;
state = GAME_STATE.DESTROYING_ITEMS;
yield return new WaitForSeconds(0.5f);
for (int i = 0; i < changingList.Count; i++)
{
var item = changingList[i];
if (item != null)
{
item.Destroy();
}
while (destroyingItems > 0)
{
yield return new WaitForSeconds(0.1f);
}
yield return new WaitForEndOfFrame();
Drop();
while (droppingItems > 0)
{
yield return new WaitForSeconds(0.1f);
}
yield return new WaitForEndOfFrame();
}
changingList.Clear();
state = originalState;
FindMatches();
}
public void DestroySameColorList()
{
StartCoroutine(StartDestroySameColorList());
}
IEnumerator StartDestroySameColorList()
{
//print("Start destroy items in the same color list");
var originalState = state;
state = GAME_STATE.DESTROYING_ITEMS;
yield return new WaitForSeconds(0.1f);
for (int i = 0; i < sameColorList.Count; i++)
{
var item = sameColorList[i];
if (item != null && item.destroying == false)
{
GameObject explosion = CFX_SpawnSystem.GetNextObject(Resources.Load(Configure.RainbowExplosion()) as GameObject);
if (explosion != null) explosion.transform.position = item.transform.position;
item.Destroy();
yield return new WaitForSeconds(0.1f);
}
}
sameColorList.Clear();
state = originalState;
FindMatches();
}
public void DestroyNeighborItems(Item item)
{
DestroyMarshmallow(item);
DestroyChocolate(item);
DestroyRockCandy(item);
}
public void DestroyMarshmallow(Item item)
{
if (item.IsMarshmallow() == true ||
item.IsCollectible() == true ||
item.IsGingerbread() == true ||
item.IsChocolate() == true ||
item.IsRockCandy() == true)
{
return;
}
if (state == GAME_STATE.PRE_WIN_AUTO_PLAYING)
{
return;
}
var marshmallows = new List<Item>();
if (item.node.TopNeighbor() != null && item.node.TopNeighbor().item != null && item.node.TopNeighbor().item.IsMarshmallow() == true)
{
marshmallows.Add(item.node.TopNeighbor().item);
}
if (item.node.RightNeighbor() != null && item.node.RightNeighbor().item != null && item.node.RightNeighbor().item.IsMarshmallow() == true)
{
marshmallows.Add(item.node.RightNeighbor().item);
}
if (item.node.BottomNeighbor() != null && item.node.BottomNeighbor().item != null && item.node.BottomNeighbor().item.IsMarshmallow() == true)
{
marshmallows.Add(item.node.BottomNeighbor().item);
}
if (item.node.LeftNeighbor() != null && item.node.LeftNeighbor().item != null && item.node.LeftNeighbor().item.IsMarshmallow() == true)
{
marshmallows.Add(item.node.LeftNeighbor().item);
}
foreach (var marshmallow in marshmallows)
{
marshmallow.Destroy();
}
}
public void DestroyChocolate(Item item)
{
if (item.IsMarshmallow() == true ||
item.IsCollectible() == true ||
item.IsGingerbread() == true ||
item.IsChocolate() == true ||
item.IsRockCandy() == true)
{
return;
}
if (state == GAME_STATE.PRE_WIN_AUTO_PLAYING)
{
return;
}
var chocolates = new List<Item>();
if (item.node.TopNeighbor() != null && item.node.TopNeighbor().item != null && item.node.TopNeighbor().item.IsChocolate() == true)
{
chocolates.Add(item.node.TopNeighbor().item);
}
if (item.node.RightNeighbor() != null && item.node.RightNeighbor().item != null && item.node.RightNeighbor().item.IsChocolate() == true)
{
chocolates.Add(item.node.RightNeighbor().item);
}
if (item.node.BottomNeighbor() != null && item.node.BottomNeighbor().item != null && item.node.BottomNeighbor().item.IsChocolate() == true)
{
chocolates.Add(item.node.BottomNeighbor().item);
}
if (item.node.LeftNeighbor() != null && item.node.LeftNeighbor().item != null && item.node.LeftNeighbor().item.IsChocolate() == true)
{
chocolates.Add(item.node.LeftNeighbor().item);
}
foreach (var chocolate in chocolates)
{
chocolate.Destroy();
}
}
public void DestroyRockCandy(Item item)
{
if (item.IsMarshmallow() == true ||
item.IsCollectible() == true ||
item.IsGingerbread() == true ||
item.IsChocolate() == true ||
item.IsRockCandy() == true)
{
return;
}
if (state == GAME_STATE.PRE_WIN_AUTO_PLAYING)
{
return;
}
var rocks = new List<Item>();
if (item.node.TopNeighbor() != null && item.node.TopNeighbor().item != null && item.node.TopNeighbor().item.IsRockCandy() == true && item.node.TopNeighbor().item.color == item.color)
{
rocks.Add(item.node.TopNeighbor().item);
}
if (item.node.RightNeighbor() != null && item.node.RightNeighbor().item != null && item.node.RightNeighbor().item.IsRockCandy() == true && item.node.RightNeighbor().item.color == item.color)
{
rocks.Add(item.node.RightNeighbor().item);
}
if (item.node.BottomNeighbor() != null && item.node.BottomNeighbor().item != null && item.node.BottomNeighbor().item.IsRockCandy() == true && item.node.BottomNeighbor().item.color == item.color)
{
rocks.Add(item.node.BottomNeighbor().item);
}
if (item.node.LeftNeighbor() != null && item.node.LeftNeighbor().item != null && item.node.LeftNeighbor().item.IsRockCandy() == true && item.node.LeftNeighbor().item.color == item.color)
{
rocks.Add(item.node.LeftNeighbor().item);
}
foreach (var rock in rocks)
{
rock.Destroy();
}
}
#endregion
#region Collect
// if item is the target to collect
public void CollectItem(Item item)
{
GameObject flyingItem = null;
var order = 0;
// cookie
if (item.IsCookie())
{
if (LevelLoader.instance.target1Type == TARGET_TYPE.COOKIE && LevelLoader.instance.target1Color == item.color && target1Left > 0)
{
target1Left--;
flyingItem = new GameObject();
order = 1;
}
else if (LevelLoader.instance.target2Type == TARGET_TYPE.COOKIE && LevelLoader.instance.target2Color == item.color && target2Left > 0)
{
target2Left--;
flyingItem = new GameObject();
order = 2;
}
else if (LevelLoader.instance.target3Type == TARGET_TYPE.COOKIE && LevelLoader.instance.target3Color == item.color && target3Left > 0)
{
target3Left--;
flyingItem = new GameObject();
order = 3;
}
else if (LevelLoader.instance.target4Type == TARGET_TYPE.COOKIE && LevelLoader.instance.target4Color == item.color && target4Left > 0)
{
target4Left--;
flyingItem = new GameObject();
order = 4;
}
if (flyingItem != null)
{
flyingItem.transform.position = item.transform.position;
flyingItem.name = "Flying Cookie";
flyingItem.layer = LayerMask.NameToLayer("On Top UI");
SpriteRenderer spriteRenderer = flyingItem.AddComponent<SpriteRenderer>();
GameObject prefab = null;
switch (item.color)
{
case 1:
prefab = Resources.Load(Configure.Cookie1()) as GameObject;
break;
case 2:
prefab = Resources.Load(Configure.Cookie2()) as GameObject;
break;
case 3:
prefab = Resources.Load(Configure.Cookie3()) as GameObject;
break;
case 4:
prefab = Resources.Load(Configure.Cookie4()) as GameObject;
break;
case 5:
prefab = Resources.Load(Configure.Cookie5()) as GameObject;
break;
case 6:
prefab = Resources.Load(Configure.Cookie6()) as GameObject;
break;
}
if (prefab != null)
{
spriteRenderer.sprite = prefab.GetComponent<SpriteRenderer>().sprite;
}
StartCoroutine(CollectItemAnim(flyingItem, order));
}
}
// gingerbread
else if (item.IsGingerbread())
{
if (LevelLoader.instance.target1Type == TARGET_TYPE.GINGERBREAD && target1Left > 0)
{
target1Left--;
flyingItem = new GameObject();
order = 1;
}
else if (LevelLoader.instance.target2Type == TARGET_TYPE.GINGERBREAD && target2Left > 0)
{
target2Left--;
flyingItem = new GameObject();
order = 2;
}
else if (LevelLoader.instance.target3Type == TARGET_TYPE.GINGERBREAD && target3Left > 0)
{
target3Left--;
flyingItem = new GameObject();
order = 3;
}
else if (LevelLoader.instance.target4Type == TARGET_TYPE.GINGERBREAD && target4Left > 0)
{
target4Left--;
flyingItem = new GameObject();
order = 4;
}
if (flyingItem != null)
{
flyingItem.transform.position = item.transform.position;
flyingItem.name = "Flying Gingerbread";
flyingItem.layer = LayerMask.NameToLayer("On Top UI");
SpriteRenderer spriteRenderer = flyingItem.AddComponent<SpriteRenderer>();
GameObject prefab = Resources.Load(Configure.GingerbreadGeneric()) as GameObject;
if (prefab != null)
{
spriteRenderer.sprite = prefab.GetComponent<SpriteRenderer>().sprite;
}
StartCoroutine(CollectItemAnim(flyingItem, order));
}
}
// marshmallow
else if (item.IsMarshmallow())
{
if (LevelLoader.instance.target1Type == TARGET_TYPE.MARSHMALLOW && target1Left > 0)
{
target1Left--;
flyingItem = new GameObject();
order = 1;
}
else if (LevelLoader.instance.target2Type == TARGET_TYPE.MARSHMALLOW && target2Left > 0)
{
target2Left--;
flyingItem = new GameObject();
order = 2;
}
else if (LevelLoader.instance.target3Type == TARGET_TYPE.MARSHMALLOW && target3Left > 0)
{
target3Left--;
flyingItem = new GameObject();
order = 3;
}
else if (LevelLoader.instance.target4Type == TARGET_TYPE.MARSHMALLOW && target4Left > 0)
{
target4Left--;
flyingItem = new GameObject();
order = 4;
}
if (flyingItem != null)
{
flyingItem.transform.position = item.transform.position;
flyingItem.name = "Flying Marshmallow";
flyingItem.layer = LayerMask.NameToLayer("On Top UI");
SpriteRenderer spriteRenderer = flyingItem.AddComponent<SpriteRenderer>();
GameObject prefab = Resources.Load(Configure.Marshmallow()) as GameObject;
if (prefab != null)
{
spriteRenderer.sprite = prefab.GetComponent<SpriteRenderer>().sprite;
}
StartCoroutine(CollectItemAnim(flyingItem, order));
}
}
// chocolate
else if (item.IsChocolate())
{
if (LevelLoader.instance.target1Type == TARGET_TYPE.CHOCOLATE && target1Left > 0)
{
target1Left--;
flyingItem = new GameObject();
order = 1;
}
else if (LevelLoader.instance.target2Type == TARGET_TYPE.CHOCOLATE && target2Left > 0)
{
target2Left--;
flyingItem = new GameObject();
order = 2;
}
else if (LevelLoader.instance.target3Type == TARGET_TYPE.CHOCOLATE && target3Left > 0)
{
target3Left--;
flyingItem = new GameObject();
order = 3;
}
else if (LevelLoader.instance.target4Type == TARGET_TYPE.CHOCOLATE && target4Left > 0)
{
target4Left--;
flyingItem = new GameObject();
order = 4;
}
if (flyingItem != null)
{
flyingItem.transform.position = item.transform.position;
flyingItem.name = "Flying Chocolate";
flyingItem.layer = LayerMask.NameToLayer("On Top UI");
SpriteRenderer spriteRenderer = flyingItem.AddComponent<SpriteRenderer>();
GameObject prefab = Resources.Load(Configure.Chocolate1()) as GameObject;
if (prefab != null)
{
spriteRenderer.sprite = prefab.GetComponent<SpriteRenderer>().sprite;
}
StartCoroutine(CollectItemAnim(flyingItem, order));
}
}
// column_row_breaker
else if (item.IsColumnBreaker(item.type) == true || item.IsRowBreaker(item.type) == true)
{
if (LevelLoader.instance.target1Type == TARGET_TYPE.COLUMN_ROW_BREAKER && target1Left > 0)
{
target1Left--;
flyingItem = new GameObject();
order = 1;
}
else if (LevelLoader.instance.target2Type == TARGET_TYPE.COLUMN_ROW_BREAKER && target2Left > 0)
{
target2Left--;
flyingItem = new GameObject();
order = 2;
}
else if (LevelLoader.instance.target3Type == TARGET_TYPE.COLUMN_ROW_BREAKER && target3Left > 0)
{
target3Left--;
flyingItem = new GameObject();
order = 3;
}
else if (LevelLoader.instance.target4Type == TARGET_TYPE.COLUMN_ROW_BREAKER && target4Left > 0)
{
target4Left--;
flyingItem = new GameObject();
order = 4;
}
if (flyingItem != null)
{
flyingItem.transform.position = item.transform.position;
flyingItem.name = "Flying Column Row Breaker";
flyingItem.layer = LayerMask.NameToLayer("On Top UI");
SpriteRenderer spriteRenderer = flyingItem.AddComponent<SpriteRenderer>();
GameObject prefab = Resources.Load(Configure.ColumnRowBreaker()) as GameObject;
if (prefab != null)
{
spriteRenderer.sprite = prefab.GetComponent<SpriteRenderer>().sprite;
}
StartCoroutine(CollectItemAnim(flyingItem, order));
}
}
// generic bomb breaker
else if (item.IsBombBreaker(item.type) == true)
{
if (LevelLoader.instance.target1Type == TARGET_TYPE.BOMB_BREAKER && target1Left > 0)
{
target1Left--;
flyingItem = new GameObject();
order = 1;
}
else if (LevelLoader.instance.target2Type == TARGET_TYPE.BOMB_BREAKER && target2Left > 0)
{
target2Left--;
flyingItem = new GameObject();
order = 2;
}
else if (LevelLoader.instance.target3Type == TARGET_TYPE.BOMB_BREAKER && target3Left > 0)
{
target3Left--;
flyingItem = new GameObject();
order = 3;
}
else if (LevelLoader.instance.target4Type == TARGET_TYPE.BOMB_BREAKER && target4Left > 0)
{
target4Left--;
flyingItem = new GameObject();
order = 4;
}
if (flyingItem != null)
{
flyingItem.transform.position = item.transform.position;
flyingItem.name = "Flying Bomb Breaker";
flyingItem.layer = LayerMask.NameToLayer("On Top UI");
SpriteRenderer spriteRenderer = flyingItem.AddComponent<SpriteRenderer>();
GameObject prefab = Resources.Load(Configure.GenericBombBreaker()) as GameObject;
if (prefab != null)
{
spriteRenderer.sprite = prefab.GetComponent<SpriteRenderer>().sprite;
}
StartCoroutine(CollectItemAnim(flyingItem, order));
}
}
// generic x_breaker
else if (item.IsXBreaker(item.type) == true)
{
if (LevelLoader.instance.target1Type == TARGET_TYPE.X_BREAKER && target1Left > 0)
{
target1Left--;
flyingItem = new GameObject();
order = 1;
}
else if (LevelLoader.instance.target2Type == TARGET_TYPE.X_BREAKER && target2Left > 0)
{
target2Left--;
flyingItem = new GameObject();
order = 2;
}
else if (LevelLoader.instance.target3Type == TARGET_TYPE.X_BREAKER && target3Left > 0)
{
target3Left--;
flyingItem = new GameObject();
order = 3;
}
else if (LevelLoader.instance.target4Type == TARGET_TYPE.X_BREAKER && target4Left > 0)
{
target4Left--;
flyingItem = new GameObject();
order = 4;
}
if (flyingItem != null)
{
flyingItem.transform.position = item.transform.position;
flyingItem.name = "Flying X Breaker";
flyingItem.layer = LayerMask.NameToLayer("On Top UI");
SpriteRenderer spriteRenderer = flyingItem.AddComponent<SpriteRenderer>();
GameObject prefab = Resources.Load(Configure.GenericXBreaker()) as GameObject;
if (prefab != null)
{
spriteRenderer.sprite = prefab.GetComponent<SpriteRenderer>().sprite;
}
StartCoroutine(CollectItemAnim(flyingItem, order));
}
}
// rainbow
else if (item.type == ITEM_TYPE.COOKIE_RAINBOW)
{
if (LevelLoader.instance.target1Type == TARGET_TYPE.RAINBOW && target1Left > 0)
{
target1Left--;
flyingItem = new GameObject();
order = 1;
}
else if (LevelLoader.instance.target2Type == TARGET_TYPE.RAINBOW && target2Left > 0)
{
target2Left--;
flyingItem = new GameObject();
order = 2;
}
else if (LevelLoader.instance.target3Type == TARGET_TYPE.RAINBOW && target3Left > 0)
{
target3Left--;
flyingItem = new GameObject();
order = 3;
}
else if (LevelLoader.instance.target4Type == TARGET_TYPE.RAINBOW && target4Left > 0)
{
target4Left--;
flyingItem = new GameObject();
order = 4;
}
if (flyingItem != null)
{
flyingItem.transform.position = item.transform.position;
flyingItem.name = "Flying Rainbow";
flyingItem.layer = LayerMask.NameToLayer("On Top UI");
SpriteRenderer spriteRenderer = flyingItem.AddComponent<SpriteRenderer>();
GameObject prefab = Resources.Load(Configure.CookieRainbow()) as GameObject;
if (prefab != null)
{
spriteRenderer.sprite = prefab.GetComponent<SpriteRenderer>().sprite;
}
StartCoroutine(CollectItemAnim(flyingItem, order));
}
}
// rock candy
else if (item.IsRockCandy() == true)
{
if (LevelLoader.instance.target1Type == TARGET_TYPE.ROCK_CANDY && target1Left > 0)
{
target1Left--;
flyingItem = new GameObject();
order = 1;
}
else if (LevelLoader.instance.target2Type == TARGET_TYPE.ROCK_CANDY && target2Left > 0)
{
target2Left--;
flyingItem = new GameObject();
order = 2;
}
else if (LevelLoader.instance.target3Type == TARGET_TYPE.ROCK_CANDY && target3Left > 0)
{
target3Left--;
flyingItem = new GameObject();
order = 3;
}
else if (LevelLoader.instance.target4Type == TARGET_TYPE.ROCK_CANDY && target4Left > 0)
{
target4Left--;
flyingItem = new GameObject();
order = 4;
}
if (flyingItem != null)
{
flyingItem.transform.position = item.transform.position;
flyingItem.name = "Flying Rock Candy";
flyingItem.layer = LayerMask.NameToLayer("On Top UI");
SpriteRenderer spriteRenderer = flyingItem.AddComponent<SpriteRenderer>();
GameObject prefab = Resources.Load(Configure.RockCandyGeneric()) as GameObject;
if (prefab != null)
{
spriteRenderer.sprite = prefab.GetComponent<SpriteRenderer>().sprite;
}
StartCoroutine(CollectItemAnim(flyingItem, order));
}
}
}
public void CollectWaffle(Waffle waffle)
{
GameObject flyingItem = null;
var order = 0;
if (LevelLoader.instance.target1Type == TARGET_TYPE.WAFFLE && target1Left > 0)
{
target1Left--;
flyingItem = new GameObject();
order = 1;
}
else if (LevelLoader.instance.target2Type == TARGET_TYPE.WAFFLE && target2Left > 0)
{
target2Left--;
flyingItem = new GameObject();
order = 2;
}
else if (LevelLoader.instance.target3Type == TARGET_TYPE.WAFFLE && target3Left > 0)
{
target3Left--;
flyingItem = new GameObject();
order = 3;
}
else if (LevelLoader.instance.target4Type == TARGET_TYPE.WAFFLE && target4Left > 0)
{
target4Left--;
flyingItem = new GameObject();
order = 4;
}
if (flyingItem != null)
{
flyingItem.transform.position = waffle.transform.position;
flyingItem.name = "Flying Waffle";
flyingItem.layer = LayerMask.NameToLayer("On Top UI");
flyingItem.transform.localScale = new Vector3(0.75f, 0.75f, 0);
SpriteRenderer spriteRenderer = flyingItem.AddComponent<SpriteRenderer>();
GameObject prefab = Resources.Load(Configure.Waffle1()) as GameObject; ;
spriteRenderer.sprite = prefab.GetComponent<SpriteRenderer>().sprite;
StartCoroutine(CollectItemAnim(flyingItem, order));
}
}
public void CollectCage(Cage cage)
{
GameObject flyingItem = null;
var order = 0;
if (LevelLoader.instance.target1Type == TARGET_TYPE.CAGE && target1Left > 0)
{
target1Left--;
flyingItem = new GameObject();
order = 1;
}
else if (LevelLoader.instance.target2Type == TARGET_TYPE.CAGE && target2Left > 0)
{
target2Left--;
flyingItem = new GameObject();
order = 2;
}
else if (LevelLoader.instance.target3Type == TARGET_TYPE.CAGE && target3Left > 0)
{
target3Left--;
flyingItem = new GameObject();
order = 3;
}
else if (LevelLoader.instance.target4Type == TARGET_TYPE.CAGE && target4Left > 0)
{
target4Left--;
flyingItem = new GameObject();
order = 4;
}
if (flyingItem != null)
{
flyingItem.transform.position = cage.transform.position;
flyingItem.name = "Flying Cage";
flyingItem.layer = LayerMask.NameToLayer("On Top UI");
flyingItem.transform.localScale = new Vector3(0.75f, 0.75f, 0);
SpriteRenderer spriteRenderer = flyingItem.AddComponent<SpriteRenderer>();
GameObject prefab = Resources.Load(Configure.Cage1()) as GameObject; ;
spriteRenderer.sprite = prefab.GetComponent<SpriteRenderer>().sprite;
StartCoroutine(CollectItemAnim(flyingItem, order));
}
}
// if the collectible
bool CollectCollectible()
{
if (LevelLoader.instance.target1Type != TARGET_TYPE.COLLECTIBLE &&
LevelLoader.instance.target2Type != TARGET_TYPE.COLLECTIBLE &&
LevelLoader.instance.target3Type != TARGET_TYPE.COLLECTIBLE &&
LevelLoader.instance.target4Type != TARGET_TYPE.COLLECTIBLE)
{
return false;
}
var items = GetListItems();
foreach (var item in items)
{
bool collectable = false;
// check each item in last row and in column which can collect and item is collectible
if (item != null &&
(item.node.i == row - 1) &&
LevelLoader.instance.collectibleCollectColumnMarkers.Contains(item.node.j) &&
item.IsCollectible() == true)
{
collectable = true;
}
// collectible marker by node
if (item != null &&
LevelLoader.instance.collectibleCollectNodeMarkers.Contains(NodeOrder(item.node.i, item.node.j)) &&
item.IsCollectible() == true)
{
collectable = true;
}
if (collectable == true)
{
GameObject flyingItem = null;
var order = 0;
if (LevelLoader.instance.target1Type == TARGET_TYPE.COLLECTIBLE && LevelLoader.instance.target1Color == item.color && target1Left > 0)
{
target1Left--;
flyingItem = new GameObject();
order = 1;
}
else if (LevelLoader.instance.target2Type == TARGET_TYPE.COLLECTIBLE && LevelLoader.instance.target2Color == item.color && target2Left > 0)
{
target2Left--;
flyingItem = new GameObject();
order = 2;
}
else if (LevelLoader.instance.target3Type == TARGET_TYPE.COLLECTIBLE && LevelLoader.instance.target3Color == item.color && target3Left > 0)
{
target3Left--;
flyingItem = new GameObject();
order = 3;
}
else if (LevelLoader.instance.target4Type == TARGET_TYPE.COLLECTIBLE && LevelLoader.instance.target4Color == item.color && target4Left > 0)
{
target4Left--;
flyingItem = new GameObject();
order = 4;
}
if (flyingItem != null)
{
flyingItem.transform.position = item.transform.position;
flyingItem.name = "Flying Collectible";
flyingItem.layer = LayerMask.NameToLayer("On Top UI");
SpriteRenderer spriteRenderer = flyingItem.AddComponent<SpriteRenderer>();
GameObject prefab = null;
switch (item.color)
{
case 1:
prefab = Resources.Load(Configure.Collectible1()) as GameObject;
break;
case 2:
prefab = Resources.Load(Configure.Collectible2()) as GameObject;
break;
case 3:
prefab = Resources.Load(Configure.Collectible3()) as GameObject;
break;
case 4:
prefab = Resources.Load(Configure.Collectible4()) as GameObject;
break;
case 5:
prefab = Resources.Load(Configure.Collectible5()) as GameObject;
break;
case 6:
prefab = Resources.Load(Configure.Collectible6()) as GameObject;
break;
case 7:
prefab = Resources.Load(Configure.Collectible7()) as GameObject;
break;
case 8:
prefab = Resources.Load(Configure.Collectible7()) as GameObject;
break;
case 9:
prefab = Resources.Load(Configure.Collectible9()) as GameObject;
break;
case 10:
prefab = Resources.Load(Configure.Collectible10()) as GameObject;
break;
case 11:
prefab = Resources.Load(Configure.Collectible11()) as GameObject;
break;
case 12:
prefab = Resources.Load(Configure.Collectible12()) as GameObject;
break;
case 13:
prefab = Resources.Load(Configure.Collectible13()) as GameObject;
break;
case 14:
prefab = Resources.Load(Configure.Collectible14()) as GameObject;
break;
case 15:
prefab = Resources.Load(Configure.Collectible15()) as GameObject;
break;
case 16:
prefab = Resources.Load(Configure.Collectible16()) as GameObject;
break;
case 17:
prefab = Resources.Load(Configure.Collectible17()) as GameObject;
break;
case 18:
prefab = Resources.Load(Configure.Collectible18()) as GameObject;
break;
case 19:
prefab = Resources.Load(Configure.Collectible19()) as GameObject;
break;
case 20:
prefab = Resources.Load(Configure.Collectible20()) as GameObject;
break;
}
if (prefab != null)
{
spriteRenderer.sprite = prefab.GetComponent<SpriteRenderer>().sprite;
}
StartCoroutine(CollectItemAnim(flyingItem, order));
item.Destroy(true);
return true;
}
}
}
return false;
}
// item fly to target
IEnumerator CollectItemAnim(GameObject item, int order)
{
yield return new WaitForFixedUpdate();
GameObject target = null;
switch (order)
{
case 1:
target = target1;
break;
case 2:
target = target2;
break;
case 3:
target = target3;
break;
case 4:
target = target4;
break;
}
flyingItems++;
// AnimationCurve curveX = new AnimationCurve(new Keyframe(0, item.transform.localPosition.x), new Keyframe(0.4f, target.transform.position.x));
// AnimationCurve curveY = new AnimationCurve(new Keyframe(0, item.transform.localPosition.y), new Keyframe(0.4f, target.transform.position.y));
// curveX.AddKey(0.2f, item.transform.localPosition.x + UnityEngine.Random.Range(-2f, 2f));
// curveY.AddKey(0.2f, item.transform.localPosition.y + UnityEngine.Random.Range(-1f, 0f));
// float startTime = Time.time;
// float speed = 2.0f + flyingItems * 0.25f;
// float distCovered = 0;
// while (distCovered < 0.4f)
// {
// distCovered = (Time.time - startTime) / speed;
// item.transform.localPosition = new Vector3(curveX.Evaluate(distCovered), curveY.Evaluate(distCovered), 0);
// yield return new WaitForFixedUpdate();
// }
AudioManager.instance.CollectTargetAudio();
switch (order)
{
case 1:
UITarget.UpdateTargetAmount(1);
break;
case 2:
UITarget.UpdateTargetAmount(2);
break;
case 3:
UITarget.UpdateTargetAmount(3);
break;
case 4:
UITarget.UpdateTargetAmount(4);
break;
}
Destroy(item);
flyingItems--;
}
#endregion
#region Popup
void TargetPopup()
{
StartCoroutine(StartTargetPopup());
}
IEnumerator StartTargetPopup()
{
state = GAME_STATE.OPENING_POPUP;
yield return new WaitForSeconds(0.5f);
AudioManager.instance.PopupTargetAudio();
targetPopup.OpenPopup();
yield return new WaitForSeconds(1.0f);
var popup = GameObject.Find("TargetPopup(Clone)");
if (popup)
{
popup.GetComponent<Popup>().Close();
}
yield return new WaitForSeconds(0.5f);
state = GAME_STATE.WAITING_USER_SWAP;
if (Help.instance.help == false)
{
StartCoroutine(CheckHint());
}
else
{
Help.instance.Show();
}
// Plus 5 moves popup
if (Configure.instance.beginFiveMoves == true)
{
StartCoroutine(Plus5MovesPopup());
}
}
IEnumerator Plus5MovesPopup()
{
Configure.instance.beginFiveMoves = false;
plus5MovesPopup.OpenPopup();
yield return new WaitForSeconds(1.0f);
var popup = GameObject.Find("Plus5MovesPopup(Clone)");
if (popup)
{
popup.GetComponent<Popup>().Close();
}
}
void ShowInspiringPopup()
{
//print("Excellent!, Amazing!, Great!, Nice!");
int encouraging = Random.Range(0, 3);
switch (encouraging)
{
case 0:
StartCoroutine(InspiringPopup(amazingPopup, encouraging));
// sound
AudioManager.instance.amazingAudio();
break;
case 1:
StartCoroutine(InspiringPopup(excellentPopup, encouraging));
// sound
AudioManager.instance.exellentAudio();
break;
case 2:
StartCoroutine(InspiringPopup(greatPopup, encouraging));
// sound
AudioManager.instance.greatAudio();
break;
}
}
IEnumerator InspiringPopup(PopupOpener popupOpener, int encouraging)
{
// prevent multiple call
if (showingInspiringPopup == false) showingInspiringPopup = true;
else yield return null;
popupOpener.OpenPopup();
yield return new WaitForSeconds(1.0f);
GameObject popup = null;
switch (encouraging)
{
case 0:
popup = GameObject.Find("AmazingPopup(Clone)");
break;
case 1:
popup = GameObject.Find("ExcellentPopup(Clone)");
break;
case 2:
popup = GameObject.Find("GreatPopup(Clone)");
break;
}
if (popup)
{
popup.GetComponent<Popup>().Close();
}
yield return new WaitForSeconds(1f);
showingInspiringPopup = false;
}
#endregion
#region Complete
bool IsLevelCompleted()
{
if (target1Left == 0 && target2Left == 0 && target3Left == 0 && target4Left == 0)
{
return true;
}
return false;
}
// auto play the left moves when target is reached
IEnumerator PreWinAutoPlay()
{
HideHint();
// reset drop time
dropTime = 1;
state = GAME_STATE.OPENING_POPUP;
yield return new WaitForSeconds(0.5f);
// completed popup
completedPopup.OpenPopup();
AudioManager.instance.PopupCompletedAudio();
yield return new WaitForSeconds(1.0f);
if (GameObject.Find("CompletedPopup(Clone)"))
{
GameObject.Find("CompletedPopup(Clone)").GetComponent<Popup>().Close();
}
yield return new WaitForSeconds(0.5f);
state = GAME_STATE.PRE_WIN_AUTO_PLAYING;
var items = GetRandomItems(moveLeft);
foreach (var item in items)
{
item.SetRandomNextType();
item.nextSound = false;
moveLeft--;
UITop.DecreaseMoves(true);
var prefab = Instantiate(Resources.Load(Configure.StarGold())) as GameObject;
prefab.transform.position = UITop.GetComponent<UITop>().movesText.gameObject.transform.position;
var startPosition = prefab.transform.position;
var endPosition = item.gameObject.transform.position;
var bending = new Vector3(1, 1, 0);
var timeToTravel = 0.2f;
var timeStamp = Time.time;
while (Time.time < timeStamp + timeToTravel)
{
var currentPos = Vector3.Lerp(startPosition, endPosition, (Time.time - timeStamp) / timeToTravel);
currentPos.x += bending.x * Mathf.Sin(Mathf.Clamp01((Time.time - timeStamp) / timeToTravel) * Mathf.PI);
currentPos.y += bending.y * Mathf.Sin(Mathf.Clamp01((Time.time - timeStamp) / timeToTravel) * Mathf.PI);
currentPos.z += bending.z * Mathf.Sin(Mathf.Clamp01((Time.time - timeStamp) / timeToTravel) * Mathf.PI);
prefab.transform.position = currentPos;
yield return null;
}
Destroy(prefab);
item.Destroy();
yield return new WaitForSeconds(0.1f);
}
yield return new WaitForSeconds(0.5f);
while (GetAllSpecialItems().Count > 0)
{
while (GetAllSpecialItems().Count > 0)
{
var specials = GetAllSpecialItems();
var item = specials[UnityEngine.Random.Range(0, specials.Count)];
if (item.type == ITEM_TYPE.COOKIE_RAINBOW)
{
item.DestroyItemsSameColor(LevelLoader.instance.RandomColor());
}
item.Destroy();
while (destroyingItems > 0)
{
yield return new WaitForSeconds(0.1f);
}
yield return new WaitForEndOfFrame();
Drop();
while (droppingItems > 0)
{
yield return new WaitForSeconds(0.1f);
}
yield return new WaitForEndOfFrame();
}
yield return StartCoroutine(DestroyMatches());
}
while (destroyingItems > 0)
{
yield return new WaitForSeconds(0.1f);
}
yield return new WaitForEndOfFrame();
while (droppingItems > 0)
{
yield return new WaitForSeconds(0.1f);
}
yield return new WaitForEndOfFrame();
yield return new WaitForSeconds(0.5f);
state = GAME_STATE.OPENING_POPUP;
SaveLevelInfo();
AudioManager.instance.PopupWinAudio();
winPopup.OpenPopup();
}
List<Item> GetRandomItems(int number)
{
var avaiableItems = new List<Item>();
var returnItems = new List<Item>();
foreach (var item in GetListItems())
{
if (item != null)
{
if (item.node != null)
{
if (item.IsCookie())
{
avaiableItems.Add(item);
}
}
}
}
while (returnItems.Count < number && avaiableItems.Count > 0)
{
var item = avaiableItems[Random.Range(0, avaiableItems.Count)];
returnItems.Add(item);
avaiableItems.Remove(item);
}
return returnItems;
}
List<Item> GetAllSpecialItems()
{
var specials = new List<Item>();
foreach (var item in GetListItems())
{
if (item != null)
{
if (item.type == ITEM_TYPE.COOKIE_RAINBOW || item.IsColumnBreaker(item.type) || item.IsRowBreaker(item.type) || item.IsBombBreaker(item.type) || item.IsXBreaker(item.type))
{
specials.Add(item);
}
}
}
return specials;
}
public void SaveLevelInfo()
{
score = LevelLoader.instance.score2Star;
// level star
if (score < LevelLoader.instance.score1Star)
{
star = 0;
}
else if (LevelLoader.instance.score1Star <= score && score < LevelLoader.instance.score2Star)
{
star = 1;
}
else if (LevelLoader.instance.score2Star <= score && score < LevelLoader.instance.score3Star)
{
star = 2;
}
else if (score >= LevelLoader.instance.score2Star)
{
star = 3;
}
// score and star
GameData.instance.SaveLevelStatistics(LevelLoader.instance.level, score, star);
// open next level
int openedLevel = GameData.instance.GetOpendedLevel();
if (LevelLoader.instance.level == openedLevel)
{
if (openedLevel < Configure.instance.maxLevel)
{
GameData.instance.SaveOpendedLevel(openedLevel + 1);
}
}
// add bonus coin
int coin = GameData.instance.GetPlayerCoin();
if (star == 1)
{
GameData.instance.SavePlayerCoin(coin + Configure.instance.bonus1Star);
}
else if (star == 2)
{
GameData.instance.SavePlayerCoin(coin + Configure.instance.bonus2Star);
}
else if (star == 3)
{
GameData.instance.SavePlayerCoin(coin + Configure.instance.bonus3Star);
}
}
#endregion
#region Hint
public void Hint()
{
StartCoroutine(CheckHint());
}
public IEnumerator CheckHint()
{
//Debug.Log("CheckHint()");
// prevent multiple call this function only last call is triggered
checkHintCall++;
if (checkHintCall > 1)
{
checkHintCall--;
//Debug.Log("Cancel checking hint because of multiple hint call");
yield break;
}
if (Configure.instance.showHint == false)
{
yield break;
}
if (moveLeft <= 0)
{
yield break;
}
// put delay here user also need to wait when the is no matches
//yield return new WaitForSeconds(Configure.instance.hintDelay);
// need to call hide hint here in case items destroy after no matches generate
HideHint();
while (state != GAME_STATE.WAITING_USER_SWAP)
{
//Debug.Log("Wait for checking hint because of game state");
yield return new WaitForSeconds(0.1f);
}
while (lockSwap == true)
{
//Debug.Log("Wait for checking hint because of lock swap");
yield return new WaitForSeconds(0.1f);
}
//Debug.Log("Start checking hint");
// check for rainbow item / breaker / color
if (GetHintByRainbowItem() == true || GetHintByBreaker() == true || GetHintByColor() == true)
{
StartCoroutine(ShowHint());
checkHintCall--;
yield break;
}
// if reach this code that mean there is no matches
else
{
// prevent multiple call
if (!GameObject.Find("NoMatchesdPopup(Clone)"))
{
state = GAME_STATE.NO_MATCHES_REGENERATING;
lockSwap = true;
AudioManager.instance.PopupNoMatchesAudio();
// show and close popup
noMatchesPopup.OpenPopup();
yield return new WaitForSeconds(1.0f);
if (GameObject.Find("NoMatchesdPopup(Clone)"))
{
GameObject.Find("NoMatchesdPopup(Clone)").GetComponent<Popup>().Close();
}
yield return new WaitForSeconds(0.5f);
var position = Camera.main.aspect * Camera.main.orthographicSize * 2;
// hide board
iTween.MoveTo(gameObject, iTween.Hash(
"x", -position,
"easeType", iTween.EaseType.easeOutBack,
"time", 0.5
));
yield return new WaitForSeconds(0.5f);
NoMoveRegenerate();
while (GetHintByColor() == false)
{
NoMoveRegenerate();
yield return new WaitForEndOfFrame();
}
// show board
iTween.MoveTo(gameObject, iTween.Hash(
"x", 0,
"easeType", iTween.EaseType.easeOutBack,
"time", 0.5
));
yield return new WaitForSeconds(0.5f);
state = GAME_STATE.WAITING_USER_SWAP;
FindMatches();
}
checkHintCall--;
}
}
public IEnumerator ShowHint()
{
//Debug.Log("ShowHint()");
showHintCall++;
// prevent multiple call
if (showHintCall > 1)
{
//Debug.Log("Cancel showing hint because of multiple call");
showHintCall--;
yield break;
}
if (Configure.instance.showHint == false)
{
yield break;
}
yield return new WaitForSeconds(Configure.instance.hintDelay);
while (state != GAME_STATE.WAITING_USER_SWAP)
{
yield return new WaitForSeconds(0.1f);
}
while (lockSwap == true)
{
yield return new WaitForSeconds(0.1f);
}
//Debug.Log("Start showing hint");
// make sure only items in hint list run animation
foreach (var item in GetListItems())
{
if (item != null)
{
if (!hintItems.Contains(item))
{
iTween.StopByName(item.gameObject, "HintAnimation");
item.gameObject.transform.rotation = Quaternion.Euler(new Vector3(0, 0, 0));
}
}
}
foreach (var item in hintItems)
{
if (item != null)
{
//Debug.Log("Show hint: " + item.node.name);
iTween.ShakeRotation(item.gameObject, iTween.Hash(
"name", "HintAnimation",
"amount", new Vector3(0f, 0f, 50f),
"easetype", iTween.EaseType.easeOutBack,
//"looptype", iTween.LoopType.pingPong,
"oncomplete", "OnCompleteShowHint",
"oncompletetarget", gameObject,
"oncompleteparams", new Hashtable() { { "item", item } },
//"delay", 2f,
"time", 1f
));
}
}
// only wait if hint items run animation
// if there is no item that mean the hint list is clean in clear hint function
if (hintItems.Count > 0)
{
yield return new WaitForSeconds(1.5f);
}
showHintCall--;
StartCoroutine(CheckHint());
}
// when shake a item it is not in good place we need to reset it
public void OnCompleteShowHint(Hashtable args)
{
var item = (Item)args["item"];
//Debug.Log("On Complete Shake Item: " + item.node.name);
iTween.RotateTo(item.gameObject, iTween.Hash(
"rotation", Vector3.zero,
"time", 0.2f
));
}
public void HideHint()
{
//Debug.Log("Hide Hint");
foreach (var item in hintItems)
{
if (item != null)
{
//print("Hide item in node: " + item.node.name);
iTween.StopByName(item.gameObject, "HintAnimation");
iTween.RotateTo(item.gameObject, iTween.Hash(
"rotation", Vector3.zero,
"time", 0.2f
));
}
}
// clear hint list to make sure show hint function do not runs animation
hintItems.Clear();
}
List<int> Shuffle(List<int> list)
{
System.Random rng = new System.Random();
int n = list.Count;
while (n > 1)
{
n--;
int k = rng.Next(n + 1);
int value = list[k];
list[k] = list[n];
list[n] = value;
}
return list;
}
void CheckHintNode(Node node, int color, bool needMove = false)
{
if (node != null)
{
if (node.item != null && node.item.color == color)
{
if (needMove)
{
if (node.item.Movable() && node.item.Matchable())
{
hintItems.Add(node.item);
}
}
else
{
if (node.item.Matchable())
{
hintItems.Add(node.item);
}
}
}
}
}
void NoMoveRegenerate()
{
//print("No moves generate");
foreach (var item in GetListItems())
{
if (item != null)
{
if (item.Movable() && item.IsCookie())
{
item.color = LevelLoader.instance.RandomColor();
item.ChangeSpriteAndType(item.color);
}
}
}
}
bool GetHintByColor()
{
foreach (int color in Shuffle(LevelLoader.instance.usingColors))
{
for (int j = 0; j < column; j++)
{
for (int i = 0; i < row; i++)
{
Node node = GetNode(i, j);
if (node != null)
{
if (node.item == null || !(node.item.Movable()))
{
continue;
}
// current node is x
// o-o-x
// o
CheckHintNode(GetNode(i + 1, j), color, true);
CheckHintNode(GetNode(i, j - 1), color);
CheckHintNode(GetNode(i, j - 2), color);
if (hintItems.Count == 3)
{
return true;
}
else
{
hintItems.Clear();
}
// o
// o-o x
CheckHintNode(GetNode(i - 1, j), color, true);
CheckHintNode(GetNode(i, j - 1), color);
CheckHintNode(GetNode(i, j - 2), color);
if (hintItems.Count == 3)
{
return true;
}
else
{
hintItems.Clear();
}
// x o o
// o
CheckHintNode(GetNode(i + 1, j), color, true);
CheckHintNode(GetNode(i, j + 1), color);
CheckHintNode(GetNode(i, j + 2), color);
if (hintItems.Count == 3)
{
return true;
}
else
{
hintItems.Clear();
}
// o
// x o o
CheckHintNode(GetNode(i - 1, j), color, true);
CheckHintNode(GetNode(i, j + 1), color);
CheckHintNode(GetNode(i, j + 2), color);
if (hintItems.Count == 3)
{
return true;
}
else
{
hintItems.Clear();
}
// o
// o
// x o
CheckHintNode(GetNode(i, j + 1), color, true);
CheckHintNode(GetNode(i - 1, j), color);
CheckHintNode(GetNode(i - 2, j), color);
if (hintItems.Count == 3)
{
return true;
}
else
{
hintItems.Clear();
}
// x o
// o
// o
CheckHintNode(GetNode(i, j + 1), color, true);
CheckHintNode(GetNode(i + 1, j), color);
CheckHintNode(GetNode(i + 2, j), color);
if (hintItems.Count == 3)
{
return true;
}
else
{
hintItems.Clear();
}
// o
// o
// o x
CheckHintNode(GetNode(i, j - 1), color, true);
CheckHintNode(GetNode(i - 1, j), color);
CheckHintNode(GetNode(i - 2, j), color);
if (hintItems.Count == 3)
{
return true;
}
else
{
hintItems.Clear();
}
// o x
// o
// o
CheckHintNode(GetNode(i, j - 1), color, true);
CheckHintNode(GetNode(i + 1, j), color);
CheckHintNode(GetNode(i + 2, j), color);
if (hintItems.Count == 3)
{
return true;
}
else
{
hintItems.Clear();
}
// o-x-o-o
CheckHintNode(GetNode(i, j - 1), color, true);
CheckHintNode(GetNode(i, j + 1), color);
CheckHintNode(GetNode(i, j + 2), color);
if (hintItems.Count == 3)
{
return true;
}
else
{
hintItems.Clear();
}
// o-o-x-o
CheckHintNode(GetNode(i, j + 1), color, true);
CheckHintNode(GetNode(i, j - 1), color);
CheckHintNode(GetNode(i, j - 2), color);
if (hintItems.Count == 3)
{
return true;
}
else
{
hintItems.Clear();
}
// o
// x
// o
// o
CheckHintNode(GetNode(i - 1, j), color, true);
CheckHintNode(GetNode(i + 1, j), color);
CheckHintNode(GetNode(i + 2, j), color);
if (hintItems.Count == 3)
{
return true;
}
else
{
hintItems.Clear();
}
// o
// o
// x
// o
CheckHintNode(GetNode(i + 1, j), color, true);
CheckHintNode(GetNode(i - 1, j), color);
CheckHintNode(GetNode(i - 2, j), color);
if (hintItems.Count == 3)
{
return true;
}
else
{
hintItems.Clear();
}
// o
// o x o
// o
int h = 0;
int v = 0;
Node neighbor = null;
neighbor = node.LeftNeighbor();
if (neighbor != null)
{
if (neighbor.item != null && neighbor.item.Matchable() && neighbor.item.color == color)
{
hintItems.Add(neighbor.item);
h++;
}
}
neighbor = node.RightNeighbor();
if (neighbor != null)
{
if (neighbor.item != null && neighbor.item.Matchable() && neighbor.item.color == color)
{
hintItems.Add(neighbor.item);
h++;
}
}
neighbor = node.TopNeighbor();
if (neighbor != null)
{
if (neighbor.item != null && neighbor.item.Matchable() && neighbor.item.color == color)
{
hintItems.Add(neighbor.item);
v++;
}
}
neighbor = node.BottomNeighbor();
if (neighbor != null)
{
if (neighbor.item != null && neighbor.item.Matchable() && neighbor.item.color == color)
{
hintItems.Add(neighbor.item);
v++;
}
}
if (hintItems.Count == 3)
{
if (v > h && hintItems[0].node.item != null && hintItems[0].node.item.Movable())
{
return true;
}
else if (v < h && hintItems[2].node.item != null && hintItems[2].node.item.Movable())
{
return true;
}
else
{
hintItems.Clear();
}
}
else if (hintItems.Count == 4)
{
if (hintItems[0].node.item.Movable())
{
hintItems.RemoveAt(1);
return true;
}
else if (hintItems[1].node.item.Movable())
{
hintItems.RemoveAt(0);
return true;
}
else if (hintItems[2].node.item.Movable())
{
hintItems.RemoveAt(3);
return true;
}
else if (hintItems[3].node.item.Movable())
{
hintItems.RemoveAt(2);
return true;
}
else
{
hintItems.Clear();
}
}
else
{
hintItems.Clear();
}
}
} // end for row
}
} // end foreach color
return false;
}
bool GetHintByRainbowItem()
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
{
Node node = GetNode(i, j);
if (node != null)
{
if (node.item == null || !(node.item.Movable()))
{
continue;
}
if (node.item.type == ITEM_TYPE.COOKIE_RAINBOW)
{
Node neighbor = null;
neighbor = node.LeftNeighbor();
if (neighbor != null)
{
if (neighbor.item != null && neighbor.item.Movable())
{
hintItems.Add(node.item);
return true;
}
}
neighbor = node.RightNeighbor();
if (neighbor != null)
{
if (neighbor.item != null && neighbor.item.Movable())
{
hintItems.Add(node.item);
return true;
}
}
neighbor = node.TopNeighbor();
if (neighbor != null)
{
if (neighbor.item != null && neighbor.item.Movable())
{
hintItems.Add(node.item);
return true;
}
}
neighbor = node.BottomNeighbor();
if (neighbor != null)
{
if (neighbor.item != null && neighbor.item.Movable())
{
hintItems.Add(node.item);
return true;
}
}
} // end if item is rainbow
}
}
}
return false;
}
bool GetHintByBreaker()
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
{
Node node = GetNode(i, j);
if (node != null)
{
if (node.item == null || !(node.item.Movable()))
{
continue;
}
if (node.item.IsBreaker(node.item.type))
{
Node neighbor = null;
neighbor = node.LeftNeighbor();
if (neighbor != null)
{
if (neighbor.item != null && neighbor.item.Movable() && neighbor.item.IsBreaker(neighbor.item.type))
{
hintItems.Add(neighbor.item);
hintItems.Add(node.item);
return true;
}
}
neighbor = node.RightNeighbor();
if (neighbor != null)
{
if (neighbor.item != null && neighbor.item.Movable() && neighbor.item.IsBreaker(neighbor.item.type))
{
hintItems.Add(neighbor.item);
hintItems.Add(node.item);
return true;
}
}
neighbor = node.TopNeighbor();
if (neighbor != null)
{
if (neighbor.item != null && neighbor.item.Movable() && neighbor.item.IsBreaker(neighbor.item.type))
{
hintItems.Add(neighbor.item);
hintItems.Add(node.item);
return true;
}
}
neighbor = node.BottomNeighbor();
if (neighbor != null)
{
if (neighbor.item != null && neighbor.item.Movable() && neighbor.item.IsBreaker(neighbor.item.type))
{
hintItems.Add(neighbor.item);
hintItems.Add(node.item);
return true;
}
}
} // end if
}
}
}
return false;
}
#endregion
#region Gingerbread
bool GenerateGingerbread()
{
if (IsGingerbreadTarget() == false)
{
return false;
}
if (skipGenerateGingerbread == true)
{
return false;
}
// calculate the total gingerbread need to generate
var needGenerate = 0;
for (int i = 1; i <= 4; i++)
{
switch (i)
{
case 1:
if (LevelLoader.instance.target1Type == TARGET_TYPE.GINGERBREAD)
{
needGenerate += target1Left;
}
break;
case 2:
if (LevelLoader.instance.target2Type == TARGET_TYPE.GINGERBREAD)
{
needGenerate += target2Left;
}
break;
case 3:
if (LevelLoader.instance.target3Type == TARGET_TYPE.GINGERBREAD)
{
needGenerate += target3Left;
}
break;
case 4:
if (LevelLoader.instance.target4Type == TARGET_TYPE.GINGERBREAD)
{
needGenerate += target4Left;
}
break;
}
}
if (needGenerate <= 0)
{
return false;
}
// check gingerbread on board
var amount = GingerbreadOnBoard().Count;
if (amount >= LevelLoader.instance.maxGingerbread)
{
return false;
}
// prevent multiple call
if (generatingGingerbread == true)
{
return false;
}
// skip generate randomly
if (Random.Range(0, 2) == 0 && skipGingerbreadCount < 2)
{
skipGingerbreadCount++;
return false;
}
skipGingerbreadCount = 0;
generatingGingerbread = true;
// get node to generate gingerbread
var currRow = row - 1;
var column = LevelLoader.instance.gingerbreadMarkers[Random.Range(0, LevelLoader.instance.gingerbreadMarkers.Count)];
var node = GetNode(currRow, column);
//print(node.name);
if (node != null && node.item != null)
{
node.item.ChangeToGingerbread(LevelLoader.instance.RandomGingerbread());
return true;
}
return false;
}
bool IsGingerbreadTarget()
{
if (LevelLoader.instance.target1Type == TARGET_TYPE.GINGERBREAD ||
LevelLoader.instance.target2Type == TARGET_TYPE.GINGERBREAD ||
LevelLoader.instance.target3Type == TARGET_TYPE.GINGERBREAD ||
LevelLoader.instance.target4Type == TARGET_TYPE.GINGERBREAD)
{
return true;
}
return false;
}
List<Item> GingerbreadOnBoard()
{
var list = new List<Item>();
var items = GetListItems();
foreach (var item in items)
{
if (item != null && item.IsGingerbread())
{
list.Add(item);
}
}
return list;
}
bool MoveGingerbread()
{
if (IsGingerbreadTarget() == false)
{
return false;
}
// prevent multiple call
if (movingGingerbread == true)
{
return false;
}
movingGingerbread = true;
var isMoved = false;
//print("Move gingerbread");
foreach (var gingerbread in GingerbreadOnBoard())
{
if (gingerbread != null)
{
var upper = GetUpperItem(gingerbread.node);
if (upper != null && upper.node != null && upper.IsGingerbread() == false && gingerbread.node.cage == null)
{
var gingerbreadPosition = NodeLocalPosition(upper.node.i, upper.node.j);
var upperItemPosition = NodeLocalPosition(gingerbread.node.i, gingerbread.node.j);
gingerbread.neighborNode = upper.node;
gingerbread.swapItem = upper;
touchedItem = gingerbread;
swappedItem = upper;
gingerbread.SwapItem();
gingerbread.gameObject.GetComponent<SpriteRenderer>().sortingOrder = 1;
// animation
iTween.MoveTo(gingerbread.gameObject, iTween.Hash(
"position", gingerbreadPosition,
"easetype", iTween.EaseType.linear,
"time", Configure.instance.swapTime
));
iTween.MoveTo(upper.gameObject, iTween.Hash(
"position", upperItemPosition,
"easetype", iTween.EaseType.linear,
"time", Configure.instance.swapTime
));
}
else if (upper == null || upper.node == null)
{
AudioManager.instance.GingerbreadExplodeAudio();
gingerbread.color = LevelLoader.instance.RandomColor();
gingerbread.ChangeSpriteAndType(gingerbread.color);
// after changing a gingerbread to a cookie. skip generate one turn on generate call right after this function
skipGenerateGingerbread = true;
}
isMoved = true;
}
}
return isMoved;
}
public Item GetUpperItem(Node node)
{
var top = node.TopNeighbor();
if (top == null)
{
return null;
}
else
{
if (top.tile.type == TILE_TYPE.NONE || top.tile.type == TILE_TYPE.PASS_THROUGH)
{
return GetUpperItem(top);
}
else if (top.item != null && top.item.Movable())
{
return top.item;
}
else
{
return node.item;
}
}
}
#endregion
#region Booster
void DestroyBoosterItems(Item boosterItem)
{
if (boosterItem == null)
{
return;
}
if (boosterItem.Destroyable() && booster != BOOSTER_TYPE.OVEN_BREAKER)
{
if (booster == BOOSTER_TYPE.RAINBOW_BREAKER && boosterItem.IsCookie() == false)
{
return;
}
lockSwap = true;
switch (booster)
{
case BOOSTER_TYPE.SINGLE_BREAKER:
DestroySingleBooster(boosterItem);
break;
case BOOSTER_TYPE.ROW_BREAKER:
StartCoroutine(DestroyRowBooster(boosterItem));
break;
case BOOSTER_TYPE.COLUMN_BREAKER:
StartCoroutine(DestroyColumnBooster(boosterItem));
break;
case BOOSTER_TYPE.RAINBOW_BREAKER:
StartCoroutine(DestroyRainbowBooster(boosterItem));
break;
}
Booster.instance.BoosterComplete();
// hide help object
if (LevelLoader.instance.level == 7 && Help.instance.step == 2)
{
Help.instance.Hide();
}
if (LevelLoader.instance.level == 12 && Help.instance.step == 2)
{
Help.instance.Hide();
}
if (LevelLoader.instance.level == 15 && Help.instance.step == 2)
{
Help.instance.Hide();
}
if (LevelLoader.instance.level == 18 && Help.instance.step == 2)
{
Help.instance.Hide();
}
}
if (boosterItem.Movable() && booster == BOOSTER_TYPE.OVEN_BREAKER)
{
StartCoroutine(DestroyOvenBooster(boosterItem));
}
}
void DestroySingleBooster(Item boosterItem)
{
HideHint();
AudioManager.instance.SingleBoosterAudio();
if (boosterItem.type == ITEM_TYPE.COOKIE_RAINBOW)
{
boosterItem.DestroyItemsSameColor(LevelLoader.instance.RandomColor());
}
boosterItem.Destroy();
FindMatches();
}
IEnumerator DestroyRowBooster(Item boosterItem)
{
HideHint();
AudioManager.instance.RowBoosterAudio();
// animation
// destroy a row
var items = new List<Item>();
items = RowItems(boosterItem.node.i);
foreach (var item in items)
{
// this item maybe destroyed in other call
if (item != null)
{
if (item.type == ITEM_TYPE.COOKIE_RAINBOW)
{
item.DestroyItemsSameColor(LevelLoader.instance.RandomColor());
}
item.Destroy();
}
yield return new WaitForSeconds(0.1f);
}
FindMatches();
}
IEnumerator DestroyColumnBooster(Item boosterItem)
{
HideHint();
AudioManager.instance.ColumnBoosterAudio();
// animation
// destroy a row
var items = new List<Item>();
items = ColumnItems(boosterItem.node.j);
foreach (var item in items)
{
// this item maybe destroyed in other call
if (item != null)
{
if (item.type == ITEM_TYPE.COOKIE_RAINBOW)
{
item.DestroyItemsSameColor(LevelLoader.instance.RandomColor());
}
item.Destroy();
}
yield return new WaitForSeconds(0.1f);
}
FindMatches();
}
IEnumerator DestroyRainbowBooster(Item boosterItem)
{
HideHint();
AudioManager.instance.RainbowBoosterAudio();
boosterItem.DestroyItemsSameColor(boosterItem.color);
yield return new WaitForFixedUpdate();
}
IEnumerator DestroyOvenBooster(Item boosterItem)
{
HideHint();
if (ovenTouchItem == null)
{
ovenTouchItem = boosterItem;
// add active
ovenTouchItem.node.AddOvenBoosterActive();
AudioManager.instance.ButtonClickAudio();
}
else
{
// the same item
if (ovenTouchItem.node.OrderOnBoard() == boosterItem.node.OrderOnBoard())
{
// remove active
ovenTouchItem.node.RemoveOvenBoosterActive();
ovenTouchItem = null;
AudioManager.instance.ButtonClickAudio();
}
// swap
else
{
lockSwap = true;
// hide help object
if (LevelLoader.instance.level == 25 && Help.instance.step == 2)
{
Help.instance.Hide();
}
boosterItem.node.AddOvenBoosterActive();
AudioManager.instance.OvenBoosterAudio();
AudioManager.instance.ButtonClickAudio();
// animation
iTween.MoveTo(ovenTouchItem.gameObject, iTween.Hash(
"position", boosterItem.gameObject.transform.position,
"easetype", iTween.EaseType.linear,
"time", Configure.instance.swapTime
));
iTween.MoveTo(boosterItem.gameObject, iTween.Hash(
"position", ovenTouchItem.gameObject.transform.position,
"easetype", iTween.EaseType.linear,
"time", Configure.instance.swapTime
));
yield return new WaitForSeconds(Configure.instance.swapTime);
ovenTouchItem.node.RemoveOvenBoosterActive();
boosterItem.node.RemoveOvenBoosterActive();
var ovenTouchNode = ovenTouchItem.node;
var boosterItemNode = boosterItem.node;
// swap item
ovenTouchNode.item = boosterItem;
boosterItemNode.item = ovenTouchItem;
// swap node
ovenTouchItem.node = boosterItemNode;
boosterItem.node = ovenTouchNode;
// swap on hierarchy
ovenTouchItem.gameObject.transform.SetParent(boosterItemNode.gameObject.transform);
boosterItem.gameObject.transform.SetParent(ovenTouchNode.gameObject.transform);
yield return new WaitForEndOfFrame();
ovenTouchItem = null;
Booster.instance.BoosterComplete();
yield return new WaitForSeconds(0.1f);
FindMatches();
}
}
yield return new WaitForFixedUpdate();
}
#endregion
#region Collectible
List<ITEM_TYPE> CheckGenerateCollectible()
{
if (LevelLoader.instance.target1Type != TARGET_TYPE.COLLECTIBLE &&
LevelLoader.instance.target2Type != TARGET_TYPE.COLLECTIBLE &&
LevelLoader.instance.target3Type != TARGET_TYPE.COLLECTIBLE &&
LevelLoader.instance.target4Type != TARGET_TYPE.COLLECTIBLE)
{
return null;
}
var collectibles = new List<ITEM_TYPE>();
if (CollectibleOnBoard() >= LevelLoader.instance.collectibleMaxOnBoard)
{
return null;
}
for (int i = 0; i <= 4; i++)
{
TARGET_TYPE targetType = TARGET_TYPE.NONE;
int targetColor = 0;
int collectibleOnBoard = 0;
int targetLeft = 0;
switch (i)
{
case 1:
targetType = LevelLoader.instance.target1Type;
targetColor = LevelLoader.instance.target1Color;
collectibleOnBoard = CollectibleOnBoard(LevelLoader.instance.target1Color);
targetLeft = target1Left;
break;
case 2:
targetType = LevelLoader.instance.target2Type;
targetColor = LevelLoader.instance.target2Color;
collectibleOnBoard = CollectibleOnBoard(LevelLoader.instance.target2Color);
targetLeft = target2Left;
break;
case 3:
targetType = LevelLoader.instance.target3Type;
targetColor = LevelLoader.instance.target3Color;
collectibleOnBoard = CollectibleOnBoard(LevelLoader.instance.target3Color);
targetLeft = target3Left;
break;
case 4:
targetType = LevelLoader.instance.target4Type;
targetColor = LevelLoader.instance.target4Color;
collectibleOnBoard = CollectibleOnBoard(LevelLoader.instance.target4Color);
targetLeft = target4Left;
break;
}
if (targetType == TARGET_TYPE.COLLECTIBLE && collectibleOnBoard < targetLeft)
{
for (int k = 0; k < targetLeft - collectibleOnBoard; k++)
{
collectibles.Add(ColorToCollectible(targetColor));
}
}
}
return collectibles;
}
ITEM_TYPE ColorToCollectible(int color)
{
switch (color)
{
case 1:
return ITEM_TYPE.COLLECTIBLE_1;
case 2:
return ITEM_TYPE.COLLECTIBLE_2;
case 3:
return ITEM_TYPE.COLLECTIBLE_3;
case 4:
return ITEM_TYPE.COLLECTIBLE_4;
case 5:
return ITEM_TYPE.COLLECTIBLE_5;
case 6:
return ITEM_TYPE.COLLECTIBLE_6;
case 7:
return ITEM_TYPE.COLLECTIBLE_7;
case 8:
return ITEM_TYPE.COLLECTIBLE_8;
case 9:
return ITEM_TYPE.COLLECTIBLE_9;
case 10:
return ITEM_TYPE.COLLECTIBLE_10;
case 11:
return ITEM_TYPE.COLLECTIBLE_11;
case 12:
return ITEM_TYPE.COLLECTIBLE_12;
case 13:
return ITEM_TYPE.COLLECTIBLE_13;
case 14:
return ITEM_TYPE.COLLECTIBLE_14;
case 15:
return ITEM_TYPE.COLLECTIBLE_15;
case 16:
return ITEM_TYPE.COLLECTIBLE_16;
case 17:
return ITEM_TYPE.COLLECTIBLE_17;
case 18:
return ITEM_TYPE.COLLECTIBLE_18;
case 19:
return ITEM_TYPE.COLLECTIBLE_19;
case 20:
return ITEM_TYPE.COLLECTIBLE_20;
default:
return ITEM_TYPE.NONE;
}
}
int CollectibleOnBoard(int color = 0)
{
int amount = 0;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
{
var node = GetNode(i, j);
if (node != null && node.item != null && node.item.IsCollectible() == true)
{
if (color == 0)
{
amount++;
}
else
{
if (node.item.color == color)
{
amount++;
}
}
}
}
}
return amount;
}
#endregion
#region Marshmallow
bool CheckGenerateMarshmallow()
{
if (LevelLoader.instance.target1Type != TARGET_TYPE.MARSHMALLOW &&
LevelLoader.instance.target2Type != TARGET_TYPE.MARSHMALLOW &&
LevelLoader.instance.target3Type != TARGET_TYPE.MARSHMALLOW &&
LevelLoader.instance.target4Type != TARGET_TYPE.MARSHMALLOW)
{
return false;
}
var needGenerate = 0;
for (int i = 1; i <= 4; i++)
{
switch (i)
{
case 1:
if (LevelLoader.instance.target1Type == TARGET_TYPE.MARSHMALLOW)
{
needGenerate += target1Left;
}
break;
case 2:
if (LevelLoader.instance.target2Type == TARGET_TYPE.MARSHMALLOW)
{
needGenerate += target2Left;
}
break;
case 3:
if (LevelLoader.instance.target3Type == TARGET_TYPE.MARSHMALLOW)
{
needGenerate += target3Left;
}
break;
case 4:
if (LevelLoader.instance.target4Type == TARGET_TYPE.MARSHMALLOW)
{
needGenerate += target4Left;
}
break;
}
}
if (needGenerate + LevelLoader.instance.marshmallowMoreThanTarget <= MarshmallowOnBoard())
{
return false;
}
return true;
}
int MarshmallowOnBoard()
{
int amount = 0;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
{
var node = GetNode(i, j);
if (node != null && node.item != null && node.item.IsMarshmallow() == true)
{
amount++;
}
}
}
return amount;
}
#endregion
#region HeroSkill
public GameObject HeroSkillPrefab;
public List<PuzzleSkillDisplayer> SkillDisplayerList = new List<PuzzleSkillDisplayer>();
public bool GetHeroSkillCanDisplay(PuzzleHero hero)
{
return false;
}
public List<CountAndPosData> GetMinEffectPosList(PuzzleHero hero)
{
List<CountAndPosData> currPosList = new List<CountAndPosData>();
SkillConfig? config = PuzzleGameMode.main.GetSkillConfig(hero.AttackSkillID);
if (config == null)
{
return currPosList;
}
int maxRow = row - config.Value.SkillSize.x;
int maxColumn = column - config.Value.SkillSize.y;
Vector2 currPos;
int finalCount = 0;
for (int j = 0; j < maxRow + 1; j++)
{
for (int k = 0; k < maxColumn + 1; k++)
{
currPos.x = j;
currPos.y = k;
int currCount = GetCardTypeCount(currPos, config.Value.SkillSize);
if (finalCount < currCount)
{
currPosList.Clear();
CountAndPosData newPos = new CountAndPosData();
newPos.PosData = new Vector2(j, k);
newPos.Count = currCount;
newPos.BoardIndex = BoardIndex;
currPosList.Add(newPos);
finalCount = currCount;
}
else if (finalCount == currCount)
{
CountAndPosData newPos = new CountAndPosData();
newPos.PosData = new Vector2(j, k);
newPos.Count = currCount;
newPos.BoardIndex = BoardIndex;
currPosList.Add(newPos);
}
}
}
return currPosList;
}
int GetCardTypeCount(Vector2 startPos, Vector2Int size)
{
List<ITEM_TYPE> TypeList = new List<ITEM_TYPE>();
for (int j = 0; j < size.x; j++)
{
for (int k = 0; k < size.y; k++)
{
var order = NodeOrder(j + (int)startPos.x, k + (int)startPos.y);
if (nodes[order].item != null)
{
if (!TypeList.Contains(nodes[order].item.type))
{
TypeList.Add(nodes[order].item.type);
}
}
}
}
return TypeList.Count;
}
public void CreateHeroSkillCard(PuzzleHero hero, Vector2 posData)
{
SkillConfig? config = PuzzleGameMode.main.GetSkillConfig(hero.AttackSkillID);
if (config == null)
{
return;
}
GameObject heroSkillDisplayer = Instantiate(HeroSkillPrefab, transform);
heroSkillDisplayer.transform.localPosition = NodeLocalPosition((int)posData.x, (int)posData.y) + new Vector3(NodeSize() * 0.5f * (config.Value.SkillSize.y - 1), -NodeSize() * 0.5f * (config.Value.SkillSize.x - 1), 0);
PuzzleSkillDisplayer currSkillDisplayer = heroSkillDisplayer.transform.GetComponent<PuzzleSkillDisplayer>();
currSkillDisplayer.SetHero(hero, this, (int)posData.x, (int)posData.y);
SkillDisplayerList.Add(currSkillDisplayer);
DestroyItem((int)posData.x, (int)posData.y, config.Value.SkillSize);
}
public void CreateHeroSkillCard(PuzzleHero hero)
{
SkillConfig? config = PuzzleGameMode.main.GetSkillConfig(hero.AttackSkillID);
if (config == null)
{
return;
}
heroSkillDisplay = true;
int maxRow = row - config.Value.SkillSize.x;
int maxColumn = column - config.Value.SkillSize.y;
int currRow = Random.Range(0, maxRow + 1);
int currColumn = Random.Range(0, maxColumn + 1);
GameObject heroSkillDisplayer = Instantiate(HeroSkillPrefab, transform);
heroSkillDisplayer.transform.localPosition = NodeLocalPosition(currRow, currColumn) + new Vector3(NodeSize() * 0.5f * (config.Value.SkillSize.y - 1), -NodeSize() * 0.5f * (config.Value.SkillSize.x - 1), 0);
PuzzleSkillDisplayer currSkillDisplayer = heroSkillDisplayer.transform.GetComponent<PuzzleSkillDisplayer>();
currSkillDisplayer.SetHero(hero, this, currRow, currColumn);
SkillDisplayerList.Add(currSkillDisplayer);
DestroyItem(currRow, currColumn, config.Value.SkillSize);
}
void DestroyItem(int startRow, int startColumn, Vector2Int skillSize)
{
for (int j = 0; j < skillSize.x; j++)
{
for (int k = 0; k < skillSize.y; k++)
{
Node currNode = GetNode(startRow + j, startColumn + k);
currNode.SkillMasked();
}
}
StartCoroutine(DelayDealNoMatchCase(startRow, startColumn, skillSize));
}
IEnumerator DelayDealNoMatchCase(int startRow, int startColumn, Vector2Int skillSize)
{
while (destroyingItems > 0)
{
yield return new WaitForSeconds(0.1f);
}
DealNoMatchCase(originlaPos);
}
public void ResetSkill(PuzzleHero hero)
{
SkillConfig? config = PuzzleGameMode.main.GetSkillConfig(hero.AttackSkillID);
if (config == null)
{
return;
}
heroSkillDisplay = false;
PuzzleSkillDisplayer currSkillDisplay = null;
for (int j = 0; j < SkillDisplayerList.Count; j++)
{
if (hero == SkillDisplayerList[j].Hero)
{
currSkillDisplay = SkillDisplayerList[j];
}
}
var skillSize = config.Value.SkillSize;
for (int j = 0; j < skillSize.x; j++)
{
for (int k = 0; k < skillSize.y; k++)
{
Node currNode = GetNode(currSkillDisplay.startRow + j, currSkillDisplay.startColumn + k);
currNode.SkillReset();
currNode.GenerateItem(ITEM_TYPE.COOKIE_RAMDOM);
}
}
DealNoMatchCase(originlaPos);
Destroy(currSkillDisplay.gameObject);
}
#endregion
}
public enum RowAlignmentType
{
Left,
Center,
Right,
}
public enum ColumnAlignmentType
{
Upper,
Middle,
Lower,
}
public class CountAndPosData
{
public Vector2 PosData;
public int Count;
public int BoardIndex;
}