Сповіщення
Очистити все

Назначення скриптам гарячих клавіш. Частина 1: Скрипти


Ранг:
Майстер
Роль:
Гість
Записи:
752
Приєднався:
2 роки тому
 

Вступ

Вивчивши мод від камраду Jeppa, вирішив створити невеликий посібник зі створення нових інтерфейсних вікон, прив'язки скриптів на кнопки, реакцію на натискання клавіш, спавн предметів прямо в грі.

На жаль, у самій грі можливість прибіндити запуск скрипту або ще якусь дію на нову кнопку відсутня, тому доводиться вигадувати щось своє. Jeppa вийшов зі становища створивши нове діалогове вікно на основі старого інтерфейсу завантаження спавн файлів. Він додав на нього 10 кнопок з описами, при натисканні на кожну викликався скрипт або функція.

Нам знадобляться такі розпаковані (або наявні) файли:

config\system.ltx
scripts\ui_main_menu.script

Решту робитимемо з нуля. Я дотримуюсь політики мінімального втручання у наявні файли.

Скрипт

Отже, як це зробити. Почнемо з найпростішого. Спочатку створимо наш новий скрипт, який і займатиметься викликом інших скриптів. Назвемо його ui_cheat.script і покладемо до всіх інших скриптів.

Тепер треба якось скрипт викликати. Я вирішив піти второваною доріжкою і викликати його з головного меню. Поки що ми не створюватимемо там нових кнопок, а повісимо його запуск на гарячу клавішу. Наприклад, на F1, з гри буде зручно тиснути Esc і відразу F1. Але можете й іншу кнопку використати. Отже, відкриваємо файл ui_main_menu.script , йдемо в самий кінець і шукаємо там таку ф-ію:

function main_menu:OnKeyboard ( dik, keyboard_action )

Це обробник натискань клавіш. Клавіші, що використовуються, перераховані в lua_help.script (шукайте рядок C++ class DIK_keys ). Отже, замість

--	if dik == DIK_keys.DIK_S then
-- self:OnButton_load_spawn()
 
-- else
if dik == DIK_keys.DIK_Q then
self:OnMessageQuitWin()
end

ми напишемо

-- раскомментируем и заодно включим убранное спавн меню 
if dik == DIK_keys.DIK_S then
self:OnButton_load_spawn()
elseif dik == DIK_keys.DIK_Q then
self:OnMessageQuitWin()
-- а вот это обработка кнопки F1. при ее нажатии будет вызываться ф-ия OnButton_cheat()
elseif dik == DIK_keys.DIK_F1 then
self:OnButton_cheat()
end

Тобто при натисканні на S буде викликати спавн меню, на Q - миттєвий вихід з гри, а F1 запустить функцію OnButton_cheat() . Тобто, ось один із варіантів запуску, прив'язка до гарячої клавіші. Але ще немає самої ф-ії, тому допишемо в кінець файлу:

function main_menu:OnButton_cheat()
-- если еще ни разу не вызывали, то обозначим наш новый скрипт
if self.cheat_dlg == nil then
self.cheat_dlg = ui_cheat.cheat()
self.cheat_dlg.owner = self
end
-- останавливаем родительский элемент, запускаем свой, но родителя показываем.
self:GetHolder():start_stop_menu(self.cheat_dlg, true)
self:GetHolder():start_stop_menu(self, true)
self:Show(true)
end

Запуск по кнопці вже є, але немає повернення назад. Виправимо це, повернемося до файлу ui_cheat.script і зробимо там обробник натискань клавіш. До кінця файлу допишемо:

function cheat:OnKeyboard(dik, keyboard_action)
CUIScriptWnd.OnKeyboard(self,dik,keyboard_action)
if keyboard_action == ui_events.WINDOW_KEY_PRESSED then
-- сразу же производим действия для возврата
self:on_quit()
-- на выход повесим Esc
if dik == DIK_keys.DIK_ESCAPE then
-- тут ничего не делаем
end
end
return true
end

Тепер треба перевірити працездатність. Запускаємо гру, в головному меню тиснемо F1 , анімація повинна гальмувати, миша бігати. Якщо відбувся виліт – відкриваємо блокнот і вставляємо з буфера передсмертне послання гри. (Сподіваюся, все пам'ятав, що при помилці та фарбуванні в буфері залишається лог помилки?) Якщо вильоту немає, то натискаємо Esc і повертаємося в меню. Таку ж перевірку бажано провести і у самій грі. Візуально повинен зникнути HUD, але має залишитися картинка. Можна знімати скріншоти 🙂

Предмети

Тепер наше завдання полягає в тому, щоб в обробник натискань клавіш внести нові ф-ії. Почнемо, наприклад, зі спавна предметів. Подивимося, як сповняться квестові монстри та речі і зробимо також (додаємо в кінець ui_cheat.script ):

-- spawn_item - необходимый предмет
-- dist - радиус появления (случайно)
function cheat:spawn_item(spawn_item, dist)
local pos = db.actor:position()
local dir = db.actor:direction()
pos = pos:add(dir:mul(dist))
-- создаем предмет в dist метрах прямо перед нами
alife():create(spawn_item, pos, 1, db.actor:game_vertex_id())
end
image
Можна спавнити предмети прямо в інвентар
Функція буде виглядати наступним чином (відповідно треба враховувати відсутність параметра dist, при виклику функції та не застосовувати при спавні техніки та монстрів):

function cheat:spawn_item(spawn_item)
 	alife():create	(spawn_item, db.actor:position(),  db.actor:level_vertex_id(),
 			db.actor:game_vertex_id(), db.actor:id())
 end

 

Додавання від HikeR.
Таким чином, до речі, передаються квестові предмети. Використовуйте у своїх скриптах та нових квестах.
Функцію можна додати до існуючої, тоді при її виклику буде перевірено кількість аргументів
і викликатись потрібна. У С++ це називається "перевантаження" (якщо не помиляюсь;)

Тепер потрібно викликати цю функцію. Прив'яжемо кнопки 1 та 2 на цифровій клавіатурі до появи Грози та патронів до неї. У функцію cheat:OnKeyboard після рядка:

if dik == DIK_keys.DIK_ESCAPE then

додамо таке:

elseif dik == DIK_keys.DIK_NUMPAD1 then self:cheat1 ( ) 
elseif dik == DIK_keys.DIK_NUMPAD2 then self:cheat2 ( )

і створимо ці функції (знову додаємо в кінець файлу):

function cheat:cheat1 ( ) 
- чаклуємо грозу на відстані 3 метрів.
self:spawn_item ( "wpn_groza" , 3 )
end
function cheat:cheat2 ( )
self:spawn_item ( "ammo_9x39_sp5" , 3 )
end

Транспорт

Сповнити транспорт ми аналогічно, але тут є невелика проблема. У конфігах для транспортування відсутні необхідні параметри, все-таки машини у грі були вирізані. Але нам це не перешкода, тож почнемо з Ниви.

Створимо новий файл з ім'ям cars_spawn.ltx

[ven_niva] 
class = SCRPTCAR
cform = skeleton
visual = physics\vehicles\niva\veh_niva_u_01.ogf

Збережемо його до інших конфіг транспорту, тобто в config\models\vehicles . Це мінімальний набір для правильної появи нового об'єкта в грі. Але гра ще не знає, що ми додали новий конфіг, тому трохи підредагуємо system.ltx . На початку файлу є безліч команд #include... , вони підключають конфіги. Знайдемо останній include та додамо наш конфіг:

#include "models\vehicles\cars_spawn.ltx"

Далі накатаною доріжкою. Допишемо функцію виклику спавна:

function cheat:cheat3 ( )
self:spawn_item ( "ven_niva" , 5 , 10 )
end

та призначимо їй кнопку 3 на цифровій клавіатурі:

elseif dik == DIK_keys.DIK_NUMPAD3 then self:cheat3 ( )

Всі. Можна запускатись і дивитися. Тиснемо Esc, потім F1 (головне меню пропадає, залишається просто картинка), потім 1, 2 або 3 на цифровій клавіатурі. у вибраному радіусі з'являтимуться автомати, патрони та Ниви.

Однак, зброя та боєприпаси при появі падають на землю, а от транспорт залишається висіти в повітрі. Я намагаюся зрозуміти, що можна зробити, але поки що просто киньте в неї болт. Машина впаде та покотиться, якщо стоїть на нерівній поверхні.

Монстри

Аналогічно додаємо монстрів та іншу живність. Функція:

function cheat:cheat4 ( ) 
-- створюємо монстра подалі від нас
self:spawn_item ( "dog_weak" , 20 )
end

Обробка клавіші 4

elseif dik == DIK_keys.DIK_NUMPAD4 then self:cheat4 ( )

Сон за бажанням

Якщо у Вас встановлений Dream mod, то можна його повісити на кнопку.

function cheat:cheat5 ( )
sleep_manager.sleep_three_hours ( )
end

Передбачається, що ім'я скрипта sleep_manager.script , а в ньому є функція sleep_three_hours() , тобто спати 3 години. Сам я не користувався цим модом, тому можу помилятися.

Прим. від Empro: особисто у мене не запрацювало та повисло. Взагалі, викликати сон із головного меню, та ще й у режимі паузи – невдячна справа. Прим. від HikeR: спочатку зняти з паузи, а потім спати. Тоді все працює.

Увага!!!

За описаного способу спавна є деякі труднощі. Предмет створює у напрямку вектора гравця, який не завжди збігається з поглядом. Ви можете увімкнути зовнішній огляд і побачити, що при невеликих поворотах ноги гравця не рухаються. Щоб гарантовано повернутись зробіть пару кроків уперед

Бажано вибирати рівну поверхню або поверхню з нахилом від гравця. Якщо сповнити в гору – то предмет взагалі не з'явиться, вірніше він з'явиться, але провалиться під рівень.


   
Цитата
Ранг:
Майстер
Роль:
Гість
Записи:
752
Приєднався:
2 роки тому

   
ВідповіcтиЦитата
Ранг:
Майстер
Роль:
Гість
Записи:
752
Приєднався:
2 роки тому

   
ВідповіcтиЦитата