Разбор vehiclelayouts.meta: сиденья, точки входа и анимации

Автор: Nilo3D · Обновлено:

vehiclelayouts.meta описывает, как педы пользуются транспортом: какие у него сиденья, где в него садятся и какие анимации проигрываются при посадке, сидении и выходе. Транспорт выбирает один layout по имени в поле layout файла vehicles.meta. Свой layout позволяет аддон-транспорту получить собственную позу езды или анимацию посадки, не меняя никакой другой транспорт.

Что такое layout транспорта?

Layout это именованный список сидений и точек входа. Каждое сиденье связывает определение сиденья (какая кость, какие соседи) с определением анимаций сиденья (какие клипы в нём проигрываются). Каждая точка входа связывает определение двери с определением анимаций входа. Всё связывается по именам, поэтому один layout может использовать части стоковых layout.

Это стоковый LAYOUT_STANDARD, вариант по умолчанию для машин, сокращённый до двух передних сидений:

<Item type="CVehicleLayoutInfo">
  <Name>LAYOUT_STANDARD</Name>
  <Seats>
    <Item>
      <SeatInfo ref="SEAT_STANDARD_FRONT_LEFT" />
      <SeatAnimInfo ref="SEAT_ANIM_STANDARD_FRONT_LEFT" />
    </Item>
    <Item>
      <SeatInfo ref="SEAT_STANDARD_FRONT_RIGHT" />
      <SeatAnimInfo ref="SEAT_ANIM_STANDARD_FRONT_RIGHT" />
    </Item>
  </Seats>
  <EntryPoints>
    <Item>
      <EntryPointInfo ref="ENTRY_POINT_STANDARD_FRONT_LEFT" />
      <EntryPointAnimInfo ref="ENTRY_POINT_ANIM_STANDARD_FRONT_LEFT" />
    </Item>
    <Item>
      <EntryPointInfo ref="ENTRY_POINT_STANDARD_FRONT_RIGHT" />
      <EntryPointAnimInfo ref="ENTRY_POINT_ANIM_STANDARD_FRONT_RIGHT" />
    </Item>
  </EntryPoints>
  <LayoutFlags>StreamAnims UseDoorOscillation UseLeanSteerAnims UseSteeringWheelIk</LayoutFlags>
  <BicycleInfo ref="NULL" />
  <AnimRateSet ref="STD_LOW_ANIM_RATE_SET" />
  <HandsUpClipSetId>busted_vehicle_std</HandsUpClipSetId>
  <SteeringWheelOffset x="0.000000" y="0.350000" z="0.320000" />
</Item>

Как устроен vehiclelayouts.meta?

Корневой элемент называется CVehicleMetadataMgr. Он содержит по одному списку на каждый вид определений. Файлу нужны только те списки, в которые он что-то добавляет. Имена, на которые он ссылается, но сам не определяет, берутся из файлов самой игры.

СписокТип элементаЧто определяет
VehicleLayoutInfosCVehicleLayoutInfoLayout: сиденья, точки входа, флаги.
VehicleSeatInfosCVehicleSeatInfoСиденье: кость, связи для пересаживания, флаги сиденья.
VehicleSeatAnimInfosCVehicleSeatAnimInfoАнимации на сиденье, настройка drive-by.
VehicleEntryPointInfosCVehicleEntryPointInfoСпособ попасть внутрь: кость двери, сторона, до каких сидений можно добраться.
VehicleEntryPointAnimInfosCVehicleEntryPointAnimInfoАнимации посадки и выхода для одной точки входа.
ClipSetMapsCClipSetMapИменованные списки clip set, на которые указывают anim info.
VehicleDriveByInfos, VehicleDriveByAnimInfosПрицеливание и стрельба с сиденья.
AnimRateSets, BicycleInfos, VehicleExtraPointsInfos, EntryAnimVariations, VehicleCoverBoundOffsetInfos, VehicleExplosionInfosСкорости анимаций, вращение педалей велосипеда, дополнительные позиции входа, вариации входа, настройки укрытий и взрывов.

Какие поля есть у layout?

ПолеЗначение
NameИмя layout. Его пишут в поле layout файла vehicles.meta.
SeatsПо одному элементу на сиденье, в каждом ссылки SeatInfo и SeatAnimInfo.
EntryPointsПо одному элементу на каждый способ попасть внутрь, в каждом ссылки EntryPointInfo и EntryPointAnimInfo.
LayoutFlagsФлаги поведения, разделённые пробелами (см. ниже).
BicycleInfoНастройка вращения педалей для велосипедов, в остальных случаях NULL.
AnimRateSetНабор скоростей анимаций для посадки и выхода.
HandsUpClipSetIdClip set для позы с поднятыми руками (по умолчанию busted_vehicle_std).
SteeringWheelOffsetПозиция руля, по которой размещаются руки (по умолчанию 0, 0.35, 0.32).
FirstPersonAdditiveIdleClipSets, FirstPersonRoadRageClipSetsClip set для idle и для агрессии на дороге в виде от первого лица.

