Створення гоночної місії для GTA Vice City

В цій статті я вам розповім про принципи створення гонки для GTA VC, для цієї гри поки ще не створили Race Mission Builder, але й з VC Mission Builder'ом можна навчитися створювати гонки.
Отже, для створення знадобиться VC Mission Builder (бажано v1.5) і сама гра GTA Vice City.
Отже, запускаємо завантажений VCMissionBuilder і відкриваємо файл Stripped_complete.txt (це скрипт 100% проходження) (він в: папка Mission Builder'a Stripped scripts), і ось у нас перед очима код, шукаємо де у нас
DEFINE MISSIONS 1 ;; кількість місій
DEFINE MISSION 0 AT ЈЈLabel031F34 ;; завжди номери місій починаються з 0
Це прописка місій, тут тільки одна (це створення всіх припаркованих тачок, зброї, пікапів (типу здоров'я, броні) і т.д.), ці рядки ми змінюємо на:
DEFINE MISSIONS 2
DEFINE MISSION 0 AT ЈЈLabel031F34
DEFINE MISSION 1 AT ЈЈRACE ;; прописка нашої гонки
P.S. Label'и, це мітки, на які переходить гра
Далі створюємо стартер для місії, для цього шукаємо де у нас всі create_thread'и і ставимо там в кінці ось таку строчку:
004F: create_thread ЈЈstartracer ;; це посилання на мітку зі стартером, startracer - мітка, але в Mission Builder'e є такий баг, що компілятор не завжди розуміє JJ у посиланнях, наприклад:
0002: jump ЈЈLabel00994C
(0002: - опкод, команда jump компілятором ігнорується і тому можна записати і так:
0002: JJLabel00994C )
JJ ставиться тільки в області MAIN, а
J ставиться тільки в місіях, якщо ж ставити JJ в місіях, то компілятор це прийме, але гра може видавати помилки, а якщо J в MAIN'і писати, то компілятор видасть повідомлення, що в MAIN'і слід використовувати тільки JJ.
Повертаємося до стартера гонки:
:startracer
02A7: $icon = create_icon_marker_and_sphere 35 at -236.929 -465.912 10.300 ;; створюємо маркер з іменем $icon типу 35 (типи можна дізнатися в текстовому файлі radar_icons.txt, знову ж він в папці MissionBuilder'a) на карті і позначку
:strt1
0001: wait 250 ms ;; чекаємо 250 мс
00D6: if 0 ;; якщо
0256: player $PLAYER_CHAR defined ;; живий і не арештований
004D: jump_if_false ЈЈstrt1 ;; якщо хибно, то на мітку strt1, якщо правда, то йдемо далі
00D6: if 0
00F9: player $PLAYER_CHAR stopped 0 ()near_point_on_foot -236.929 -465.912 10.300 radius 1.0 1.0 2.0 ;; гравець на точці
004D: jump_if_false ЈЈstrt1
00D6: if 0
0038: $ONMISSION == 0 ;; цілі числові значення ;; гравець не на місії
004D: jump_if_false ЈЈstrt1
00D6: if 0
03EE: player $PLAYER_CHAR controllable ;; гравець керований (сам не знаю навіщо це, але писати це треба)
004D: jump_if_false ЈЈstrt1
0164: disable_marker $icon ;; прибрати маркер $icon з карти
0417: start_mission 1 ;; почати місію
004E: end_thread ;; завершити стартер (ну.. або потік, як це узагальнено сказати)
Все це пишеться тільки в області MAIN'a, і, як видно, тут юзається JJ
в самому кінці коду пишемо:
;---------------Місія 1--------------
:ГОНКА ;;мітка початку місії
0050: gosub Јstarting ;; gosub - це певне звернення до іншої мітки, яке можна завершити командою 0051: return
00D6: if 0
0112: wasted_or_busted
004D: jump_if_false Јend
0050: gosub ЈFAIL
:end
0050: gosub Јclean
004E: end_thread
;;все, що вище, потрібно, щоб якщо Томмі помер під час місії, то місія завершиться з провалом.
:starting
0317: increment_mission_attempts ;; команда, для того щоб у статистиці до спроби місій додалося 1
03A4: name_thread "ГОНКА" ;; починаємо потік з назвою ГОНКА
01E8: create_forbidden_for_cars_cube -252.929 -337.286 9.307 -455.861 -499.581 10.210 ;; створюємо заборонену для машин область, де старт гонки, щоб машини не заважали стартувати
0004: $checkpoint = 1 ;; цілі числові значення ;; як би прапор, скільки міток пройшов гравець
0004: $crd = 1 ;; цілі числові значення ;; як би прапор, скільки міток пройшов суперник
0005: $x = -527.164 ;; дійсні числа
0005: $y = -487.341 ;; дійсні числа
0005: $z = 10.087 ;; дійсні числа
0005: $xZ = -527.164 ;; дійсні числа
0005: $yZ = -487.341 ;; дійсні числа
0005: $zZ = 10.087 ;; дійсні числа
0005: $x1 = -829.568 ;; дійсні числа
0005: $y1 = -710.641 ;; дійсні числа
0005: $z1 = 9.947 ;; дійсні числа
0005: $x2 = -973.242 ;; дійсні числа
0005: $y2 = -1074.749 ;; дійсні числа
0005: $z2 = 13.717 ;; дійсні числа
0005: $x3 = -1198.370 ;; дійсні числа
0005: $y3 = -934.293 ;; дійсні числа
0005: $z3 = 13.717 ;; дійсні числа
0005: $x4 = -1420.124 ;; дійсні числа
0005: $y4 = -783.965 ;; дійсні числа
0005: $z4 = 13.717 ;; дійсні числа
;;координати гонки
0004: $finish = 0 ;; цілі числові значення ;; прапор кінцевої контрольної точки гонки
0004: $race = 0 ;; цілі числові значення ;; прапор часу гонки
0004: $ONMISSION = 1 ;; прапор "гравець на місії", якщо 1 - то на місії, якщо 0 - то не на місії
0247: request_model #HOTRING ;; запитуємо модель машини Хотринг, це обов'язково!!!
0247: request_model #WMYGO ;;запитуємо модель водія цієї машини
038B: load_requested_models ;; як би завантаження запитаних моделей, без неї можуть бути виїзди
:ava ;; мітка з ім'ям ava
00D6: if 1 ;; якщо 1(це значить якщо те і те), якщо 21(значить якщо те або те)
8248: NOT model #HOTRING available ;; модель не існує
8248: NOT model #WMYGO available
004D: jump_if_false Јstart ;; йдемо на start якщо брехня
0001: wait 0 ms ;; якщо правда, то чекаємо 0 мс і йдемо до початку мітки ava
0002: jump Јava
;; P.S. тут всі "джампи" використовуються з J, тому що в місії
:start
00A5: $zbr = create_car #HOTRING at -238.277 -477.260 10.092 ;; створюємо тачку хотринг з іменем $zbr на координатах -238.277 -477.260 10.092, координати беруться програмою PlayerPos(краща версія 1.3)
0129: $vd = create actor 4 #WMYGO in car $zbr driverseat ;; створюємо актора 4(сам не знаю що це значить) в машині $zbr водієм
00AD: set_car $zbr max_speed_to 127.9 ;; задаємо нашій тачці максимальну швидкість 127.9 миль в годину
00AF: set car $zbr driver behaviour to 2 ;; потрібно для реальності
00A9: set car $zbr to normal driver ;; робимо водія тачки акуратним
00AE: unknown set car $zbr to ignore traffic lights 2 ;; машина ігнорує все, що на дорозі, варто зазначити, що цифра 2 - тачка об'їжджає все, 1 - штовхає, 0 - схоже що взагалі їде по ПДР
020A: set_car $zbr door_status_to 2 ;; стан дверей тачки, 1 - відкриті, 2 - закриті
01ED: reset_actor $vd flags ;; видаляємо всі прапори противника (які я не знаю, але писати це треба)
0224: set car $zbr health to 2000 ;; встановлюємо для машини як би здоров'я на 2000
02C2: car $zbr drive_to_point -238.277 -477.260 10.092 ;; машина нікуди не їде, стоїть на початкових координатах, це потрібно, тому що в вайсі є такий баг, що якщо поставити на дорогу тачку з водієм, то тачка кудись все час їде
0428: unknown_car $zbr flag 0 ;; потрібно теж, для чого точно я не знаю
0175: set_car $zbr z_angle_to 90.0 ;; тачка спочатку повернута на північ, ми її повертаємо на 90 градусів проти годинникової стрілки, таким чином тачка повертається на захід
03AB: (unknown) $zbr 1 ;; unknown - щось невідоме з тачкою, писати треба, щоб не вилетіло
039C: (unknown) $zbr 1 ;; аналогічно тому, що вище
03ED: (unknown) $zbr 1 ;; тут теж
018A: $chk = create_checkpoint_at $x $y $z ;; створюємо чекпоінт (маркер) на карті з іменем $chk і координатами $x $y $z - це змінні, їх ми писали на самому початку місії
0165: set marker $chk color to 1 ;; задаємо колір нашому маркеру під номером 1(це зелений)
0186: $mrk = create_marker_above_car $zbr ;; створюємо ще один маркер з іменем $mrk, тільки вже над машиною, він буде все час над нею
0168: show_on_radar $mrk 1 ;; наш маркер $mrk на радарі буде виглядати як маленький квадратик
03BC: $sph = create_sphere -238.262 -481.053 10.082 2.0 ;; створюємо мітку $sph на координатах -238.262 -481.053 10.082 з радіусом 2.0 метра
:inc
00D6: if 1 ;; якщо
80FA: NOT player $PLAYER_CHAR stopped 0 (in-sphere)near_point_in_car -238.262 -481.053 10.082 radius 2.0 2.0 2.0 ;; гравець не на точці -238.262 -481.053 10.082 в машині з радіусами 2.0 2.0 2.0
0001: wait 0 ms
004D: jump_if_false Јcount ;; якщо брехня, т.е. якщо гравець на точці в машині
;; якщо правда то:
00D6: if 1 ;; якщо
8118: NOT actor $vd dead ;; актор (водій) $vd не помер
0001: wait 0 ms
004D: jump_if_false ЈPROTD ;; якщо помер то переходимо до мітки PROTD
0002: jump Јinc ;; переходимо на початок мітки inc
:count ;; від цієї мітки починається відлік
03BD: destroy_sphere $sph ;; видалити мітку $sph
03C1: $playcar = player $PLAYER_CHAR car ;; машина гравця записується в пам'яті під іменем $playcar
03AB: (unknown) $playcar 1 ;; щось невідоме, писати все одно треба
0224: set car $playcar health to 2000 ;; задаємо здоров'я тачці гравця, рівне 2000
0428: unknown_car $zbr flag 1 ;; задаємо якийсь прапор машині супротивника - $zbr
01B4: set player $PLAYER_CHAR frozen state 0 (frozen) ;; відключаємо управління гравцем
00BA: text_styled "RACE2" 1000 ms 5 ;; виводимо текст - "3"
018C: play_sound 1 at 0.0 0.0 0.0 ;; програємо звук (номера звуків ніде не описані, але розібратися спробую)
0001: wait 1000 ms
00BA: text_styled "RACE3" 1000 ms 5 ;; виводимо текст - "2"
018C: play_sound 1 at 0.0 0.0 0.0
0001: wait 1000 ms
00BA: text_styled "RACE4" 1000 ms 5 ;; виводимо текст - "1"
018C: play_sound 1 at 0.0 0.0 0.0
0001: wait 1000 ms
00BA: text_styled "RACE5" 1000 ms 5 ;; виводимо текст - "GO!"
018C: play_sound 10 at 0.0 0.0 0.0
;; 010E: set player $PLAYER_CHAR minimum wanted level to 4 ;; цеоо, ми задаємо гравцеві рівень розшуку 4, це ставити не обов'язково
01B4: set player $PLAYER_CHAR frozen state 1 (frozen) ;; вмикаємо управління гравцеві
014E: set_timer_to $race type 0 ;; створюємо таймер відліку гонки з змінною $race, ми її вказували на початку типу 0 - це відлік від 0, а 1 - це зворотний відлік - до 0
:startrace ;; початок гонки після відліку
02C2: car $zbr drive_to_point $x $y $z ;; машина супротивника їде на координати $x $y $z - змінні з координатами, вказані на початку
:cnt
00D6: if 1
80E3: NOT player $PLAYER_CHAR 0 ()near_point $x $y radius 6.0 6.0 ;; гравець на координатах $x $y з радіусами 6.0 6.0
0001: wait 0 ms
004D: jump_if_false Јpank
0050: gosub Јcorona ;; звернення до мітки з короною(т.е. великим колом)
00D6: if 1
81AF: NOT car $zbr 0 ()near point $xZ $yZ $zZ radius 6.0 6.0 6.0 ;; машина супротивника не на точці $xZ $yZ $zZ (теж змінні) з радіусами 6.0 6.0 6.0
0001: wait 0 ms
004D: jump_if_false Јchangecrd
0050: gosub Јcorona
00D6: if 1
8118: NOT actor $vd dead ;; якщо актор $vd жив
0001: wait 0 ms
004D: jump_if_false ЈPROTD ;; якщо мертвий то йдемо до мітки провалу місії, для чого це? ну.. буває, що застрелиш свого супротивника і поїдеш один, це захист від цього
0050: gosub Јcorona
0002: jump Јcnt
:corona
00D6: if 0
0038: $finish == 1 ;; integer values ;; якщо прапор фінішу = 1
004D: jump_if_false Јgreen ;; якщо ні то йдемо до green
;; якщо так то:
024F: create_corona 6.0 6 0 with_color 255 0 0 at_point $x $y $z ;; створюємо коло з радіусом 6.0, 6 0 - не знаю що це, з кольором 255 0 0 (колір як видно отримується за допомогою RGB палітри) на координатах $x $y $z
0051: return ;; повернення назад
:green
024F: create_corona 6.0 6 0 with_color 14 235 50 at_point $x $y $z
0051: return
:pank
00D6: if 1
8039: NOT $checkpoint == 1 ;; integer values ;; гравець не пройшов 1-у відмітку
0001: wait 0 ms
004D: jump_if_false Јx1 ;; якщо пройшов, то йдемо до x1, те ж саме і далі, окрім 5 - останньої
00D6: if 1
8039: NOT $checkpoint == 2 ;; integer values
0001: wait 0 ms
004D: jump_if_false Јx2
00D6: if 1
8039: NOT $checkpoint == 3 ;; integer values
0001: wait 0 ms
004D: jump_if_false Јx3
00D6: if 1
8039: NOT $checkpoint == 4 ;; integer values
0001: wait 0 ms
004D: jump_if_false Јx4
00D6: if 1
8039: NOT $checkpoint == 5 ;; integer values
0001: wait 0 ms
004D: jump_if_false ЈPASSED ;; якщо гравець пройшов останню відмітку, то йдемо до мітки з виведенням повідомлення про виграш
0002: jump Јpank
:x1
018C: play_sound 1 at 0.0 0.0 0.0 ;; програємо звук
0164: disable_marker $chk ;; видаляємо маркер $chk
0086: $x = $x1 ;; floating-point values only ;; задаємо конкретно змінній $x значення змінної $x1
0086: $y = $y1 ;; floating-point values only
0086: $z = $z1 ;; floating-point values only
018A: $chk = create_checkpoint_at $x $y $z
0165: set marker $chk color to 1
0008: $checkpoint += 1 ;; integer values ;; додаємо 1 пункт до кількості пройдених відміток
0002: jump Јcnt
:x2
018C: play_sound 1 at 0.0 0.0 0.0
0164: disable_marker $chk
0086: $x = $x2 ;; floating-point values only
0086: $y = $y2 ;; floating-point values only
0086: $z = $z2 ;; floating-point values only
018A: $chk = create_checkpoint_at $x $y $z
0165: set marker $chk color to 1
0008: $checkpoint += 1 ;; integer values
0002: jump Јcnt
:x3
018C: play_sound 1 at 0.0 0.0 0.0
0164: disable_marker $chk
0086: $x = $x3 ;; floating-point values only
0086: $y = $y3 ;; floating-point values only
0086: $z = $z3 ;; floating-point values only
018A: $chk = create_checkpoint_at $x $y $z
0165: set marker $chk color to 1
0008: $checkpoint += 1 ;; integer values
0002: jump Јcnt
:x4
018C: play_sound 1 at 0.0 0.0 0.0
0164: disable_marker $chk
0086: $x = $x4 ;; floating-point values only
0086: $y = $y4 ;; floating-point values only
0086: $z = $z4 ;; floating-point values only
018A: $chk = create_checkpoint_at $x $y $z
0165: set marker $chk color to 5
0008: $checkpoint += 1 ;; integer values
0008: $finish += 1 ;; integer values
0002: jump Јcnt
:changecrd ;; це аналогічно тому, що з гравцем, тільки якщо суперник набереться 5 пунктів кількості пройдених ним відміток, то гонка програна
00D6: if 1
8039: NOT $crd == 1 ;; integer values
0001: wait 0 ms
004D: jump_if_false Јx11
00D6: if 1
8039: NOT $crd == 2 ;; integer values
0001: wait 0 ms
004D: jump_if_false Јx21
00D6: if 1
8039: NOT $crd == 3 ;; integer values
0001: wait 0 ms
004D: jump_if_false Јx31
00D6: if 1
8039: NOT $crd == 4 ;; integer values
0001: wait 0 ms
004D: jump_if_false Јx41
00D6: if 1
8039: NOT $crd == 5 ;; integer values
0001: wait 0 ms
004D: jump_if_false ЈRACEFA ;; йдемо на мітку з виведенням тексту про провал місії
0002: jump Јchangecrd
:x11
0086: $xZ = $x1 ;; floating-point values only
0086: $yZ = $y1 ;; floating-point values only
0086: $zZ = $z1 ;; floating-point values only
0008: $crd += 1 ;; integer values ;; додаємо 1 пункт до кількості пройдених суперником міток
02C2: car $zbr drive_to_point $xZ $yZ $zZ ;; машина суперника їде на координати $xZ $yZ $zZ
0002: jump Јcnt
;; все, що нижче, аналогічно описанню мітки x11
:x21
0086: $xZ = $x2 ;; floating-point values only
0086: $yZ = $y2 ;; floating-point values only
0086: $zZ = $z2 ;; floating-point values only
0008: $crd += 1 ;; integer values
02C2: car $zbr drive_to_point $xZ $yZ $zZ
0002: jump Јcnt
:x31
0086: $xZ = $x3 ;; floating-point values only
0086: $yZ = $y3 ;; floating-point values only
0086: $zZ = $z3 ;; floating-point values only
0008: $crd += 1 ;; integer values
02C2: car $zbr drive_to_point $xZ $yZ $zZ
0002: jump Јcnt
:x41
0086: $xZ = $x4 ;; floating-point values only
0086: $yZ = $y4 ;; floating-point values only
0086: $zZ = $z4 ;; floating-point values only
0008: $crd += 1 ;; integer values
02C2: car $zbr drive_to_point $xZ $yZ $zZ
0002: jump Јcnt
:PASSED ;; мітка з виведенням повідомлення про виграш гонки та про пройдену місію
0394: play_music 1 ;; програємо музику пройденої місії
0014: $race /= 1000 ;; integer values ;; ділимо число таймера гонки на 1000
01E5: text_1number_highpriority "TIME" $race 5000 ms 1 ;; виводимо текст з іменем TIME та з числом $race, тобто виводить "час: (число $race) "
0110: clear_player $PLAYER_CHAR wanted_level ;; ставимо рівень розшуку гравця на 0
01E3: text_1number_styled "RACES18" 30000 3000 ms 1 ;; вивід повідомлення про виграш гонки
0109: player $PLAYER_CHAR money += 30000 ;; даємо гравцеві приз у $30000
042F: save_record 1 $race ;; начебто зберігаємо рекорд гонки - число $race, але в статистиці він не відобразиться
0002: jump Јclean ;; йдемо до мітки очищення місії
:RACEFA ;; мітка з текстом про провал гонки
00BC: text_highpriority "RACEFA" 4000 ms 1 ;; виводимо текст про те, що гонка не виграна
0002: jump ЈFAIL
:PROTD ;; мітка для очікування 0 мс, можна не використовувати, але заважати це не буде
0001: wait 0 ms
:FAIL
00BA: text_styled "M_FAIL" 4000 ms 1 ;; виводимо текст про провал місії, до речі, 4000 ms - це час, скільки буде текст на екрані, 1 - це тип тексту, змініть його на 2 3 4 5 6, побачите різницю
0051: return ;; повернення до чогось, не знаю тільки до чого, писати все-таки слід
:clean ;; мітка очищення місії
0004: $ONMISSION = 0 ;; ставимо прапор "гравець не на місії"
004F: create_thread ЈЈstartracer ;; створюємо посилання на потік startracer
;; P.S. create_thread - виняток з правил J, JJ буде всюди і в місії, і в MAIN'e.
03BD: destroy_sphere $sph ;; прибираємо мітку $sphere
01E7: remove_forbidden_for_cars_cube -252.929 -337.286 9.307 -455.861 -499.581 10.210 ;; прибираємо заборонену область для машин на старті гонки
014F: stop_timer $race ;; зупиняємо і прибираємо таймер $race
0164: disable_marker $mrk ;; прибираємо з карти маркер над противником $mrk
0164: disable_marker $chk ;; прибираємо з карти маркер контрольної точки $chk
01C3: remove_references_to_car $zbr ;; Як перетворити машину на будь-яку випадкову машину ;; робимо тачку супротивника "вуличною"
01C3: remove_references_to_car $playcar ;; Як перетворити машину на будь-яку випадкову машину ;; робимо тачку гравця "вуличною"
01C2: remove_references_to_actor $vd ;; Як перетворити актора на випадкового пішохода ;; робимо супротивника в гонці звичайним перехожим
0249: release_model #HOTRING ;; видаляємо з пам'яті модель тачки
0249: release_model #WMYGO ;; видаляємо з пам'яті моделі водія
00D8: mission_cleanup ;; видаляємо код місії з пам'яті
0051: return ;; повертаємось до попереднього стану, яке було до місії
Ну от! Я навчив вас створенню гонки, з цим матеріалом ви навчитеся створювати гонки на 2 гонщиків.
З повагою, zx300
Рекомендовані файли

HD Universe GTA Vehicles [Update XIII]

PS2 to Mobile + Fixes

Updated Classic Uncover - Vice City (Build 23)

Реалістичні пішоходи - Real Peds Overhaul

Grand Theft Auto: Sindacco Chronicles - PSP Видання

Zombie Andreas Complete Final (Build 75)

Hot Coffee Mobile (Improved Mobile main.scm)

GTA SA Classic v1.7 - Атмосфера ПК-версії гри в GTA SA Mobile

Вид від першої особи - First Person Mod 3.0 (Fixed)

Vice City: Nextgen Edition Patch v1.2

Велика збірка CLEO-скриптів

Повний пак машин з GTA 5

TXD Tool версія 1.4.9.3 (тільки Android)

VGSA 2.0 - реалістична графіка
