Так не скомпилируется, поскольку в списке-инициализаторе можно указывать только константы. Зачем тебе эти посредники? Если тебе потребуется обращаться к элементам массива, можно использовать такую нотацию, как у меня в скрипте:
//заменить слот 1 на пистолет
cells[0] = 2;
//проверить, есть ли в слотах плазмаган
bool hasPlasma = false;
for (int j = 0; j < 5; ++j) {
if (cells[j] == 6) {
hasPlasma = true;
}
}
//...
Это значительно удобнее синтаксически, чем куча переменных, в названиях которых легко сделать опечатку.
Void Weaver То, что ты написал, более похоже на DECORATE, чем на ACS. В ACS "var" не используется, префикс "user_" не требуется (кстати, и в ZSCRIPT тоже), в третьей строке int не нужен.
Doomgay1999 Audacity, по-моему, раньше по теме советовали, попробуй там в меню выбрать "Effect" -> "Reverse".
1. Как отключить для всех карт в ваде (при помощи acs, декорейта или зскрипта) покачивание камеры?
Пытался на acs делать при начале каждой карты (пытался и через ENTER и потом через OPEN) смену цвара игрока - movebob на 0, не помогло
2. Как сделать тёмный дым (rgb: r = 0, g = 0, b = 0) на всех секторах и чтобы он был виден? Т.к. через Sector_SetFade(0, 0, 0, 0) не получается.
+3. Как сделать чтобы дамаг у оружия зависел от расстояния к врагу? (чем ближе, тем мощнее) (хитскан)
1. А зачем так жёстко ес не секрет? Мувбоббинг спокойно же отключается в опциях гоззы даже без консоли.
3. Изи. Вот например пистоль с двумя вариантами корреляции урона от дистанции:
Actor PistFP : Pistol replaces Pistol
{
Weapon.SlotNumber 2
Weapon.SlotPriority 1
States
{
Fire:
PISG A 4
PISG B 0 A_FireBullets(5.6,0,1,0,"MyBulletPuff",FBF_USEAMMO|FBF_NORANDOMPUFFZ)
PISG B 0 A_PlaySound("weapons/pistol",1)
PISG B 6 A_GunFlash
PISG C 4
PISG B 5 A_ReFire
Goto Ready
}
}
Actor MyBulletPuff : BulletPuff
{
Height 1
Radius 1
+FORCERADIUSDMG
+PUFFGETSOWNER
+PUFFONACTORS
var float user_DmgPerDistance;
States
{
XDeath:
TNT1 A 0 A_ChangeFlag("ALLOWPARTICLES",0) //Чтобы вместе с кровью не спавнились серые партикли
TNT1 A 0 {user_DmgPerDistance=GetDistance(1)-8;} //8 это дефолтный радиус думгая, в идеале значение берётся по скрипту или счёту токенов
//TNT1 A 0 A_Explode(user_DmgPerDistance,1,XF_EXPLICITDAMAGETYPE,0,1) //Урон растёт по мере увеличения дистанции до цели
TNT1 A 0 A_Explode(1000/user_DmgPerDistance,1,XF_EXPLICITDAMAGETYPE,0,1) //Урон растёт по мере уменьшения дистанции до цели
Stop
}
}
В принципе аналогичный, более изящный трик можно провернуть на АЦС\ЗСкрипт измерив дистанцию непосредственно между игроком и целью в прицеле и записав это значение как множитель урона прямо в A_FireBullets.
States
{
Death:
TNT1 A 0 A_ChangeFlag("ALLOWPARTICLES",0)
TNT1 A 0 {user_DmgPerDistance=GetDistance(1)-8;}
//TNT1 A 0 A_Explode(user_DmgPerDistance,1,XF_EXPLICITDAMAGETYPE,0,1)
TNT1 A 0 A_Explode(1000/user_DmgPerDistance,1,XF_EXPLICITDAMAGETYPE,0,1)
Stop
XDeath:
TNT1 A 0 A_ChangeFlag("ALLOWPARTICLES",0)
TNT1 A 0 {user_DmgPerDistance=GetDistance(1)-8;}
//TNT1 A 0 A_Explode(user_DmgPerDistance,1,XF_EXPLICITDAMAGETYPE,0,1)
TNT1 A 0 A_Explode(1000/user_DmgPerDistance,1,XF_EXPLICITDAMAGETYPE,0,1)
Stop
}
}
В принципе аналогичный, более изящный трик можно провернуть на АЦС\ЗСкрипт измерив дистанцию непосредственно между игроком и целью в прицеле и записав это значение как множитель урона прямо в A_FireBullets.
Лично у меня всё работает, вплотную импов и зомб валит с 1 шота, причём зомб гарантировано рвёт в мясо.
Скорее всего у тебя не получается поскольку ты прописал Death стэйт, убери его - он не нужен. Спаун пуффа на нон-шутэбл объектах определяется родительскими стэйтами БуллетПуффа.
Если же ты просто не ощущаешь эффекта то просто выстрели в моба вплотную. В любом случае это '1000/user_DmgPerDistance' формула навскидку, т. е. ты должен сам подобрать формулу желаемой корреляции; мб. нечто более комплексное типа: 1000/(user_DmgPerDistance-1)+1.
И вообще, для демонстративности работоспособности данной механики лучше было сначала заценить прямопропорциональную корреляцию 'A_Explode(user_DmgPerDistance,1,XF_EXPLICITDAMAGETYPE,0,1)' - в этом случае эффект будет куда заметнее.
Бтв, '|FBF_NORANDOM' не нужен в A_FireBullets поскольку урон там нулевой, а значит и множитель random(1,3) будет обнулён.
1. Как отключить для всех карт в ваде (при помощи acs, декорейта или зскрипта) покачивание камеры?
Пытался на acs делать при начале каждой карты (пытался и через ENTER и потом через OPEN) смену цвара игрока - movebob на 0, не помогло
Тогда лучше выполнять A_CheckFlag("ISMONSTER","XDeath",AAPTR_TRACER) в генерализированном Spawn, чтобы при попадании по монстру конструкция гарантированно срабатывала.
N00b2015 Void Weaver железо поломалось, только сейчас отвечаю. СПАСИБО! Но, я не понял моменты в скриптах, которые вы написали, потому сел смотреть за массивы, ибо здвики например умалчивает, что значит строка array[0] = x;
сейчас вроде понятно более-менее кроме вот такого синтаксиса.
(int j = 0; j < 5; ++j
первая часть строки ясна, но зачем ++j; --j ? Это вроде называется пре-ин/декремент, и в моем понимании делает что-то типа j++; delay(1); но как бы одновременно, до того как поменяется условие, блин что я такое сказал
но зачем ++j; --j ? Это вроде называется пре-ин/декремент, и в моем понимании делает что-то типа j++; delay(1);
Не знаю, есть ли разница в ACS/ZScript, но в C/C++ такая конструкция работает БЫСТРЕЕ, чем j++, j--.
Потому что производит непосредственное увеличение переменной "in situ", без предварительной ее загрузки в регистр процессора. Кажется, как-то так.
И вместо ТРЁХ операций (загрузка в регистр, инкремент, выгрузка обратно в память), мы получаем ОДНУ (инкремент значения, находящегося непосредственно в памяти).
INC <операнд>
DEC <операнд>
(операндом может быть регистр или ячейка памяти любого размера)
Кроме того, значением выражения "j++" будет измененное на +1 значение переменной, а выражения "++j" - неизмененное (j).
По привычке написал ++j. Причина привычки верно изложена VladGuardian-ом. Однако учитывая, что этот цикл будет далеко не самым ресурсоёмким при работе такой крупной программы, как gzdoom, можно этот пре-инкремент смело заменять на пост-инкремент j++. Разницы ощущаться не будет никакой (особенно учитывая нагрузку от сложных игровых объектов).
Единственная функциональная разница между ++j и j++ --- возвращаемое значение:
int a = 23;
int b = a++;
//теперь a == 24, b == 23
int c = 14;
int d = ++c;
//теперь c == 15, d == 15
Zeberpal_98 Эта запись означает следующее:
1. Присвоить j значение 0.
2. Если j < 5, перейти к пункту 3. Иначе завершить выполнение.
3. Выполнить внутренние команды цикла для текущего j.
4. Увеличить j на 1, перейти к пункту 2.
Void Weaver Сначала происходит проверка индекса, затем выполняется код внутри, затем индекс увеличивается. После этого индекс опять проверяется, и так далее. Для j == 0 условие верно, так что cells[0] заведомо будет проверен.
я не понимал, что происходит, поэтому для себя решил расписать. Посмотрите пожалуйста, все ли верно?
int cells[5] = {3, 7, 4, 5, 6};
script "ShiftCellsRight" (void)
{
int temp = cells[4]; // temp это оружие Плазма в данном случае
for (int i = 4; i > 0; --i) //дано: (i это все между 1 и 4 включительно) // но зачем в таких случаях --i;++i;i--;i++ если уже вроде дано указание взять отрезок с 1 по 4?
{
cells[i] = cells[i - 1]; //cells[ячейки 1 по 4] = cells[[ячейки 1 по 4] - 1 позиция]
}
cells[0] = temp; // первая ячейка = старая пятая. Вопрос, но остальные же тоже направо сдвинулись? cells[i - 1] это оно?
}
//заменить слот 2 на пистолет
cells[0] = 2;
//проверить, есть ли в слотах плазмаган
bool hasPlasma = false;
for
(
int j = 0;j < 5; ++j) // j это все между 0 включительно и 4
{
if (cells[j] == 6) //если в ячейках[1,2,3,4,5] есть плазма
{
hasPlasma = true; //то она там воистину
}
}
// но зачем в таких случаях --i;++i;i--;i++ если уже вроде дано указание взять отрезок с 1 по 4?
Фактически нотация
for (A; B; C) {
D;
}
работает как
A;
while (B) {
D;
C;
}
A --- инициализация, B --- условие продолжения, C --- переход к новой итерации, D --- "полезная работа" цикла.
В примере выше A = "int i = 4", B = "i > 0", C = "--i", D = "cells[i] = cells[i - 1]".
В качестве C может быть написано и "i += 2" (пройтись вперёд по индексам той же чётности), и "i /= 2", что угодно программисту. Условие B вообще может быть не связано с переменной-счётчиком i. Что-то из A, B, C и D вообще может быть пустым.
Такая запись цикла даёт программисту значительно большую свободу действий, чем паскалевское
//cells[ячейки 1 по 4] = cells[[ячейки 1 по 4] - 1 позиция]
Давай распишем пошагово действия скрипта.
Запоминаем в temp значение последней клетки.
Присваиваем i значение 4.
i > 0? Да, выполняем внутренность цикла.
Присваиваем cells[4] значение, стоящее в cells[3]. cells теперь выглядит как {3, 7, 4, 5, 5}.
--i, теперь i равно 3.
i > 0? Да.
Присваиваем cells[3] значение, стоящее в cells[2]. cells теперь выглядит как {3, 7, 4, 4, 5}.
--i, теперь i равно 2.
i > 0? Да.
...
Присваиваем cells[1] значение, стоящее в cells[0]. cells теперь выглядит как {3, 3, 7, 4, 5}.
--i, теперь i равно 0.
i > 0? Нет! Выходим из цикла.
Ставим в первую (cells[0]) клетку сохранённое значение temp.
Итого имеем cells вида {6, 3, 7, 4, 5}.