Xtor Если не особо шаришь в структуре стэйтовджампов, то лучше действительно начать с тупо выдачи 3 разных пистолей, а не мутить 1 но с разными спрайтами под каждого игрока, для тебя это будет та ещё морока.
Ну и коль тебе так приспичило рескинить пистоль под каждый класс, то можно использовать следующий вариант:
Скрытый текст:
Лучше юзать просто инвентори-итем (ака токен), типа такого:
Actor SwitchCheckerSL : Inventory
{
Inventory.Amount 1 //Число сколько выдаётся данного предмета за раз
Inventory.MaxAmount 3 //Максимально возможное число данного итема для трёх классов и, соответственно, для трёх спрайтов пистоля
}
Далее, каждому классу игрока на старте надо выдавать разное ко-во данного итема, например DoomSlayer - 1, DoomCyborg - 2, DoomMarine - 3 (остальные имена от балды, хз как их звать).
Ну и наконец, в самом пистоле в стэйте "Select" надо прописать 3 разные проверки типа:
Select: //Именно в порядке убывания ко-ва итемов!
TNT1 A 0 A_JumpIfInventory("SwitchCheckerSL",3,"SelectMarine")
TNT1 A 0 A_JumpIfInventory("SwitchCheckerSL",2,"SelectCyborg")
TNT1 A 0 A_JumpIfInventory("SwitchCheckerSL",1,"SelectSlayer")
//Стэйт можно вообще не закрывать
//А далее ставим 3 соответствующих кастомных Select-стэйта:
SelectMarine:
СПРАЙТЫ_ПИСТОЛЯ_МАРИНА A 1 A_Raise
Loop
SelectCyborg:
СПРАЙТЫ_ПИСТОЛЯ_КИБОРГА A 1 A_Raise
Loop
SelectSlayer:
СПРАЙТЫ_ПИСТОЛЯ_СЛЭЙЕРА A 1 A_Raise
Loop
Ready: //Снова клепаем общий стэйт проверки классов, но теперь уже для Рэди стэйта
TNT1 A 0 A_JumpIfInventory("SwitchCheckerSL",3,"ReadyMarine")
TNT1 A 0 A_JumpIfInventory("SwitchCheckerSL",2,"ReadyCyborg")
TNT1 A 0 A_JumpIfInventory("SwitchCheckerSL",1,"ReadySlayer")
//Аналогично ставим 3 соответствующих кастомных Ready-стэйтов:
ReadyMarine:
СПРАЙТЫ_ПИСТОЛЯ_МАРИНА A 1 A_WeaponReady
Loop
ReadyCyborg:
СПРАЙТЫ_ПИСТОЛЯ_КИБОРГА A 1 A_WeaponReady
Loop
ReadySlayer:
СПРАЙТЫ_ПИСТОЛЯ_СЛЭЙЕРА A 1 A_WeaponReady
Loop
Аналогично с Fire стэйтом (и всеми другими, включая Deselect), но там надо учитывать в какой стэйт будет возвращаться оружие после выстрела (A_ReFire).
Надеюсь схема понятна, и теперь ты видишь что не всё так просто как могло показаться, да и как правильно заметил MyNameIs в твоём случае просто нет такой необходимости.
Зато будет полезная практика если доделаешь.
Добавлено спустя 1 день 18 часов 50 секунд: //==========================//
1. Я правильно понимаю что из анон ф-ции невозможно прописать такие джампы как A_CheckLOF, A_CheckFlag, A_JumpIfHealthLower(по поинтеру кроме DEFAULT), A_JumpIfTargetInLOS, A_CheckSpecies, A_Warp, A_Teleport и другие?
-----------------------
2. Этот вопрос отпадает если по всем ф-циям первого вопроса ответ утвердительный. Можно ли внутри анон ф-ции записать инкрементальный цикл с джампом из него, например цикл увеличивающий на 1 значение угла в A_CheckLOF и завершающийся джампом по достижению значения угла в 360?
Иными словами, можно ли упаковать такое:
Скрытый текст:
TNT1 A 0 A_SetUserVar("user_CLOFangle",0) //setting of uservar initial value
CLOFCircleA:
TNT1 A 0 A_CheckLOF("ChargeEND",CLOFF_JUMPENEMY|CLOFF_JUMPFRIEND|CLOFF_JUMPOBJECT|CLOFF_JUMPNONHOSTILE|CLOFF_MUSTBESOLID|CLOFF_JUMP_ON_MISS|CLOFF_ALLOWNULL|CLOFF_CHECKPARTIAL,Radius+25,0,user_CLOFangle,0,20,0,AAPTR_DEFAULT,0) //uservar assignment to CheckLOF angle
TNT1 A 0 A_SetUserVar("user_CLOFangle",user_CLOFangle+1) //1 degree uservar increasement
TNT1 A 0 A_JumpIf(user_CLOFangle==360,"StepB") //360 degrees uservar check, then jumping out of loop
Goto CLOFCircleA
внутрь анонки?
-----------------------
3. Имеется 7 разных токен-итемов:
Actor A : Inventory {Inventory.MaxAmount 1}
Actor B
Actor C
Actor D
Actor E
Actor F
Actor G
Необходимо получить все возможные джампы по соответствующим комбинациям всех токенов исключая повторы, т. е. чтобы при наличии A+B+C+D+E+F+G был один джамп, совсем другой при A+B+C+D+E, третий - при наличии F+G+B+C, и так все возможные комбинации. Очевидно что A_JumpIfInventory тут совершенно не уместна и необходимо юзать анонку вида If(CountInv("A")==1||CountInv("B")==1||...).
Собс-но вопросы к шарящим в матике и оптимизации:
1) Можно ли записать эти чеки как-то ещё более ёмко\рационально?
2) Сколько вообще получится комбинаций и как это всё записывать чтобы ни глаза не вытекли ни мозг не лопнул? От больших к меньшим полагаю, или не?
-----------------------
4. Кто-нибудь знает специфику гибридных акторов (монстр-миссиль например)? Или это можно только выяснить кропотливыми экспериментами и дотошным лурчанием по форумам?
Скриптов не предлагать.
It is possible to use an A_Jump-type function inside the condition part of the if statement. The jump will not happen, but if it would have, the condition is considered as true.
То есть, можно написать
TNT1 A 0 {
if (A_CheckLOF("ChargeEND",CLOFF_JUMPENEMY|CLOFF_JUMPFRIEND|blah-blah-blah...,AAPTR_DEFAULT,0)) {
return state("ChargeEND"); //описано чуть выше на той же странице
}
return state("");
}
Если что, я не тестил.
3. 2^7 = 128 комбинаций (каждого актора может быть либо ноль, либо один). Можно сделать
Actor M: Inventory {Inventory.MaxAmount 127} //0, 1, 2, ..., 127 --- 128 чисел
и потом загонять комбинации в двоичную запись (например, A будет соответствовать 64, B --- 32, C --- 16... G --- 1) и проверять CountInv на точное равенство (ещё лучше попробовать switch/case, он должен работать в decorate):
switch(CountInv("M")) {
case 0: //пусто
return state("State0");
break;
case 1: //G
return state("State1");
break;
...
case 127: //ABCDEFG
return state("State127");
break;
}
Только после этого нужно аккуратно работать с выдачей и отбором предметов.
Как записывать, чтобы глаза не вытекли? Чёрт его знает. А ты точно уверен, что тебе нужны эти 128 вариантов, и разбор каждого из них будет существенно отличаться от другого?
Ещё, как вариант, можно сделать
TNT1 A 0 A_Jump(256,1 + CountInv("M"))
TNT1 A 0 A_Jump(256, "State0")
TNT1 A 0 A_Jump(256, "State1")
...
TNT1 A 0 A_Jump(256, "State127")
Но все эти методы индусские. Нужны детали, в том числе информация о том, для какой цели эти джампы будут использоваться.
4. Акторы, у которых одновременно стоят Monster и Projectile/+MISSILE, что ли? Вряд ли кто-то прописывал в движке специальный разбор таких случаев (если вообще такой актор может быть создан). Здесь, кажется, вариантов действительно немного, могу только предложить в особенно запутанных случаях смотреть код gzdoom (по той же ссылке есть zscript-исходники из gzdoom.pk3, куда очень много логики перенесено, но их не предлагаю ).
А ты точно уверен, что тебе нужны эти 128 вариантов, и разбор каждого из них будет существенно отличаться от другого?
Собс-но это одна большая заготовка, шаблон "на все случаи"; я вот только не понял откуда столько вариантов?! Чё-т шибко дофига получается, тем более что в счёт идут только тру-комбинации.
Не понял... вообще. o_0
Ну как бы в думе имеется 7 подбираемых волын и надо обеспечить джампы в зависимости от возможных наличествующих пушек. Т. е. если есть пистоль то джамп на "А", если же компанию пистолю составляет РЛаунчер то джамп на "Д", ну и так все возможные комбинации.
4. Ну да, именно такие комбинации и схожие. На удивление используется не так уж редко (лично юзал), при этом открывает доступ к весьма интересному поведению. Ок, будем искать моар.
Ну так если смотреть со стороны, то пистолета может быть, а может не быть --- две возможности; дробовика может быть, а может и нет; ... BFG также может иметься, а может и отсутствовать. Причём эти наличия/отсутствия независимые друг от друга.
Можно для наглядности просто в строчку записать 7 нулей/единиц, например, так: "1010110" --- есть пистолет, ssg, rl, плазма. Эта двоичная запись соответствует десятичному числу 64 + 16 + 4 + 2 = 86. Вот в стейте State86 можно и разобрать этот случай.
Что такое "тру-комбинации"?.. Не понимаю.
Ну так я в предыдущем посте как раз написал пример. Switch/case --- узкоспециализированная конструкция, созданная ровно для подобного разбора случаев. Синтаксис аналогичен C/C++, все детали гуглятся одним кликом.
В первой строчке я считаю, сколько у меня акторов типа M в инвентаре, и считаю offset, на который нужно сделать первый прыжок (прибавляя 1, поскольку иначе при CountInv == 0 произойдёт рекурсия, которая не входит в наши планы). Следующие 128 строчек (их можно сгенерировать чем угодно, не вручную же писать) --- это собственно джампы.
Ну так если смотреть со стороны, то пистолета может быть, а может не быть --- две возможности; дробовика может быть, а может и нет; ... BFG также может иметься, а может и отсутствовать. Причём эти наличия/отсутствия независимые друг от друга.
Это когда общая проверка JumpIf(CountInv("SSGmark")==1 && CountInv("RLmark")==1 && CountInv("BFGmark")==1) возвращает "TRUE" и так для всех 7 пушек, а всеми теми вариантами когда возвращается "FALSE" можно пренебречь, ибо после них будет один и тот же Goto, а вот каждый "тру" должен прыгать в уникальный стэйт.
Может быть, для твоей цели достаточно не разбирать каждую комбинацию отдельно? Иначе я не понимаю, что тут дальше оптимизировать
В общем же суть в том чтобы монстр менял пул доступных ему атак в зависимости от пула же подобранного оружия, идею чего я уже описывал в соотв. теме форума. Я хз что тут можно оптимизировать, но проверка выходит очень громоздкая, вот и интересуюсь какой вид записи будет наиболее оптимален.
1. Можно ли средствами GZDoom сделать "бесконечный океан" с использованием Line_Horizon и прозрачного 3d-пола, чтобы в него мог погружаться игрок? Может, есть вады с примерами? Увеличение размера карты мне не подойдёт.
Туда же: как сделать равномерное течение 3d-пола, уносящее актора, его касающегося, но не обязательно стоящего на дне?
2. Можно ли с текущим GZDoom получить более-менее адекватное "интерполяционное" движение актора (камеры) через секторные порталы с помощью InterpolationPoint? Интересно послушать и про линии, но менее важно. Сейчас пробую сделать вершинами интерполяции соответствующие точки на порталах (пересечение траектории с плоскостью портала), а между ними установить бесконечную скорость, но это, естественно, влияет на сплайны (вектор скорости-то считается без учета порталов), и картинка дёргается.
Если есть возможность обойти ограничения движка, скажите.
1. "Бесконечный" это такой в секторе которого можно вечно плыть в одну сторону без остановки и преткновений в блоклайн мапы? Если это именно оно, то мб попробовать "зациклить" Sector_Set3dFloorтелепортлайном или аналогичным экшеном? Правда если это реально, то надо будет как-то считать ко-во совершённых телепортов в одну сторону, чтобы для реалистичности совершить столько же проходов при движении в обратную.
Не уверен, но тут похоже тред с аналогичным вопросом.
И вновь доброго времени суток, уважаемые Думеры.
Благодарю всех тех, кто откликнулся на мою проблему, кто предложил свои варианты разрешения вопроса - я чрезвычайно вам благодарен
Я внимательно (в пределах своих возможностей и DECORATE-планирования) изучал предложения MyNameIs и Void Weaver. Именно второе решение мне позволило стремительно продвинуться в моей задумке и как минимум воплотить самый минимум задуманного.
Оружие осталось прежним, спрайты переключаются.
Но, к несчастью для меня, появились новые проблемы:
1) звуки бензопилы теперь работают некорректно (нет даже жужжания во время простоя в инвентаре);
2) почему-то при поднятии обычного рюкзака на HUD панели сразу пропадает и лицо класса игрока, и шкала для бензопилы, которую я сделал отдельно по типy "interpolate verical scale".
Эти два огреха появились после того, как я решил перенести все свои подключаемые отдельные *.wad, *.pk3 файлы в единый *.pk3 файл. Не уверен, вызвано ли это тем, что теперь ZScript и Decorate временно соседствуют бок о бок. В дальнейшем я планирую переписать всё на ZScript.
И если с первым у меня ещё есть идеи, как быть, то со вторым я подошёл в тупик.
Я начал изучать проблему в поисках причины - смотрел свой код по всем файлам внутри архива, особенно SBARINFO (как ни странно, если его на время убрать, возвращается старая безглючная информационная панель).
Может ли кто помочь мне разобраться с данными симптомами? Или хотя бы примерно направить, куда стоит копнуть. Благодарю за внимание.
UPD1: прошу прощения, что потревожил, но проблема с исчезающим лицом на HUD решилась следующим образом:
в файле SBARINFO на 43 строке кода я заменил отображение панели с топливом бензопилы на следующее содержание:
в псевдорандоме следующее значение конкретно определённым образом основывается на предыдущем, которое называется "seed" — и подставляя его, можно влиять на сохраняемость рандома.
А где хранится(откуда считывается) этот самый seed? Ну если конечно можно кратко и "на пальцах"?
В самом думе по идее при использовании оператора random[...]() или frandom[...]() оно хранится автоматом где-то там в сейве.
Но если вдруг не хранится (кто их знает) то всегда можно руками рандом сделать.
1. Это случаем не оно: SetRandomSeed?
2. И если да, то где можно глянуть пример использования?
2.1 Это только для скриптов?
3. Нифига не понял что за "identifier", почему он опционален и как его применять:
[identifier] is optional. Calls to a random function with an identifier do not interfere with the RNG for calls with a different identifier, which can be used to make the outcome of some events unaffected by others.
Оно, но я не это имел в виду. По идее значение разных random[...] должно сохраняться автоматически. С точки зрения моддера достаточно убедиться, что он использует уникальное значение [...] для операций, которые должны быть повторяемыми после загрузки.
Не читал весь диалог, но если цель "сделать чтобы рандом нельзя было заабузить сейвами, и твой мод умел детектить факт загрузки сейва и после этого менял рандом", я это реализовывал через CVAR-ы
Вопрос по обычному ванильному геймплею: при работе над балансом патронов стоит ли учитывать наличие на карте шотганнеров и чейнганнеров и класть меньше шеллов и патронов, полагая, что игрок всё равно наберёт нужное количество патронов с трупов?
Вопрос по обычному ванильному геймплею: при работе над балансом патронов стоит ли учитывать наличие на карте шотганнеров и чейнганнеров и класть меньше шеллов и патронов, полагая, что игрок всё равно наберёт нужное количество патронов с трупов?
На мой дилетантский геймерский взгляд:
1) Нужно учитывать - Если чейнганнеры/сержанты находятся в пределах легкой доступности. (то есть, трупы легко обобрать)
2) Не нужно учитывать - Если чейнганнеры/сержанты находятся на возвышениях/в нишах. Либо если эту братву прикрывает эквивалентное число тяжелых монстров (бароны/манкубусы/ревенанты)
Вопрос по обычному ванильному геймплею: при работе над балансом патронов стоит ли учитывать наличие на карте шотганнеров и чейнганнеров и класть меньше шеллов и патронов, полагая, что игрок всё равно наберёт нужное количество патронов с трупов?
Вообще странная постановка вопроса... Стоит\не стоит зависит ТОЛЬКО от того как ты сам склонен позиционировать сложность своей карты. Соотв. если мапа ориентирована на:
а) осторожного\экономного игрока то нужно учитывать наличие дроп-амуниции.
б) расслабленный геймплэй, то наличием дроп-амуниции можно и пренебречь.
1. Решил написать своего рода "Ауру Тьмы", визуальная часть которой основана на субтрактивном динлайте, но возникли некоторые проблемы.
Во-первых, динлайт не "чернит" поверхности находящиеся под углом к вектору освещения ("затемнения" в моём случае):
В то же время, к актору носителю Ауры также привинчен обычный фиолетовый динлайт, но к сожалению он не отображается "на фоне" чёрного. Вместо этого он просто ведёт себя как обычный динлайт: подсвечивает только физические поверхности:
Собс-но вопросы:
1) Возможно ли сделать так чтобы чёрный свет равномерно затемнял все поверхности в радиусе?
2) Возможно ли сделать так чтобы цветной динлайт светился на фоне чёрного аки фонарь или это невозможно из-за ограничений двиги?
Акторы Ауры:
Скрытый текст:
Actor Smth_AuraOfDarkness
{
+NOTIMEFREEZE
+RANDOMIZE
+NOGRAVITY
-BRIGHT
RenderStyle Add
Alpha 0.55
Scale 0.45
States
{
Spawn:
TNT1 A 0 NoDelay A_SpawnItemEx("Smth_SubAuraOfDarkness",0,0,0,0,0,0,0,SXF_NOCHECKPOSITION|SXF_SETMASTER)
SpawnL:
PLS2 AB random(1,4)
{
A_Light(-20);
A_Warp(AAPTR_MASTER,frandom(-0.25,0.25),frandom(-0.25,0.25),Height*2+14,0,WARPF_NOCHECKPOSITION|WARPF_INTERPOLATE);
}
Loop
Death:
TNT1 A 0
Stop
}
}
Actor Smth_SubAuraOfDarkness
{
+NOINTERACTION
+NOTIMEFREEZE
+RANDOMIZE
+NOGRAVITY
-BRIGHT
States
{
Spawn:
TNT1 AB random(1,4)
{
A_Light(10);
A_Warp(AAPTR_MASTER,frandom(-0.25,0.25),frandom(-0.25,0.25),Height*2+14,0,WARPF_NOCHECKPOSITION|WARPF_INTERPOLATE);
}
Loop
Death:
TNT1 A 0
Stop
}
}
2. Возможно ли на декоре задать переменную или какой-то кастомный множитель который бы прямопропорционально базировался на дистанции до источника звука или динлайта?
Т. е. чтобы работал так: чем ближе к источнику света\звука, тем выше значение (урон например).
Один чел посоветовал мне просто юзать рассеивание урона A_Explode, но мне это не очень подходит поскольку точная формула не известна + нет возможности динамично регулировать это значение. Плюс радиус динлайта\взрыва будет увеличиваться с уровнем Ауры (из вопроса выше^).
На данный момент я использую примерно следующую костыльную "лесенку":
Здравствуйте, товарищи думгаи и думгерлы!
Как в zscript проверить, есть ли у моего актора перед носом какое-либо твердое препятствие? Актор является оружием, не прожектайлом, если что. (Делаю метательное оружие, хочу, чтобы если перед ним стенка или твердый предмет, то оно висело в воздухе ("воткнулось"), а если нет, - то падало. И чтобы его можно было подобрать с пола либо вытащить из стенки.)
axredneck Если тебе это надо именно на зскрипте то полагаю надо начинать с чека по всемогущей LineTrace.
Хотя Юра таки прав и вся задача также изи делается и на декоре, но явно не способом предложенным выше. Практически только что пилил очень похожий реквест:
Скрытый текст:
Actor IronBolt //: FastProjectile
{
Radius 2
Height 2
Scale 0.5
Speed 36
Damage (Random(4, 12))
SeeSound "misc/shot"
DeathSound "misc/shotx"
PROJECTILE
+DONTREFLECT
+NOEXTREMEDEATH
+MOVEWITHSECTOR
+RIPPER
+THRUGHOST
-ACTIVATEIMPACT
-ACTIVATEPCROSS
States
{
Spawn:
//HSHT A 0 NoDelay A_ChangeVelocity(136,0,0,CVF_RELATIVE|CVF_REPLACE)
SpawnL:
HSHT A -1
Death:
Crash:
TNT1 A 0 A_PlaySound("Weapons/NailHitFlat")
Goto ArrowSticks
XDeath:
TNT1 A 0 A_PlaySound("Weapons/NailHitBleed")
Goto ArrowSticks
ArrowSticks:
TNT1 A 0 A_ChangeFlag("NOCLIP",1)
HSHT AA 1 A_ChangeVelocity(1,0,0,CVF_RELATIVE|CVF_REPLACE)
HSHT A 1 A_Stop
TNT1 A 0 A_ChangeFlag("NOCLIP",0)
TNT1 A 0 A_SpawnItemEx("IronBoltWall",-10,0,0,1,0,-1,0,SXF_SETMASTER|SXF_ORIGINATOR)
POSS A -1 A_CheckFloor("Remove")
Stop
Remove:
TNT1 A 0
Stop
}
}
Actor IronBoltWall
{
radius 5
height 5
scale 0.5
Speed 0
damage 0
renderstyle translucent
alpha 1.0
Projectile
-ACTIVATEIMPACT
-ACTIVATEPCROSS
+fixmapthingpos
+forcexybillboard
+movewithsector
+notautoaimed
+thruactors
+ghost
states
{
Spawn:
HSHT A 1
HSHT A 0 A_Warp(AAPTR_MASTER,-10,0,0,0,WARPF_INTERPOLATE,"Spawn")
//HSHT A 0 A_RearrangePointers(AAPTR_DEFAULT,AAPTR_NULL,AAPTR_DEFAULT)
//HSHT A 0 A_ChangeVelocity(0,0,-1.5,CVF_RELATIVE|CVF_REPLACE)
FallL:
HSHT A 1
Loop
Death:
TNT1 A 0
Stop
}
}
Соответственно вместо IronBoltWall должно спауниться твоё метательное копьё-Weapon а не Projectile и главное чтобы в нём не было флага THRUACTORS. Т. е. в твоём случае должно получаться что IronBoltWall при броске на самом деле запускает IronBolt, а IronBolt при попадании в ноншутэбл объект спаунит подбираемый\вытаскиваемый IronBoltWall и так по кругу.
Мне кажется тут сложность в том чтобы топор не втыкался в монстров и вообще во всё то, что не только твёрдое, но и движется (у нас даже стена может внезапно подвинуться, если это полиобъект, а топор останецца висеть в воздухе).
Поэтому + к скрипту, но писать конечно же не буду ) Во всяком случае прям щас с утра.
Предложенный вариант был запилен именно для того чтобы учитывать внезапное движение дверей и лифтов. В нём всё воткнутое отваливается при движении "фундамента".
Но офк зскрипт подходит больше ибо выполняет ту же задачу корректней и глаже.