Это гарантированный жёпп для несчастного моба - он будет залочен в пэйн стэйте даже с учётом пустых тнт1. Я уже сталкивался с такой шнягой когда эмулировал лайтнинг энчантед моба (100% шанс стрельнуть снаряд при ударе по мобу), но с таким не забалуешь - хочешь жить придётся приостанавливать огонь. В случае же вгона моба в пэйн со 100%-ым шансом без риска для здоровья, ни враждебный моб ни игрок останавливаться не будут, и братишка бесславно сдохнет не выходя из псевдопэйна (даже с учётом того что периодически будет эвэйдить урон).
Пожалуй лучше сделать инверсивно: PainChance 76 (около 30%) а уж в нём прописать джамп в альт-стэйт бога с шансом под ~85% что виртуально даст как раз около 25%.
Герр Смертоносец:
Насколько часто это делать - вопрос философский. Я считаю, что достаточно одной сверки на выходе из стейта Pain, но для надежности можно делать это при каждом проходе стейта See.
Собсно это меня и беспокоит. Получается что моб может эвэйдиться только в сии стэйте, и то только при начале цикла, что при учёте огромного ко-ва кадров дьябло-монстров означает практически нулевой шанс. В оригинале же эта фича могла активироваться в любом стэйте. Блин, хуйню сморозил. Но A_SetUserVar таки придётся копипастить во все кадры. (
Герр Смертоносец:
Здесь даже ACS не нужен - просто A_SetHealth(user_currenthealth)
Да, я уже допёр с твоего прошлого поста, данке. ^_^
Добавлено спустя 34 минуты:
Бтв, ща пришла мысль что абилка моба будет ломаться ПЭЙНЛЕСС атаками.
Добавлено спустя 1 день 1 час 23 минуты 10 секунд:
Shadowman
Void Weaver:
Скрытый текст:
Shadowman:
Void Weaver:
PoisonDamage value[, duration[, period]]
value: Значение урона, наносимого каждый раз по прошествии количества тиков заданных в "period".
duration: Значение (в у. е.) задающее общее количество вызовов урона. Т. е. отвечает за то, сколько раз в итоге яд стукнет.
period: Количество тиков между вызовами ядовитого урона. Дефолтное значение 0 означает вызов раз в секунду, т. е. period(0) = period(35).
Все это здорово, но под такой яд нельзя соорудить противоядие (используемый айтем вроде бутылки здоровья, только снимает эффект яда). Также не совсем понятно, можно ли настроить в этом случае "зеленую ауру" на экран при отравлении.
У меня тоже нет мыслей как прервать действие PoisonDamage яда. Возможно яд на А_Дэмэдж ф-циях прервать куда реальнее. Через какой-нибудь хитрый ДжампИфИнвентори с вызовом скрипта-прерывателя.
Кое-какие соображения по поводу антидота:
1. Способ применения антидота.
а) "превентивный" - заюзал и получил временный иммун к яду. Но комментс.
б) прерывающий (классический) - заюзал и отравление остановлено.
2. Тип яда.
а) на PoisonDamage свойстве.
б) на A_Damage%% ф-ции.
Поскольку интерес представляет антидот-б, то предположения следующие: в идеале было бы чекать ДэмэджТайп получаемого урона и уже производить какое-либо действие, но такой возможности в декоре вроде нет, поэтому можно попробовать следующее:
а) заюзанный антидот выдаёт игроку кастомитем с A_Remove (AAPTR_(зависит от ф-ции А_Дэмэдж),0,"акторкласс яда") - полагаю что убьёт яд ЕСЛИ А_Дмг вызывалась в Дэс стэйте ядо-актора. Есть опасение что также будет ремувиться отравленный актор. :/
б) сопровождать столкновение яд-актора с игроком выдачей "маркер"-итема ("PoisonMark" например), а заюзанный антидот будет выдавать яд-актору итем ("Detox" например), включающий оному актору кастом стэйт смерти. Как-то так:
Скрытый текст:
Actor Poison
{
States
{
Spawn:
...
Loop
Death:
TNT1 A 1 A_GiveInventory ("PoisonMark")
TNT1 A 0 A_JumpIfInventory ("Detox",1,"Detoxed")
TNT1 A 35 A_Damage%% (x,"Poison")
TNT1 A 0 A_JumpIfInventory ("Detox",1,"Detoxed")
TNT1 A 35 A_Damage%% (x,"Poison")
TNT1 A 0 A_JumpIfInventory ("Detox",1,"Detoxed")
...
Stop
Detoxed:
TNT1 A 0
Stop
Actor Antidote : CustomInventory
{
+Inventory.AutoActivate
+Inventory.AlwaysPickup
Inventory.MaxAmount 0
States
{
Spawn:
TNT1 A 1
Loop
Pickup:
TNT1 A 0 A_GiveInventory ("Detox")
Stop
======
в) в случае с PoisonDamage ядом также сопровождать столкновение яд-актора с игроком выдачей "маркер"-итема ("PoisonMark" например), а заюзанный антидот будет чекать "PoisonMark" и при наличии итема выдавать яд-актору итем ("Detox" например), включающий оному актору кастом стэйт с A_SetDamageType ("Detoxed"), причём у игрока должен быть заранее прописан DamageFactor "Detoxed", 0.0.
Скрытый текст:
Actor Poison
PoisonDamage 1,100,7
{
States
{
Spawn:
ABCD ABCDE 1 A_JumpIfInventory ("Detox",1,"AutoDetoxed")
Loop
Death:
TNT1 A 1 A_GiveInventory ("PoisonMark")
Stop
AutoDetoxed:
TNT1 A 1 A_SetDamageType ("Detoxed")
Stop
Actor Antidote : CustomInventory
{
+Inventory.AutoActivate
+Inventory.AlwaysPickup
Inventory.MaxAmount 0
States
{
Spawn:
TNT1 A 1
Loop
Pickup:
TNT1 A 0 A_JumpIfInventory ("PoisonMark",1,"Detoxicate")
Stop
Detoxicate:
TNT1 A 0 A_GiveInventory ("Detox")
Stop
Но возможно ни один вариант не взлетит, надо проверять. Отпишись если какой сработает.
Зыс ван. Условие тривиальное - при столкновении моба с чьим-то кулаком или маслиной с Х% шансом входит в кастом стэйт и игнорит текущий входящий урон. Со снарядами у меня таки пришла мысля типа прописать какой-нибудь чек акторов в предельно малом радиусе, и при обнаружении в оном миссайлей прыгать в стэйт включающий бога. А вот как быть с мили - хз.
Я наверное уже поднадоел всем, но пишите уже на зскрипте ёпт. Там есть виртуальная функция под каждым актором, называется DamageMobj и вызывается при любом дамаге по мобу входящему из любого источника.
Вроде бы указанная функция проверяет инвентарь актора, т.е. "Яда", а не игрока. А антидот дает детокс игроку. Надо как-то иначе, типа A_JumpIfInTargetInventory (но что является таргетом для актора "Яд"? точно ли игрок?)
по моему на скриптах будет проще, но и сам яд тогда должен работать через ацс.
Карта под бум.
Есть 12 секторов с одним тегом (кроме этих секторов он больше нигде не используется), на каждом выставлен "Linght Blinks (0.5 sec, synhronized)" в настройках сектора (что б все в унисон барахлили), у всех одинаковая исходная яркость.
И у 2х из них почему-то в темное время блика яркость снижаться до 0.
Ron_Dalas Пункты 2 и 3 утверждают, что неплохо бы этим двум секторам добавить тёмных соседей.
Если на карте в этом месте проблемы с пространством, можно нарисовать контрольные сектора где-нибудь на задворках и соединить их с данными.
Actor Dtx : CustomInventory
{
+Inventory.AlwaysPickup
Inventory.MaxAmount 0
States
{
Spawn:
TNT1 A 1
Loop
Pickup:
TNT1 A 0 A_SpawnItemEx("Detox",0,0,15) //zoffset needs for work in water
Stop
}
}
Actor Detox
{
Projectile
Damage (0) //Damage SHOULD be assigned ONLY as expression "()"
PoisonDamage 1,0,1 //It's a MINIMAL value!
States
{
Spawn:
TNT1 A 1 NoDelay A_ClearTarget //In newer GZDoom you can try to use https://zdoom.org/wiki/Actor_flags#HITOWNER flag instead
Loop
Death:
TNT1 A 0
Stop
}
}
Есть правда кое-какие нюансы, но я всё расписал в гайде.
Касаемо _Damage%% ядов надо мозговать отдельно, хотя де-факто этот антидот такие тоже хилит, на деле же они как правило происходят из стороннего источника урона и бьют внутри стэйта. Т. е. нужно непосредственно стопить актор в котором работает _Damage ф-ция.
Кстати ф-ция A_ClearTarget оказалась ключом к Пойзон Ауре на PoisonDamage. Завтра апдэйт.
Олсо, такая шняга на зскрипте должна килять PoisonDamage яды:
{
PoisonDurationReceived = 0;
}
==============
1. Краем уха слышал что существует небольшая, но тем не менее, разница в ресурсоёмкости между Goto, Loop и _Jump. Если это правда, то что из этого лучше использовать для снижения ресурсоёмкости?
2. Кто-нибудь пробовал давать мобам Drain пауэрап? Или он только на волынах игрока пашет?
3. И всё-таки, как в декоре можно получить SpawnHealth по указателю (таргет, мастер, трэйсер)? Может как-то через итемы и промежуточных акторов получать?
yarikidkfa Мы не экстрасенсы, к сожалению, а может и к счастью, поэтому конкретнее суть проблемы можно? Вопросов как бы много. Постараюсь задать основные:
1. Порт в котором делаешь.
2. На что заменить?
3. Код на котором ты хочешь это сделать (только в Гозе есть следующие варианты: просто заменить, Dehacked, Decorate & ACS, ZScript)
А так механизм прост. Делаешь pk3/wad - пихаешь все ресурсы туда. Спрайты, звуки, код (если нужен). Увы конкретнее пока сказать не могу.
Ребят, можно ли на декоре сделать так чтобы актор "А" отвечал актору "Б", если у "Б" прописан +NOTARGET? Специес у них разные, но актор "Б" править нельзя.
Полагаю что надо отключить флаг через выдачу агрессору кастомитема, но вот как его выдать ума не приложу.
Actor EyeOpener: CustomInventory
{
+INVENTORY.ALWAYSPICKUP
Inventory.MaxAmount 0
States
{
Pickup:
TNT1 A 0 A_ChangeFlag("NOTARGET",0)
Stop
}
}
Полагаю что надо отключить флаг через выдачу агрессору кастомитема
Нет не так.
Нужно Снаряд от актора Б назначить с неким дама-типом. Когда данный снаряд попадет в Актора А - у него уже будет предварительно тобой прописан ПЕЙН стейт этого же типа (как у снаряда), в котором ты ставишь Чэндж-Флэг и убираешь NOTARGET с добавлением флага КВИК ТУ РЕТАЛИАТЕ (забыл как на иглише пишется)...
Также стоит установить Пейн Шанс этого типа на более высокий наверное.
Когда данный снаряд попадет в Актора А - у него уже будет предварительно тобой прописан ПЕЙН стейт этого же типа (как у снаряда), в котором ты ставишь Чэндж-Флэг и убираешь NOTARGET
какой смысл убирать отсутствующий NOTARGET в кастомПэйне актора А, когда надо кильнуть флаг актора Б?
Плюс,
Void Weaver:
актор "Б" править нельзя.
Поясняю: актор "Б" - Минотавр из Еретика, актор "А" - мой кастомный, и поскольку не только у Минотавра есть НОТАРГЕТ, то нужно какое-то универсальное решение.
В целом задача сводится к: "как обнаружить абстрактный актор с НОТАРГЕТ (до или после его атаки)".
В принципе это лечится поиском через ЧекПроксимити конкретного актора (Минотавра, Арча, и т. д.) с последующей выдачей оным кастомитема снимающего флаг, но тогда нужно прописывать доп. строки на каждого обладателя НОТАРГЕТ.
Господа, я скорее не с вопросом, а с просьбой. Насколько сложно сделать мод, чтобы в режиме Survival в зандронуме играла определённая песня, когда в живых остался последний выживший?
Очень бы хотелось сделать подобие TNS-сервера, но эта фишка Zdaemon'а в Зандро не работает.
script 1 OPEN //Server - Setup
{
//Do a bunch of things
ACS_EXECUTE(3,0,true);
}
script 2 ENTER // Client - Setup
{
//Do a bunch of things
DoCodeClient[PlayerNumber()] = false;
acs_executealways(4,0);
}
// RoundReal 0 = Waiting between minigames (Intermission music)
// RoundReal 50 = Win/Loss screen (Win/Lose Music)
// RoundReal 100+ = Minigame itself
// RoundReal 666 = Game Over
script 3 (void) // Server - Round Runner
{
RoundReal = 0; // Round Real is a global variable which keeps track of the round stuff that was in the comment stack above this one
// Do a bunch of things
delay(140);
int round;
round = random(0,15)+100;
RoundReal = round;
ACS_Execute(round,0); // This executes one of the rounds.
}
script 4 (void) // Client - Round Music
{
if (RoundReal == 0 && RoundNum < MaxRounds) // Play intermission music
{
ACS_ExecuteAlways(9,0);
if ((RoundNum == speedupround1 || RoundNum == speedupround2 || RoundNum == speedupround3 || RoundNum == speedupround4))
ACS_Execute(11,1,0);
else
ACS_Execute(11,0,0);
if (!(RoundNum == speedupround1 || RoundNum == speedupround2 || RoundNum == speedupround3 || RoundNum == speedupround4))
hudmessage(s:"";HUDMSG_PLAIN,1,cR_ORANGE,0.5,0.3,1);
else if (RoundReal == 0 && (RoundNum == speedupround1 || RoundNum == speedupround2 || RoundNum == speedupround3 || RoundNum == speedupround4))
hudmessage(s:"Speed Up";HUDMSG_PLAIN,1,cR_BLUE,0.5,0.3,1);
}
if (RoundReal == 50 && RoundSongPlaying == false) // Play Victory/fail music
{
if ((CheckInventory("WonRoundItem") == 0) || (PlayerDiedInRound[PlayerNumber()] == true))
{
SetFont("BIGFONT");
if (SpeedupNum == 0)
LocalAmbientSound("DoomWare/Fail",127);
if (SpeedupNum == 1)
LocalAmbientSound("DoomWare/Fail2",127);
if (SpeedupNum == 2)
LocalAmbientSound("DoomWare/Fail3",127);
if (SpeedupNum == 3)
LocalAmbientSound("DoomWare/Fail4",127);
if (SpeedupNum == 4)
LocalAmbientSound("DoomWare/Fail5",127);
WinSongPlaying[PlayerNumber()] = true;
hudmessage(s:"You Failed!";HUDMSG_PLAIN,1,cR_RED,0.5,0.3,1);
}
else if (PlayerDiedInRound[PlayerNumber()] == false)
{
SetFont("BIGFONT");
Score[PlayerNumber()] += 1;
if (SpeedupNum == 0)
LocalAmbientSound("DoomWare/Win",127);
if (SpeedupNum == 1)
LocalAmbientSound("DoomWare/Win2",127);
if (SpeedupNum == 2)
LocalAmbientSound("DoomWare/Win3",127);
if (SpeedupNum == 3)
LocalAmbientSound("DoomWare/Win4",127);
if (SpeedupNum == 4)
LocalAmbientSound("DoomWare/Win5",127);
WinSongPlaying[PlayerNumber()] = true;
hudmessage(s:"You Won!";HUDMSG_PLAIN,1,cR_Green,0.5,0.3,1);
}
}
if (RoundReal == 104) // Client - Stop Moving
{
if (DoCodeClient[PlayerNumber()] == true) // This is to stop players that join mid round from playing
{
DoCodeClient[PlayerNumber()] = false;
SetFont("BIGFONT");
hudmessage(s:"Stop Moving";HUDMSG_PLAIN,1,cR_ORANGE,0.5,0.3,1);
delay(70-(SpeedupNum*2));
if (CalcSpeed(GetActorVelX(ID[PlayerNumber()]),GetActorVely(ID[PlayerNumber()])) > 11)
thing_damage(ID[PlayerNumber()],10000000,MOD_BARREL);
delay(35);
}
}
delay(1);
restart;
}
script 11 (int mus) // Client - Round Music
{
if (mus == 1)
{
if (RoundNum == speedupround1) {
LocalAmbientSound("DoomWare/SPEEDUP",127); }
if (RoundNum == speedupround2) {
LocalAmbientSound("DoomWare/Speedup2",127); }
if (RoundNum == speedupround3) {
LocalAmbientSound("DoomWare/Speedup3",127); }
if (RoundNum == speedupround4) {
LocalAmbientSound("DoomWare/Speedup4",127); }
if (SpeedupNum == 1)
delay(125);
if (SpeedupNum == 2)
delay(120);
if (SpeedupNum == 3)
delay(110);
if (SpeedupNum == 4)
delay(100);
if (SpeedupNum == 0)
delay(140);
if (SpeedupNum == 1)
delay(130);
if (SpeedupNum == 2)
delay(115);
if (SpeedupNum == 3)
delay(100);
if (SpeedupNum == 4)
delay(90);
}
if (mus == 0)
{
if (SpeedupNum == 0) {
LocalAmbientSound("DoomWare/intro",127); }
if (SpeedupNum == 1) {
LocalAmbientSound("DoomWare/intro2",127); }
if (SpeedupNum == 2) {
LocalAmbientSound("DoomWare/intro3",127); }
if (SpeedupNum == 3) {
LocalAmbientSound("DoomWare/intro4",127); }
if (SpeedupNum == 4) {
LocalAmbientSound("DoomWare/intro5",127); }
if (SpeedupNum == 0)
delay(140);
if (SpeedupNum == 1)
delay(130);
if (SpeedupNum == 2)
delay(115);
if (SpeedupNum == 3)
delay(100);
if (SpeedupNum == 4)
delay(90);
}
}
Script 104 (void) // Gamemode Example
{
setMusic("D_MOVEIT");
delay(70-(SpeedupNum*2));
delay(35);
setMusic(""); // at this point, the round over music should play, which tells the player that they won or lost
RoundReal = 50;
delay(66-(7*SpeedupNum)); // Give time to play the win/lose music before restarting the round running script.
RoundNum +=1;
ACS_EXECUTE(3,0);
}
как сделать, чтобы актор не падал на пол при спауне на высоте Z? У меня лучик падает на пол и сквозь 3д полы. Флаги +NOGRAVITY и/или +DONTFALL не помогли.
Добавлено спустя 15 минут 13 секунд:
Трабл с тем же лучом. Поставил луч в дырку 3д пола, смотрю с одного ракурса — всё оки. Стоит мне только подойти с другого ракурса — лучик смещается не вокруг своей оси, оставаясь в дырке, а как бы вокруг неё, словно крутится по маленькой окружности сходя со своей центральной позиции. Что я сделал неправильно? Код предельно прост:
Скрытый текст:
Actor RedRay 15021
{
//$Category Effects
Height 40
Radius 8
RenderStyle Add
Alpha 0.75
+NOGRAVITY
States
{
Spawn:
RAYR A -1 Bright
Stop
}
}
Если актор предназначен чисто для декорации и не подразумевает прямого взаимодействия с другими акторами, то добавь к НОГРАВИТИ ещё и +NOINTERACTION. Если не поможет, попробуй поставить Mass 0 в свойствах луча.
А можно скрин-другой луча и спрайт оного? Бтв, спрайты имеют 0-вой дирекшн?
1. ЕЯПП, то флаг FRIENDLY условно делит монстров на 2 типа: на всегда враждебных к игроку - "обычных", и на всегда дружественных.
Вопрос: можно ли на декоре выполнить проверку дружественности\враждебности между "обычными" монстрами? Т. е. можно ли сделать так, чтобы файрбол импа коцал зомбимэна только в случае если зомбимэн попал по импу первым?
2. Нашёл занятную экспрешн ф-цию GetMissileDamage, но не оч. понял можно ли с её помощью передать значение дамага снаряд-актора "Б" хозяину этого снаряда монстр-актору "А"?
2.1 Вообще можно ли сделать так, чтобы актор "узнавал" сколько дамага он нанёс другому?