◆Cobblemon Wiki

애드온 제작

탑승 설정

시작하기 전에

이 튜토리얼은 Cobblemon에 사용자 지정 탑승 포켓몬을 추가하는 방법을 설명합니다. 절차는 비교적 간단하지만 Blockbench의 기본 조작과 JSON을 읽는 방법을 알아 두는 것이 좋습니다.

1단계: 로케이터 추가

플레이어가 포켓몬에 앉을 수 있도록 모델에 seat_1이라는 로케이터를 추가합니다. 로케이터는 닻 모양으로 표시됩니다. 여러 좌석이 필요하면 seat_2, seat_3처럼 번호를 이어 추가합니다. Blockbench의 도구 모음 사용자 지정에서 Add Locator 도구를 찾을 수 있습니다.

모델 파일은 assets/cobblemon/bedrock/pokemon/models/[포켓몬 이름 폴더]에 [pokemon].geo.json이라는 이름으로 배치합니다.

공식 예시는 리자몽 모델의 1인승, 쥬레곤 모델의 2인승, 폭타 모델의 6인승입니다. 좌석마다 해당 위치에 별도 로케이터를 배치합니다.

2단계: 탑승 데이터 추가

포켓몬의 species 파일에 탑승 행동을 추가합니다. species additions를 이용해 추가할 수도 있습니다. 다음은 윈디의 예시입니다.

"riding": {
  "behaviours": {
    "LAND": {
      "key": "cobblemon:land/horse",
      "rideSounds": [],
      "stats": {
        "ACCELERATION": "70-90",
        "JUMP": "45-65",
        "SKILL": "40-80",
        "SPEED": "45-70",
        "STAMINA": "35-80"
      }
    }
  },
  "seats": [
    { "locator": "seat_1" }
  ]
}

behaviours는 탑승 중 포켓몬이 이동하는 방식을 정의합니다. LAND는 지상, AIR는 공중, LIQUID는 액체에서의 이동입니다. 각 범주의 key는 사용할 탑승 스타일을 선택합니다. 예를 들어 크리에이티브 비행처럼 떠다닐지, 새처럼 날지를 결정하므로 중요합니다.

rideSounds는 탑승 시 재생할 소리이며, seats에는 모델의 좌석 로케이터를 나열합니다. stats는 포켓몬의 종족값과 비슷한 탑승 능력치입니다. 각 값은 최소-최대 범위 문자열이며 0–100 안으로 유지하는 것이 좋습니다. 능력치의 구체적 작용은 탑승 스타일마다 다릅니다.

능력치의미
ACCELERATION최대 속도에 도달하는 빠르기입니다.
JUMP점프 높이입니다. 공중 스타일에서는 다른 작용도 하며, 새 스타일에서는 활공 효율 등에 영향을 줍니다.
SKILL회전하는 빠르기입니다. 부유 스타일에서는 감속률에 영향을 줍니다.
SPEED도달할 수 있는 최대 속도입니다.
STAMINA해당 스타일로 탑승할 수 있는 시간입니다. 예를 들어 지상 탑승에서는 질주 지속 시간입니다.

추가 설정: rideSounds

소리와 그 음량을 설정합니다. 주로 공중 탑승에 사용합니다. 다음은 드래펄트의 예시입니다.

"rideSounds": [
  {
    "muffleEnabled": true,
    "pitchExpr": "math.max(1.0 ,0.2 + math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2))",
    "playForNonPassengers": true,
    "soundLocation": "cobblemon:ride.loop.wind",
    "volumeExpr": "math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2)"
  }
]
필드의미
muffleEnabled소리의 먹먹한 처리를 활성화할지 여부입니다.
pitchExpr음높이를 정하는 Molang 표현식입니다.
playForNonPassengers현재 포켓몬에 타지 않은 플레이어에게도 소리를 재생할지 여부입니다.
soundLocation탑승 중 재생할 소리입니다. 반복 소리는 cobblemon:ride.loop.leather, cobblemon:ride.loop.plumage, cobblemon:ride.loop.chitin, cobblemon:ride.loop.wind 네 가지입니다.
volumeExpr음량을 정하는 Molang 표현식입니다.

추가 설정: seats

좌석 수와 로케이터를 지정합니다. 모델에 있는 좌석 로케이터를 모두 나열해야 합니다.

1인승:

"seats": [
  { "locator": "seat_1" }
]

2인승:

"seats": [
  { "locator": "seat_1" },
  { "locator": "seat_2" }
]

사용할 수 있는 탑승 키

자세한 스타일 설명은 포켓몬 탑승 문서를 참고하세요. 아래 경로 앞에 cobblemon:을 붙여 key로 지정합니다.

