인기멤버
태백광노
2023.02.17. 04:36조회 2
댓글 0URL 복사
제목: 유닛에 콜백등록의 개선판
작성일: February 16, 2023 at 23:06
작성자: new-a
내용:
유닛의 콜백시리즈는 다양하다, 예를 들어 이러한 항목이 있다
사용됨
격추됨
충돌하는 중
회수되었음
버려졌음
플러스 버전에서 사용중인 방식은 개별 콜백에 대하여 사용하지 않을 것으로 추정하는 필드를 사용한다, 그러나 그것은 추정에 불과하다. 실제로 그 필드가 사용될 수도 있다. 또한 모듈에서 필드 오프셋을 재정의 할 수 있도록 했다. 그 이유가 바로 이것이다. 다른곳에서 사용될 여지가 있어서다. 이제 EUD-CC에서 사용하는 개선된 유닛 콜백처리 방식을 소개한다
그 방식은 스크립트 이름주소공간을 사용한다. 정확히 말하면 이름주소공간을 상속받아 사용한다. 이것의 의미를 아래에서 설명한다
static void reallocExtendedField(NoxObject *ptr) { char *alc; if (!ptr->ScriptNameMB) { alc = (char *)MemAlloc(sizeof(ExtendedCallbackType)); NoxByteMemset(alc, sizeof(ExtendedCallbackType), 0); ptr->ScriptNameMB = alc; return; } int len = StringGetLength(ptr->ScriptNameMB); if (!len) return; int *check = (int *)(ptr->ScriptNameMB + len + 1); if (*check == MY_STX) return; alc = (char *)MemAlloc(sizeof(ExtendedCallbackType)); NoxByteMemset(alc, sizeof(ExtendedCallbackType), 0); CopyString(ptr->ScriptNameMB, alc); check = (int *)( alc + len + 1 ); *check = MY_STX; char *pOld = ptr->ScriptNameMB; ptr->ScriptNameMB = alc; MemFree(pOld); }
내가 그 함수를 작성했다. 내가 의도하는 내용이 그 안에 포함된다. 그러므로 블럭 마다 설명한다
if (!ptr->ScriptNameMB) { alc = (char *)MemAlloc(sizeof(ExtendedCallbackType)); NoxByteMemset(alc, sizeof(ExtendedCallbackType), 0); ptr->ScriptNameMB = alc; return; }
스크립트 이름이 지정되지 않은 경우이다. 이러한 경우에 아예 처음부터 새 구조체를 할당한 후 거기에 대입한다, 그러나 스크립트 이름이 지정된 경우를 확인한다
int len = StringGetLength(ptr->ScriptNameMB); if (!len) return; int *check = (int *)(ptr->ScriptNameMB + len + 1); if (*check == MY_STX) return;
이것은 스크립트 이름이 지정된 경우이다. 그러나 방금 전에 새 구조체를 할당했다면, 문자열은 비어있을 것이다. 그러므로 길이를 얻고, 그것이 제로이면 통과한다. 그러나 문자열이 비어있지 않을 수 있다. 예를 들어 스크립트 이름이 지정된 유닛에게 새 콜백을 등록하려고 시도한 경우이다. 이름공간 길이를 구한다. 그리고 null 문자로 부터 +1위치를 STX와 비교한다. STX 이 가지는 값은, 0x81C481C4 이다
예시
H | e | l | l | o | (space) | W | o | r | l | d | (null) | C4 | 81 | C4 | 81 | |
(null) 바로 다음이 C4 81 C4 81 인지 확인한다. 만약 동등하면 통과한다
alc = (char *)MemAlloc(sizeof(ExtendedCallbackType)); NoxByteMemset(alc, sizeof(ExtendedCallbackType), 0); CopyString(ptr->ScriptNameMB, alc); check = (int *)( alc + len + 1 ); *check = MY_STX; char *pOld = ptr->ScriptNameMB; ptr->ScriptNameMB = alc; MemFree(pOld);
STX 와 불일치 하는 경우이다. 예를 들어 "Hello world" 이라고 부르는 스크립트 이름을 가졌다. 그러나 (null) 다음이 C4 81 C4 81 이 아니다. 이러한 경우 순수 문자열 배열이다. 다시 말하면 확장된 콜백 구조체로 할당된 영역이 아니다. 그러므로 새 구조체 영역을 할당한다. 문자열을 필드로 복사한다. (null) 다음에 STX 값을 대입한다. 이전 메모리는 지운다
static void onBlackbookUse() { NoxCastSpellObjectObject(SPELL_FORCE_OF_NATURE, OTHER, OTHER); } void TestTest22() { int item = CreateObjectAt("BlackBook1", NoxGetObjectX(OTHER), NoxGetObjectY(OTHER)); SetUnitCallbackOnUse(item, &onBlackbookUse); }
그나저나 이것을 사용해서 예제를 만들었다. 비콘을 밟으면 검은책이 생성된다. 그 검은책을 사용하면, "포스오브네이쳐" 이 발사된다. 따라오는 그림이 결과를 보여준다
검은 책 생성 시험입니다
검은책을 누릅니다=>사용했습니다
지연없이 발사됩니다
에너지를 충전하고 있습니다
같은 방식으로 나머지
격추됨
충돌하는 중
회수되었음
버려졌음
콜백을 구현할 수 있다
//이상입니다