Прототипы в Space Station 14

SS14_#1 // Полный гайд по YAML-прототипам // Время чтения: 30 мин

Введение

Прототипы - это фундаментальный механизм Space Station 14 для определения данных игры в YAML-файлах, которые затем загружаются и используются движком Robust Toolbox. Они помогают отделить логику от данных: например, если вы хотите изменить внешний вид или характеристики предмета, вам не нужно перекомпилировать весь код - достаточно изменить соответствующий YAML-прототип.

Основные концепции

1. Что такое прототип?

Прототип - это шаблон или описание игрового объекта (или другого элемента игры), написанный в YAML-формате. Каждый прототип имеет:

  • Уникальный идентификатор (ID) - по нему код находит и использует прототип
  • Набор свойств - определяют, как будет выглядеть и вести себя объект в игре
  • Возможность наследования - прототип может взять свойства от одного или нескольких других прототипов (как класс в программировании)

2. Что такое компонент?

Компонент - это модуль функционала для сущностей. Каждый компонент добавляет определённую способность сущности:

  • Sprite - добавляет спрайт (графику)
  • Physics - делает сущность физическим объектом (с массой, гравитацией)
  • Item - делает объект поднимаемым и переносимым
  • Damageable - позволяет сущности получать урон

Сущность - это собрание компонентов. Без компонентов сущность не будет ни видно, ни взаимодействовать с миром.

3. Ключевые интерфейсы

В Robust Toolbox существуют два основных интерфейса для работы с прототипами:

IPrototype

Базовый интерфейс для всех прототипов. Определяет обязательное свойство ID.

csharp
public interface IPrototype
{
    string ID { get; }
}

IInheritingPrototype

Расширение IPrototype, позволяющее прототипу наследовать свойства от родительских прототипов.

csharp
public interface IInheritingPrototype
{
    string[]? Parents { get; }
    bool Abstract { get; }
}

Структура YAML-прототипа

Общий формат

yaml
- type: <тип_прототипа>
  id: <уникальный_идентификатор>
  <свойство1>: <значение1>
  <свойство2>: <значение2>

Пример: EntityPrototype (Сущность)

Сущности - это основные игровые объекты. Они описываются с помощью компонентов.

yaml
- type: entity
  id: BaseControllable
  abstract: true
  save: false
  components:
  - type: Sprite
    noRot: true
    drawdepth: Mobs
  - type: GravityAffected
  - type: Physics
  - type: Fixtures
    fixtures:
      fix1:
        shape: !type:PhysShapeCircle
          radius: 0.35
        density: 50
        mask: [MobMask]
        layer: [MobLayer]

Основные типы прототипов

EntityPrototype (Сущности и предметы)

Сущность - это основной игровой объект: моб, предмет, устройство, стены и т.д.

Пример: Простой предмет (гаечный ключ)

yaml
- type: entity
  name: wrench
  parent: BaseItem
  id: Wrench
  description: "A common tool for assembly and disassembly."
  components:
  - type: Sprite
    sprite: Objects/Tools/wrench.rsi
    state: icon
  - type: Item
    size: Small
  - type: Tag
    tags:
    - Wrench
  - type: MeleeWeapon
    wideAnimationRotation: 135
    attackRate: 1.5
    damage:
      types:
        Blunt: 4.5
  - type: Tool
    qualities:
      - Anchoring
    useSound:
      path: /Audio/Items/ratchet.ogg

TagPrototype (Теги)

Теги используются для классификации сущностей и создания белых/чёрных списков.

yaml
- type: Tag
  id: Airlock

SoundCollectionPrototype (Звуковые коллекции)

yaml
- type: soundCollection
  id: MetalThud
  files:
    - /Audio/Effects/metal_thud1.ogg
    - /Audio/Effects/metal_thud2.ogg
    - /Audio/Effects/metal_thud3.ogg

Наследование прототипов

Базовое наследование

Прототипы могут наследовать свойства от других прототипов, используя поле parent.

yaml
- type: entity
  id: BaseMob
  abstract: true
  parent: BaseControllable
  components:
  - type: MobCollision
  - type: Physics
    bodyType: KinematicController

Множественное наследование

Для множественного наследования используется массив в parent.

