You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
884 lines
28 KiB
884 lines
28 KiB
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(); |
|
} |
|
}
|
|
|