던브/모드 제작/키리키리 팁

최근 수정 시각 : 2026-11-05 06:02:46 | 조회수 : 5
분류 : (+)

목차
1. 개요
2. 변수 체계 및 이벤트 제어
2.1. 변수 스코프별 특성
2.2. 세이브 데이터 호환 및 이벤트 중복 push 방지
2.3. 거점 및 시설의 단계 관리 (eventStep)
3. 파티원 및 조건 판정 스크립트
3.1. 성별 및 특정 캐릭터 유무 판정
3.2. 캐릭터 발화 및 존재 확인
4. 아이템 풀 구성 및 장비 패시브 제어
4.1. 아이템 목록 수집 및 가챠 풀 구성
4.2. 장비 소지 시 상태이상/스탯 부여 패시브
5. 전투 시스템 및 행동 제어
5.1. living.tjs의 행동 결정 메커니즘
5.2. 몬스터 판정 시 객체 비교 오류 방지
6. 게스트 및 신규 캐릭터 제작 규격
6.1. 스탠딩 일러스트 및 표정 차분 네이밍
6.2. 데이터 등록 절차
7. 텍스트 기반 맵 데이터 작성 사양
7.1. 유효 칸과 벽 행 구조

1. 개요 ✎

본 문서는 키리키리(吉里吉里) 및 KAG/TJS 엔진 기반 롤플레잉 게임의 스크립트 개발, 모딩, 시스템 제어 방식에 관한 기술 정보와 개발진 질의응답 내용을 정리한 문서이다. 이벤트 플래그 처리, 파티원 판정, 전투 로직 제어, 게스트 캐릭터 등록, 맵 데이터 작성 사양 등 개발 및 데이터 수정 전반에 필요한 핵심 규격을 다룬다.

2. 변수 체계 및 이벤트 제어 ✎

2.1. 변수 스코프별 특성 ✎

게임 내에서 사용되는 변수는 수명 주기와 보존 영역에 따라 스코프가 구분된다.
  • tf.○○ (임시 변수): 게임 프로세스 종료 시 초기화된다. 일시적인 계산이나 임시 리스트 작성 시 사용된다.
  • f.○○ (세이브 데이터 종속 변수): 각 세이브 데이터 파일에 저장 및 연동된다. 특정 세이브 파일 내의 퀘스트 진행도나 이벤트 발생 여부를 판정하는 플래그로 적합하다.
  • sf.○○ (전역 시스템 변수): 모든 세이브 데이터가 공유하는 공통 영역에 저장된다. 환경 설정(옵션), 도감 수집 이력, CG 및 회상 개방 등에 사용된다.
  • 특정 회차나 세이브 데이터 독립적으로 진행되어야 하는 이벤트에 sf 변수를 사용하면, 한 세이브 데이터에서 열람한 이벤트가 다른 세이브 데이터에서도 이미 발생한 것으로 간주되는 문제가 발생하므로 주의해야 한다.

2.2. 세이브 데이터 호환 및 이벤트 중복 push 방지 ✎

기존 세이브 데이터를 불러올 때 새롭게 추가된 이벤트를 적용하려면 로드 시점에 이벤트를 목록에 주입(push)해야 한다. 단, 조건문 없이 주입할 경우 세이브 데이터를 불러올 때마다 중복으로 push되는 오류가 발생한다.

이를 방지하는 대표적인 처리 패턴은 다음과 같다.
  • f 변수 플래그 방식: 주입 여부를 세이브 변수에 기록하여 1회만 실행되도록 제어한다.
if (f.slum === void) o.スラム・モスロック.push2(0);
// 모스록의 이벤트 0번 스크립트 내부에서 f.slum = 1 처리
  • 더미 이벤트 및 delevent 연계 방식:
  • 로드 시점에서 목표 이벤트(예: event0)와 더미 판정용 빈 이벤트(예: event99)의 존재 여부를 동시에 검사한다(`if (!events.has(0) && !events.has(99))`).
  • 두 이벤트를 모두 push한 뒤, event0이 시작될 때 둘 중 하나를 삭제(`delevent`)하여 다음 로드 시 중복 실행되지 않도록 차단한다.

2.3. 거점 및 시설의 단계 관리 (eventStep) ✎

  • `eventStep`은 라이벌 파티나 특정 개체의 단계 제어에 기본 정의된 변수이다.
  • 마을(town)이나 시설(house)에 임의로 `eventStep` 변수를 선언하여 사용할 경우 세이브 시 보존되지 않고 초기화될 수 있다.
  • 마을 및 시설에서 단계적 플래그 관리를 영속화하려면 해당 객체(`town`, `house`)에 `var eventStep = 0;`을 명시적으로 선언하고 데이터 사전(`dic`)에 직렬화하여 저장하거나, `f.변수`를 통하여 제어해야 한다.