yaml
- type: entity
  id: ComplexMob
  abstract: true
  parent: [BaseMob, MobDamageable, MobCombat]
  components:
  - type: CustomComponent
    customProperty: "value"

Абстрактные прототипы

Абстрактные прототипы не могут быть использованы напрямую, только наследованы. Они используются для создания базовых шаблонов.

yaml
- type: entity
  id: BaseControllable
  abstract: true
  save: false
  components:
  - type: Sprite
  - type: Input

Создание собственного типа прототипа

Если вам нужен новый тип прототипа, создайте класс в C#:

csharp
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.Manager.Attributes;

namespace Content.Shared.MyModule
{
    [Prototype("customItem")]
    public sealed class CustomItemPrototype : IPrototype
    {
        [IdDataField]
        public string ID { get; private set; } = default!;

        [DataField("name")]
        public string Name { get; private set; } = "Неизвестный предмет";

        [DataField("price")]
        public int Price { get; private set; } = 0;

        [DataField("modifiers")]
        public ItemModifiers Modifiers { get; private set; } = new();
    }

    public sealed class ItemModifiers
    {
        [DataField("fireDamage")]
        public int FireDamage { get; private set; } = 0;

        [DataField("attackSpeedBonus")]
        public float AttackSpeedBonus { get; private set; } = 0f;
    }
}

Теперь создайте YAML-файл с прототипами:

yaml
- type: customItem
  id: CustomSword
  name: custom-sword-test
  price: 50
  modifiers:
    fireDamage: 10
    attackSpeedBonus: 0.2

Спавн сущностей в коде [C#]

Для спавна сущностей используйте IEntityManager:

csharp
using Robust.Shared.Prototypes;
using Robust.Shared.Map;

public class MySystem : EntitySystem
{
    [Dependency] private readonly IEntityManager _entityManager = default!;
    [Dependency] private readonly IPrototypeManager _prototypeManager = default!;

    public void SpawnItemAtLocation(string prototypeId, EntityUid targetEntity)
    {
        var transform = _entityManager.GetComponent(targetEntity);
        var item = _entityManager.SpawnEntity(prototypeId, transform.Coordinates);
    }
}

Практические советы для новичков

1. Как начать с прототипов?

  1. Сначала изучите существующие прототипы в /Resources/Prototypes/
  2. Создайте копию простого прототипа
  3. Измените его свойства (имя, спрайт, компоненты)
  4. Проверьте, работает ли ваш прототип

2. Пример: Создайте простой предмет "Моя Лампа"

yaml
- type: entity
  id: MyLamp
  name: "Моя Лампа"
  description: "Простая лампа, которую я создал!"
  components:
  - type: Sprite
    sprite: Objects/Lights/table_lamp.rsi
    state: icon
  - type: Item
    size: 1
  - type: Physics
    bodyType: Dynamic
  - type: Fixtures
    fixtures:
      fix1:
        shape: !type:PhysShapeAabb
          bounds: "-0.25,-0.25,0.25,0.25"
        density: 5
  - type: PointLight
    color: "#ffffaa"
    radius: 3
    energy: 0.8

3. Советы по организации

  • Уникальные ID: Используйте описательные названия (Wrench, TableLamp)
  • Абстрактные прототипы: Используйте их для шаблонов
  • Наследование: Максимально используйте для уменьшения дублирования
  • Комментарии: Добавляйте комментарии для пояснения

FAQ - Часто задаваемые вопросы

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

Используйте SpriteComponent и укажите путь к RSI-файлу:

yaml
- type: Sprite
  sprite: Objects/MyCustomItem.rsi
  state: icon

Как сделать предмет поднимаемым?

Добавьте ItemComponent:

yaml
- type: Item
  size: Small    # Tiny, Small, Normal, Large, Huge

Как добавить свет к сущности?

Используйте PointLightComponent:

yaml
- type: PointLight
  color: "#ffffff"
  radius: 5
  energy: 1.0

Важные директории

  • /Resources/Prototypes/ - Основная директория с прототипами
  • /Resources/Prototypes/Entities/ - Прототипы сущностей
  • /Resources/Prototypes/Entities/Mobs/ - Прототипы мобов
  • /Resources/Prototypes/Entities/Objects/ - Прототипы объектов