범주키별칭
LANDland/horsestandard
AIRair/bird—
AIRair/jet—
AIRair/hoverufo
AIRair/rocket—
LIQUIDliquid/boat—
LIQUIDliquid/submarine—
LIQUIDliquid/dolphin—

점프하지 못하게 하려면 "canJump": false를, 질주하지 못하게 하려면 "canSprint": false를 추가합니다. 다음은 드래펄트의 지상 행동 예시입니다.

"LAND": {
  "key": "cobblemon:land/horse",
  "rideSounds": [],
  "canJump": false,
  "canSprint": false,
  "stats": {
    "ACCELERATION": "10-40",
    "JUMP": "10-40",
    "SKILL": "80-100",
    "SPEED": "10-40",
    "STAMINA": "10-40"
  }
}

3단계: 애니메이션

탑승 애니메이션은 선택 사항이며, 탑승 기능 자체에 필수는 아닙니다.

탑승 포켓몬에는 주로 오버레이, 점프, 달리기 애니메이션이 추가됩니다. 오버레이는 탑승 애니메이션 위에 겹쳐 재생되며 Molang으로 역동적인 움직임을 표현합니다.

Blockbench의 변수 기능을 사용합니다. 변수 슬라이더를 만들려면 다음 내용을 복사하고, yaw_change를 제어할 변수로 바꿉니다. q는 query를 뜻하며 q.r 부분은 그대로 둡니다.

q.r.yaw_change = slider('yaw_change', 0.02, -1.0, 1.0)
변수의미
yaw_change좌우 움직임입니다. 1은 오른쪽, -1은 왼쪽입니다.
pitch_change상하 움직임입니다. 1은 위쪽, -1은 아래쪽입니다.
velocity_y점프의 상하 움직임입니다. 1은 상승, -1은 하강입니다.
dive공중 급강하입니다. 0은 급강하하지 않는 상태, 1은 최대 속도 급강하입니다.

예를 들어 슬라이더가 좌우 회전에 영향을 주게 하려면 키프레임에 q.r.yaw_change를 넣습니다. 회전 키프레임에 q.r.yaw_change(0)*7을 넣으면 슬라이더의 값에 따라 해당 부위가 좌우로 7도 회전합니다.

이동 방식주로 사용하는 애니메이션
지상ride_ground_run, ride_ground_walk, ride_jump
공중ride_air_fly, air_glide, ride_air_dive
액체ride_water_swim

포저(Poser)

포저에서 탑승 애니메이션을 설정합니다. "animations": [] 안에 조건부 애니메이션을 추가하고 조건을 q.is_ridden으로 지정하면 탑승 중일 때만 재생됩니다. 다음은 리자몽의 탑승 달리기 오버레이입니다.

{
  "condition": "q.is_ridden",
  "animation": "q.bedrock('charizard', 'ride_ground_run')"
}

달리기를 추가할 때는 달리기 포즈에 q.is_sprinting, 걷기 포즈에 !q.is_sprinting 조건을 지정합니다. 점프 포즈에는 q.in_air, 달리기·걷기·대기 같은 지상 포즈에는 !q.in_air 조건을 추가합니다. 다음은 신비록의 포저 예시입니다.

"in-air": {
  "poseTypes": ["STAND", "WALK"],
  "isBattle": false,
  "condition": "q.in_air && q.is_ridden",
  "animations": ["q.look('head')", "q.bedrock('wyrdeer', 'ride_jump')"],
  "transformTicks": 2,
  "transformToTicks": 2
},
"walk": {
  "poseName": "walk",
  "poseTypes": ["WALK"],
  "isBattle": false,
  "condition": "!q.in_air && !q.is_sprinting",
  "animations": [
    "q.look('head')",
    "q.bedrock('wyrdeer', 'ground_walk')",
    {
      "condition": "q.is_ridden",
      "animation": "q.bedrock('wyrdeer', 'ride_ground_run')"
    }
  ],
  "quirks": ["q.bedrock_quirk('wyrdeer', 'blink')"],
  "transformTicks": 10
},
"run": {
  "poseName": "run",
  "poseTypes": ["STAND", "WALK"],
  "isBattle": false,
  "condition": "!q.in_air && q.is_sprinting",
  "animations": [
    "q.look('head')",
    "q.bedrock('wyrdeer', 'ground_run')",
    {
      "condition": "q.is_ridden",
      "animation": "q.bedrock('wyrdeer', 'ride_ground_run')"
    }
  ],
  "quirks": ["q.bedrock_quirk('wyrdeer', 'blink')"],
  "transformTicks": 10
}