Некоторые флаги layout, смысл которых понятен из названий: NoDriver, StreamAnims, WarpIntoAndOut, BikeLeansUnlessMoving, UseSteeringWheelIk, UseLeanSteerAnims, MustCloseDoor, AutomaticCloseDoor, DisableJackingAndBusting, UseDoorOscillation, WarpInWhenStoodOnTop. Всего в схеме их 32. Начните с флагов стокового layout, самого близкого к вашему транспорту, и меняйте по одному.

Как определяются сиденья и точки входа?

Сиденье привязано к кости в модели транспорта, а точка входа к кости двери. Если в модели нет кости, которую называет определение, это сиденье или дверь работать не будет. Вот стоковые сиденье водителя и дверь водителя у машины:

<Item type="CVehicleSeatInfo">
  <Name>SEAT_STANDARD_FRONT_LEFT</Name>
  <SeatBoneName>seat_dside_f</SeatBoneName>
  <ShuffleLink>SEAT_STANDARD_FRONT_RIGHT</ShuffleLink>
  <RearSeatLink>SEAT_STANDARD_REAR_LEFT</RearSeatLink>
  <DefaultCarTask>TASK_DRIVE_WANDER</DefaultCarTask>
  <SeatFlags>IsFrontSeat</SeatFlags>
  <HairScale value="-0.2750000" />
</Item>

<Item type="CVehicleEntryPointInfo">
  <Name>ENTRY_POINT_STANDARD_FRONT_LEFT</Name>
  <DoorBoneName>door_dside_f</DoorBoneName>
  <SecondDoorBoneName />
  <DoorHandleBoneName>handle_dside_f</DoorHandleBoneName>
  <WindowId>FRONT_LEFT</WindowId>
  <VehicleSide>SIDE_LEFT</VehicleSide>
  <AccessableSeats>
    <Item ref="SEAT_STANDARD_FRONT_LEFT" />
  </AccessableSeats>
  <VehicleExtraPointsInfo ref="EXTRA_VEHICLE_POINTS_STD_LEFT" />
  <Flags>BlockJackReactionUntilJackerIsReady</Flags>
  <BlockJackReactionSides>
    <Item>SIDE_LEFT</Item>
  </BlockJackReactionSides>
</Item>
ПолеЗначение
SeatBoneNameКость, к которой прикрепляется пед. Машины используют seat_dside_f, seat_pside_f, seat_dside_r и seat_pside_r (сторона водителя и сторона пассажира, спереди и сзади).
ShuffleLinkСиденье, на которое пед пересаживается, например с пассажирского на водительское.
RearSeatLinkСиденье позади этого.
SeatFlagsНапример, IsFrontSeat, IsIdleSeat, NoIndirectExit, KeepOnHeadProp, FakeSeat.
DoorBoneName, DoorHandleBoneNameКости двери и ручки, к которым пед подходит и тянется, например door_dside_f и handle_dside_f. У транспорта без дверей остаются пустыми.
WindowIdFRONT_LEFT, FRONT_RIGHT, REAR_LEFT, REAR_RIGHT, MID_LEFT, MID_RIGHT, FRONT_WINDSCREEN, REAR_WINDSCREEN или INVALID.
VehicleSideSIDE_LEFT, SIDE_RIGHT или SIDE_REAR.
AccessableSeatsСиденья, до которых можно добраться из этой точки входа. Тег действительно пишется через a.

Как анимации связываются с сиденьем?

Анимации доходят до сиденья через четыре звена. Каждое звено это поиск по имени, поэтому при разрыве в любом месте цепочки вы получите стоковую анимацию или вообще никакой.

  1. Файл анимации, словарь клипов (.ycd), кладётся в папку stream ресурса.
  2. Clip set в clip_sets.xml даёт этому словарю имя clip set. Файл загружается строкой data_file 'CLIP_SETS_FILE'.
  3. CClipSetMap в vehiclelayouts.meta указывает это имя clip set в ClipSetId.
  4. Anim info сиденья указывает на карту через InsideClipSetMap (клипы, которые проигрываются сидя), а anim info точки входа через EntryClipSetMap, ExitClipSetMap и CommonClipSetMap.
