alekv theleo_ua Ок, это вроде понятно. Другой вопрос --- можно ли это делать как-нибудь не случайно (проверяя некоторое условие)? Например, я делаю актора-морпеха, который на дальние расстояния стреляет из рейлгана, на средние --- из плазмагана, а в упор --- из BFG. В DECORATE же нет условного ветвления, или я неправ? Всё понял.
Создаю класс игрока. Работа почти закончена, осталось лишь запретить игроку пользоваться оружием, когда он находится в присяди. Читал в ЗДумвики что стейта "Приседания" как такового нельзя организовать - не поддерживается движком, поэтому есть опция "Player.CrouchSprite". Поэтому реализовываю через добавление и проверку инвентаря. То есть, сначала объявляю нужный "предмет".
Actor IsCrouched: Inventory
{
inventory.maxamount 1
}
Затем выдаю игроку "предмет" через декорейт. Вот тут главная заковыка, возможно я выбрал неверные параметры, по которым определять, сидит игрок или нет.
ACTOR BLAHBLAHBLAH : PlayerPawn
{
...
States
{
Spawn:
SSNK A 0 A_JumpIfInventory("HasWeaponEquipped",1,"IdleWWeapon")
SSNK A 0 A_JumpIfInventory("HasCigarettesEquipped",1,"Smoke")
SSNK A 0 A_JumpIf("Player.ViewHeight < 30", "Crouch")
SSNK A 1
Loop
Crouch:
SNKC A 0 A_Giveinventory("IsCrouched",1)
...
}
Затем, код на оружии, которое надо убрать при приседе.
ACTOR Beretta : Pistol replaces Pistol
{
Inventory.Pickupmessage "Picked up an beretta"
States
{
Ready:
TNT1 A 0 A_JumpIfInventory("IsCrouched",1,"Deselect")
PISG A 1 A_WeaponReady
Loop
...
Не работает. Что посоветуете сделать? По сути моя главная задача - не дать игроку выбрать определенное оружие, если он в присяди, а если оно уже выбрано - переключиться на другое. Может есть более простой способ сделать это, нежели я пытаюсь, или я допустил ошибку в попытках определения?
MrTrololosh Player.ViewHeight - это не переменная, а неизменяемый параметр актора. В процессе приседания ни он, ни физическая высота с точки зрения кода не меняются, поэтому A_JumpIf его не видит.
Копать надо через ACS, который бы вызывался вместо A_JumpIfInventory. Код примерно такой:
int buttons = GetPlayerInput(-1, INPUT_BUTTONS);
if (buttons & BT_CROUCH)
{
SetWeapon("Fist");
}
Хочу чтобы после замораживания конкретного монстра он после "ледяного взрыва" генерил не стандартные icechunks, а мои собственные акторы (переопределение актора IceChunk не катит, так как другие монстры должны спавнить стандартный IceChunk). Проблема в том, что если я напишу например так:
Ice: TROO V 5 A_FreezeDeath TROO V 1 A_FreezeDeathChunks wait
то придется указывать спрайты (тобишь фреймы), а фреймов там, во-первых, очень много, а во-вторых, придется париться с тем, чтобы помнить последний фрейм, с которого был прыжок на ice, что тоже адский геморрой, если учесть "количество фреймов" у монстра.
Каким образом можно переопределить Ice стейт, чтобы он продолжал использовать "последний фрейм, который был перед попаданием в Ice стейт" ?
Ещё один вопрс. Как в основном правильно прятать секреты ? Т.е. Я думаю что обычное изменение тестуры в стене уже никого не удивит а рычаг который открывает дверь за 100500 км от самого рычага как-то уж не очень гуманно.
Нет такого понятия - "правильно" прятать. Это уже все зависит от твоего стиля маппинга и мышления. Каждый спрячет по разному, например я, как сторонник Дюковского реализма, спрячу рычаг от открытия оружейной, в одном из кабинетов. Если ты делаешь карты под классический стиль - просто пройди дум/дум2 еще разок, чтобы перенять немного стиля. В основном, тамошние секреты, это именно стена немного с иной текстурой, или же комната, где в которой берешь предмет, и на тебя сразу нападает куча монстров, и то место, откуда они вылезли, считается секретом. Не стесняйся удивить игрока, все ограничено лишь твоим мышлением. А вообще, хорошо спрятать - это когда прячешь прямо под носом Но это так, к слову.
theleo_ua:
Каким образом можно переопределить Ice стейт, чтобы он продолжал использовать "последний фрейм, который был перед попаданием в Ice стейт" ?
Возможно, поможет этот метод.
Ice:
"####" "#" 5 A_FreezeDeath
Именно так как я написал, в кавычках. Решетки нужны для повторения предыдущего фрейма, который рендерился, в твоем случае, сразу перед входом в стейт.
1) Как сделать, чтобы труп либо актор с Health<=0 умел детектить что по нему попал проджектайл либо любая другая атака (например хитскан) и прыгал на соответствующий стейт?
2) Как определить, что актор-труп находится на воде? Waterlevel не пашет, он всегда ноль, хоть на земле хоть на воде. В идеале также определять что актор над водой (т.е. floorz актора находится на воде)
2) Как определить, что актор-труп находится на воде? Waterlevel не пашет, он всегда ноль, хоть на земле хоть на воде. В идеале также определять что актор над водой (т.е. floorz актора находится на воде)
Возможно это поможет > CheckActorFloorTexture т.е. проверяет на какой текстуре стоит игрок...
theleo_ua:
1) Как сделать, чтобы труп либо актор с Health<=0 умел детектить что по нему попал проджектайл либо любая другая атака (например хитскан) и прыгал на соответствующий стейт?
если не особо важно что у трупа хелсов 0, то по моим догадкам можно заюзать switchableDecoration с флагом bumpspecial (только в теории..) Или вместо обычного трупа при смерти монстра спавнить не убивающегося актора трупа который будет делать что тебе надо. Или совместить 2 варианта, что более похоже на рабочий способ, т.е. после смерти монстра спавнится труп наследованный от switchable decoration и флагом bumpspecial что значит когда в такого трупа попадут чем либо то он перепрыгнет в стейт active, а там уже делай чего душе угодно. Может есть и по проще варианты тут уже тестить надо, может в декорейте можно в стейте death делать цикл и чекать как-то..
Возможно это поможет > CheckActorFloorTexture т.е. проверяет на какой текстуре стоит игрок...
Спасибо, посмотрю чуть позже
alekv:
Или вместо обычного трупа при смерти монстра спавнить не убивающегося актора
Суть вот в чем:
Скрытый текст:
мне нужно, чтобы актор, которого заморозили, ждал рандомное время (например от 5 до 10 секунд) по следующему принципу: 1) Если ничего не происходит, то через отведенное время дохнет 2) Если его продамажили, то дохнет сразу же
такой код при срабатывании таймера или дамажинге монстра спавнит стандартные icechunks. Теперь я хочу, чтобы спавнились не стандартные icechunks, а мои кастомные акторы вместо них. Код делаю уже такой:
"####" "#" 5 A_GenericFreezeDeath "####" "#" 1 //убираем A_FreezeDeathChunks чтобы не спавнились стандартные icechunks "####" "#" бла бла бла (здесь идет мой кастомный код смерти)
такой код вызывает вышеописанную проблему: если монстра атакуешь, он игнорирует демейж. Так как используется A_GenericFreezeDeath, то я не могу:
alekv:
вместо обычного трупа при смерти монстра спавнить не убивающегося актора
либо я неправильно тебя понял. Также мне не очень понятно, как в таком случае применить switchabledecoration.
А отказаться от A_GenericFreezeDeath не могу по причине того, что она делает ice translation для 3D модели (я не знаю, какими другими способами сделать ice транслейшн для "труколорной текстуры")
Также напомню, что замороженный монстр должен отображать предыдущий фрейм, с которого он попал на ice state, что я делаю через "####" "#" , соответственно если я на стадии заморозки уберу текущего актора и заменю другим, то анимация изменится или исчезнет, что меня не устраивает.
Пока я вижу только один способ решения проблемы: пускать ACS, который спавнит с uniquetid специального невидимого актора поверх текущего (новый актор должен быть на несколько "пикселей" толще и выше, чтобы атаки действовали строго на него, а также с 1хп), и каждый тик двигает нового актора поверх старого, и соответственно при детекте, что у нового актора "health <=0", передает эту информацию старому актору через uservar и терминейтит скрипт. Просто такой способ немного геморный, думал может проще способы есть.
Возможно это поможет > CheckActorFloorTexture т.е. проверяет на какой текстуре стоит игрок...
вот такой ACS код
if (CheckActorFloorTexture(0, "FLTWAWA1")) {SetResultValue(1);} else {SetResultValue(0);}
крашит и гоззу 2.0.0.5 и здум 2.7.1 / 2.8pre (ивад heretic.wad)
MrTrololosh:
Нечто вроде системы добивания?
Стандартная система добивания замороженного монстра из хексена: Frozen death
MrTrololosh:
Такое вполне грамотно реализовано в Брутал доме, ты можешь поискать там, в коде любого монстра.
Спасибо, посмотрю
Добавлено спустя 3 часа 23 минуты 56 секунд:
MrTrololosh:
Такое вполне грамотно реализовано в Брутал доме, ты можешь поискать там, в коде любого монстра.
Посмотрел, и на мое удивление, там спавнится дополнительный актор по аналогии как я описывал выше (разве что не учитывается нюанс фреймов, так как спрайт заморозки в бруталдуме всегда один (в рамках одного актора) ).
В общем у меня получилось реализовать способом, который я описал выше, и больше всего удивило то, что актору, которого спавним поверх, надо сразу на стадии spawn делать a_die, иначе для убивания замороженного монстра потребуется делать 2 выстрела вместо одного. Так и не понял, почему
З.Ы. А каким способом предполагается замораживать монстров в бруталдуме? Я, для проверки заморозки, "костылями" давал себе второе оружие мага из хексена
if (CheckActorFloorTexture(0, "FLTWAWA1")) {SetResultValue(1);} else {SetResultValue(0);} крашит и гоззу 2.0.0.5 и здум 2.7.1 / 2.8pre (ивад heretic.wad)
Возможно потому что ты вызываешь SetResultValue 2 раза, а надо 1 Вот как надо записать(скрипт 999) скрипт 998 просто для проверки что значение передается правильно.
Script 998 Enter
{
while(true){
Int InWater = ACS_ExecuteWithResult(999,0);
If(InWater == yes)
PrintBold(s:"inwater");
else PrintBold(s:"out water");
delay(1);}
}
script 999 (int water)
{
if (CheckActorFloorTexture(0, "BRDR_BR2")) water=1;
else water=0;
SetResultValue(water);
}
Если надо в декорейте то
States{Spawn: TNT1 A 1 A_JumpIf(CallACS(999)==true,"inwater") //если текстура воды под игроком
loop
... что-то в этом духе..
Да и я не много ошибся, проверяется текстура под игроком, а не на которой он стоит, т.е. игрок может стоять и не на полу, но текстура проверится и определиться. Думаю в связке waterline и GetActorZ или FloorZ что-то сделать можно
Да и я не много ошибся, проверяется текстура под игроком, а не на которой он стоит, т.е. игрок может стоять и не на полу, но текстура проверится и определиться. Думаю в связке waterline и GetActorZ или FloorZ что-то сделать можно
в моем случае все гораздо проще: стейт Bounce.Floor
alekv:
Возможно потому что ты вызываешь SetResultValue 2 раза, а надо 1
Можно вызывать хоть 10 раз. Специально убрал один из них, и все равно крашится (а раньше использовал многократные сетрезалты и все работало без крашей)
ZZYZX:
CallACS требует строку-название скрипта. Потому что это алиас к ACS_NamedExecuteWithResult.
все, теперь заработало, всем спасибо за хелп
Добавлено спустя 2 часа 37 минут 10 секунд:
theleo_ua:
вот такой ACS код
if (CheckActorFloorTexture(0, "FLTWAWA1")) {SetResultValue(1);} else {SetResultValue(0);}
крашит и гоззу 2.0.0.5 и здум 2.7.1 / 2.8pre (ивад heretic.wad)
alekv:
Возможно потому что ты вызываешь SetResultValue 2 раза, а надо 1 Вот как надо записать(скрипт 999) скрипт 998 просто для проверки что значение передается правильно.
Скрытый текст:
Script 998 Enter { while(true){ Int InWater = ACS_ExecuteWithResult(999,0); If(InWater == yes) PrintBold(s:"inwater"); else PrintBold(s:"out water"); delay(1);} }
Если надо в декорейте то States{Spawn: TNT1 A 1 A_JumpIf(CallACS(999)==true,"inwater") //если текстура воды под игроком loop
... что-то в этом духе..
VladGuardian:
Возможно, кавычки там лишние?..
ZZYZX:
CallACS требует строку-название скрипта. Потому что это алиас к ACS_NamedExecuteWithResult.
Все оказалось смешнее. В общем после того, как код алекв, пофикшенный рекомендациями ZZYZX, заработал, я решил понять, в чем ключевая разница с моим предыдущим кодом, и начал постепенно переобразовыать код алекв в мой код. По итогу, получил вот такой короткий односкриптовый код:
Который в декорейте вызывается вот так: "####" "#" 1 A_JumpIf( ACS_NamedExecuteWithResult("CheckActivatorOnWater") == 0, 2) "####" "#" 1 A_SpawnItemEx("ArtiHealth") "####" "#" 0
и, внимание, код заработал! Пытаясь понял, почему один и тот же код вчера крашил здум/гоззу, а сегодня уже нет, понял, что проблема была в том, что во вчерашнем коде была пропущена скобка в декорейте: