Створення місій для GTA Vice City.
Структура скрипта місій.
Умовно весь код поділений на 4 блоки
1. Блок пам'яті це всього одна строчка - DEFINE MEMORY а далі йде кількість зарезервованої пам'яті в байтах.
2. Блок визначення 3D-об'єктів, починається з рядка DEFINE OBJECTS 204 - 204 це загальна кількість об'єктів. Далі йде визначення самих об'єктів - DEFINE OBJECT і ім'я об'єкта.
Навіщо визначати об'єкти в коді. що б керувати ними, наприклад ворота на острів StarFish спочатку закриті, а потім в процесі проходження гри вони відкриваються.
3. Блок визначення місій, DEFINE MISSIONS - загальна кількість місій і далі список місій і покажчики на мітку з початком місії. DEFINE MISSION 1 AT ЈЈMission1 - це рядок визначає місію з номером 1 на мітці: Mission1.
4. Блок коду власне в цьому блоці вже пишеться сам код місій.
Тепер про структуру команд.
03CB: set camera $ X $ Y $ Z - ця команда встановить камеру на заданих координатах.
03СB: - опкод.
set camera - команда, ігноруються компілятором.
$ X $ Y $ Z - параметри, в даній випадку це координати камери.
Як написано вище сама команда ігнорується компілятором, тобто для компілятора 03CB: set camera $ X $ Y $ Z і 03CB: $ X $ Y $ Z одне і теж. Навіщо ж тоді потрібні самі команди, так дуже просто для зручності, адже набагато простіше запам'ятати команду ніж опкод. Пишемо set camera, натискаємо F1 і опкод і параметри дописують самі.
Змінні.
В усіх мовах програмування Високово рівня використовуються змінні
і Mission Builder не виняток. Змінні в ньому позначаються знаком $. Навіщо потрібні змінні знову ж для зручності написання коду. Наприклад вище ти бачив таку строчку 03CB: set camera $ X $ Y $ Z - тут координати камери визначені в змінних $ X $ Y $ Z, можна було написати так - 03CB: set camera 3.0 1.0 4.0, але якщо ти і далі будеш використовувати ці координати, то простіше укласти їх в змінні:
0005: $ X = 3.0. ця команда встановлює що змінна $ X дорівнюватиме 3.0
0005: $ Y = 1.0. ця команда встановлює що змінна $ Y дорівнюватиме 1.0 і т.д.
Крім того всі математичні операції, складання, розподіл можуть вестися тільки з перемінними. В змінні полягати не тільки числа але взагалі будь-які об'єкти,
009A: $ ACTOR1 = create_actor 4 #COP at 1.0 1.0 1.0 - цією командою ми створили копа зі змінною $ ACTOR1.
Математичні операції.
Зі змінними розібралися тепер про математичних операціях.
У Mission Builder'е повсюдно використовуються координати. Створити гравця вводите координати, відправити тачку що б їхала туди-то знову координати. Утиліта Player Pos, зберігає після натискання кнопки F4 поточний стан гравця. завантажити
У MB використовуються два типи чисел:
Integer - цілі числа. 100 ціле число.
Float - число з плаваючою комою, 3.0.
Опкоди для роботи з різними типами чисел різні.
0004: $ X = 10, визначаємо що змінна $ X дорівнює 10.
0008: $ X + = 5, складаємо до змінної 5 разом 15.
0010: $ X * = 2, множимо на два разом 30.
000C: $ X - = 10, віднімаємо 10 разом 20.
0014: $ X / = 4, ділимо на 4 разом 5.
Тепер опкоди для чисел з плаваючою комою.
0009: - Додавання.
000D: - Вирахування.
0011: - Множення.
0015: - Розподіл.
Типи використовувані в MB.
Тут розглянемо типи позначень які використовуються в MB.
Один тип ми вже знаємо, знаком $ позначаються змінні.
Використовуються ще один тип змінних, позначається він знаком @. Використовуються він для 16-бітних значень в основному у внутрішніх таймерах. Ім'я змінної може бути тільки числове тобто ніяких CAR @ і PED @, тільки числа.
0006: 2 @ = 100, встановлюємо змінну 2 @ зі значення 100.
Тип JJ - так позначається перехід на мітку в будь-якому місці коду.
0002: jump ЈЈLabel1, перехід на мітку: Label1
Тип J - позначає перехід на мітку тільки всередині певного блоку.
Знаком # позначаються машини, педи, зброю.
Зі знаком переходу на мітки - J, дуже багато геморою, це пов'язано з кодуванням Windows, мало того в Windows 9x він взагалі відображається по іншому, краще цей знак копіювати з попередніх рядків або не вийде скомпілювати код.
Тепер коли ти маєш загальне поняття про типи, змінних ми напишемо свою простеньку місію. Місія буде полягає в тому що потрібно буде обігнати оборзевщего копа в гонці.
Також гонку можна буде виграти, розбивши машину опонента. Гонка буде відбуватися на острові StarFish. Запускаємо VC Mission Builder, якщо ти запускаєш його в перший раз то треба вказати папку з Vice City.Чтоби не писала весь код з нуля, ми візьмемо за основу файл в якому вирізані всі сюжетні місії, натискаємо Ctrl + O і відкриваємо файл Stripped_complete.txt , який знаходиться в папці MissionBuilder \ Stripped scripts. Для початку нам треба додати нашу місію в блок місій. У меню Edit вибери Find (Пошук) і у вікні, напиши DEFINE MISSIONS, тепер ми знайшли місце де визначені місії. Змінюємо загальна кількість місій на DEFINE MISSIONS 2 і після DEFINE MISSION 0 додаємо рядок з нашою місією, DEFINE MISSION 1 AT ЈЈMyMission. Так ми вказали що наша місія буде знаходиться на мітці. MyMission.
Переходимо в самий кінець файлу, і перед рядком 004E: end_thread, додаємо всього одну сходинку - 0417: start mission 1, так ми стартуємо нашу місію. А тепер найцікавіше, сам код нашої місії.
Пишемо: MyMission - стартова позначка місії. Створюємо потік місії з ім'ям MISSION, 03A4: name_thread "MISSION", створювати потік обов'язково оскільки при його створенні виділяється необхідна пам'ять. Робимо невелику затримку в 1000мс - 0001: wait 1000 ms. потім переносимо гравця до початку гонки 0055: put_player $ PLAYER_CHAR at -273.507 -489.287 10.063. $ PLAYER_CHAR - якраз позначає гравця а далі йдуть координати по осях X, Y, Z.Теперь треба створити машину для нас і опонента і самого опонента, оборзевщего копа :). Робимо запит на моделі
: RequestModels; мітка
0247: request model #DELUXO; запитуємо модель машини Deluxo
0247: request model #COP; запитуємо модель копа
далі треба перевірити чи існують такі моделі взагалі.
: CheckCars
00D6: if 21; якщо
8248: NOT model #DELUXO available; модель Deluxo не існує
8248: NOT model #COP available; і модель Сop не існує
004D: jump_if_false ЈCreateCars; якщо існують
0001: wait 0 ms; затримка
0002: jump ЈCheckCars; переходимо на мітку: CheckCars
Розберемо цей блок докладніше якщо моделі тачки і копа існують то переходимо на наступну позначку, якщо не існують то переходимо знову на початок блоку і все повторюється знову. Якщо ти помітив у if cтоит 21 це тому що ми перевіряємо відразу 2 умови. Далі ми створюємо машини і копа.
: CreateCars
Очищаємо територію де будуть створюватися тачки.
0395: clear area 1 at -274.309 -486.170 range 10.0 10.0
власне створюємо самі тачки
00A5: $ PLAYER_CAR = create_car #DELUXO at -274.309 -486.170 10.071
00A5: $ OPP_CAR = create_car #DELUXO at -272.837 -476.868 10.095
Ми так ми створили дві тачки Deluxo, в змінній $ PLAYER_CAR - машина гравця, а в $ OPP_CAR - машина опонента. #DELUXO - визначає що створювати треба саме тачку Deluxo а не ще щось. В принципі можна замінити на # PCJ600 тоді гонки будуть на мотоциклах, тільки не забудь в запитах і в перевірці теж # PCJ600 поставити.
Далі ми повертаємо тачки на дев'яносто градусів.
0175: set_car $ PLAYER_CAR z_angle_to 90.
0175: set_car $ OPP_CAR z_angle_to 90.0
створюємо копа за кермом тачки $ OPP_CAR
0129: $ OPP_COP = create_actor 4 #COP in_car $ OPP_CAR driverseat
далі встановлюємо властивості тачки.
Встановлюємо максимальну швидкість тачки.
00AD: set car $ OPP_CAR max speed to 50.0
Ставимо щоб машина опонента ігнорувала світлофори
00AE: unknown_set_car $ OPP_CAR to_ignore_traffic_lights 2
робимо водив психом :)
00A8: set car $ OPP_CAR to psycho driver
скидаємо прапори копа
01ED: reset actor $ OPP_COP flags
Є один баг, відразу після створення в тачці водії він весь час намагається куди-то виїхати, причому навіть якщо ми йому це не дозволяли. Тому пишемо таку строчку
02C2: car $ OPP_CAR drive to point -272.837 -476.868 10.095
так ми вказуємо куди їхати тачці $ OPP_CAR. Але координати на які треба їхати, це і є координати де ми створили тачку. Таким чином тачка нікуди не їде, але від бага ми позбулися.
Далі коли всі машини створені, пора починати гонку.
Але не відразу а як тільки гравець сяде в тачку.
: CheckInCar
0001: wait 0 ms; затримка
00D6: if 0; якщо
80DC: NOT player $ PLAYER_CHAR driving $ PLAYER_CAR; Гравець не в машині
004D: jump_if_false ЈBackCount; Якщо в машині переходимо на мітку
0001: wait 0 ms; затримка
0002: jump ЈCheckInCar; Переходимо на мітку: CheckInCar
У цей коді ми перевіряємо, якщо гравець ($ PLAYER_CHAR) в машині ($ PLAYER_CAR) то ми переходимо на наступну позначку, якщо немає то переходимо на початок блоку. Таким чином поки гравець не сяде в машину гонка не почнеться. Тобі цікаво навіщо потрібно вставляти затримки 0001: wait 0 ms. а потім що цей шматок коду - цикл. І якщо цей цикл буде повторюватися без затримки то гра просто зависне.
Далі починаємо вважати 3, 2, 1 після чого стартуємо гонку.
Спочатку заморожуємо гравця, тобто їм на час не можна буде управляти.
01B4: set player $ PLAYER_CHAR frozen state 0
Говоримо копам тверде ні :)
01F7: set_player $ PLAYER_CHAR ignored_by_cops_state_to 1
і починаємо рахувати
00BA: text_styled "RACE2" 1500 ms 4; виводимо на екран повідомлення 3
018C: play_sound 7 at 0.0 0.0 0.0; програємо звук
0001: wait 1500 ms; чекаємо 1500 мс
0395: clear area 1 at -274.309 -486.170 range 11.0 1.0; очищаємо майданчик
так повторюємо це код 3 рази змінюючи лише виведений на екран текст.
Після чого виводимо повідомлення про початок гонки і розморожуємо гравця.
00BA: text_styled "RACE1" 1200 ms 4; виводимо повідомлення про початок гонки
01B4: set player $ PLAYER_CHAR frozen state 1; "Розморожуємо гравця"
ну і нарешті починаємо гонку.
0001: wait 0 ms; очікуємо
0186: $ OPP_MRK = create marker above car $ OPP_CAR; створюємо маркер на радарі навколо машини опонента
02C2: car $ OPP_CAR drive to point -696.092 -489.462 9.890; вказуємо щоб машина опонента їхала на координати завершення місії
018A: $ F_CHECK = create checkpoint at -696.092 -489.462 9.890; створюємо чекпоінт на радарі він позначає місце фіналу гонки
далі перевіряємо умови виграшу гонки, якщо опонент мертвий або гравець перший приїхав до фінішу.
: CheckWin;
00D6: if 0; якщо
8118: NOT actor $ OPP_COP dead; опонент коп живий
004D: jump_if_false ЈEndMission; якщо мертвий то переходимо на мітку завершення місії
00D6: if 0; якщо
; гравець в машині не на координатах проїхавши які ми виграєте місію з радіусом X Y Z
80F7: NOT player $ PLAYER_CHAR 0 near point in car -696.092 -489.462 9.890 radius 6.0 6.0 6.0
004D: jump_if_false ЈEndMission; якщо на координатах то переходм на завершення гонки
0001: wait 0 ms; затримка
перевіряємо умови програшу, якщо опонент перший приїхав до фінішу.
: CheckFailed
00D6: if 0; якщо
; машина опонента нема на координатах завершення гонки
81AF: NOT car $ OPP_CAR 0 () near point -696.092 -489.462 9.890 radius 6.0 6.0 4.0
004D: jump_if_false ЈMissFailed; якщо на них то ми програли місію і переходимо на мітку програшу
0001: wait 0 ms; затримка
0002: jump ЈCheckWin; переходимо на мітку: CheckWin
далі мітки, гравець виграв або програв
; програли
: MissFailed
00BA: text_styled "M_FAIL" 5000 ms 1; Виводимо повідомленні про пройгрише місії
0002: jump ЈEnd; Переходимо на мітку: End
; виграли
: EndMission
0394: play_music 1; програємо музику
01E3: text_1number_styled "M_PASS" 3000 5000 ms 1; Виводимо повідомленні про завершення місії
і завершуємо.
: End
034F: destroy actor with fade $ OPP_COP; знищуємо актора $ OPP_COP, нашого опонента
00A6: destroy car $ OPP_CAR; знищуємо машину опонента
0164: disable_marker $ F_CHECK; відключаємо маркер на радарі
01F7: set player $ PLAYER_CHAR ignored by cops state to 0 (true);
004E: end_thread; Завершуємо потік
Тепер залишилося скомпілювати наш код, в scm - файл, натискаємо F9 і Mission Builder створить main.scm скопіює його в папку Vice City і запустить гру.
Ось і кінець статті у мене вже руки втомилися, стукати по клаві :).
Не так давно вийшов GTA Сан-Андреас і хочу сказати що кодинг місій для нього,
нічим не відрізняється від написання місій для Vice city. Ну і звичайно на цьому тема створення місій не закриті і незабаром я опублікую статтю по написанні більш складних місій. А ще є думка зробити онлайнову базу даних опкодов з їх опису та параметрами але це все в майбутньому ... Вихідний код місії можеш завантажити звідси. Якщо у тебе виникли якісь питання по Mission Builder'у пиши мені на [email protected]. але не варто завалювати мене спамом з проханнями типу "а як написати мод за мотивами фільму Бригада" такі листи я відразу кидаю в треш. Я можу допомогти тільки з конкретного питання.