메이플스토리의 맵에는 퀘스트의 진행 상태에 따라 변화되는 요소들이 있다. 키 입력 방향을 나타내는 오브젝트도 있을 수 있고, 건축물이 점점 건축되어 가는 모습의 오브젝트도 있을 수 있다. 이 것들은 오직 하나의 퀘스트에 대해서만 연결되어 있어서 미리 구현해 놓았지만, NPC의 경우 condition이 여러 개 있어 구현이 조금 어려웠다. 조금씩 구현 방향을 고민하다가 오늘 드디어 해냈다.
C#에는 LINQ가 있다. 람다 함수를 통해 여러 데이터들을 처리할 수 있는 매우 강력한 구조라고 생각한다. 아래는 실제로 이번에 추가된 코드 중 일부이다.
if ((conditionNode.Nodes.Any(n => n.Text.All(char.IsDigit)) && conditionNode.Nodes.Where(n => n.Text.All(char.IsDigit)).All(n => resLoader.PatchVisibility.IsVisibleExact(int.Parse(n.Text), Convert.ToInt32(n.Value)))) || (conditionNode.Nodes["dateStart"].GetValueEx<long>(0) <= date && date <= conditionNode.Nodes["dateEnd"].GetValueEx<long>(0)))
Logical OR의 뒷부분은 크게 복잡하지 않으니 앞부분만 하나씩 살펴보자. 먼저 conditionNode.Nodes
는 IEnumerable
정도로 생각하면 되겠다. n.Text
는 노드의 이름이다.
conditionNode.Nodes.Any(n => n.Text.All(char.IsDigit))
Nodes 중에서 이름이 숫자로만 되어 있는 것이 있는지를 검사한다. 왜 검사를 해야 하는지는 후술한다.
conditionNode.Nodes.Where(n => n.Text.All(char.IsDigit))
Nodes 중에서 이름이 숫자로만 되어 있는 것들만 추려낸 IEnumerable
을 받는다.
.All(n => resLoader.PatchVisibility.IsVisibleExact(int.Parse(n.Text), Convert.ToInt32(n.Value)))
받은 IEnumerable
의 모든 요소가 IsVisibleExact
조건을 만족하는지를 확인한다. 여기서 문제는 All
메서드가 IEnumerable
의 요소가 0개일 때에도 true
를 반환하는 점이다. 따라서 앞에서 해당 요소가 있는지를 따로 검사해 준 것이다.
참고로 렌더링 기준 시간에 따른 NPC 모양의 변화도 있다. 카산드라(9010010)가 대표적이다.