А игроку можно запилить что-то типа "магнитного" скилла который при юзе будет собирать дроп в радиусе на некоторой дистанции.
Кстати, в моде Guncaster такая фича уже реализована, причем работает в пассивном режиме, а не "по нажатию", просто автоматом сгребаются все деньги (которые там выпадают с монстров) в неком радиусе от игрока. Правда эта фича работает только если у игрока есть специальный айтем ("том философа", как-то так называется).
Это не шило на мыло, я вообще не вижу в твоём коде проверку checkinventory, которая бы обеспечивала "принудительную единственность" (либо её корректный аналог). Есть проверка на здоровье и проверка на флаг CORPSE, которые сразу же ведут на GiveReward, и не существует никаких преград перед тем, чтобы на GiveReward переключилось бы сразу несколько акторов.
Ваще-т существует. Наличие ХИТТРАСЕР подразумевает что если флаг навешен значит урон прошёл и если трэйсер оказался трупом (или хп<1) то ВОТ ПРЯМО СЕЙЧАС я (пуфф) лично завалил этот трэйсер.
Другие же пуффы должны пролететь несолоно хлебавши. И в общем-то всё так и происходит, но при плотном пулемётном огне ~25% срабатывает мультиревард.
Твой же вариант всё также допускает наличие общей цели для нескольких турелей, только ещё добавляет усложнение в виде доп звена для активации выдачи реварда. Вот твой вариант:
Скрытый текст:
ACTOR Turret_pistol
{
Radius 20
Height 56
Monster
Translation 1
Species "PlayerAlly"
//+NOINTERACTION //Вкл если не нужна физика актора
//+NEVERTARGET //Вкл если не хочешь чтобы актор мог стать чьей-либо целью
+DONTTHRUST
+FRIENDLY
var int user_lootClass;
States
{
Spawn:
CPOS A 0 NoDelay A_GiveInventory("Uniter",1,AAPTR_MASTER)
Idle:
CPOS A 10 A_LookEx(LOF_NOSOUNDCHECK,0,500,0,360,"See")
Loop
See:
CPOS A 0 A_Chase("","Missile",CHF_DONTMOVE|CHF_NODIRECTIONTURN)
CPOS AAA 1
{
If(GetDistance(1)>Radius+500){A_ClearTarget;Return state("Idle");}
Else{Return state("");}
}
Loop
Missile:
/*
CPOS AB 6 A_FaceTarget
CPOS C 0 A_PlaySound("grunt/attack")
CPOS C 0 A_CustomBulletAttack(2,0,1,10,"TurretPuff",0,CBAF_NORANDOM)
CPOS C 8 //A_CheckFlag("CORPSE","GiveReward",AAPTR_TARGET)
Goto See
*/
CPOS E 10 A_FaceTarget
CPOS F 0 A_PlayWeaponSound("chainguy/attack")
CPOS F 4 bright A_CustomBulletAttack(22.5,0,1,10,"BulletPuff",0,CBAF_NORANDOM)
TNT1 A 0 A_JumpIfHealthLower(1,2,AAPTR_TARGET)
TNT1 A 0 A_Jump(256,3)
TNT1 A random(1,6) A_GiveToTarget("RewardActivator")
TNT1 A 0 A_JumpIfInventory("RewardActivator",1,"GiveReward",AAPTR_TARGET)
CPOS E 1 A_PlayWeaponSound("chainguy/attack")
CPOS E 4 bright A_CustomBulletAttack(22.5,0,1,random(1,5)*3,"BulletPuff",0,CBAF_NORANDOM)
TNT1 A 0 A_JumpIfHealthLower(1,2,AAPTR_TARGET)
TNT1 A 0 A_Jump(256,3)
TNT1 A random(1,6) A_GiveToTarget("RewardActivator")
TNT1 A 0 A_JumpIfInventory("RewardActivator",1,"GiveReward",AAPTR_TARGET)
CPOS F 1 A_CPosRefire
Goto Missile+1
//*
GiveReward:
TNT1 A 0 A_PlaySound("brain/pain",0)
TNT1 A 0
{
If(CheckClass("ZombieMan",AAPTR_TARGET,1)){user_lootClass=1;Return state("");}
Else If(CheckClass("ShotgunGuy",AAPTR_TARGET,1)){user_lootClass=2;Return state("");}
Else If(CheckClass("ChaingunGuy",AAPTR_TARGET,1)){user_lootClass=4;Return state("");}
Else If(CheckClass("DoomImp",AAPTR_TARGET,1)){user_lootClass=3;Return state("");}
Else If(CheckClass("Demon",AAPTR_TARGET,1)){user_lootClass=4;Return state("");}
Else If(CheckClass("LostSoul",AAPTR_TARGET,1)){user_lootClass=0;Return state("");}
Else If(CheckClass("Revenant",AAPTR_TARGET,1)){user_lootClass=7;Return state("");}
Else If(CheckClass("Cacodemon",AAPTR_TARGET,1)){user_lootClass=6;Return state("");}
Else If(CheckClass("HellKnight",AAPTR_TARGET,1)){user_lootClass=7;Return state("");}
Else If(CheckClass("BaronofHell",AAPTR_TARGET,1)){user_lootClass=8;Return state("");}
Else If(CheckClass("Arachnotron",AAPTR_TARGET,1)){user_lootClass=7;Return state("");}
Else If(CheckClass("Fatso",AAPTR_TARGET,1)){user_lootClass=8;Return state("");}
Else If(CheckClass("Archvile",AAPTR_TARGET,1)){user_lootClass=9;Return state("");}
Else If(CheckClass("SpiderMastermind",AAPTR_TARGET,1)){user_lootClass=10;Return state("");}
//Else If(CheckClass("Cyberdemon",AAPTR_TARGET,1)){user_lootClass=10;Return state("");}
Else{user_lootClass=10;Return state("");} //Значит остался только Кибер
}
TNT1 A 0 A_TakeFromTarget("RewardActivator")
TNT1 A 0 A_ClearTarget
TNT1 A 0 A_GiveInventory("Shell",user_lootClass,AAPTR_MASTER)
Goto Spawn
//*/
Death:
CPOS A 0 A_GIveInventory("DeUniter",AAPTR_MASTER)
Stop
}
}
Может я неправильно тебя понял, но если выполнить дословно то что ты советовал то получится именно такая конструкция.
Добавлено спустя 29 минут:
Т. е. чтобы твой или мой (который не на пуффе) варианты сработали как положено, то первая же пушка получившая от трупа итем-пасс должна немедленно обнулить таргетфилд ВСЕМ турелям которые также имеют этого монстра своей целью. Но даже если это грамотно прописать, то всё по-прежнему останется на воле РНГ случайной длительности буфферного кадра.
Ваще-т существует. Наличие ХИТТРАСЕР подразумевает что если флаг навешен значит урон прошёл и если трэйсер оказался трупом (или хп<1) то ВОТ ПРЯМО СЕЙЧАС я (пуфф) лично завалил этот трэйсер.
Другие же пуффы должны пролететь несолоно хлебавши.
Вот абсолютно не обязательно. Твой метод работает на "физическом" уровне, мой на программном. Поскольку время у нас квантуется, то вполне вероятна такая ситуация, при которой несколько пуффов уткнутся в недоубитого монстра в один и тот же тик, и "ВОТ ПРЯМО СЕЙЧАС" для них будет действовать одновременно и равноценно. Для физического уровня возможны одновременные события.
На программном уровне всё происходит иначе. Процессор читает код аки книгу по порядку, и вносит изменения тоже по порядку. Здесь у нас не может быть одновременных событий, а события внутри "нулевого" отрезка времени разделены между собой номерным порядком и причинно-следственной связью. Например, возможно такое, что один актор уже обработан - и он переключил некую глобальную переменную из А в Б. А другой актор ещё не обработан, и к началу его обработки глобальная переменная уже стала Б.
(Конечно, из этого принципа могут быть исключения на каких-нибудь движках, где внутри понапиханы всякие мутные костыли, влияющие на порядок обработки малопредсказуемым образом. Но в теории всё выглядит именно так.)
Может я неправильно тебя понял, но если выполнить дословно то что ты советовал то получится именно такая конструкция.
Я сейчас придумал чуть иначе.
Missile:
CPOS AB 6 A_FaceTarget
CPOS C 0 A_PlaySound("grunt/attack")
CPOS C 0 A_CustomBulletAttack(2,0,1,10,"TurretPuff",0,CBAF_NORANDOM)
CPOS C 0 A_JumpIfHealthLower(1, "GiveReward" ,AAPTR_TARGET) // Если подох - переходим в режим ожидания.
CPOS F 1 A_CPosRefire
Goto Missile+1
GiveReward:
CPOS C random(1,6)
CPOS C 0 A_JumpIfInventory("RewardActivatorBlocker",1,"ExitReward",AAPTR_TARGET) //Если подохший хоть раз был помечен - он нас более не интересует. Сбрасываем и выходим.
CPOS C 0 A_GiveToTarget("RewardActivatorBlocker") //Пометить подохшего.
CPOS C 0 //дать игроку 500 рублей на водку//
CPOS C 0 //....//
Goto ExitReward
ExitReward:
CPOS C 0 A_ClearTarget
Goto See
Здесь минимум спагетти, всё легко и однозначно читается (однозначность можно похерить, пытаясь сделать код компактнее) и нет ничего лишнего. Здесь итем помечает не труп, по которому можно совершать выплаты, а труп, по которому нельзя. Помечается он необратимо, распомечен быть не может никем и ни при каких обстоятельствах, поэтому здесь всё должно работать стабильнее. Если и тут будет лагать - для верности можно попробовать повесить A_JumpIfInventory и A_GiveToTarget на один фрейм в зскрипте.
Поскольку время у нас квантуется, то вполне вероятна такая ситуация, при которой несколько пуффов уткнутся в недоубитого монстра в один и тот же тик, и "ВОТ ПРЯМО СЕЙЧАС" для них будет действовать одновременно и равноценно. Для физического уровня возможны одновременные события.
Да блд, а как же тогда та самая "распределённая одновременность" с которой мы пытались сладить в задаче с гибс-пуффами? Я думал что просчёт попадания хитскана это и есть программный уровень.
Здесь итем помечает не труп, по которому можно совершать выплаты, а труп, по которому нельзя.
Конечно довольно изящный инверсивный механизм, но, как я и предрекал выше, реально завязан на рнг random(1,6) и его стабильность обратнопропорциональна ко-ву турелей на цель И плотности толпы.
Ставим 6 турелей => спауним толпу на 10 импов => в итоге можем получить ~24-27 голды вместо 30. Вот те и программный уровень. Офк при увеличении диапазона random(x,y) стабильность возрастает но турель уже превращается в "покоцанную" которая работает на честном слове.
Да блд, а как же тогда та самая "распределённая одновременность" с которой мы пытались сладить в задаче с гибс-пуффами? Я думал что просчёт попадания хитскана это и есть программный уровень.
Там это работало чуть иначе, по принципу параллельных вычислений: каждый элемент независимо делает свою задачу, ждёт остальных, смотрит, что у всей группы в итоге получилось - и на основании этого принимает решение.
Здесь всё хуже. Здесь обработка первого элемента меняет логику обработки остальных. Это не параллельные вычисления, а грязный хак, который на одних архитектурах может работать так, а на других эдак. Это такая "спекуляция на псевдоодновременности".
Ставим 6 турелей => спауним толпу на 10 импов => в итоге можем получить ~24-27 голды вместо 30. Вот те и программный уровень. Офк при увеличении диапазона random(x,y) стабильность возрастает но турель уже превращается в "покоцанную" которая работает на честном слове.
Ну, значит, в GZDoom обработка акторов и их взаимных изменений происходит в другом порядке. Сначала все независимо друг от друга прогоняются по стейтам текущего тика, а уже после этого к ним применяются взаимные изменения. Тогда этот фокус не пройдёт.
Upd: Есть смешное решение.
1. Допустим, имп стоит 40 рублей. В цель прилетает 4 пуффа, срабатывают абсолютно одновременно, и в сумме должны дать игроку 160 рублей.
2. Одновременно каждый пуфф выдал цели CountItem. У дохлого импа их 4 штуки.
3. После небольшой задержки каждый пуфф знает, во сколько раз он ошибся.
4. Каждый пуфф даёт игроку по 40/4 = 10 рублей, суммарно игрок получает 40.
Здесь распределённая одновременность обуздана по всем правилам, взаимных конфликтов нет, всё чики-пуки. Сложность только с возникающими в процессе неудобными дробями. Но здесь уже есть масса вариантов, как её решать. Можно, например, заменить рубли на биткоины, состоящие из миллиона сатоши, уменьшив ошибку округления во много раз. Можно выдавать всю кассу не сразу игроку, а подыхающему монстру, и запустить от его имени какой-нибудь скрипт, который поделит кассу на количество CountItem-ов и уже полученное значение выдаст игроку.
Главное, что тут нет войны с логикой: мы не пытаемся её обмануть, подменив переменную в процессе обработки объектов. Мы входим с ней в гармонию и используем данные об ошибке, как инструмент для ликвидации последствий ошибки. Это прельстиво и математикоугодно.
А вот теперь самое время дообмазать это механизмом RewardActivatorBlocker. Если в цель в какое-то мгновение прилетело N пуффов - это будет уже железобетонная гарантия, что в будущем N останется равным N.
только теперь ещё добавилась проблема "левых" значений, создаваемых дробями:
Ну здесь самое простое - платить игроку не сразу в рублях, а в державнiх карбованцах. Игрок время от времени проверяет, есть ли у него карбованцi, и если да - обменивает их по курсу 1000 за рубль. Таким образом, допустим, в случае деления 7 рублей на 3 пуффа игрок получает 6999 карбованцiв, которые будут округлены до 7 рублей. Вероятность словить ошибку здесь крайне мала.
... и тут я такой вспоминаю про битовые сдвиги и чсв сразу так припухаэ:
Скрытый текст:
Actor TurretPuff : BulletPuff
{
+PUFFONACTORS
+HITTRACER
+PUFFGETSOWNER
var int user_lootClass;
var int user_lootClassResult; //Окончательный результат после манипуляции всеми избыточными значениями мультилута
States
{
Spawn:
TNT1 A 0 NoDelay A_CheckFlag("NOBLOOD","XDeath",AAPTR_TRACER)
Goto Super::Spawn
XDeath:
TNT1 A 1 A_ChangeFlag("ALLOWPARTICLES",0)
TNT1 A 1 A_GiveInventory("RewardMistakeCounter",1,AAPTR_TRACER) //Выдаём токен-свидетель, типа я таки влупил по этому трэйсеру
TNT1 A 0
{
If(A_JumpIfHealthLower(1,"GiveReward",AAPTR_TRACER)||A_CheckFlag("CORPSE","GiveReward",AAPTR_TRACER)){Return state("GiveReward");}
Else{Return state("");}
}
TNT1 A 0 A_TakeInventory("RewardMistakeCounter",1,0,AAPTR_TRACER) //Лан, возьму назад коли ТРЭЙСЕР ещё жив.
Stop
GiveReward:
TNT1 A 0 A_PlaySound("brain/pain",0)
TNT1 A 0
{
If(CheckClass("ZombieMan",AAPTR_TRACER,1)){user_lootClass=1;Return state("");}
Else If(CheckClass("ShotgunGuy",AAPTR_TRACER,1)){user_lootClass=2;Return state("");}
Else If(CheckClass("ChaingunGuy",AAPTR_TRACER,1)){user_lootClass=4;Return state("");}
Else If(CheckClass("DoomImp",AAPTR_TRACER,1)){user_lootClass=3;Return state("");}
Else If(CheckClass("Demon",AAPTR_TRACER,1)){user_lootClass=4;Return state("");}
Else If(CheckClass("LostSoul",AAPTR_TRACER,1)){user_lootClass=0;Return state("");}
Else If(CheckClass("Revenant",AAPTR_TRACER,1)){user_lootClass=7;Return state("");}
Else If(CheckClass("Cacodemon",AAPTR_TRACER,1)){user_lootClass=6;Return state("");}
Else If(CheckClass("HellKnight",AAPTR_TRACER,1)){user_lootClass=7;Return state("");}
Else If(CheckClass("BaronofHell",AAPTR_TRACER,1)){user_lootClass=8;Return state("");}
Else If(CheckClass("Arachnotron",AAPTR_TRACER,1)){user_lootClass=7;Return state("");}
Else If(CheckClass("Fatso",AAPTR_TRACER,1)){user_lootClass=8;Return state("");}
Else If(CheckClass("Archvile",AAPTR_TRACER,1)){user_lootClass=9;Return state("");}
Else If(CheckClass("SpiderMastermind",AAPTR_TRACER,1)){user_lootClass=10;Return state("");}
//Else If(CheckClass("Cyberdemon",AAPTR_TRACER,1)){user_lootClass=10;Return state("");}
Else{user_lootClass=10;Return state("");} //Значит остался только Кибер
}
TNT1 A 0 {user_lootClassResult=(user_lootClass*65535)/(CountInv("RewardMistakeCounter",AAPTR_TRACER)*65535);} //Основная манипуляция. Для начала переводим лут-юзерварку и ко-во токен-свидетелей в 16-шку, теперь остатки нам не страшны. А результат деления присваиваем новой выарке...
TNT1 A 0 {user_lootClassResult/65535;} //... которую переводим обратно в 10-ную.
TNT1 A 0 A_GiveToTarget("Cell",user_lootClassResult,AAPTR_MASTER)
//TNT1 A 0 A_TakeInventory("RewardMistakeCounter",1,0,AAPTR_TRACER)
TNT1 A 0 A_RearrangePointers(AAPTR_DEFAULT,AAPTR_DEFAULT,AAPTR_NULL)
TNT1 A 0 {user_lootClass=0;}
Stop
}
}
Actor RewardMistakeCounter : Inventory{Inventory.MaxAmount 0x7FFFFFFF}
И вот впервые всё идёт офигенно... пока ВНЕЗАПНО:
ФААА~
Ну почему не 105?!
А вот теперь самое время дообмазать это механизмом RewardActivatorBlocker. Если в цель в какое-то мгновение прилетело N пуффов - это будет уже железобетонная гарантия, что в будущем N останется равным N.
Замхал блок непосредственно в пуфф. Бучие дроби таки умудряются просачиваться: 104, 107, 185.
Добавлено спустя 1 день 19 часов 3 минуты 12 секунд:
Какой механизм запрещает выполнять атаку FRIENDLY монстру если между ним и целью находится игрок? Т. е. если он не входит в стэйт атаки значит где-то проваливается выполнение A_Chase.
Как это можно обойти (за исключением триггера рэйндж атаки через MeleeRange)? Граф сказал что это намеренное поведение заданное P_HitFriend и обойти это на данный момент невозможно.
Сорс P_HitFriend()
Это точно граф сказал??? Я просто не очень понял вопрос - тебе надо чтобы дружественный не стрелял если ты попал под прицел, когда он кого-то "шпилит" или наоборот (просто в обычном режиме друж. монстр НЕ прекращает вести "тупой" огонь, даже если его друж игрок попал под "струю")?
Если НУЖНО чтобы прекращал стрелять, то у меня так прописано:
SENT A 0 A_CheckLOF("MissileC", CLOFF_SKIPFRIEND|CLOFF_JUMPENEMY|CLOFF_JUMPOBJECT|CLOFF_JUMPNONHOSTILE|CLOFF_JUMP_ON_MISS)
goto See1
Один из флагов как раз заставляет остановить атаку по врагу, если друг попал под "струю"
или наоборот (просто в обычном режиме друж. монстр НЕ прекращает вести "тупой" огонь, даже если его друж игрок попал под "струю")?
Что за режим такой? У меня проблема как раз в том что монстр прекращает вести огонь и A_CheckLOF тут НЕ помогает. Т. е. для движущегося монстра это в принципе не проблема, - обошёл игрока и всех делов, тогда как стационарные тупо не могут отойти.
Самая обычная ситуация - то что ты рассказываешь для меня новость и если ты прав, нафига вообще нужен флаг CLOFF_SKIPFRIEND тогда? или я чего то не понимаю опять...
Монстр никогда (по умолчанию и пока не установлено иное) не останавливает атаку, даже если союзник-игрок пересекает линию стрельбы...
У меня реализован СентриГан - и именно благодаря A_ckecklof c флагами он работает именно так, как нужно и прекращает стрельбу если союзник на линии огня
Возможно нечто новое опять ввели с ЗСриптом в новых версиях...
У меня реализован СентриГан - и именно благодаря A_ckecklof c флагами он работает именно так, как нужно и прекращает стрельбу если союзник на линии огня
Сдаётся мне что ты просто не обращал внимание на то что ФРЕНДы и так не стреляют без всяких условий, если их ЛоФ пересекает другой ФРЕНД или союзный игрок. Либо у тя какой-то изощрённый С-Ган.
Полагаю что ФРЕНД-флаги A_ckecklof не предусматривают обхода дефолтного поведения, а предназначены для других проверок и\или джампов в иные стэйты НЕ подразумевающие наличие дистанционной атаки.
Так, я чего-то не понимаю.
В первой версии моего недоделанного мода про фошистов ещё во времена Zdoom 2.1.7 имелась проблема того, что френдли мобы мочили друг друга, для чего пришлось городить громоздкую систему тестовых снарядов, улетающих обратно в солдата, чтобы разрешить ему выстрел. Функции A_CheckLOF тогда не было. Позже она появилась, и жить стало легче. Но вылезла другая проблема: танки перестали стрелять, потому что башня находилась внутри коллижен-бокса шасси - и пришлось вешать на танк GHOST-флаг, а на A_CheckLOF вешать CLOFF_IGNOREGHOST, чтобы хоть как-то работало.
Но как минимум в GZdoom 3.2.1 танки всё ещё стреляли, несмотря на то, что выстрел происходил сквозь союзника, и при жёстком ограничении его бы быть не могло.
Герр Смертоносец Я могу сказать только одно - создав когда-то давным давно СентриГан, он без зазрения совести мочил меня, если я вставал на линии огня, что меня сильно бесило - и как ты и сказал, тогда A-CheckLof еще не родилась. После она появилась и эта проблема исчезла, т.к. появилась возможность внутри стейта делать проверку и прыжок - собственно благодоря флагу CLOFF_SKIPFRIEND. О чем говорит Void Weaver - мне не известно... может быть "темные силы" зскрипта...
Во-первых, хватит приплетать сюда зскрипт. В GZDoom 2.2.0 разумеется никакой зскрипт и не ночевал. Нынешние сорсы, ссыли на которые приведены выше, это всего-лишь репликация сей фичи на зскрипте. Т. е. я допускаю что рестрикция френдли файра появилась в ещё более ранней версии гоззы нежели 2.2, но к зскрипту это не имеет прямого отношения.
Во-вторых, нет проблем в том чтобы запретить атаку через A_CheckLOF, - проблема как раз в обратном. Разумеется нет ничего сложного чтобы запретить атаку или вызвать джамп куда-то ещё:
Missile:
CPOS E 10 A_FaceTarget
//TNT1 A 0 A_CheckLOF("See",CLOFF_JUMPENEMY,65000,0,0,0,Height/4,0,AAPTR_TARGET) //Будет всегда обрывать атаку
CPOS FE 4 Bright A_CPosAttack
CPOS F 1 A_CPosRefire
//TNT1 A 0 A_CheckLOF("Death",CLOFF_SKIPFRIEND,65000,0,0,0,Height/4,0,AAPTR_TARGET) //Стрелок сдохнет как только игрок сойдёт с линии огня
Goto Missile+1
Ну и в-третьих, да, A_CheckLOF может обойти этот запрет но только в том случае если последовательность не содержит в себе чек на видимость цели. Например штатная A_CPosRefire подразумевает возврат в See если не видно цели и в случае с FRIENDLY на линии огня всё время будет возвращать в See:
See:
CPOS AABBCCDD 3
{
A_Chase("","Missile",CHF_DONTMOVE);
A_FaceTarget;
If(A_CheckLOF("Missile",CLOFF_JUMPFRIEND,65000,0,0,0,Height/4,0,AAPTR_TARGET)){Return state("Missile");}
Else{Return state("");}
}
Loop
Missile:
CPOS E 10 A_FaceTarget
CPOS FE 4 Bright A_CPosAttack
CPOS F 1 A_CPosRefire //Здесь атака будет постоянно обрываться
Goto Missile+1
Итог: я хз как было раньше, но как минимум с GZDoom 2.2 игра хардкожено расценивает наличие FRIENDLY на линии огня другого FRIENDLY как препятствие.
И да, обходится по A_CheckLOF("",CLOFF_JUMPFRIEND), но с оговорками.
Причём зум реализован очень интересным образом.При задействовании альатаки включается зум ( трёхкратный вроде) если удерживать клавишу приближение увеличивается до нужного.Можно прямо попасть импу в глаз) Ещё тап на альтернативку- оптика выключается. Что хотелось бы? Вырезать этот зум вместе с прицелом так,чтобы было возможно использовать его отдельно и с любым оружием,назначив активацию на произвольную кнопку ( не альтернативной атаки) Пробовал по разному- не хочет работать.Кто нибудь может помочь?Буду вам благодарен.