<?xml version="1.0" encoding="UTF-8"?>
<fwClipSetManager>
  <clipSets>
    <Item type="fwClipSet" key="veh@bike@mybike@front@base">
      <fallbackId />
      <clipDictionaryName>veh@bike@mybike@front@base</clipDictionaryName>
      <clipItems />
      <moveNetworkFlags />
    </Item>
  </clipSets>
  <clipDictionaryMetadatas>
    <Item key="veh@bike@mybike@front@base">
      <streamingPolicy>SP_STREAMING</streamingPolicy>
      <memoryGroup>MG_Vehicle</memoryGroup>
      <streamingPriority>SP_Medium</streamingPriority>
    </Item>
  </clipDictionaryMetadatas>
</fwClipSetManager>

Игра запрашивает у clip set клипы по фиксированным именам, поэтому свой словарь сохраняет имена клипов стокового словаря, который он заменяет, и меняет только движение внутри них.

Как дать одному транспорту собственную анимацию?

Создайте layout с новым именем, скопируйте стоковый layout, который транспорт использовал бы обычно, и замените только те ссылки, которые хотите изменить. Всё, что вы не переопределяете, продолжает указывать на стоковые определения.

<CVehicleMetadataMgr>
  <ClipSetMaps>
    <Item type="CClipSetMap">
      <Name>INSIDE_CLIPSET_MAP_MYBIKE_FRONT</Name>
      <Maps>
        <Item>
          <ClipSetId>veh@bike@mybike@front@base</ClipSetId>
          <VarClipSetId>InsideVarClipSet</VarClipSetId>
          <ConditionFlags />
          <InformationFlags />
        </Item>
      </Maps>
    </Item>
  </ClipSetMaps>

  <VehicleSeatAnimInfos>
    <Item type="CVehicleSeatAnimInfo">
      <Name>SEAT_ANIM_MYBIKE_FRONT</Name>
      <DriveByInfo ref="DRIVEBY_BIKE_SCOOTER" />
      <InsideClipSetMap ref="INSIDE_CLIPSET_MAP_MYBIKE_FRONT" />
      <!-- remaining tags copied from the stock seat anim info you start from -->
    </Item>
  </VehicleSeatAnimInfos>

  <VehicleLayoutInfos>
    <Item type="CVehicleLayoutInfo">
      <Name>LAYOUT_MYBIKE</Name>
      <Seats>
        <Item>
          <SeatInfo ref="SEAT_BIKE_FRONT" />
          <SeatAnimInfo ref="SEAT_ANIM_MYBIKE_FRONT" />
        </Item>
      </Seats>
      <EntryPoints>
        <Item>
          <EntryPointInfo ref="ENTRY_POINT_BIKE_FRONT_LEFT" />
          <EntryPointAnimInfo ref="ENTRY_POINT_ANIM_BIKE_SCOOTER_FRONT_LEFT" />
        </Item>
      </EntryPoints>
      <!-- flags and remaining tags copied from the stock layout -->
    </Item>
  </VehicleLayoutInfos>
</CVehicleMetadataMgr>

Затем задайте <layout>LAYOUT_MYBIKE</layout> в vehicles.meta. У layout своё имя, поэтому другой транспорт на сервере он не затрагивает. Именно так Coil S-Cooter получает позу езды стоя, а ховерборды свою стойку: свой layout, свои clip set и словари анимаций, без единого скрипта.

Чтобы это работало, соблюдайте два правила. Используйте имена, которых нет ни в одном другом ресурсе, потому что layout, сиденья и карты clip set ищутся по имени по всей игре. И следите, чтобы файл layout загружался раньше vehicles.meta, потому что транспорт ищет свой layout в момент регистрации. FiveM сам обеспечивает этот порядок, как описано в справочнике data_file.

Полный пример транспорта на собственном layout разобран в гайде как ховерборд FiveM работает без скрипта.

Частые вопросы

Что делает поле layout в vehicles.meta?
Оно называет запись в vehiclelayouts.meta, которую транспорт использует для сидений, точек входа и анимаций. По умолчанию это LAYOUT_STANDARD.
Нужен ли vehiclelayouts.meta для аддон-машины?
Нет. Обычная машина может использовать стоковый layout, например LAYOUT_STANDARD. Свой файл нужен только для своей посадки, своих анимаций или необычного числа сидений.
Как загрузить vehiclelayouts.meta в FiveM?
Укажите его в files в fxmanifest.lua и добавьте data_file 'VEHICLE_LAYOUTS_FILE' с тем же путём. Свои clip set загружаются строкой data_file 'CLIP_SETS_FILE'.
Почему не проигрывается моя анимация транспорта?
Проверьте цепочку по порядку: .ycd лежит в stream, clip set в clip_sets.xml называет этот словарь, карта clip set в vehiclelayouts.meta называет этот clip set, anim info сиденья или входа ссылается на карту, а vehicles.meta использует имя вашего layout.
Изменит ли свой layout другой транспорт?
Нет, если у него своё имя. Его использует только тот транспорт, в записи vehicles.meta которого указан этот layout.

Источники

Товары из гайда

Все гайды