상태 이상 기반 자체는 꽤 오래전에 다져 놨으나, 항상 처리되는 상태 이상을 조금 고민하던 와중에 해결책이 떠올랐고, 일단 상태이상 시스템을 완성함

08b3c52babc236a14e81d2b628f1756472822ece

모든 상태이상은 enum으로 관리함. 상태 이상의 적용 시점과 사용성을 모두 고려하여 이런 방식으로 해두었음


3bbcc22fe4d034a320afd8b236ef203e3cb87c88f46fdb76

추가적으로 카테고리 분류를 위한 배열이라던가 특정 조건에서 체크해야 할 "부정적 효과" 를 위한 해쉬셋
그리고 Delegate return용 매핑 함수를 만들었음. Dictionary가 아니라 Switch-Case를 쓴 이유는 TryGetValue하기가 매우 귀찮기도 하고 코드 일관성을 확보 가능하기도 해서...



0cb9d407ebd60aa36aaad5b058c12a3a2d9160abf102cef2e60e6c73

기본적인 상태 효과 추가 함수. 볼 건 그다지 없고, 추가 및 갱신 예외 처리나 UI갱신을 위한 대리자 정도만 존재함. 적들은 아직 리팩터링 덜 끝내서 못 넣음 ㅋㅋ


1fb8d634e0c130af60b8e5a117c5312e0c7d05740837cd0969fcede1f4fd6a303691f5a23f57

상태 이상 갱신 함수. 이것 말고도 _rdc = 1로 잡은 파라미터가 없는 함수도 있음. 순서를 보장하기 위해, enum을 통해 실행되는 타이밍을 정렬했기에 "함수 등록 -> 대리자 덮어쓰기" 를 반복하는 구조로 간단하게 만들 수 있었음.

DoesSeAffectUnit을 통해 대리자에 등록할 함수를 분류함. 예를 들어 "부정적 효과 + 무적" 상태면, 애초에 대리자에 등록이 안되서 효과를 발휘하지 못하도록 했고,

이 함수에 한해서는 후술할 ALWAYS의 실행이 필요하지 않아서 제외함.(ALWAYS 타이밍에 등록된 함수들은 턴 시작과 동시에 호출되며, 따라서 이 함수 실행이 끝나면 흐름에 따라 알아서 실행될 것이기 때문)

지금 보니까 RefreshStats는 Stat 갱신하면서 지워도 됐는데 깜빡하고 안 지웠다 ㅋㅋㅋ


18a9d92adae131ab7eb3d3fb06df231dbbe976b52afd6332d205

이건 그냥 유틸리티 함수임 아까 말했던 무적 + 부정적 효과도 위처럼 처리하는거고

아래는 그냥 지속시간 반환하는 함수


0cbec433e4de78946bb2d9a313912533ec4382e2a1c1862bea70b8b06069356d25b3c436fe7e8c889af5c8ea9d4119266f0484cbc5d9

AddEffect는 뭐 함수 넣고 RefreshStatusEffect 돌려도 됐겠지만, 그래도 최적화 조금 해준답시고 카테고리 분류해서 그 부분만 갱신하도록 했고,
RemoveEffect 같은 경우에는 카테고리 delegate에서 메서드를 제거해도, 순서가 깨질일 없기 때문에 그냥 직접 빼줬음.
주석 처리된 GetSubEffect는 글쓰다가 발견함 ㅋㅋ

ALWAYS 카테고리에 있는 함수들에 한해서, 등록 즉시 갱신해야하기 때문에 Add와 Remove 모두 if문으로 분리해서 처리했음.



0cbec433e4de788368b9d3b602c26a2d02a686a9e1d86f87cf8de3ff54c4

실제 사용될 상태 이상 함수들. Main과 Sub를 통해서, 타이밍 관리를 추가적으로 해주도록 함. 이 구조는 효과 시점과 효과 종료 시점을 좀 더 유연하게 설정하기 위해서 만듬.


Faint같은건 호출 즉시 효과 적용 -> Sub 등록 -> RefreshStatusEffect를 통해 갱신 -> 턴 시작 시 Sub 호출 (ALWAYS_SUB 타이밍을 의도적으로 ALWAYS 타이밍보다 먼저 호출하도록 만듬) -> 지속 시간이 존재하여 대리자에 존재한다면 호출
이런 식으로 턴 시작 시점에 갱신하는 방식으로 아무 때나 적용 시 효과 적용 + 턴 기반 지속을 구현함.