3. 파티원 및 조건 판정 스크립트 ✎

3.1. 성별 및 특정 캐릭터 유무 판정 ✎

KAG 인라인 식(`exp`)에서 파티원의 구성 상태를 판정할 때 다음 함수를 활용한다.
  • 남성/여성 존재 여부 판정:
  • `game.party.getFirstGuy() === void`: 파티에 남성 캐릭터가 없음
  • `game.party.getFirstHeroine() === void`: 파티에 여성 캐릭터가 없음
  • `game.party.getFirstHeroine() !== void`: 파티에 여성 캐릭터가 최소 1명 이상 존재함
  • 파티 리더 성별 판정:
  • `game.leader.sex == "男"`: 현재 리더의 성별이 남성인지 확인

3.2. 캐릭터 발화 및 존재 확인 ✎

  • `TEO` vs `isTEO`의 차이:
  • `isTEO`: 현재 발화 대상(`curChara`)이 해당 캐릭터일 때 참을 반환한다.
  • `TEO`: 파티 내에 해당 캐릭터가 존재할 경우, 그 캐릭터를 즉시 `curChara`로 전환하여 대사를 출력하게 만든다.
  • 비선두 및 파티 멤버 존재 판정:
  • `game.leader`는 진형의 선두에 위치한 캐릭터만 가리키므로, 선두가 아닌 파티원을 찾을 때는 적합하지 않다.
  • 단순히 특정 캐릭터가 파티 멤버로 등록되어 있는지 확인하려면 `game.party.members.has(...)` 형태를 검사하는 것이 안전하다.
  • `o.캐릭터명` 또는 `game.playerChara`를 직접 참조할 경우, 파티에 없더라도 데이터베이스에 등록된 캐릭터 객체 자체가 반환될 수 있으므로 분기 조건 설정 시 유의해야 한다.

4. 아이템 풀 구성 및 장비 패시브 제어 ✎

4.1. 아이템 목록 수집 및 가챠 풀 구성 ✎

특정 범주의 아이템을 추출하여 보물상자나 가챠 풀을 동적으로 생성할 때의 구현 절차이다.
1. `@call storage="appendix.ks" target=*items_list` (방어구: `*armors_list`, 무기: `*weapons_list`) 매크로를 호출하여 전체 목록 데이터를 메모리에 로드한다.
2. `game.collectionList` 배열을 순회하며 특정 카테고리(예: "링", "장식품")이면서 이벤트 전용 아이템(`event == false`)이 아닌 항목을 임시 목록(`tf.list`)에 수집한다.
3. 랭크(`rank`) 및 제외 목록(`game.closeItems`)을 필터링하여 출현 확률 테이블(`tf.pool`)에 등록한다.
  • 저랭크 아이템의 출현 빈도를 높이려면 반복문 루프 횟수를 늘려 풀에 동일 아이템 이름을 다수 삽입하는 방식을 취한다.

4.2. 장비 소지 시 상태이상/스탯 부여 패시브 ✎

인벤토리에 특정 아이템을 소지하고 있을 때 자동으로 스탯 보너스나 상태이상을 부여하는 로직이다.
1. `statdata.tjs`: 신규 스테이터스 데이터를 정의하고, `affectedParam` 속성을 통해 증감치를 지정한다. (전투 중에만 적용하려면 `master.inBattle` 조건을 추가)
2. `item.tsv`: 해당 아이템의 기본 데이터를 정의한다.
3. `party.tjs`: 이동 시 상태를 점검하는 `checkStatusByMoving()` 함수의 시작 부분에서 `findItem` 판정을 수행한다. 소지 중(`true`)이면 `setStatus`로 해당 상태이상을 부여하고, 미소지(`false`) 상태면 상태이상을 제거하도록 처리한다.

5. 전투 시스템 및 행동 제어 ✎

5.1. living.tjs의 행동 결정 메커니즘 ✎

NPC의 자동 행동(`.auto == true`)은 `living.tjs`의 `getUsableActions()` 함수에서 추첨된다.
  • `cond`와 `determined`의 차이:
  • `cond`: 스킬 사용의 전제 조건이다. 조건을 만족하면 행동 후보 목록에 등록된다.
  • `determined`: `true`로 평가되는 순간, 후속 후보를 탐색하지 않고 해당 스킬로 행동을 즉시 확정한다. 특정 턴이나 특정 상황에서 반드시 특정 행동을 강제하고자 할 때 사용된다.
  • 주의사항: `cond` 판정이 `determined`보다 먼저 실행된다. `determined`를 부적절하게 구성하면 매 턴 동일한 행동만 반복하는 현상이 발생할 수 있다.

