Поскольку тема ZScript в новых гэзэдумах не сильно раскрыта, то предлагаю вынести все обсуждения/вопросы/гайды/примеры сюда.
Из-за того, что Decorate относится к ZScript не более чем Майкл Джордан к Эдди Мерфи, то вариант перебрасывания в "Тему для новичков" выглядит глупо.
Здесь я выложу кусок кода для "нового" пистолета с подробными комментариями:
Скрытый текст:
// Теперь вместо слова ACTOR используется class для обозначения
// оружия, монстров, игрока, патронов и т. д.
class nPistol : Weapon
{
// Также можно объявлять внутри любого из объектов любые переменные, указав их тип
float xbob;
float ybob;
float bobcycle;
Default
{
// Теперь не нужно прописывать слот оружия в KEYCONF, достаточно написать это
weapon.slotnumber 2;
// Флаги, списка которых нет, и фиг знает что они делают
+weapon.noalert;
}
// Здесь все ровно так же, как в декорейте
States
{
Ready:
// Только теперь в один стейт можно запихнуть все, что угодно, даже, наверное, закодить тетрис
PISG A 1
{
A_WeaponReady(WRF_NOBOB);
invoker.bobcycle = (invoker.bobcycle + 0.6) % 360; // Задаем простой счетчик
invoker.ybob = ((abs(vel.x)+abs(vel.y))*(1 - abs(sin(invoker.bobcycle*10))))*0.65; // Сложная математика для воссоздания думовского BOB'a
invoker.xbob = ((abs(vel.x)+abs(vel.y))*cos(invoker.bobcycle*10))*0.75;
A_WeaponOffset(invoker.xbob,40-invoker.ybob); // Сдвигаем наш пистолет на экране (вместе со всем остальным)
}
Wait;
Deselect:
PISG A 1
{
A_Lower();
}
Loop;
Select:
PISG A 1 {
A_Raise();
}
Loop;
Fire:
PISG A 4
{
A_WeaponOffset(invoker.xbob,38-invoker.ybob);
// Теперь спрайт пистолета не вернется в изначальное положение, а продолжит стрельбу из последней
// точки, в которой началась стрельба
}
PISG B 6
{
A_WeaponOffset(invoker.xbob,38-invoker.ybob);
A_FirePistol();
// Оверлей - это тот же A_GunFlash, только круче, теперь можно добавлять дикое множество оверлеев с разной альфой, рендерстайлом и шейдерами
A_Overlay(2,"Flash");
A_OverlayAlpha(2,0.5);
A_OverlayRenderstyle(2,STYLE_Add);
A_OverlayFlags(2,PSPF_ADDWEAPON|PSPF_ALPHA|PSPF_RENDERSTYLE,true);
A_AlertMonsters();
}
PISG C 4
{
A_WeaponOffset(invoker.xbob,38-invoker.ybob);
}
PISG B 5 {
A_WeaponOffset(invoker.xbob,38-invoker.ybob);
A_ReFire();
}
Goto Ready;
Flash:
// Сам стейт оверлея, он будет выполнять свою анимацию в параллель с основной анимацией.
PISF A 1 Bright;
Goto FlashDone;
Spawn:
PIST A -1;
Stop;
}
}
Поскольку код использует полностью оригинальные спрайты, то можно просто самому в слейде сделать вад, вставив данный код в ламп ZSCRIPT.
На вопросы по этому коду буду отвечать, на остальное - по ситуации.
Только теперь в один стейт можно запихнуть все, что угодно, даже, наверное, закодить тетрис
Кто не знает - это работает и в новом декорэйте тоже, не только в зскрипте.
Раз уж эта тема может стать учебником по зскрипту, то сразу задам нубский (но самый главный вопрос для начинающего): а как собственно определять зскрипт для здума? Это что, должен быть текстовый лумп Zscript, в котором пишется код (как decorate, mapinfo) или нужно еще где-то что-то указывать, чтобы здум понял, что используется зскрипт, или компились в ацс? в общем хотелось бы полной ясности в этом вопросе. Можно ли совмещать описание акторов в зскрипте (как пример в 1 посте) и описание в декорэйте или нужно что-то одно? Можно ли делать несколько файлов зскрипта для удобства (как это можно было в декорэйте - записать например оружия в один файл, мобов - в другой, декорации -в третий, а в основной декорэйт дать команду include)?
Shadowman 1. Нужно создать в корневой папке pk3 файл zscript.txt (в wad можно создать ламп ZSCRIPT, тоже работает).
2. Совмещать можно. Wiki говорит, что ZScript парсится перед DECORATE, это означает, что единственным ограничением будет невозможность унаследовать zscript-ового актора от декорейтового (наоборот можно; сейчас, по сути, поскольку в gzdoom.pk3 почти все акторы переведены на zscript, любой класс, объявленный в decorate, будет наследоваться от zscript-ового).
3. Можно. #include работает точно так же. В pk3 нужно указывать путь до файла в архиве (по-моему, относительные тоже работают), в wad просто имя лампа (порядок лампов подходит, насколько я понимаю, какой угодно, если не засовывать между маркерами).
N00b2015, извини, что ещё раз отвечаю на вопрос Shadowman'а -- не видел твоего сообщения.
Shadowman, для ZDoom -- через ключ "zdoom.exe -zscript". В нынешних G-/Q-производных он подключается автоматически. Правда, конкретно в ZDoom он очень и очень слаб, даже в последней, невыпущенной версии; лучше конкретно в ZDoom'е его вообще не использовать, или только по-минимуму.
ZScript загружается в память прежде Decorate'а, потому можно использовать родительские классы ZScript'а в Decorate, но не наоборот.
Да, загружать через lump "ZSCRIPT". Дополнительные файлы -- тоже верно, через директиву "#include". В ACS компилировать не надо, ZScript практически полностью компилируется в C-код сразу после загрузки (да, GZDoom -- VM).
Default {
// Теперь не нужно прописывать слот оружия в KEYCONF, достаточно написать это
weapon.slotnumber 2;
// Флаги, списка которых нет, и фиг знает что они делают
+weapon.noalert;
}
"Weapon.SlotNumber"/"Weapon.SlotPriority" немножко устарел, насколько я знаю. Нет, конечно, можно его или KEYCONF ещё использовать...
Насчёт "+NOALERT": меня терзают смутные сомнения, что код не ты писал... Вкратце -- монстры не слышат выстрелов из оружия с этим флагом. Функция "A_AlertMonsters", что используется здесь в стейте "Fire", наоборот, растревоживает всех в округе.
Печенька:
Deselect:
PISG A 1
{
A_Lower();
}
Loop;
Select:
PISG A 1
{
A_Raise();
}
Loop;
Для такого можно операторные скобки и не использовать:
<...>
Select:
PISG A 1 A_Raise();
Wait;
Deselect:
PISG A 1 A_Lower();
Wait;
<...>
Печенька:
Ready: // Только теперь в один стейт можно запихнуть все, что угодно, даже, наверное, закодить тетрис
PISG A 1 {
A_WeaponReady(WRF_NOBOB);
invoker.bobcycle = (invoker.bobcycle + 0.6) % 360;
<...>
Действительно, в последних версиях Decorate можно делать то же самое. Опять же ошибка объяснения, непонятно, что за "invoker.*" у тебя здесь используется. Почему не "self.*", например? Или не "this.*"? (Кстати, действительно -- меня тоже это интересует: как именно каждому классу обращаться самому к себе?).
N00b2015 JSO x Спасибо за пояснение. Еще такой вопрос - пока что вижу зскрипт как улучшенный декорэйт (на примере того же пистолета из 1 поста), с возможностью задавать переменные и проводить операции с ними.
А как соотносятся зскрипт и скрипты на карте или в библиотеке ацс? Переменные, которые задали в зскрипте, действуют только для объекта в зскрипте (опять пример с пистолетом выше)? Можно ли делать общие переменные, которые будет понимать как зскрипт, так и ацс библиотеки или скрипты на картах, и если да, то как правильно их задавать?
Shadowman Можно вызывать статические методы зскрипта из ACS и получать оттуда какую-то инфу: https://zdoom.org/wiki/ScriptCall Напрямую переменные задавать вроде бы нельзя. Читать тем более.
Кто не знает - это работает и в новом декорэйте тоже, не только в зскрипте.
JSO x:
Действительно, в последних версиях Decorate можно делать то же самое.
Вот кстати да, анон-функции же. Или они являются очень свежей фичей?
В дополнение вопросов Шэдоумэна:
You can include other lumps for processing similar to DECORATE as so:
#include "ZScript/Const.txt"
Due to how ZScript is processed, it is possible to name a file which conflicts with other mods or the internal files. For example, if you have a file in your mod named ZScript/Const.txt, it will prevent the game from loading this file correctly as it is already defined internally. To avoid such conflicts, it is recommended to have a subfolder named after your mod, such as:
#include "MyMod/Const.txt"
Поясните плз, о чём этот абзац с вики? Типа совет избегать использования строки #include "ZScript/Const.txt" или как?
Прикрепляю спрайт, для чего все делается, чтобы убрать сомнения.
Спрайт утырил с ZDoom форума из топика Spriting carnival. Автор тоже его откуда-то стянул.
Скрытый текст:
По поводу invoker. Почему инвокер стоит в начале каждой переменной - трудно объяснить, даже если пытаться.
Инвокер используется для переменных "внутри" оружия, если приравнивать переменную без указания инвокера, то гозза посчитает, что эта переменная находится где-то у игрока (как было в строчке с оффсетами, где я доставал velx и vely, например)
Нельзя в своем моде делать файл с таким именем "ZScript/Const.txt" , т.к. он дублирует какой-то там внутренний файл здума, в результате корректного запуска не будет. Чтобы избежать глюка, называй каталог, куда помещаешь зскриптовые файлы, не ZScript, а как-то иначе.
Команда инклюд норм работает с зскриптом, выше ж написали!
По поводу invoker. Почему инвокер стоит в начале каждой переменной - трудно объяснить, даже если пытаться.
Очень просто это объяснить. Это наследие DECORATE. В декоре было принципиально невозможно указать мембера от другого объекта (например, owner.player). Поэтому, чтобы вообще была возможность из оружия и инвентаря работать с актором игрока, они заменили self на актора игрока (таким образом velx/y/z и прочие обращались именно к игроку).
В целях обратной совместимости данное поведение перешло в ZScript, а если требуется обратиться конкретно к полям инвентаря, используется invoker.
Если вкратце: invoker всегда this, а вот self — иногда не this (только у подклассов Inventory, по ситуации).
А в ЗСкрипте можно как-нибудь считать, какое оружие у игрока в руках? Например раньше всякие функции, вроде пинка или броска гранаты необходимо было прописывать в коде каждого оружия. А так можно было бы делать все переключением оружия, т.е. нажимает игрок G, игра переключает на "оружие", которое и отвечает за бросок гранаты, а потом возвращает предыдущее.
И еще играл в Guncaster, заметил прикольную фичу - рентгеновское зрение. Прям таки мечты сбываются. Только Зандронум тормозит развитие.
из обычной (насколько понял из исходников). Дальше проверяем, например, так:
if (w is "SuperBFG9000") {...}
Насчёт способа переключить достоверно не знаю, но, вероятно, это можно сделать так:
player.PendingWeapon = w;
Он-то, конечно, тормозит, только там ребятам нужно отлаживать неткод, чтобы не было десинхронизаций и (широких) возможностей для читерства. ZScript позволяет без изменения исходника порта добиваться значительно больших результатов, чем Decorate, и в этом смысле более уязвим (моддеру открыт фактически более низкий уровень абстракции, близкий непосредственно к движку).
theleo_ua, такое ещё в ZDoom 2.7.1 было, вроде... По крайней мере, для совместимости с даже ZDoom 2.8.1 (ещё 2016-й!..) я таким способом пользуюсь по-полной.
Скрытый текст:
P. S.: а за ссылку на документацию не меня благодарить нужно, а человека, что её мне дал. Увы, на данном форуме он за что-то заблокирован... Звали его "Iddqd_Idkfa_Idclev" или "Iddqd" или "x --> 0"; точно не знаю -- ещё до моей регистрации он здесь был.