Подготовка.
Перед началом, скачайте пак картинок с MEGA.
Разбираем код противника.
Писать мы будем на языке SOC. Комментарии в SOC, задаются решеткой (#)
Скопируйте данный код к себе в MAINCFG:
Freeslot
S_BOUNCY_STND
S_BOUNCY_RUN1
S_BOUNCY_RUN2
SPR_UCUP
MT_BOUNCYBALL
State S_BOUNCY_STND
SpriteName = UCUP
SpriteFrame = A
Duration = 5
Next = S_BOUNCY_STND
Action = A_Look
Var1 = 0
Var2 = 0
State S_BOUNCY_RUN1
SpriteName = UCUP
SpriteFrame = A
Duration = 80
Next = S_BOUNCY_RUN2
Action = A_BunnyHop
Var1 = 8
Var2 = 12
State S_BOUNCY_RUN2
SpriteName = UCUP
SpriteFrame = A
Duration = 5
Next = S_BOUNCY_RUN1
Action = A_FaceTarget
Var1 = 0
Var2 = 0
Object MT_BOUNCYBALL
MapThingNum = 1337
SpawnState = S_BOUNCY_STND
SpawnHealth = 1
SeeState = S_BOUNCY_RUN2
SeeSound = sfx_None
ReactionTime = 32
AttackSound = sfx_None
PainState = S_NULL
PainChance = 200
PainSound = sfx_None
MeleeState = S_NULL
MissileState = S_NULL
DeathState = S_XPLD1
XDeathState = S_NULL
DeathSound = sfx_pop
Speed = 3
Radius = 20*FRACUNIT
Height = 20*FRACUNIT
DispOffset = 0
Mass = 100
Damage = 0
ActiveSound = sfx_None
Flags = MF_ENEMY|MF_SPECIAL|MF_SHOOTABLE
RaiseState = S_NULL
Начнем его разбирать.
Freeslot. Заголовок загружаемых ресурсов.
Первым делом укажем, какие ресурсы использует объект (в нашем случае противник). Для этого, после строки Freeslot, пишем имена ресурсов с префиксом, указывающих на тип ресурса.
Первыми идут стейты
S_BOUNCY_STND
S_BOUNCY_RUN1
S_BOUNCY_RUN2
Названия стейтов начинаются с S_. Чуть позже разберем их подробнее.
Далее идут спрайты.
SPR_UCUP
Для того чтобы использовать спрайт с именем UCUP, необходимо добавить к нему префикс SPR_, в итоге получится SPR_UCUP. Также, у спрайтов, как и в DECORATE, используется первые 4 буквы названия изображения, 5-я буква задает имя кадра, а 6-я угол поворота.

Спрайты, как и в ZDoom, должны располагаться между маркерами S_START и S_END, если это wad.

И в папке Sprites (или любой его под-папке), если это pk3.

И указываем название объекта (противника). Названия объектов имеют префикс MT_.
MT_BOUNCYBALL
Подробнее про Freeslot, на вики.
Стейты.
Далее идут 3 стейта:
- S_BOUNCY_STND — стейт покоя, противник не видит игрока.
- S_BOUNCY_RUN1 — прыжок в сторону игрока.
- S_BOUNCY_RUN2 — подготовка к следующей атаке.
Разберем код стейта S_BOUNCY_STND:
State S_BOUNCY_STND #начало блока стейта S_BOUNCY_STND
SpriteName = UCUP #Имя спрайта (вернее первые 4 буквы)
SpriteFrame = A #Имя кадра (UCUPAx, где x-угол поворота)
Duration = 5 #Время до следующего стейта в тиках (35 тиков = 1 секунда)
Next = S_BOUNCY_STND #Имя следующего стейта
Action = A_Look #Действие (или функция, кому как удобнее), которое выполнит противник
Var1 = 0 #Аргумент 1, функции A_Look
Var2 = 0 #Аргумент 2, функции A_Look
В комментариях я подробно рассписал каждую строчку.
Обратите внимание на строку
Action = A_Look #Действие (или функция, кому как удобнее), которое выполнит противник
В одной этой строке, заключена вся логика стейта. Здесь вызывается действие A_Look, которое ищет игрока в области видимости.
Все действия, начинаются с префикса A_, как в DECORATE. Полный список функций (действий), доступен вики. Также, есть возможность и свои действия, на языке Lua.
Остальные стейты, имеют ту же структуру.
Стейт S_BOUNCY_RUN1, вызывает функцию A_BunnyHop, который принимает 2 аргумента:
- Силу прыжка вверх
- Силу движения вперед (в нашем случае вперед, направлен на игрока)
И, через 5 тиков, переходит на стейт S_BOUNCY_RUN2.
В котором, противник поворачивается в сторону цели (игрока) A_FaceTarget, и возвращается в стейт S_BOUNCY_RUN1.
Т.е. идет бесконечный цикл.

Далее, разберем создание объекта.
Создание объекта.
В комментариях, я рассписал значение строк.
Object MT_BOUNCYBALL #Начало блока MT_BOUNCYBALL
MapThingNum = 1337 #id обьекта в редакторе ZoneBuilder
SpawnState = S_BOUNCY_STND #Начальный стейт
SpawnHealth = 1 #Количество хп обьекта
SeeState = S_BOUNCY_RUN2 #Стейт, на который нужно перейти, если противник увидит игрока
SeeSound = sfx_None #Звук, при обнаружении противника (в данном случае, его отсутствие)
ReactionTime = 32 #Время реакции
AttackSound = sfx_None #Звук атаки (отсутствует)
PainState = S_NULL #Стейт боли (отсутствует)
PainChance = 200 #Шанс попадания в стейт боли
PainSound = sfx_None #Звук боли (отсутствует)
MeleeState = S_NULL #Стейт рукопашного боя (отсутствует)
MissileState = S_NULL #Стейт выстрела снарядом (отсутствует)
DeathState = S_XPLD1 #Стейт смерти
XDeathState = S_NULL #Стейт смерти, при получении огромного количества урона
DeathSound = sfx_pop #Звук смерти
Speed = 3 #Скорость передвижения противника (3 FRACUNIT)
Radius = 20*FRACUNIT #радиус
Height = 20*FRACUNIT #высота
DispOffset = 0 #Используется тогда, когда хотите нарисовать 1 спрайт перед другим.
Mass = 100 #Масса
Damage = 0 #Урон
ActiveSound = sfx_None #Звук активации (отсутствует)
Flags = MF_ENEMY|MF_SPECIAL|MF_SHOOTABLE #флаги = это противник, он может взаимодействовать с игроком, игрок может его покалечить.
RaiseState = S_NULL #Стейт возрождения (отсутствует)
Подробнее о флагах здесь.
Добавляем обьект на карту.
Теперь, в Zone Builder, установите свой объект на карте.

И запустите. В итоге, получилось следующее.
Итоговый результат.
