public static void Reflect(int percentDamage, Character target) { if (target.trueOldHealth > target.currentHealth) { float damage = (target.trueOldHealth - target.currentHealth) * (percentDamage / 100f); Vector3 pos = VectorUtility.PositionToInt(target.GetComponent <Transform>().position); Vector3[] direction = new Vector3[4] { new Vector3(1f, 0f, 0f), new Vector3(-1f, 0f, 0f), new Vector3(0f, 1f, 0f), new Vector3(0f, -1f, 0f) }; foreach (Vector3 d in direction) { GameObject g = Instantiate(GameManager.gm.player.GetComponent <PlayerMover>().distanceSprite, new Vector3(pos.x + d.x, pos.y + d.y, -0.25f), Quaternion.identity); g.GetComponent <SpriteRenderer>().color = new Color(0.7f, 0.7f, 0.7f, 0.8f); g.GetComponent <DistanceSprite>().Disappear(60); Entity e = GameManager.gm.map.GetEntityOnTile(pos + d); if (e != null && e.GetType().Equals(typeof(Character)) && ((Character)e).type != target.type) { // 진행 방향에 적이 있을 경우 Character opponent = (Character)e; opponent.hasReflected = true; opponent.reflectDamage += damage; opponent.reflectDirection = d; } } } }
/// <summary> /// 이동하지 않고 상하좌우로 붙어 있는 플레이어를 공격합니다. /// 공격에 성공하면 턴을 넘기고 true를 반환합니다. /// 플레이어가 주변에 없으면 턴을 넘기지 않고 false를 반환합니다. /// </summary> /// <returns></returns> private bool AttackWithoutMove() { bool isAttacked = false; List <Vector3> melee = new List <Vector3>(); for (int i = 0; i <= c.EquippedWeapon.Range; i++) { melee.Add(new Vector3(-1f * i, 0f, 0f)); melee.Add(new Vector3(1f * i, 0f, 0f)); melee.Add(new Vector3(0f, -1f * i, 0f)); melee.Add(new Vector3(0f, 1f * i, 0f)); } foreach (Vector3 v in melee) { Vector3 destination = GetCurrentPosition() + v; if (gm.map.GetEntityOnTile(destination) != null && gm.map.GetEntityOnTile(destination).GetType().Equals(typeof(Character)) && ((Character)gm.map.GetEntityOnTile(destination)).type == Character.Type.Player) { if (destination.x < GetCurrentPosition().x) { GetComponent <SpriteRenderer>().flipX = false; } else if (destination.x > GetCurrentPosition().x) { GetComponent <SpriteRenderer>().flipX = true; } Attack(VectorUtility.PositionToInt((destination - GetCurrentPosition()).normalized), false); isAttacked = true; break; } } return(isAttacked); }
public static void Flurry(int splashDamage, Character target) { // Flurry 효과는 몬스터의 무기에 적용할 수 없음 (플레이어가 한 명이므로) Vector3 pos = VectorUtility.PositionToInt(target.GetComponent <Transform>().position); Vector3[] direction = new Vector3[4] { new Vector3(1f, 0f, 0f), new Vector3(-1f, 0f, 0f), new Vector3(0f, 1f, 0f), new Vector3(0f, -1f, 0f) }; foreach (Vector3 d in direction) { GameObject g = Instantiate(GameManager.gm.player.GetComponent <PlayerMover>().distanceSprite, new Vector3(pos.x + d.x, pos.y + d.y, -0.25f), Quaternion.identity); g.GetComponent <SpriteRenderer>().color = new Color(0f, 0.8f, 0.8f, 0.8f); g.GetComponent <DistanceSprite>().Disappear(60); Entity e = GameManager.gm.map.GetEntityOnTile(pos + d); if (e != null && e.GetType().Equals(typeof(Character)) && ((Character)e).type == Character.Type.Enemy) { // 진행 방향에 플레이어가 있을 경우 Character enemy = (Character)e; enemy.gustDamage += splashDamage; enemy.gustDirection = d; } } }
private Vector3 Move(Vector3 destination) { if (VectorUtility.IsSamePosition(destination, GetCurrentPosition())) { // 제자리에 머물러 있는 경우 움직이는 애니메이션 없이 턴 넘김 // 제자리에서 인접한 네 칸 안에 플레이어가 있으면 공격함 if (!AttackWithoutMove()) { isMoved = true; } return(destination); } else if (gm.map.CanMoveToTile(destination)) { // TODO 한 턴에 2칸 이상을 이동하는 경우, 지나는 모든 타일에 대한 고려가 필요함 if (destination.x < GetCurrentPosition().x) { GetComponent <SpriteRenderer>().flipX = false; } else if (destination.x > GetCurrentPosition().x) { GetComponent <SpriteRenderer>().flipX = true; } StartCoroutine(MoveAnimation(destination)); return(destination); } else if (gm.map.GetTypeOfTile(destination) == 0 && gm.map.GetEntityOnTile(destination) != null && gm.map.GetEntityOnTile(destination).GetType().Equals(typeof(Character)) && ((Character)gm.map.GetEntityOnTile(destination)).type == Character.Type.Player) { // 진행 방향으로 한 칸 앞에 플레이어가 있는 경우 if (destination.x < GetCurrentPosition().x) { GetComponent <SpriteRenderer>().flipX = false; } else if (destination.x > GetCurrentPosition().x) { GetComponent <SpriteRenderer>().flipX = true; } Attack(VectorUtility.PositionToInt((destination - GetCurrentPosition()).normalized), false); // TODO 택시 거리 1칸이 보장되지 않음 return(GetCurrentPosition()); } else { // TODO 일단은 가려고 하는 곳이 갈 수 없는 지형이면 움직이지 않고 턴 넘김 // 제자리에서 인접한 네 칸 안에 플레이어가 있으면 공격함 if (!AttackWithoutMove()) { isMoved = true; } return(GetCurrentPosition()); } }
/// <summary> /// 순찰 경로를 초기화하는 함수입니다. /// </summary> /// <param name="checkpoints">들러야 하는 지점의 목록(순서대로)</param> private void InitializeCheckpoints(List <Vector3> checkpoints) { headCheckpoints = new Stack <Vector3>(); passedCheckpoints = new Stack <Vector3>(); passedCheckpoints.Push(GetCurrentPosition()); if (checkpoints != null) { for (int i = checkpoints.Count - 1; i >= 0; i--) { headCheckpoints.Push(VectorUtility.PositionToInt(checkpoints[i])); } } }
IEnumerator MoveAnimation(Vector3 destination) { isMoving = true; int frame = 18; Vector3 origin = t.position; // 애니메이션이 시작하기 전에 이동 판정 완료 gm.map.SetEntityOnTile(null, origin); gm.map.SetEntityOnTile(c, destination); for (int i = 0; i < frame; i++) { t.position = Vector3.Lerp(origin, destination, (float)i / frame); yield return(null); } t.position = destination; isMoving = false; Attack(VectorUtility.PositionToInt((destination - origin).normalized), true); // TODO 택시 거리 1칸이 보장되지 않음 }
/// <summary> /// 현재 이 오브젝트의 위치를 정수 좌표로 반환합니다. /// </summary> /// <returns></returns> private Vector3 GetCurrentPosition() { return(VectorUtility.PositionToInt(t.position)); }
// Update is called once per frame void Update() { if (gm == null) { gm = GameManager.gm; return; } if (isDistanceNone) { if (distanceType == DistanceType.None) { Debug.LogWarning("Enemy distanceType is None!"); return; // Character의 Initialize에서 설정해 줄 때까지 대기 } else if (distanceType == DistanceType.Manhattan) { distance += VectorUtility.ManhattanDistance; isDistanceNone = false; } else if (distanceType == DistanceType.Chebyshev) { distance += VectorUtility.ChebyshevDistance; isDistanceNone = false; } } if (!gm.IsSceneLoaded) { return; } if (gm.Turn == 0 && isMoved) { isMoved = false; } else if (gm.Turn == 1 && !isMoving && !isMoved) { if (c.hasStuned) { c.hasStuned = false; StartCoroutine(StunedAnimation()); return; } Vector3 playerPos = VectorUtility.PositionToInt(gm.player.GetComponent <Transform>().position); Vector3 destination; Discover(playerPos, GetCurrentPosition()); if (!AttackWithoutMove()) { if (hasTaunted) { // 한 번 도발당한 경우 처음 도발당한 위치에서 leaveDistance만큼 멀어지기 전까지 플레이어를 쫓아감 // 플레이어가 시야에서 벗어나도 쫓아감 destination = Move1Taxi(playerPos); if (distance(tauntedPosition, destination) <= leaveDistance) { destination = Move(destination); } else { // 플레이어가 사라지면 도발 상태가 풀리고 처음 도발당한 위치로 돌아감 hasTaunted = false; if (myTauntedSprite != null) { Destroy(myTauntedSprite); myTauntedSprite = null; } if (myDistanceSprite != null) { myDistanceSprite.GetComponent <DistanceSprite>().Disappear(); myDistanceSprite = null; } destination = Move1Taxi(tauntedPosition); destination = Move(destination); // 처음 도발당한 위치로 돌아간 경우 정상 경로를 따라 순찰함 if (VectorUtility.IsSamePosition(destination, tauntedPosition)) { isTauntedPositionValid = false; } } } else if (isTauntedPositionValid) { // 도발 상태가 풀렸지만 아직 처음 도발당한 위치로 돌아가지 못한 경우 destination = Move1Taxi(tauntedPosition); destination = Move(destination); // 처음 도발당한 위치로 돌아간 경우 정상 경로를 따라 순찰함 if (VectorUtility.IsSamePosition(destination, tauntedPosition)) { isTauntedPositionValid = false; } } else { // 시야에 플레이어가 없는 경우 정상 경로를 따라 순찰 destination = Move1Taxi(movePattern(), true); destination = Move(destination); } Discover(playerPos, destination); } } }