5.2. 몬스터 판정 시 객체 비교 오류 방지 ✎

전투 중 특정 몬스터를 판정할 때 단일 객체 인스턴스 비교(`m.몬스터명`)를 사용하면 오작동할 수 있다.
  • 몬스터는 필드에 동일한 종류가 여러 마리 출현할 수 있으므로, 단일 객체 포인터(`m[...]`)는 하나만 유지된다.
  • 따라서 특정 인덱스의 적을 식별할 때는 객체 직접 비교가 아닌 문자열 이름(`enemy.members[i].name == "몬스터명"`)을 비교해야 정상적으로 인식된다.

6. 게스트 및 신규 캐릭터 제작 규격 ✎

6.1. 스탠딩 일러스트 및 표정 차분 네이밍 ✎

기본 스탠딩 CG 이미지 이름 접두사(`img`)를 기준으로 접미사를 조합하여 작성한다.
  • 의상 차분 접미사:
  • `_default`: 기본 스탠딩 일러스트 (평상복)
  • `_topless`: 상하의 속옷 상태
  • `_under`: 팬티만 착용한 상태
  • `_swim`: 수영복
  • `_nude`: 전라
  • `_bigbelly`: 전라 임신 상태
  • `_sweat`: 전라 땀 상태
  • `_fight`: 무기를 소지한 전투 스탠딩 (누락 시 로딩 에러 발생 원인이 되므로 필수 제작 필요)
  • 표정 차분: 접두사 뒤에 `_00`, `_24` 등의 번호로 분리 저장
  • MOD 추가 특수 의상:
  • `[이름]_special.png` ~ `special8.png` 형식으로 명명
  • 미에로 장비(노출도 중간)와 에로 장비(전라에 준하는 레벨)로 구분
  • 최근 패치 규격에서는 PNG 대신 WebP 포맷을 사용하며, XP3로 패킹하여 배치

6.2. 데이터 등록 절차 ✎

1. monster.csv 등록: 몬스터 및 게스트의 기본 스탯, 속성, 기술, 직업, 진형 데이터를 등록한다.
  • 게스트 캐릭터는 `mLV` 값을 `-2`로 지정한다.
2. name.ks 매크로 등록: 대화창 및 이름 표시 매크로를 정의한다.
[macro name="캐릭터명"][swname * n=&'mp.tagname' key=&'mp.tagname' buf=고유번호][endmacro]
  • `buf` 번호는 기존에 사용되지 않은 고유 번호를 순차적으로 부여한다.
3. gamerun.tjs 좌표 및 설정:
  • `face`: 대화 시 표정 오버레이가 배치될 좌상단 좌표 `[x, y]`
  • `trim`: 대화창 컷인 잘라내기 시작 위치 `[x, y]`
  • `figureTop`: 스탠딩 CG의 화면 높이 오프셋
  • `threeSize`: 신체 치수 `[B, W, H]`
  • `isNPC`: 동료화 이전 정보 표시 여부 (`true` 시 NPC로 표기)

7. 텍스트 기반 맵 데이터 작성 사양 ✎

7.1. 유효 칸과 벽 행 구조 ✎

텍스트 에디터 상에서 맵을 구성할 때 지나갈 수 있는 타일과 벽/문 타일의 좌표 체계를 분리해야 한다.
  • 시스템상 벽과 문은 시각적으로는 얇은 경계선이지만, 내부 데이터 배열에서는 독립된 1행 전체를 점유한다.
  • 행 계산 규칙:
  • 실제 필요한 데이터 행 수 = `(이동 가능한 유효 칸의 행 수) + (유효 칸의 행 수 + 1)`
  • 예시: 3×3 크기의 방을 만들 경우 총 7행의 데이터가 필요하다.
  • 1행: 외벽
  • 2행: 유효 이동 칸 1
  • 3행: 내벽
  • 4행: 유효 이동 칸 2
  • 5행: 내벽
  • 6행: 유효 이동 칸 3
  • 7행: 하단 외벽 및 문
  • 배치 시 주의사항:
  • 보물상자, 계단, 진입 이벤트 등은 반드시 '유효 이동 칸(바닥)' 행에 배치해야 한다. 벽 행에 배치하면 트리거가 소실된다.
  • 벽이나 문 오브젝트를 '유효 이동 칸'에 배치하면 판정이 충돌하거나 증발하므로 정해진 벽 전용 행에만 배치해야 한다.
  • 텍스트 맵 작업 시 MS Gothic 등 고정폭(등폭) 폰트 환경의 Excel 또는 VS Code를 활용하면 열과 행 정렬 오류를 줄일 수 있다.