Неверно в корне, ибо при таком подходе у тя никогда не получится нормально распараллелить действия и синхронизировать анимацию.
Если таки запиливать эту фичу на декоре то необходимо использовать:
а) A_Overlay и её родственные функции или, если нужна повышенная обратная совместимость, базовую A_GunFlash; и
б) GetPlayerInput
В общих чертах механизм алгоритма следующий. В КАЖДЫЙ КАДР желаемой анимационной последовательности (например Reload) прописываем чек на нажатие определённой клавиши (или даже их сочетания - так можно замутить комбо!) через GetPlayerInput, => если клавиша была нажата то вызываем через A_Overlay или A_GunFlash кастомный стэйт с анимацией удара ногой например, разумеется в этом стэйте также полноценно прописываются все А_Функции - урон, звуки, эффекты и т. д. Иными словами A_Overlay и A_GunFlash позволяют "расщеплять" оружие и выполнять параллельно совершенно различные действия.
Пример использования GetPlayerInput+A_Overlay - готовый шотган с возможностью стрельнуть ракетой В ЛЮБОЙ МОМЕНТ АНИМАЦИИ. Т. е. идёт обычный выстрел но параллельно можно шмальнуть ракетой.
Та же схема и для релоада и параллельного удара с ногирукибфгисапоги...
------
А учитывая что из ГанФлэшОверлэй можно вызвать другой ГанФлэшОверлэй из которого можно вызвать ещё ГанФлэшОверлэй... то открываются и вовсе фантастические перспективы оружейного дела. Т .е. через эти функции можно вызвать просто колоссальный каскад различных действий и анимаций всего лишь с одного выстрела. Ну или даже просто достав или перезарядив оружие.
Добавлено спустя 1 час 53 минуты 17 секунд:
Скрытый текст:
Fire:
TNT1 A 0 A_JumpIfInventory("ZoomToken",1,"FireScope") //Если есть хотя бы 1 зум-токен, значит это зум атака
TNT1 A 0 A_PlayWeaponSound("Weapons/RifleFire")
TNT1 A 0 A_AlertMonsters(8192,AMF_TARGETEMITTER) //Обычная атака слышна хорошо
RIFG A 0 A_GunFlash
RIFG A 4 A_FireBullets(1.5,1.5,1,10,"BulletPuff",FBF_NORANDOMPUFFZ/*|FBF_USEAMMO|FBF_NORANDOM*/,16384)
RIFG BCDCB 2
RIFG A 3
TNT1 A 0 A_GiveInventory("CurrentMagRemainsToken") //Используем для того что бы знать сколько патронов нужно ДОЗАРЯДИТЬ
TNT1 A 0 A_CheckForReload(8,"Ready") //8 - при магазине на 8 патронов
//==================БЛОК ПЕРЕЗАРЯДКИ==================//
//* //Закрой этот блок для отключения магазинной перезарядки.
//НЕ ЗАБУДЬ ВКЛЮЧИТЬ ПОТРЕБЛЕНИЕ ПАТРОНОВ ОТ ОБЫЧНЫХ АТАК!!!
Reload: //Дефолтный стэйт перезарядки, в данном случае используем для перезарядки и ДОЗАРЯДКИ оружия!
TNT1 A 0 A_WeaponReady(WRF_NOFIRE|WRF_DISABLESWITCH|WRF_NOSWITCH|WRF_NOBOB) //Запрещаем смену оружия во время перезарядки чтобы смена оружия не сломала алгоритм перезарядки!
TNT1 A 0 A_JumpIf(CountInv("CurrentMagRemainsToken")==0,"Ready") //Если магазин полон, то возвращаемся к Рэди-стэйтам
TNT1 A 0 A_ZoomFactor(1.0) //Нормализуем зум на время перезарядки
TNT1 A 0 A_SetSpeed(1) //Нормализуем скорость на время перезарядки
//Помести сюда соответствующую анимационную последовательность и звуки
ReloadSequence:
RIFR ABCD 3
{
If(CountInv("KickToken")>0){Return state("");} //Если кик-токена ещё нет, то...
Else If(GetPlayerInput(MODINPUT_OLDBUTTONS)&BT_USE) //... можно проверять нажата ли кнопка USE, если нажата, то...
{
A_GiveInventory("KickToken"); //... даём кик-токен - это значит что пошёл удар ногой и пока он не завершится атаковать повторно нельзя, а затем...
A_Overlay(2,"ReloadLegAttack"); //... затем вызываем собственно оверлэй удара с ноги
Return state(""); //... а тем временем продолжается анимация перезарядки
}
Else{Return state("");} //Если же кнопка НЕ была нажата то продолжаем анимацию перезарядки
}
TNT1 A 0 A_PlayWeaponSound("weapons/sshoto")
RIFR EFGGGGGGGGIK 3
{
If(CountInv("KickToken")>0){Return state("");}
Else If(GetPlayerInput(MODINPUT_OLDBUTTONS)&BT_USE)
{
A_GiveInventory("KickToken");
A_Overlay(2,"ReloadLegAttack");
Return state("");
}
Else{Return state("");}
}
TNT1 A 0 A_PlayWeaponSound("weapons/sshotc")
RIFR LDCBA 3
{
If(CountInv("KickToken")>0){Return state("");}
Else If(GetPlayerInput(MODINPUT_OLDBUTTONS)&BT_USE)
{
A_GiveInventory("KickToken");
A_Overlay(2,"ReloadLegAttack");
Return state("");
}
Else{Return state("");}
}
TNT1 A 0 A_PlayWeaponSound("weapons/sshot1")
SVDR MNOPQRSTSRQPONM 3
{
If(CountInv("KickToken")>0){Return state("");}
Else If(GetPlayerInput(MODINPUT_OLDBUTTONS)&BT_USE)
{
A_GiveInventory("KickToken");
A_Overlay(2,"ReloadLegAttack");
Return state("");
}
Else{Return state("");}
}
//^Помести сюда соответствующую анимационную последовательность и звуки
TNT1 A 0 A_TakeInventory("RifleAmmo",CountInv("CurrentMagRemainsToken")) //Забираем столько патронов сколько у нас "накопилось" токенов отстрелянных патронов
TNT1 A 0 A_TakeInventory("CurrentMagRemainsToken") //Обнуляем токены растраты патронов, теперь магазин полон
TNT1 A 0 A_ResetReloadCounter
TNT1 A 0 A_JumpIfInventory("ZoomToken",2,2) //Если есть 2 зум-токена то...
TNT1 A 0 A_Jump(256,"Check2ndZoomTokenForSlowDown")
TNT1 A 0 A_ZoomFactor(8.0) //... то увеличиваем зум до 8...
TNT1 A 0 A_SetSpeed(Speed/16) //Замедляем ходьбу в 16 раз //Заблочь строку если не хочешь замедления игрока в режиме зума
Goto ReadyScope //... и возвращаемся к ReadyScope, иначе...
Check2ndZoomTokenForSlowDown:
TNT1 A 0 A_JumpIfInventory("ZoomToken",1,1) //... иначе проверяем есть ли хотя бы 1 зум-токен. Если есть то...
Goto Ready
TNT1 A 0 A_ZoomFactor(2.0) //... то увеличиваем зум до 2...
TNT1 A 0 A_SetSpeed(Speed/4) //Замедляем ходьбу в 4 раза //Заблочь строку если не хочешь замедления игрока в режиме зума
Goto ReadyScope //... и возвращаемся к ReadyScope
//*/ //^Закрой этот блок для отключения магазинной перезарядки.
//==================^БЛОК ПЕРЕЗАРЯДКИ^==================//
Goto Ready
ReloadLegAttack:
SRLA ABCDEFGH 2 A_CustomPunch(2*random(1,10),1,0) //Используй кастомпанч, иначе лишишься всей амуниции за пару пинков
TNT1 A 0 A_TakeInventory("KickToken") //Анимация пинка завершилась, изымаем токен и можем пинать повторно
Stop
Не забываем прописать кик-токен Actor KickToken : Inventory {Inventory.MaxAmount 1}
Результат:
Ну и в пинок можно ещё замхать такой пуфф для откидывания врагов:
Actor ThrustPuff : BulletPuff
{
+NODECAL
States
{
Melee:
TNT1 A 0 A_ChangeFlag("ALLOWPARTICLES",0)
TNT1 A 0 A_RadiusThrust(500,8,RTF_NOIMPACTDAMAGE) //Пинок откидывает врагов
Goto Super::Melee
}
}
при подъеме пушки (Select) вызываем зацикленный оверлей, а селектовский Loop, если он есть, продолжаем в другом месте, например, в Select1.
и чек на желание напнуть пишется не каждый раз для каждого кадра пушки, а лишь один раз, конкретно в этом отдельном зацикленном стейте для оверлея, вся остальная пушка получается нетронутой.
Это годится если дозволяется выполнять действие в любом стэйте оружия, генерализация так ск-ть. А если какое-то действие разрешено выполнять только в конкретной последовательности? А хотя да, можно напичкать фоновый Оверлэй токен-чеками разных стэйтов, а в самих стэйтах ставить токен-маркеры: стэйт начался - дали уникальный токен, завершился - изъяли. А так да, - Оверлэй атаки из фонового Оверлэя. -----
Жаль что для регулярных акторов так и не запилили подобие Оверлэя или ГанФлэша.
У меня недавно была такая ошибка (только без "Floating point value expected for key x")
Посмотри, чтобы размер секторов (или длина линий) не превышали значение 32767
(это макс. значение переменной типа short int, вероятно где-то происходит переполнение (overflow))
Но повторюсь, в моём случае не было сообщения "Floating point value expected for key x"
при подъеме пушки (Select) вызываем зацикленный оверлей, а селектовский Loop, если он есть, продолжаем в другом месте, например, в Select1.
и чек на желание напнуть пишется не каждый раз для каждого кадра пушки, а лишь один раз, конкретно в этом отдельном зацикленном стейте для оверлея, вся остальная пушка получается нетронутой.
Да, так значительно компактней.
Select:
TNT1 A 0 A_Overlay(3,"KeyCheckerOverlay")
SelectL:
RIFG A 1 A_Raise
Loop
Reload: //Дефолтный стэйт перезарядки, в данном случае используем для перезарядки и ДОЗАРЯДКИ оружия!
TNT1 A 0 A_WeaponReady(WRF_NOFIRE|WRF_DISABLESWITCH|WRF_NOSWITCH|WRF_NOBOB) //Запрещаем смену оружия во время перезарядки чтобы смена оружия не сломала алгоритм перезарядки!
TNT1 A 0 A_JumpIf(CountInv("CurrentMagRemainsToken")==0,"Ready") //Если магазин полон, то возвращаемся к Рэди-стэйтам
TNT1 A 0 A_ZoomFactor(1.0) //Нормализуем зум на время перезарядки
TNT1 A 0 A_SetSpeed(1) //Нормализуем скорость на время перезарядки
//Помести сюда соответствующую анимационную последовательность и звуки
ReloadSequence:
TNT1 A 0 A_GiveInventory("ReloadingToken") //Добавляем токен который указывает фоновому оверлэю что начался процесс перезарядки
RIFR ABCD 3
TNT1 A 0 A_PlayWeaponSound("weapons/sshoto")
RIFR EFGGGGGGGGIK 3
TNT1 A 0 A_PlayWeaponSound("weapons/sshotc")
RIFR LDCBA 3
TNT1 A 0 A_PlayWeaponSound("weapons/sshot1")
SVDR MNOPQRSTSRQPONM 3
TNT1 A 0 A_TakeInventory("ReloadingToken") //Изымаем токен перезарядки, - оверлэй пинка не вызовется в других стэйтах
//^Помести сюда соответствующую анимационную последовательность и звуки
KeyCheckerOverlay:
TNT1 A 1
{
If(CountInv("KickToken")>0||CountInv("ReloadingToken")<1){Return state("");} //Если кик-токена ещё нет И ЕСТЬ релоад-токен, то...
Else If(GetPlayerInput(MODINPUT_OLDBUTTONS)&BT_USE) //... можно проверять нажата ли кнопка USE, если нажата, то...
{
A_GiveInventory("KickToken"); //... даём кик-токен - это значит что пошёл удар ногой и пока он не завершится атаковать повторно нельзя, а затем...
A_Overlay(2,"ReloadLegAttack"); //... затем вызываем собственно оверлэй удара с ноги
Return state(""); //... а тем временем висим в фоновом режиме; продолжается анимация перезарядки
}
Else{Return state("");} //Если же кнопка НЕ была нажата то продолжаем работать в фоновом режиме
}
Loop
//ВАРНИНГ! Фоновый и временный оверлэи должны находиться на разных слоях!!!
ReloadLegAttack:
SRLA ABCDEFGH 2 A_CustomPunch(2*random(1,10),1,0,"ThrustPuff") //Используй кастомпанч, иначе лишишься всей амуниции за пару пинков
TNT1 A 0 A_TakeInventory("KickToken") //Анимация пинка завершилась, изымаем токен и можем пинать повторно
Stop
Landsberg Я так понимаю этот вопрос касается кода снайперки?
Учитывая что нынешний код использует Reload для перезарядки, Fire для стрельбы, а Altfire для смены режимов зума, то пожалуй лучший вариант для пинка вместо Use задействовать команды BT_USER1\BT_USER2\BT_USER3\BT_USER4 - они как раз свободны по умолчанию и на них можно назначить любую удобную клавишу в настройках управления порта. Например ту же клавишу 'Q' или 'E'.
Разумеется получит, поскольку совет выше касается удаления уже имеющегося оружия из инвентаря игрока но не из игры. Тебе стоило сформулировать вопрос точнее.
Для удаления уже имеющегося стандартного арсенала на уровнях и избежания получения его через читы лучше использовать 'replaces' кейворд замещающий один актор другим.
Как дать декорейту понять, где искать спрайты в папках pk3?
Просто спрайты должны лежать в папке "Sprites". Ничего больше делать не надо.
Также будут опознаны спрайты, лежащие в подпапках, находящихся в папке "Sprites".