Enforce는 공격 직전에 공격력 * 1.5 이후 공격력 정상화, Burn은 공격 직후에 체력 -1을 구현하기 위해 그냥 동일하게 BEFORE_ATTACK 타이밍에 Main을 넣고, Sub함수를 통해 AFTER_ATTACK 시점에 다시 효과 적용 및 복원을 구현함. 상태 이상을 BEFORE_ATTACK, AFTER_ATTACK 으로 분류하면 너무 더럽기도 하니까.


Invincible 같은 경우에는 모든 Sub함수의 방식을 통일한다는 전제 하에서 저렇게 만들 수 있었음 모든 Sub 함수는 호출 시 자신이 등록된 델리게이트에서 반드시 자신을 제거하고, Main함수가 적용되었다는 플래그가 존재하면, 복원을 담당하는 형식임. (Burn같은 예외도 있긴 하지만). 이후 RefreshStatusEffect(0) (지속시간이 줄지 않는 갱신)을 통해서, 부정적인 효과를 적용되지 않게 만듦. 물론 무적이라 체력 감소 방지 처리 이런 것도 해야겠지만, 일단은 나중으로 미루어둠... 아마도 CurHP 프로퍼티의 set에 직접 DoesSeAffectUnit 플래그를 체킹하는 식으로 구현 할듯?


아무튼 이렇게 구현된 놈들을 플레이어 유닛의 이펙트 관련 클래스에 넣어주고


1fb8d72ff6c63db420afd8b236ef203eaed8e3d13e40dc


1fb8d72fcdd734b620afd8b236ef203edae0b52ce7ea0a

이런 식으로 간접적으로 등록해주고(이 역시 순서 보장을 위해서임)

또한 플레이어 유닛은 ON_MY_TURN_END 타이밍의 액션과 상태효과 갱신을 OnEnemyPhaseEnds에 실행되도록 했지만,

적 유닛은 ON_MY_TURN_END 타이밍의 액션을 OnPlayerPhaseEnds에 등록했음. 물론 아직 리팩토링 덜 끝나서 아직 테스트는 못해봤지만...



이제 구현은 끝났으니 대충 테스트 코드 넣고 돌려봤음

0fbcc323d6c639b27df1c6bb11f11a390ccff23c734016ac

일단 유닛의 스탯을 이렇게 잡아두고



0bbcd928f19c28a8699fe8b115ef046595e0a118


기절 -> 시야 감소 + 행동력 0으로 제한

04b0dd23e1db39b26bffe4b015de3238ac4b99f862d4df9d1025882b1ab8dff89c

무적 획득 즉시 기절 효과 무효화 (행동력 감소까지는 무효화하지 못하게 할거임) 기절 상태는 Flag 기반으로 아이템 사용 및 드랍등의 제한도 걸려있어서, 해제 하고나면 행동력 회복 아이템 등을 사용할 수 있음

04b3c62febf03da061add39317d82a29b264f0c0f8a074e3f3bbef534cda01


다만, 무적이 기절 전에 걸렸다면 무효화 가능



09bcdd27e2d776b660b8f68b12d21a1d6ee0640971

강화 -> 3~3 데미지 - 방어력 3 이라 데미지가 0이여야 하지만, 강화를 적용해 3*1.5를 반올림해서 5가 됐기에 2데미지가 들어가는 모습.



0fb1d523e1db36a120afd8b236ef203ef6b4c3d2493af9

출혈 (행동력 감소 시 데미지 1)



0fa8c228abc236a14e81d2b628f17168dfb853

화상(공격 시 데미지 1, 테스트를 위해 일부러 공격이 행동력을 소모하지 않게 해놓음)



19aadf19d1cb28a37d80d9b329e12b34efed5bbb3a8b8255aadf32c90cb0a9333148

독과 맹독 적용 이후 턴 갱신 (독은 턴 종료 1데미지, 맹독은 턴 종료 시점 남은 지속 시간만큼 데미지 이긴 한데, 둘 다 1이라 최종적으로 2만 감소했음)

아마 나중에 필요하면 Main - Sub를 묶어서 하나의 클래스로 만들고, 함수에 들어가는 수치를 커스텀 가능하게 만들수도 있을듯?