|
|
|
|
using DG.Tweening;
|
|
|
|
|
using System.Collections;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
using UnityEngine.AI;
|
|
|
|
|
|
|
|
|
|
public class MapBlock : MonoBehaviour
|
|
|
|
|
{
|
|
|
|
|
public enum Type { None, Monster, Boss, Mini, Hidden, Shop, Wave, Empty }
|
|
|
|
|
|
|
|
|
|
//private void OnEnable()
|
|
|
|
|
//{
|
|
|
|
|
// Door_Init();
|
|
|
|
|
// CLEAR = false;
|
|
|
|
|
//}
|
|
|
|
|
public EventConnect ecMapBlock = new EventConnect();
|
|
|
|
|
public void OnEvent(int type, object value)
|
|
|
|
|
{
|
|
|
|
|
switch ((MapEvent)type)
|
|
|
|
|
{
|
|
|
|
|
case MapEvent.DoorInit:
|
|
|
|
|
{
|
|
|
|
|
Door_Init();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case MapEvent.DoorConnect://맵이 생성 된 직후 호출 되며 인접한 블럭끼리의 문을 연결합니다.
|
|
|
|
|
{
|
|
|
|
|
Dictionary<Vector2, MapBlock> blks = (Dictionary<Vector2, MapBlock>)value;
|
|
|
|
|
var list = blks.Values.ToList().FindAll(a => a.number == number + 1 || a.number == number - 1);
|
|
|
|
|
for (int i = 0; i < list.Count; i++)
|
|
|
|
|
Door_Connect(list[i]);
|
|
|
|
|
|
|
|
|
|
//Floor_Setting();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case MapEvent.DoorNearSave:
|
|
|
|
|
{
|
|
|
|
|
blkNears = new List<MapBlock>(new MapBlock[4]);
|
|
|
|
|
dirEmpty.Clear();
|
|
|
|
|
|
|
|
|
|
Dictionary<Vector2, MapBlock> blks = (Dictionary<Vector2, MapBlock>)value;
|
|
|
|
|
var list = blks.Values.ToList().FindAll(a => (a.idx.x == idx.x + 1 || a.idx.x == idx.x - 1) || (a.idx.y == idx.y + 1 || a.idx.y == idx.y - 1));
|
|
|
|
|
for (int i = 0; i < list.Count; i++)
|
|
|
|
|
NearSave(list[i]);
|
|
|
|
|
|
|
|
|
|
cntNear = blkNears.FindAll(a => a != null).Count;
|
|
|
|
|
NearEmptyIndex_Save();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Vector2 posBlk = new Vector2(22, 15);
|
|
|
|
|
[HideInInspector]
|
|
|
|
|
public MapManager manager;
|
|
|
|
|
public int number;
|
|
|
|
|
[OnlyRead]
|
|
|
|
|
public Vector2 idx;
|
|
|
|
|
public List<GameObject> initOn;
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 블럭의 초기화를 진행합니다.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="manager"></param>
|
|
|
|
|
/// <param name="number"></param>
|
|
|
|
|
/// <param name="idx"></param>
|
|
|
|
|
/// <param name="blkType"></param>
|
|
|
|
|
public void OnInitialized(MapManager manager, int number, Vector2 idx, Type blkType)
|
|
|
|
|
{
|
|
|
|
|
this.blkType = blkType;
|
|
|
|
|
this.manager = manager;
|
|
|
|
|
this.number = number;
|
|
|
|
|
|
|
|
|
|
mobAlives.Clear();
|
|
|
|
|
dropItems.Clear();
|
|
|
|
|
|
|
|
|
|
OnDropChanged = null;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < initOn.Count; i++)
|
|
|
|
|
initOn[i].SetActive(true);
|
|
|
|
|
//블럭의 위치
|
|
|
|
|
this.idx = idx;
|
|
|
|
|
transform.localPosition = new Vector3(posBlk.x * idx.x, 0, posBlk.y * idx.y);
|
|
|
|
|
|
|
|
|
|
tileDatas = null;
|
|
|
|
|
CLEAR = false;
|
|
|
|
|
|
|
|
|
|
TintFade(0.8f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[OnlyRead]
|
|
|
|
|
public bool CLEAR = false;
|
|
|
|
|
[OnlyRead]
|
|
|
|
|
public Type blkType = Type.None;
|
|
|
|
|
MapBlockShop shopComponent;
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 해당 블럭의 타입을 설정 합니다.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void TypeSetting()
|
|
|
|
|
{
|
|
|
|
|
if (CLEAR)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
idxWave = 0;
|
|
|
|
|
CLEAR = true;
|
|
|
|
|
//manager.BossMonsterAppear(null);
|
|
|
|
|
EventManager.Instance.Invoke("BossAppear", null);
|
|
|
|
|
switch (blkType)
|
|
|
|
|
{
|
|
|
|
|
case Type.None://아무것도 없는 블럭
|
|
|
|
|
idxWave = appears.Count;
|
|
|
|
|
ecMapBlock.Invoke((int)MapEvent.DoorState, true);
|
|
|
|
|
break;
|
|
|
|
|
case Type.Monster://몬스터가 존재 하는 블럭
|
|
|
|
|
{
|
|
|
|
|
CLEAR = false;
|
|
|
|
|
ecMapBlock.Invoke((int)MapEvent.DoorState, false);
|
|
|
|
|
|
|
|
|
|
appears.Clear();
|
|
|
|
|
appears.Add(manager.floorData.MonsterAppearGet());
|
|
|
|
|
|
|
|
|
|
Monster_Create(appears[idxWave++]);//일반 몬스터 블럭
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case Type.Wave:
|
|
|
|
|
{
|
|
|
|
|
waveTrigger.triggerEvent.OnTrigger.AddListener(WaveChallenge);
|
|
|
|
|
waveTrigger.gameObject.SetActive(true);
|
|
|
|
|
|
|
|
|
|
manager.floorData.WaveAppearGet(appears);
|
|
|
|
|
ecMapBlock.Invoke((int)MapEvent.DoorState, true);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case Type.Boss://보스가 존재 하는 블럭
|
|
|
|
|
{
|
|
|
|
|
BGMPlay();//보스
|
|
|
|
|
|
|
|
|
|
CLEAR = false;
|
|
|
|
|
ecMapBlock.Invoke((int)MapEvent.DoorState, false);
|
|
|
|
|
|
|
|
|
|
appearsBoss = manager.floorData.BossAppearGet();
|
|
|
|
|
|
|
|
|
|
appears.Clear();
|
|
|
|
|
appears.Add(manager.floorData.BossInferiorGet());
|
|
|
|
|
|
|
|
|
|
Monster_Create(appearsBoss, true, () =>
|
|
|
|
|
{
|
|
|
|
|
Monster_Create(appears[idxWave++]);//일반 몬스터 블럭
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case Type.Mini:
|
|
|
|
|
{
|
|
|
|
|
BGMPlay();//중보스
|
|
|
|
|
|
|
|
|
|
CLEAR = false;
|
|
|
|
|
ecMapBlock.Invoke((int)MapEvent.DoorState, false);
|
|
|
|
|
|
|
|
|
|
appearsBoss = manager.floorData.MiniAppearGet();
|
|
|
|
|
|
|
|
|
|
appears.Clear();
|
|
|
|
|
appears.Add(manager.floorData.MiniInferiorGet());
|
|
|
|
|
|
|
|
|
|
Monster_Create(appearsBoss, true, () =>
|
|
|
|
|
{
|
|
|
|
|
Monster_Create(appears[idxWave++]);//일반 몬스터 블럭
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case Type.Shop:
|
|
|
|
|
{
|
|
|
|
|
if (shopComponent == null)
|
|
|
|
|
shopComponent = GetComponent<MapBlockShop>();
|
|
|
|
|
|
|
|
|
|
if (shopComponent == null)
|
|
|
|
|
Debug.LogError($"맵블럭:샵 생성 오류, MapBlockShop 컴포넌트 없음");
|
|
|
|
|
else
|
|
|
|
|
shopComponent.OnInitialized(this, OnGain);
|
|
|
|
|
|
|
|
|
|
ecMapBlock.Invoke((int)MapEvent.DoorState, true);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case Type.Hidden:
|
|
|
|
|
ecMapBlock.Invoke((int)MapEvent.DoorState, true);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
int idxWave = 0;
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 다음 웨이브가 있는지 확인 하며 있다면 웨이브를 실행 하고 없다면 클리어 처리
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void WaveChallenge()
|
|
|
|
|
{
|
|
|
|
|
if (idxWave == 0)
|
|
|
|
|
{
|
|
|
|
|
if (blkType == Type.Wave)
|
|
|
|
|
BGMPlay();//웨이브
|
|
|
|
|
CLEAR = false;
|
|
|
|
|
ecMapBlock.Invoke((int)MapEvent.DoorState, CLEAR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (idxWave < appears.Count)
|
|
|
|
|
StartCoroutine(WaveWait());
|
|
|
|
|
//Monster_Create(appears[idxWave++]);
|
|
|
|
|
else
|
|
|
|
|
Invoke("Clear_Wait", 1f);
|
|
|
|
|
}
|
|
|
|
|
[Space(10)]
|
|
|
|
|
public WaveTrigger waveTrigger;
|
|
|
|
|
public SoundPlayer spEarthquake;
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 다음 웨이브 까지의 n초 동안 대기합니다.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
IEnumerator WaveWait()
|
|
|
|
|
{
|
|
|
|
|
yield return new WaitForSeconds(1f);
|
|
|
|
|
|
|
|
|
|
manager.tiltCamera.Shaking(0.25f, 2f);
|
|
|
|
|
|
|
|
|
|
SoundPlayer SFX = null;
|
|
|
|
|
if (spEarthquake != null)
|
|
|
|
|
SFX = SoundManager.Instance.EffectPlay(spEarthquake.gameObject);
|
|
|
|
|
|
|
|
|
|
yield return new WaitForSeconds(2f);
|
|
|
|
|
|
|
|
|
|
if (SFX != null)
|
|
|
|
|
SFX.Play_Fade(false);
|
|
|
|
|
Monster_Create(appears[idxWave++]);//웨이브 생성
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Space(10)]
|
|
|
|
|
public SpriteRenderer imgTent;
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 캐릭터가 문을 통해 이동시 적용
|
|
|
|
|
/// 현재 맵 = 어둡게
|
|
|
|
|
/// 이동 맵 = 밝게
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="fade"></param>
|
|
|
|
|
/// <param name="duration"></param>
|
|
|
|
|
public void TintFade(float fade, float duration = 0.2f)
|
|
|
|
|
{
|
|
|
|
|
imgTent.DOKill();
|
|
|
|
|
imgTent.DOFade(fade = 0, duration);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Space(10)]
|
|
|
|
|
int cntNear = 0;
|
|
|
|
|
public List<MapBlock> blkNears = new List<MapBlock>();
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 해당 블럭 주변에 있는 블럭을 저장합니다.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="blk"></param>
|
|
|
|
|
void NearSave(MapBlock blk)
|
|
|
|
|
{
|
|
|
|
|
Vector2 idxT = idx - blk.idx;
|
|
|
|
|
MapDirection dir;
|
|
|
|
|
|
|
|
|
|
if (idxT.x != 0 && idxT.y != 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (idxT.x != 0)
|
|
|
|
|
dir = 0 < idxT.x ? MapDirection.Left : MapDirection.Right;
|
|
|
|
|
else if (idxT.y != 0)
|
|
|
|
|
dir = 0 < idxT.y ? MapDirection.Down : MapDirection.Up;
|
|
|
|
|
else
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
blkNears[(int)dir] = blk;
|
|
|
|
|
}
|
|
|
|
|
[HideInInspector]
|
|
|
|
|
public List<Vector2> dirEmpty;
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 해당 블럭 주변에 없는 블럭의 좌표를 저장합니다.
|
|
|
|
|
/// </summary>
|
|
|
|
|
void NearEmptyIndex_Save()
|
|
|
|
|
{
|
|
|
|
|
Vector2 idxT = Vector2.zero;
|
|
|
|
|
for (int i = 0; i < blkNears.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
if (i == (int)MapDirection.Down)//특수블럭 생성시 아래방향 제외
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
idxT = idx + MapManager.dirs[i];
|
|
|
|
|
if (blkNears[i] == null && manager.CheckIndexRange(idxT))
|
|
|
|
|
dirEmpty.Add(idx + MapManager.dirs[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 연결되어 있지 않은 좌표를 넘깁니다.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public Vector2 NearEmptyIndex_Get()
|
|
|
|
|
{
|
|
|
|
|
return dirEmpty[Random.Range(0, dirEmpty.Count)];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Setting(string dungeonName)
|
|
|
|
|
{
|
|
|
|
|
gameObject.SetActive(true);
|
|
|
|
|
|
|
|
|
|
Wall_Create();
|
|
|
|
|
Floor_Create(dungeonName);
|
|
|
|
|
Floor_Setting(dungeonName);
|
|
|
|
|
Roof_Create();
|
|
|
|
|
DoorBlocked_Create();
|
|
|
|
|
|
|
|
|
|
NavMeshBuild();
|
|
|
|
|
}
|
|
|
|
|
[Space(10)]
|
|
|
|
|
public NavMeshSurface surfacesBoss;
|
|
|
|
|
public NavMeshSurface surfaces;
|
|
|
|
|
public void NavMeshBuild()
|
|
|
|
|
{
|
|
|
|
|
surfaces.BuildNavMesh();
|
|
|
|
|
if (blkType == Type.Boss || blkType == Type.Mini)
|
|
|
|
|
surfacesBoss.BuildNavMesh();
|
|
|
|
|
|
|
|
|
|
//for (int i = 0; i < surfaces.Count; i++)
|
|
|
|
|
// surfaces[i].BuildNavMesh();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Transform roof;
|
|
|
|
|
public GameObject roofPrefab;
|
|
|
|
|
void Roof_Create()
|
|
|
|
|
{
|
|
|
|
|
manager.ObjectCreateLocalPos(roofPrefab, roof, Vector3.one, Vector3.zero);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Space(10)]
|
|
|
|
|
public Transform floor;
|
|
|
|
|
public GameObject floorTile;
|
|
|
|
|
public Vector2 floorMin = new Vector2(-10, -4);
|
|
|
|
|
public Vector2 floorMax = new Vector2(10, 4);
|
|
|
|
|
public Vector3 floorPosNext = new Vector3(2, 0, 2);
|
|
|
|
|
//[Space(5)]
|
|
|
|
|
public Dictionary<Vector2, MapTile> tiles = new Dictionary<Vector2, MapTile>();
|
|
|
|
|
void Floor_Create(string dungeonName)
|
|
|
|
|
{
|
|
|
|
|
if (floor == null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
tiles.Clear();
|
|
|
|
|
|
|
|
|
|
Vector3 pos = Vector3.zero;
|
|
|
|
|
Vector2 idx = Vector2.zero;
|
|
|
|
|
MapTile tile = null;
|
|
|
|
|
for (int x = (int)floorMin.x; x <= floorMax.x; x++)
|
|
|
|
|
{
|
|
|
|
|
for (int y = (int)floorMin.y; y <= floorMax.y; y++)
|
|
|
|
|
{
|
|
|
|
|
idx.x = x;
|
|
|
|
|
idx.y = y;
|
|
|
|
|
|
|
|
|
|
pos.x = (x * floorPosNext.x);
|
|
|
|
|
pos.z = (y * floorPosNext.y);
|
|
|
|
|
tile = manager.CreateTile(floor, floorTile, Vector3.one, pos);
|
|
|
|
|
tiles.Add(idx, tile);
|
|
|
|
|
|
|
|
|
|
tile.OnInitialized(idx, MapTile.Type.None, manager.MaterialGet(dungeonName)[(int)MapTile.Type.None][0]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public List<TileData> tileDatas = null;
|
|
|
|
|
void Floor_Setting(string dungeonName)
|
|
|
|
|
{
|
|
|
|
|
tileDatas = manager.dataDungeon.TileGet(blkType, doors);
|
|
|
|
|
|
|
|
|
|
if(tileDatas != null && 0 < tileDatas.Count)
|
|
|
|
|
{
|
|
|
|
|
TileData data = tileDatas[Random.Range(0, tileDatas.Count)];
|
|
|
|
|
|
|
|
|
|
Vector2 idx = new Vector2();
|
|
|
|
|
for (int i = 0; i < data.tileDatas.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
idx.x = data.tileDatas[i].x;
|
|
|
|
|
idx.y = data.tileDatas[i].y;
|
|
|
|
|
|
|
|
|
|
MapTile tile = tiles[idx];
|
|
|
|
|
|
|
|
|
|
if (data.tileDatas[i].type != MapTile.Type.None)
|
|
|
|
|
tile.OnApply(data.tileDatas[i].type, manager.MaterialGet(dungeonName)[data.tileDatas[i].type][0]);
|
|
|
|
|
|
|
|
|
|
if (data.tileDatas[i].obstacle != string.Empty)
|
|
|
|
|
{
|
|
|
|
|
tile.obstacle = manager.ObjectCreateLocalPos(manager.ObstacleGet(dungeonName).Find(a => a.name.Equals(data.tileDatas[i].obstacle)), tile.transform, Vector3.one, Vector3.zero);
|
|
|
|
|
tile.obstacle.transform.localEulerAngles = new Vector3(0, data.tileDatas[i].angle, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<GameObject> wall = new List<GameObject>(new GameObject[4]);
|
|
|
|
|
[Space(10)]
|
|
|
|
|
public List<float> thickness;
|
|
|
|
|
public GameObject prefabWallUD;
|
|
|
|
|
public GameObject prefabWallLR;
|
|
|
|
|
public void Wall_Init()
|
|
|
|
|
{
|
|
|
|
|
for(int i = 0; i < wall.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
if (wall[i] != null)
|
|
|
|
|
wall[i].gameObject.SetActive(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void Wall_Create()
|
|
|
|
|
{
|
|
|
|
|
Wall_Create(prefabWallLR, (int)MapDirection.Left);
|
|
|
|
|
Wall_Create(prefabWallLR, (int)MapDirection.Right);
|
|
|
|
|
Wall_Create(prefabWallUD, (int)MapDirection.Up);
|
|
|
|
|
Wall_Create(prefabWallUD, (int)MapDirection.Down);
|
|
|
|
|
}
|
|
|
|
|
void Wall_Create(GameObject prefab, int dir)
|
|
|
|
|
{
|
|
|
|
|
wall[dir] = manager.ObjectCreateLocalPos(prefab, doorsPoint[dir], Vector3.one, Vector3.zero);
|
|
|
|
|
if (0 < thickness[dir])
|
|
|
|
|
wall[dir].SendMessage("Thickness", thickness[dir]);
|
|
|
|
|
}
|
|
|
|
|
[Header("문 설정")]
|
|
|
|
|
//public List<MapDoor> doors_Blocked = new List<MapDoor>(new MapDoor[4]);
|
|
|
|
|
public MapDoor prefabWall;
|
|
|
|
|
[HideInInspector]
|
|
|
|
|
public List<GameObject> doors_Blocked = new List<GameObject>(new GameObject[4]);
|
|
|
|
|
void DoorBlocked_Create()
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < doors_Blocked.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
if (doors[i] == null)
|
|
|
|
|
doors_Blocked[i] = manager.ObjectCreateLocalPos(prefabDoorWall.gameObject, doorsPoint[i], Vector3.one, Vector3.zero);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public List<Transform> doorsPoint = new List<Transform>(new Transform[4]);
|
|
|
|
|
[HideInInspector]
|
|
|
|
|
public List<MapDoor> doors = new List<MapDoor>(new MapDoor[4]);
|
|
|
|
|
[Header("생성하게 될 문 종류")]
|
|
|
|
|
public MapDoor prefabDoorWall;
|
|
|
|
|
public MapDoor prefabDoorWallBreak;
|
|
|
|
|
public MapDoor prefabDoorBasic;
|
|
|
|
|
public MapDoor prefabDoorBasicBreak;
|
|
|
|
|
public MapDoor prefabDoorLock;
|
|
|
|
|
public MapDoor prefabDoorBoss;
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 도어의 상태를 초기화 합니다.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void Door_Init()
|
|
|
|
|
{
|
|
|
|
|
ecMapBlock.Clear();
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < doors_Blocked.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
//doors_Blocked[i] = manager.ObjectCreateLocalPos(prefabWall.gameObject, doorsPoint[i], Vector3.one, Vector3.zero);
|
|
|
|
|
//doors_Blocked[i].gameObject.SetActive(true);
|
|
|
|
|
|
|
|
|
|
if (doors[i] != null)
|
|
|
|
|
doors[i].gameObject.SetActive(false);
|
|
|
|
|
doors[i] = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 블럭에 문을 생성합니다
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="door">문 프리팹</param>
|
|
|
|
|
/// <param name="dir">생성 방향</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public MapDoor Door_Create(MapDoor door, MapDirection dir)
|
|
|
|
|
{
|
|
|
|
|
MapDoor create = doors[(int)dir];
|
|
|
|
|
if (create == null)
|
|
|
|
|
{
|
|
|
|
|
create = manager.ObjectCreateLocalPos(door.gameObject, doorsPoint[(int)dir], Vector3.one, Vector3.zero).GetComponent<MapDoor>();
|
|
|
|
|
doors[(int)dir] = create;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return create;
|
|
|
|
|
}
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 해당 블럭의 문을 연결합니다.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="blk"></param>
|
|
|
|
|
public void Door_Connect(MapBlock blk)
|
|
|
|
|
{
|
|
|
|
|
Vector2 idxT = idx - blk.idx;
|
|
|
|
|
if (idxT.x != 0 && idxT.y != 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
MapDirection dir;
|
|
|
|
|
MapDirection dir2;
|
|
|
|
|
|
|
|
|
|
if (idxT.x != 0)
|
|
|
|
|
{
|
|
|
|
|
dir = idxT.x < 0 ? MapDirection.Left : MapDirection.Right;
|
|
|
|
|
dir2 = 0 < idxT.x ? MapDirection.Left : MapDirection.Right;
|
|
|
|
|
}
|
|
|
|
|
else if (idxT.y != 0)
|
|
|
|
|
{
|
|
|
|
|
dir = idxT.y < 0 ? MapDirection.Down : MapDirection.Up;
|
|
|
|
|
dir2 = 0 < idxT.y ? MapDirection.Down : MapDirection.Up;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
//if (doors[(int)dir2] != null)
|
|
|
|
|
// return;
|
|
|
|
|
|
|
|
|
|
List<MapDoorLink> select = null;
|
|
|
|
|
MapDoor door = null;
|
|
|
|
|
List<MapDoorLink> select2 = null;
|
|
|
|
|
MapDoor door2 = null;
|
|
|
|
|
switch(blkType)
|
|
|
|
|
{
|
|
|
|
|
case Type.Boss:
|
|
|
|
|
door = Door_Create(prefabDoorBoss, dir2);
|
|
|
|
|
door2 = blk.Door_Create(blk.prefabDoorBoss, dir);
|
|
|
|
|
break;
|
|
|
|
|
case Type.Mini:
|
|
|
|
|
case Type.Hidden:
|
|
|
|
|
case Type.Shop:
|
|
|
|
|
door = Door_Create(prefabDoorLock, dir2);
|
|
|
|
|
door2 = blk.Door_Create(blk.prefabDoorLock, dir);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
if (blkType == Type.Boss || blk.blkType == Type.Boss)
|
|
|
|
|
{
|
|
|
|
|
door = Door_Create(prefabDoorBoss, dir2);
|
|
|
|
|
door2 = blk.Door_Create(blk.prefabDoorBoss, dir);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
door = Door_Create(prefabDoorBasic, dir2);
|
|
|
|
|
door2 = blk.Door_Create(blk.prefabDoorBasic, dir);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
door.Connect(blk, door2);
|
|
|
|
|
ecMapBlock.Add(door.OnEvent);
|
|
|
|
|
|
|
|
|
|
//doors_Blocked[(int)dir2].gameObject.SetActive(false);
|
|
|
|
|
|
|
|
|
|
if(blkType == Type.Boss)
|
|
|
|
|
{
|
|
|
|
|
switch(dir2)
|
|
|
|
|
{
|
|
|
|
|
case MapDirection.Left:
|
|
|
|
|
dir = MapDirection.Right;
|
|
|
|
|
break;
|
|
|
|
|
case MapDirection.Right:
|
|
|
|
|
dir = MapDirection.Left;
|
|
|
|
|
break;
|
|
|
|
|
case MapDirection.Down:
|
|
|
|
|
dir = MapDirection.Up;
|
|
|
|
|
break;
|
|
|
|
|
case MapDirection.Up:
|
|
|
|
|
dir = MapDirection.Down;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
door = Door_Create(prefabDoorBasic, dir);
|
|
|
|
|
ecMapBlock.Add(door.OnEvent);
|
|
|
|
|
|
|
|
|
|
//doors_Blocked[(int)dir].gameObject.SetActive(false);
|
|
|
|
|
|
|
|
|
|
door.PortalSetting(manager.effectPortal);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public void Door_Setting()
|
|
|
|
|
{
|
|
|
|
|
if (CLEAR)
|
|
|
|
|
ecMapBlock.Invoke((int)MapEvent.DoorState, blkType == MapBlock.Type.None);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public GameObject prefabEffectAppear;
|
|
|
|
|
[Header("몬스터 설정")]
|
|
|
|
|
public AppearList appearsBoss;
|
|
|
|
|
public List<AppearList> appears = new List<AppearList>();
|
|
|
|
|
public List<SpwnPoint> spwnPoints;
|
|
|
|
|
[Header("살아있는 몬스터 목록")]
|
|
|
|
|
public List<Character> mobAlives = new List<Character>();
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 해당 블럭의 몬스터를 생성합니다.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void Monster_Create(AppearList appear, bool BOSS = false, System.Action OnEnd = null)
|
|
|
|
|
{
|
|
|
|
|
StartCoroutine(Monster_CreateOrder(appear, BOSS, OnEnd));
|
|
|
|
|
}
|
|
|
|
|
IEnumerator Monster_CreateOrder(AppearList appear, bool BOSS, System.Action OnEnd)
|
|
|
|
|
{
|
|
|
|
|
WaitForSeconds wait = new WaitForSeconds(0.1f);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < appear.cnt; i++)
|
|
|
|
|
{
|
|
|
|
|
SpwnPoint spwn = spwnPoints[Random.Range(0, spwnPoints.Count)];
|
|
|
|
|
Vector3 pos = spwn.PointCreate();
|
|
|
|
|
int idx = Random.Range(0, appear.mobNames.Count);
|
|
|
|
|
|
|
|
|
|
if (prefabEffectAppear != null)
|
|
|
|
|
{
|
|
|
|
|
manager.ObjectCreate(prefabEffectAppear, null, Vector3.one, pos);
|
|
|
|
|
yield return wait;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GameObject prefab = PrefabManager.Instance.PrefabGet($"Monster/{appear.mobNames[idx]}");
|
|
|
|
|
if (prefab == null)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
Character mob = manager.MonsterCreate(this, prefab.gameObject, Vector3.zero);
|
|
|
|
|
|
|
|
|
|
mob.NO_DAMAGE = true;
|
|
|
|
|
|
|
|
|
|
mob.OnInitialized(0, 0);//몬스터 생성 : 블럭 진입시
|
|
|
|
|
mob.skill.OnInitialized();
|
|
|
|
|
mob.OnDie += OnMonsterDie;
|
|
|
|
|
mob.OnWarp(pos);
|
|
|
|
|
mobAlives.Add(mob);
|
|
|
|
|
|
|
|
|
|
if (BOSS)
|
|
|
|
|
{
|
|
|
|
|
//manager.BossMonsterAppear(mobAlives[0]);
|
|
|
|
|
EventManager.Instance.Invoke("BossAppear", mobAlives[0]);
|
|
|
|
|
mobAlives[0].OnLocked(true);
|
|
|
|
|
mobAlives[0].motion.Play(Motion.Type.Appear, true, () =>
|
|
|
|
|
{
|
|
|
|
|
mobAlives[0].OnLocked(false);
|
|
|
|
|
|
|
|
|
|
if (OnEnd != null)
|
|
|
|
|
OnEnd();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
mob.OnLocked(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
yield return wait;
|
|
|
|
|
|
|
|
|
|
mob.NO_DAMAGE = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 몬스터 생성과 관련된 스킬에서 사용됨
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="ai">생성 프리팹</param>
|
|
|
|
|
/// <param name="pos">생성 위치</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public Character Monster_Create(Character ai, Vector3 pos)
|
|
|
|
|
{
|
|
|
|
|
Character mob = manager.MonsterCreate(this, ai.gameObject, Vector3.zero);
|
|
|
|
|
mob.OnDie += OnMonsterDie;
|
|
|
|
|
mobAlives.Add(mob);
|
|
|
|
|
|
|
|
|
|
return mob;
|
|
|
|
|
}
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 몬스터의 부활에 사용
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="mob"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public Character Monster_Resurrection(Character mob)
|
|
|
|
|
{
|
|
|
|
|
mob.OnDie += OnMonsterDie;
|
|
|
|
|
mobAlives.Add(mob);
|
|
|
|
|
|
|
|
|
|
return mob;
|
|
|
|
|
}
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 해당 블럭에서 생성 된 몹이 죽었으며 모두 처치 했다면 클리어 됩니다.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="mob"></param>
|
|
|
|
|
void OnMonsterDie(Character mob, Vector3 dir)
|
|
|
|
|
{
|
|
|
|
|
mobAlives.Remove(mob);
|
|
|
|
|
mob.OnDie -= OnMonsterDie;
|
|
|
|
|
|
|
|
|
|
OnDropItem_Create_MonsterDie(mob);
|
|
|
|
|
manager.player.character.skill.Active("MobKill", mob, null);
|
|
|
|
|
|
|
|
|
|
//몬스터 전멸
|
|
|
|
|
if (mobAlives.Count == 0)
|
|
|
|
|
WaveChallenge();
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < mobAlives.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
if (mobAlives[i].gameObject.activeSelf)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Header("드롭아이템 설정")]
|
|
|
|
|
public DropItem prefabDropItem;
|
|
|
|
|
public List<DropItem> dropItems = new List<DropItem>();
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 블럭에 드랍되어 있는 아이템이 있는지 확인합니다
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="idx"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public bool HoldingItemCheck(string idx)
|
|
|
|
|
{
|
|
|
|
|
return dropItems.Find(a => a.item.idx.Equals(idx) && a.gameObject.activeSelf) != null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 몬스터가 죽었으며 드롭아이템을 생성 합니다.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="mob">죽은 몬스터</param>
|
|
|
|
|
public void OnDropItem_Create_MonsterDie(Character mob)
|
|
|
|
|
{
|
|
|
|
|
if(Random.Range(0, 1000) < 200)
|
|
|
|
|
{
|
|
|
|
|
float rate = Random.Range(0, 1000);
|
|
|
|
|
if(rate < 700)
|
|
|
|
|
{
|
|
|
|
|
manager.DuplicateItemCheck(manager.items_Use, 0, 999, mob.transform);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
manager.DuplicateItemCheck(manager.items_All, 0, 999, mob.transform);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//for (int i = 0; i < mob.drops.Count; i++)
|
|
|
|
|
//{
|
|
|
|
|
// int value = mob.drops[i].Get();
|
|
|
|
|
// DropItem item = null;
|
|
|
|
|
// if (0 < value && !manager.OnHoldingItemCheck(mob.drops[i].idx))
|
|
|
|
|
// {
|
|
|
|
|
// if (1 < value)
|
|
|
|
|
// {
|
|
|
|
|
// for (int j = 0; j < value; j++)
|
|
|
|
|
// {
|
|
|
|
|
// item = manager.DropItemCreate(this, prefabDropItem.gameObject, mob.transform.position);
|
|
|
|
|
|
|
|
|
|
// mob.drops[i].value = 1;
|
|
|
|
|
// item.Drop_First(mob.drops[i], false);
|
|
|
|
|
// dropItems.Add(item);
|
|
|
|
|
|
|
|
|
|
// item.OnGain = OnGain;
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// else
|
|
|
|
|
// {
|
|
|
|
|
// item = manager.DropItemCreate(this, prefabDropItem.gameObject, mob.transform.position);
|
|
|
|
|
|
|
|
|
|
// item.Drop_First(mob.drops[i], false);
|
|
|
|
|
// dropItems.Add(item);
|
|
|
|
|
|
|
|
|
|
// item.OnGain = OnGain;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// //manager.HoldinCheck(item.item.idx);
|
|
|
|
|
// }
|
|
|
|
|
//}
|
|
|
|
|
}
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 드랍아이템을 생성 합니다.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="target"></param>
|
|
|
|
|
/// <param name="idx">생성할 아이템의 IDX</param>
|
|
|
|
|
public void OnDropItem_Create(Transform target, string idx)
|
|
|
|
|
{
|
|
|
|
|
DropItem drop = manager.DropItemCreate(this, prefabDropItem.gameObject, target.transform.position);
|
|
|
|
|
|
|
|
|
|
drop.Drop_Again(DataManager.Instance.dataItem.Search(idx));
|
|
|
|
|
drop.OnGain = OnGain;
|
|
|
|
|
|
|
|
|
|
dropItems.Add(drop);
|
|
|
|
|
|
|
|
|
|
DropItemChanged();
|
|
|
|
|
}
|
|
|
|
|
//public void OnDropItem_Create(Transform target, DropItemData item)
|
|
|
|
|
//{
|
|
|
|
|
// DropItem drop = manager.DropItemCreate(this, prefabDropItem.gameObject, target.transform.position);
|
|
|
|
|
|
|
|
|
|
// drop.Drop_First(item, true);
|
|
|
|
|
// drop.OnGain = OnGain;
|
|
|
|
|
|
|
|
|
|
// dropItems.Add(drop);
|
|
|
|
|
|
|
|
|
|
// DropItemChanged();
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 드랍아이템을 획득 처리합니다.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="owner"></param>
|
|
|
|
|
/// <param name="item"></param>
|
|
|
|
|
void OnGain(GameObject owner, DropItem item)
|
|
|
|
|
{
|
|
|
|
|
if (!owner.name.Equals("HitCheck Item"))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
manager.player.gameObject.SendMessage("GainItem", item);
|
|
|
|
|
|
|
|
|
|
if (!item.gameObject.activeSelf)
|
|
|
|
|
{
|
|
|
|
|
dropItems.Remove(item);
|
|
|
|
|
item.OnGain -= OnGain;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public System.Action<List<DropItem>> OnDropChanged;
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 맵블럭에 아이템이 드랍 혹은 습득 되어 상태를 변경 합니다.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="drop"></param>
|
|
|
|
|
public void DropItemChanged(DropItem drop = null)
|
|
|
|
|
{
|
|
|
|
|
if (drop != null)
|
|
|
|
|
{
|
|
|
|
|
dropItems.Remove(drop);
|
|
|
|
|
drop.OnGain -= OnGain;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (OnDropChanged != null)
|
|
|
|
|
OnDropChanged(dropItems);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Header("클리어 보상 설정")]
|
|
|
|
|
public DropItem prefabRewardDropItem;
|
|
|
|
|
public SoundPlayer spReward;
|
|
|
|
|
public Vector3 rewardPos = new Vector3(-0.5f, 0, -3f);
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 블럭의 몬스터를 모두 제거 했으므로 클리어 처리합니다.
|
|
|
|
|
/// </summary>
|
|
|
|
|
void Clear_Wait()
|
|
|
|
|
{
|
|
|
|
|
if (mobAlives.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
Debug.LogWarning($"{name} 블럭 클리어");
|
|
|
|
|
|
|
|
|
|
BlockClearReward();//맵블럭 클리어 보상
|
|
|
|
|
|
|
|
|
|
manager.player.character.OnAdded_Mana(1);
|
|
|
|
|
manager.player.character.skill.Active("BlkClear", null, null);
|
|
|
|
|
ecMapBlock.Invoke((int)MapEvent.DoorState, CLEAR = true);//문 열기
|
|
|
|
|
|
|
|
|
|
manager.spBGM.Play();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 클리어 보상을 생성합니다.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void BlockClearReward()
|
|
|
|
|
{
|
|
|
|
|
ItemData rewardData = manager.DuplicateItemCheck(manager.items_All, 0, 999, null, false);
|
|
|
|
|
if (rewardData == null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (spReward != null)
|
|
|
|
|
SoundManager.Instance.EffectPlay(spReward.gameObject);
|
|
|
|
|
DropItem item = manager.ObjectCreateLocalPos(prefabRewardDropItem.gameObject, transform, Vector3.one, rewardPos, false).GetComponent<DropItem>();
|
|
|
|
|
item.item = ItemData.Copy(rewardData, 1);
|
|
|
|
|
item.OnGain = OnGain;
|
|
|
|
|
item.OnInitialized();
|
|
|
|
|
|
|
|
|
|
dropItems.Add(item);
|
|
|
|
|
|
|
|
|
|
StartCoroutine(ClearReward_Wait(item));
|
|
|
|
|
}
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 플레이어 와 클리어보상이 멀어질때 보상을 활성화합니다.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="item"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
IEnumerator ClearReward_Wait(DropItem item)
|
|
|
|
|
{
|
|
|
|
|
while (Mathf.Abs(Vector3.Distance(manager.player.transform.position, item.transform.position)) < 2)
|
|
|
|
|
yield return null;
|
|
|
|
|
|
|
|
|
|
item.gameObject.SetActive(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Header("BGM")]
|
|
|
|
|
public SoundPlayer_BGM spBGM;
|
|
|
|
|
public void BGMPlay()
|
|
|
|
|
{
|
|
|
|
|
if (spBGM == null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
spBGM.Play();
|
|
|
|
|
}
|
|
|
|
|
}
|