Хочу мобу сделать станящую (оглушающую) атаку, и если движение запросто стопить выдачей игроку speed пауэрапа со значением 0, то насчёт того как на декоре временно запретить атакустрельбу соображений нет никаких. Есть идеи?
YURA_111:
Если через декор только, то выдаешь игроку некий инвентори - а в каждом оружии в стейте READY делаешь Check этого инвентори. Если присутствует - то прыжок в стейт ReadyNoFire (например) с заLOOPливанием на стейт Ready
Ну вы блин даете. Пошли в какие-то дебри. SetPlayerProperty не пробовали? Эта штука как в ACS, так и в декоре работает. Можно и через CustomInventory активировать. У этого способа замораживать игрока борода отросла. Какие-то повер-апы и скачки придумали...
Void Weaver:
таки да, ТаймИмп существует!
Этот имп там уже несколько лет существует.
Void Weaver:
Можно ли (и как) прописать актор-мобу в декоре зависимость DamageFactor от skill (сложности)? Ну типа чтобы на первой сложности резистов (DamageFactor) не было, а на 4-5 например включался иммун к огню (DamageFactor Fire, 0.0).
Если только скриптами.
Void Weaver:
пробовал health и GetActorProperty(0,APROP_Health), но выдаёт исключительно текущие и вроде всегда владельца функции.
Нужно было прописывать APROP_SpawnHealth. И да, функция проверяет только здоровье активатора. К тому же вопрос - для чего именно максимальное здоровье?
Ну вы блин даете. Пошли в какие-то дебри. SetPlayerProperty не пробовали? Эта штука как в ACS, так и в декоре работает. Можно и через CustomInventory активировать. У этого способа замораживать игрока борода отросла. Какие-то повер-апы и скачки придумали...
О как! Я даже советовал кому-то этот способ в этой теме... думал что только для скриптов.
MasterMind:
Этот имп там уже несколько лет существует.
Ну ясен пень, раз аплоад 2012, видимо я такой "внимательный" раз только что заметил.
MasterMind:
Нужно было прописывать APROP_SpawnHealth. И да, функция проверяет только здоровье активатора. К тому же вопрос - для чего именно максимальное здоровье?
О, слона-то и не приметил, спасибо! А можно ли как-то получать _SpawnHealth по указателю? Макс. здоровье для фиксированного сбалансированного хила\регена. А вызов через поинтеры нужен для разных мобов, через _трасер например для трупоеда: "съел" труп импа - похилился на 6 хп, барона ада - на 100.
mutator I won't lie to you.I'm not a developer,more like a Ripper.)) Make builds from favorite resources of different mods.Authorship do not claim,as just a hobby for fun.In General, the Assembly is almost ready, it remains to correct the little things.
Как назначить функцию актору, чтобы он наносил дамаг по 20 хелсов в секунду, например? Чтобы чем ближе подходил игрок, тем сильнее у него отнимались жизни (максимум, 20 хп).
Код актора:
Скрытый текст:
Actor FireSpawner : SwitchableDecoration 15099
{
//$Category Effects
Height 40
Radius 30
+ClientSideOnly
+NoClip
+NoBlockMap
+NoGravity
+NoSector
+NoInteraction
States
{
Spawn:
Active:
TNT1 A 0
TNT1 A 0 A_JumpIf(Args[1] > 0, 2)
TNT1 A 0 A_PlaySoundEx("SFX/FireStart", "SoundSlot7", 0)
TNT1 A 0 A_JumpIf(Args[0] == 1, "Medium")
TNT1 A 0 A_JumpIf(Args[0] > 1, "Large")
TNT1 A 0 A_JumpIf(Args[1] > 0, 2)
TNT1 A 0 A_PlaySoundEx("SFX/FireLoop1", "SoundSlot6", 1)
TNT1 A 0 A_SpawnItemEx("SmallFlame", 0, 0, 0, 0, 0, 0, 0, 128)
TNT1 A 0 A_Jump(216, 3)
TNT1 A 1 A_SpawnItemEx("Flame1A", 0, 0, 0, 0, 0, 0, 0, 128)
TNT1 A 0 A_SpawnItemEx("Ember1", 0, 0, 0, 0, 0, 0, 0, 128)
Loop
TNT1 A 0 A_Jump(176, 2)
TNT1 A 1 A_SpawnItemEx("Flame1B", 0, 0, 0, 0, 0, 0, 0, 128)
Loop
TNT1 A 0 A_Jump(136, 2)
TNT1 A 1 A_SpawnItemEx("Flame2A", 0, 0, 0, 0, 0, 0, 0, 128)
Loop
TNT1 A 0 A_Jump(96, 2)
TNT1 A 1 A_SpawnItemEx("Flame2B", 0, 0, 0, 0, 0, 0, 0, 128)
Loop
TNT1 A 0 A_Jump(56, 2)
TNT1 A 1 A_SpawnItemEx("Flame3A", 0, 0, 0, 0, 0, 0, 0, 128)
Loop
TNT1 A 1 A_SpawnItemEx("Flame3B", 0, 0, 0, 0, 0, 0, 0, 128)
Loop
Medium:
TNT1 A 0 A_JumpIf(Args[1] > 0, 2)
TNT1 A 0 A_PlaySoundEx("SFX/FireLoop2", "SoundSlot6", 1)
TNT1 A 0 A_SpawnItemEx("MediumFlame", 0, 0, 0, 0, 0, 0, 0, 128)
TNT1 A 0 A_Jump(216, 3)
TNT1 A 1 A_SpawnItemEx("Flame4A", 0, 0, 0, 0, 0, 0, 0, 128)
TNT1 A 0 A_SpawnItemEx("Ember2", 0, 0, 0, 0, 0, 0, 0, 128)
Loop
TNT1 A 0 A_Jump(176, 2)
TNT1 A 1 A_SpawnItemEx("Flame4B", 0, 0, 0, 0, 0, 0, 0, 128)
Loop
TNT1 A 0 A_Jump(136, 2)
TNT1 A 1 A_SpawnItemEx("Flame5A", 0, 0, 0, 0, 0, 0, 0, 128)
Loop
TNT1 A 0 A_Jump(96, 2)
TNT1 A 1 A_SpawnItemEx("Flame5B", 0, 0, 0, 0, 0, 0, 0, 128)
Loop
TNT1 A 0 A_Jump(56, 2)
TNT1 A 1 A_SpawnItemEx("Flame6A", 0, 0, 0, 0, 0, 0, 0, 128)
Loop
TNT1 A 1 A_SpawnItemEx("Flame6B", 0, 0, 0, 0, 0, 0, 0, 128)
Loop
Large:
TNT1 A 0 A_JumpIf(Args[1] > 0, 2)
TNT1 A 0 A_PlaySoundEx("SFX/FireLoop3", "SoundSlot6", 1)
TNT1 A 0 A_SpawnItemEx("LargeFlame", 0, 0, 0, 0, 0, 0, 0, 128)
TNT1 A 0 A_Jump (216, 3)
TNT1 A 1 A_SpawnItemEx("Flame7A", 0, 0, 0, 0, 0, 0, 0, 128)
TNT1 A 0 A_SpawnItemEx("Ember2", 0, 0, 0, 0, 0, 0, 0, 128)
Loop
TNT1 A 0 A_Jump (176, 2)
TNT1 A 1 A_SpawnItemEx("Flame7B", 0, 0, 0, 0, 0, 0, 0, 128)
Loop
TNT1 A 0 A_Jump (136, 2)
TNT1 A 1 A_SpawnItemEx("Flame8A", 0, 0, 0, 0, 0, 0, 0, 128)
Loop
TNT1 A 0 A_Jump (96, 2)
TNT1 A 1 A_SpawnItemEx("Flame8B", 0, 0, 0, 0, 0, 0, 0, 128)
Loop
TNT1 A 0 A_Jump (56, 2)
TNT1 A 1 A_SpawnItemEx("Flame9A", 0, 0, 0, 0, 0, 0, 0, 128)
Loop
TNT1 A 1 A_SpawnItemEx("Flame9B", 0, 0, 0, 0, 0, 0, 0, 128)
Loop
Inactive:
TNT1 A 0 A_JumpIf(Args[1] > 0, 2)
TNT1 A 0 A_PlaySoundEx("SFX/FireDie", "SoundSlot7", 0)
TNT1 A -1 A_StopSoundEx("SoundSlot6")
Goto Inactive+2
}
}
Так A_Expolde обычный нужен. Запускаешь его каждые 35 тиков, и всё. На крайний случай вводишь свою переменную или итем-счётчик.
Var int user_Counter;
States {
<...>
TNT1 A 0 A_SetUserVar( "user_Counter", user_Counter + 1 )
TNT1 A 0 A_JumpIf( user_Counter < 35, 3 )
TNT1 A 0 A_Expolde( 20, 64 )
TNT1 A 0 A_SetUserVar( "user_Counter", 0 )
TNT1 A 0 <...>
// Это всё можно записать в "TNT1 A 0 { <here> }", если не нужна совместимость с ZDoom/Zandronum.
// В твоём проекте, насколько я знаю, именно так.
Только код актора у тебя непонятный. "Loop" перезапускает код, начиная с ближайшей предыдущей метки. Поэтому у тебя здесь каждый раз делаются несколько лишних проверок на Arg'и.
Чтобы чем ближе подходил игрок, тем сильнее у него отнимались жизни (максимум, 20 хп).
Задать несколько А_Эксплодов с разным радиусом - по мере приближения игрок будет попадать под действие нескольких А_Эксплодов сразу, и соответственно коцаться сильнее.
JSO x:
Только код актора у тебя непонятный. "Loop" перезапускает код, начиная с ближайшей предыдущей метки. Поэтому у тебя здесь каждый раз делаются несколько лишних проверок на Arg'и.
Да вроде там всё норм... или ты о второй строке TNT1 A 0 A_JumpIf(Args[1] > 0, 2) в Active стэйте?
Да не только о ней. Там есть несколько строк, которые вполне можно проверять всего один раз (если я правильно понял суть актора). Однако в этом коде они будут проверяться каждый цикл:
DOOMGABR:
<...>
Spawn:
Active:
TNT1 A 0
TNT1 A 0 A_JumpIf(Args[1] > 0, 2)
TNT1 A 0 A_PlaySoundEx("SFX/FireStart", "SoundSlot7", 0)
TNT1 A 0 A_JumpIf(Args[0] == 1, "Medium")
TNT1 A 0 A_JumpIf(Args[0] > 1, "Large")
TNT1 A 0 A_JumpIf(Args[1] > 0, 2)
<...>
Например и кстати, здесь "SFX/FireStart" будет играть каждый раз (!) при входе в цикл, если второй Arg == 0. Если понадобится, есть функция A_SetArg.
Void Weaver:
Задать несколько А_Эксплодов с разным радиусом - по мере приближения игрок будет попадать под действие нескольких А_Эксплодов сразу, и соответственно коцаться сильнее.
Тоже вариант. Просто у A_Explode при удалении от вызывающего актора снижается и урон. Логично, что если стоишь рядом с ракетой, будет куда больнее, чем, например, если стоишь в паре Doom-метров от эпицентра. Так и я здесь предлагаю: более точно урон по радиусу рассчитываться будет, если, конечно, не нужна нелинейная зависимость.
Например и кстати, здесь "SFX/FireStart" будет играть каждый раз (!) при входе в цикл
А ты не допускаешь что оно так и задумано? :|
JSO x:
Тоже вариант.
В смысле "тоже"? Это не вариант, а всего-лишь конкретизация твоего предложения юзать _Эксплод ф-цию, DOOMGABR же интересовался ещё и корреляцией урона от дистанции. В любом случае _Эксплод позволяет задать точное распределение урона в радиусе: либо урон снижается по периферии, либо наносится в полную силу по всему радиусу.
Ну например так:
Actor Flame1A
{
DamageType Fire
Var int user_Counter;
States
{
Spawn:
<...>
SpawnFireTimer:
TNT1 A 1 A_SetUserVar( "user_Counter", user_Counter + 1 )
TNT1 A 0 A_JumpIf( user_Counter < 35, 12 )
TNT1 A 0 A_Expolde( 2, 192, 0, 0, 96 )
TNT1 A 0 A_Expolde( 2, 172.8, 0, 0, 86.4 )
TNT1 A 0 A_Expolde( 2, 153.6, 0, 0, 76.8 )
TNT1 A 0 A_Expolde( 2, 134.4, 0, 0, 67.2 )
TNT1 A 0 A_Expolde( 2, 115.2, 0, 0, 57.6 )
TNT1 A 0 A_Expolde( 2, 96, 0, 0, 48 )
TNT1 A 0 A_Expolde( 2, 76.8, 0, 0, 38.4 )
TNT1 A 0 A_Expolde( 2, 57.6, 0, 0, 28.8 )
TNT1 A 0 A_Expolde( 2, 38.4, 0, 0, 19.2 )
TNT1 A 0 A_Expolde( 2, 19.2, 0, 0, 9.6 )
TNT1 A 0 A_SetUserVar( "user_Counter", 0 )
TNT1 A 0 A_Jump (256, "SpawnFireTimer")
<...>
Goto Spawn
}
}
Плавное увеличение Fire дамага от 1 до 20 в радиусе от 192 до 9.6 с интервалом в секунду.
Ну а если серьёзно, то какой огонь тебе нужен и куда? Одиночный, массовый? В атаку монстра, в пуху или в декорацию-ловушку?
Ибо судя по реалмовскому коду за ним в оригинале может скрываться всё что угодно - от скромной жаровни до адского Везувия в зависимости от того что из себя представляют акторы "Flame" и "Ember".
Задать несколько А_Эксплодов с разным радиусом - по мере приближения игрок будет попадать под действие нескольких А_Эксплодов сразу, и соответственно коцаться сильнее.
DOOMGABR, смотри, если брать предельно простую ситуацию, то дамажную функцию логично следует прописывать в актор который должен коцать. В твоём случае Actor FireSpawner не является непосредственным источником урона, а только посредником (причём хитрожопой ДЕКОРАЦИЕЙ, т. е. никак не взаимодействующей с физ. объектами напрямую). Судя по коду, источником урона должны быть отдельные акторы типа "Flame" и\или "Ember", а соответственно в них и нужно прописывать А_Эксплод в какой-нибудь стэйт (Spawn и\или Death).
Но поскольку причина выбора столь комплексного актора как FireSpawner совсем не очевидна, то возникает закономерный вопрос: а что соб-сно тебе надо? Именно огонь или как? Ядовитое облако, травящее например через равные промежутки времени, можно прописать вообще без _Эксплод. Для кастомных типов урона можно воспользоваться связками типа A_GiveRadius+A_DamageTarget\A_DamageSelf.
Если же ты сам ещё не определился что тебе нужно, то я порекомендовал бы тебе взять один "Flame" актор и поэкспериментировать на нём для начала. Причём наиболее вероятно что во "Flame" и\или "Ember" уже присутствует А_Эксплод.
YURA_111, можно ЕЯТПП. Но если источником урона будет Эксплод, то какая разница?
Тему про скриптинг никто не смотрит, дублирую вопрос сюда.
Может ли гздум выдавать переменную - текущее состояние брони игрока? Чтобы можно было чинить броню, и взимать с игрока плату в зависимости от разницы между макс. значением брони (например, для зеленой брони это 100 ед.) и ее текущим значением (от 1 до 99)?
можно ЕЯТПП. Но если источником урона будет Эксплод, то какая разница?
Ну если прочитать внимательно вопрос, то урон должен наносить актор игроку. А конкретно A_Explode и его радиусы я так понимаю будут повреждать все живое рядом стоящее с игроком. Не уверен что это есть хорошо.
DOOMGABR:
Как назначить функцию актору, чтобы он наносил дамаг по 20 хелсов в секунду, например? Чтобы чем ближе подходил игрок, тем сильнее у него отнимались жизни (максимум, 20 хп).
YURA_111 Ааа, ну если трактовать так, то да, лучше. Но что-то мне подсказывает что камрад не подразумевал под областью воздействия урона только игрока.
что_хотел_заказчик.жпег, классика.
Shadowman А ты не пробовал получить текущее значение ко-ва армора через CheckInventory("GreenArmor") например?
Если вариант выше не работает, то можно попытаться опосредованно "вынуть" текущее значение через класс-"счетовод" Classes:BaseStatusBar
int GetArmorAmount()
{
let armor = CPlayer.mo.FindInventory("BasicArmor");
return armor? armor.Amount : 0;
}
int, int GetAmount(class<Inventory> item)
{
let it = CPlayer.mo.FindInventory(item);
int ret1 = it? it.Amount : 0;
int ret2 = it? it.MaxAmount : GetDefaultByType(item).MaxAmount;
return ret1, ret2;
}
Вот вроде пример использования GetArmorAmount() в кастом статусбаре для отображения текущего ко-ва
Void Weaver ЧекИнвентори не работает, т.к. показывает наличие брони как айтема, а не ее % повреждений.
Void Weaver:
int GetArmorAmount()
Это пример на зскрипте или ацс? Нужно, чтобы с переменной можно было работать в обычных скриптах, как с любыми другими переменными.
Можешь пояснить его построчно?
То, что статус бар умеет отображать наличное количество брони, я знаю. Но это статус бар, а не актор и не переменная.
ЧекИнвентори не работает, т.к. показывает наличие брони как айтема, а не ее % повреждений.
А что если чекать не конкретный армор а CheckInventory("BasicArmor")?
BasicArmor is the internal class used to keep track of a player's current armor rating in Doom, Heretic and Strife.
Shadowman:
Это пример на зскрипте или ацс? Нужно, чтобы с переменной можно было работать в обычных скриптах, как с любыми другими переменными.
Можешь пояснить его построчно?
То, что статус бар умеет отображать наличное количество брони, я знаю. Но это статус бар, а не актор и не переменная.
Это зскрипт; извиняй, скрипты для меня как на китайском. Я всего лишь обратил внимание что класс статусбара каким-то макаром таки получает истинные сведения о ко-ве брони и наивно решил что это может быть полезным.
Но вот то что в обоих примерах сама GetArmorAmount() получает сведения из некоего "BasicArmor" заметил только сейчас.