Этот урок позволит вам создавать новые локации на основе существующих моделей.
Первый вопрос который необходимо рассмотреть - локаторы.
В каждой модели присутствуют локаторы, которые управляют моделью в игре. Локаторы указывают где необходимо генерировать предметы, монстров, где будет переход на другую локацию и т.д.
Локатор может быть автоматическим – т.е. загрузка в следующую локацию происходит автоматически, как только игрок вступает в зону действия локатора (например локаторы в джунглях).
Локаторы могут быть закрыты и открыты. Состоянием локатора
можно управлять из кода квестов. Например:
Locations[FindLocation("Oxbay_town")].reload.l2.disable
= true;
Закрывает ворота в Оксбее.
Как видно для управления локатором надо знать его имя, это можно узнать используя программу GM Viewer, но благо глючного софта у нас ещё лет на триста припасено, поэтому я предлагаю более удобный способ.
Заходим в папку locations\locations_loader.c и ищём там комментарий:
/*
VisibleLocatorsGroup("reload", 1.0,
15.0, 255, 0, 255, 0);
VisibleLocatorsGroup("Merchant",
1.0, 15.0, 105, 0, 255, 125);
...
VisibleLocatorsGroup("sit",
1.0, 15.0, 255, 255, 0, 0);
VisibleLocatorsGroup("item", 1.0, 15.0, 255, 255, 0, 255);
//*/
И удалите символы /* и */? После чего допишите следующие строки:
VisibleLocatorsGroup("rld", 1.0,
15.0, 255, 0, 255, 0);
VisibleLocatorsGroup("box",
1.0, 15.0, 255, 255, 0, 0);
VisibleLocatorsGroup("randitem", 1.0, 15.0, 255, 255, 0, 255);
Сохраняем, загружаем игру – и о чудо, мир совсем другим зрением…это супер зрение!
Надо сказать огромное спасибо разработчикам за наличие локаторов которые не используются… Давайте задействуем какой-нибудь локатор, благо теперь имена мы можем определить…J Скажем сделаем вход к ростовщику через заднюю дверь…
Все свои опыты я ставил над островом Оксбей – т.к. не пришлось менять стартовую локацию.
Итак открываем location\init\Oxbay.c, и находим такую секцию(секция описания города):
//
-------------------------------------------------
Locations[n].filespath.models =
"locations\town_Oxbay\town";
Locations[n].image =
"loading\oxbay_town.tga";
Locations[n].id = "Oxbay_town";
Теперь ниже найдите секцию:
//Reload map
Locations[n].reload.l1.name =
"reload1";
Locations[n].reload.l1.go =
"Oxbay_port";
Locations[n].reload.l1.emerge =
"Reload1";
Locations[n].reload.l1.autoreload =
"0";
Locations[n].reload.l1.label = "Port.";
И скопируйте её куда-нибудь нижу, Но в секции описания города Оксбей.
Теперь сделайте следующие изменения:
//Новая дверь
Locations[n].reload.l12.name = "reload6";// Имя локатора который перебрасывает нас
Locations[n].reload.l12.go
= "Oxbay_UsurerHouse";// ID локации куда переходим
Locations[n].reload.l12.emerge
= "reload2";// Локатор, в котором появимся
Locations[n].reload.l12.autoreload
= "0";//самозагрузка
Locations[n].reload.l12.label
= "Loanshark
Этим мы активировали дверь на верфи(дальнюю), которая ведёт к ростовщику.
Теперь сделаем какую-нибудь локацию с автоматической загрузкой, например вход в катакомбы со стороны порта.
Находим следующий текст:
Locations[n].reload.l4.name = "reload3";
Locations[n].reload.l4.go =
"Dungeon 1";
Locations[n].reload.l4.emerge
= "reload2";
Locations[n].reload.l4.autoreload
= "0";
Locations[n].reload.l4.label
= "Cave.";
Locations[n].locators_radius.reload.reload2_back
= 3;
И меняем строку
Locations[n].reload.l4.autoreload
= "0";
На
Locations[n].reload.l4.autoreload
= "1;
Сохраняем и проверяем!
Ну немного разобрались. Идём
дальше. Теперь давайте добавим домик.
Наша задача – сделать больше
комнат в домике рядом с выходом в джунгли.
Пишем следующий код:
Locations[n].reload.l11.name
= "reload2";
Locations[n].reload.l11.go =
"Oxbay_HouseInsideR6";
Locations[n].reload.l11.emerge
= "reload1";
Locations[n].reload.l11.autoreload
= "0";
Locations[n].reload.l11.label
= "House.";
Теперь у нас есть описание телепортации, необходимо описать локацию куда будем телепортироваться.
Найдём какой-нибудь существующий дом:
//
******************************************************************************************
Locations[n].id =
"Oxbay_HouseInsideR9";
Locations[n].id.label =
"House";
Locations[n].image =
"loading\room.tga";
//Town
sack
Locations[n].townsack =
"Oxbay";
//Sound
locations[n].type =
"house";
locations[n].fastreload =
"Oxbay";
//Models
//Always
Locations[n].filespath.models
= "locations\inside\MediumHouse";
Locations[n].models.always.locators
= "mh_l";
Locations[n].models.always.house
= "mh";
Locations[n].models.always.window
= "mh_w";
Locations[n].models.always.window.tech
= "LocationWindows";
Locations[n].models.always.window.level
= 50;
//Day
Locations[n].models.day.charactersPatch
= "mh_p";
//Night
Locations[n].models.night.charactersPatch
= "mh_p";
//Environment
Locations[n].environment.weather
= "false";
Locations[n].environment.sea
= "false";
Locations[n].models.back =
"back\oxmh_";
Locations[n].reload.l1.name =
"reload1";
Locations[n].reload.l1.go =
"Oxbay_town";
Locations[n].reload.l1.emerge
= "reload9";
Locations[n].reload.l1.autoreload
= "0";
Locations[n].reload.l1.label
= "Oxbay";
Locations[n].locators_radius.reload.reload1
= 0.8;
n = n + 1;
скопируем его немного ниже и изменим только ID и локатор выхода.
Locations[n].id =
"Oxbay_HouseInsideR6"; //Новый ID
Locations[n].id.label =
"House";
Locations[n].image =
"loading\room.tga";
//Town sack
Locations[n].townsack =
"Oxbay";
//Sound
locations[n].type =
"house";
locations[n].fastreload =
"Oxbay";
//Models
//Always
Locations[n].filespath.models =
"locations\inside\MediumHouse";
Locations[n].models.always.locators
= "mh_l";
Locations[n].models.always.house =
"mh";
Locations[n].models.always.window =
"mh_w";
Locations[n].models.always.window.tech
= "LocationWindows";
Locations[n].models.always.window.level
= 50;
//Day
Locations[n].models.day.charactersPatch
= "mh_p";
//Night
Locations[n].models.night.charactersPatch
= "mh_p";
//Environment
Locations[n].environment.weather =
"false";
Locations[n].environment.sea =
"false";
Locations[n].models.back =
"back\oxmh_";
Locations[n].reload.l1.name =
"reload1";
Locations[n].reload.l1.go =
"Oxbay_town";
Locations[n].reload.l1.emerge =
"reload2"; // новый локатор выхода Locations[n].reload.l1.autoreload =
"0";
Locations[n].reload.l1.label =
"Oxbay";
Locations[n].locators_radius.reload.reload1
= 0.8;
n = n + 1;
Теперь создадим локацию, пускай это будет склад, склад на основе модели верфи.
Как всегда сначала необходимо активировать локатор, пускай
это будет локатор дома между таверной и магазином(маленький покосившийся
сарай). В секцйии опсиания города пишем:
Locations[n].reload.l13.name =
"reload14";
Locations[n].reload.l13.go = "Oxbay_warehouse";
Locations[n].reload.l13.emerge =
"reload2";
Locations[n].reload.l13.autoreload =
"0";
Locations[n].reload.l13.label = "Warehouse.";
Итак, локатор мы активировали, теперь необходимо описать саму локацию. Так как наша локация делается на основе верфи, так давайте и локацию опишем не основе описания верфи. Находим и копируем секцию:
Locations[n].filespath.models =
"locations\Inside\shipyard";
Locations[n].id =
"Oxbay_shipyard";
locations[n].id.label = "Oxbay
shipyard";
Locations[n].image = "loading\Shipyard_01.tga";
.....
.....
Locations[n].models.back =
"back\oxsh1_";
//Reload map
Locations[n].reload.l1.name =
"reload1";
Locations[n].reload.l1.go =
"Oxbay_town";
Locations[n].reload.l1.emerge =
"Reload3";
Locations[n].reload.l1.autoreload =
"0";
Locations[n].reload.l1.label =
"Oxbay.";
LAi_LocationFightDisable(&Locations[n],
true);
n = n + 1;
Теперь изменим её в соответствии с желанием:
Locations[n].filespath.models =
"locations\Inside\shipyard";
Locations[n].id =
"Oxbay_warehouse"; //ID
locations[n].id.label =
"Warehouse"; //метка
Locations[n].image =
"loading\House_04.tga"; //Картинка загрузки в локацию
//Town sack
Locations[n].townsack =
"Oxbay";
//Sound
locations[n].type =
"house"; //тип звуков
locations[n].fastreload =
"Oxbay";
//Models
//Always
Locations[n].models.always.locators
= "sh01_l";
Locations[n].models.always.shipyard
= "sh01";
Locations[n].models.always.window =
"sh01_w";
Locations[n].models.always.window.tech
= "LocationWindows";
Locations[n].models.always.window.level
= 50;
//Day
Locations[n].models.day.charactersPatch
= "sh01_p";
Locations[n].models.day.fd =
"sh01_fd";
//Night
Locations[n].models.night.charactersPatch
= "sh01_p";
Locations[n].models.night.fn =
"sh01_fn";
//Environment
Locations[n].environment.weather =
"false";
Locations[n].environment.sea =
"false";
Locations[n].models.back =
"back\oxsh1_";
//Reload map
Locations[n].reload.l1.name = "reload1"; //Выход
Locations[n].reload.l1.go =
"Oxbay_port"; //Выйдем в
порт Locations[n].reload.l1.emerge =
"Reload1"; //где появимся
Locations[n].reload.l1.autoreload =
"0";
Locations[n].reload.l1.label =
"Port."; //метка
n = n + 1;
Теперь давайте освоим управления моделями. Примером будет служить создания большого особняка на Оксбее.
Для начала откроем локатор. Пускай это будет так:
Locations[n].reload.l15.name =
"reload4";
Locations[n].reload.l15.go = "Oxbay_mansion_hall";
Locations[n].reload.l15.emerge =
"reload2";
Locations[n].reload.l15.autoreload =
"0";
Locations[n].reload.l15.label = "Mansion.";
Теперь опишем нашу локацию
Locations[n].id =
"Oxbay_mansion_hall"; //ID
locations[n].id.label =
"Mansion"; //метка
Locations[n].filespath.models =
"locations\inside\Residence_BackHall";
Locations[n].image =
"loading\house_01.tga"; //Картинка загрузки
//Town sack
Locations[n].townsack = "Oxbay"; //К какому городу относится
//Sound
locations[n].type =
"house"; //тип локации
locations[n].fastreload =
"Oxbay"; //быстрые загрузки
//Models
//Always
Locations[n].models.always.locators
= "ResB_l";
Locations[n].models.always.l1 =
"ResB";
Locations[n].models.always.window =
"ResB_w";
Locations[n].models.always.window.tech
= "LocationWindows";
Locations[n].models.always.window.level
= 50;
//Day
Locations[n].models.day.charactersPatch
= "ResB_p";
Locations[n].models.day.lights.candles
= "candelabrum_small";
//Night
Locations[n].models.night.charactersPatch
= "ResB_p";
Locations[n].models.night.lights.candles
= "candelabrum_small";
//Environment
Locations[n].environment.weather =
"false";
Locations[n].environment.sea =
"false";
Locations[n].models.back =
"back\redrsb_"; //Вид из
окон
//Reload map
Locations[n].reload.l1.name =
"reload2"; //включаем локатор
Locations[n].reload.l1.go =
"Oxbay_town"; //ID
куда ведёт локатор Locations[n].reload.l1.emerge
= "reload4"; //Где появимся
Locations[n].reload.l1.autoreload =
"0";
Locations[n].reload.l1.label =
"Town.";
Locations[n].reload.l2.name = "reload1";
Locations[n].reload.l2.go = "Oxbay_mansion_study"; Locations[n].reload.l2.emerge = "reload1";
Locations[n].reload.l2.autoreload =
"0";
Locations[n].reload.l2.label =
"Study.";
n = n + 1;
Как видно теперь у нас есть ещё одна не задействованная дверь. Мы её включили, теперь надо описать новую локацию.
Locations[n].filespath.models =
"locations\Inside\Residence3";
Locations[n].id =
"Oxbay_mansion_study";
locations[n].id.label =
"Study";
Locations[n].image = "";
//Town sack
Locations[n].townsack = "Oxbay";
//Sound
locations[n].type = "house";
locations[n].fastreload = "Oxbay";
//Models
//Always
Locations[n].models.always.locators
= "Res03_l";
Locations[n].models.always.l1 =
"Res03";
Locations[n].models.always.window =
"Res03_w";
Locations[n].models.always.window.tech
= "LocationWindows";
Locations[n].models.always.window.level
= 50;
//Day
Locations[n].models.day.charactersPatch
= "Res03_p";
//Night
Locations[n].models.night.charactersPatch
= "Res03_p";
//Environment
Locations[n].environment.weather =
"false";
Locations[n].environment.sea =
"false";
Locations[n].models.back =
"back\mures3_";
//Reload map
Locations[n].reload.l1.name =
"reload1";
Locations[n].reload.l1.go = "Oxbay_mansion_hall";
Locations[n].reload.l1.emerge = "reload1";
Locations[n].reload.l1.autoreload =
"0";
Locations[n].reload.l1.label =
"Hall";
Locations[n].reload.l2.name = "reload2";
Locations[n].reload.l2.go =
"Oxbay_mansion_bedroom"; Locations[n].reload.l2.emerge
= "reload1";
Locations[n].reload.l2.autoreload = "0";
Locations[n].reload.l2.label =
"Study.";
n = n + 1;
И последнее – ещё одна комната.
Locations[n].id = "Oxbay_mansion_bedroom";
locations[n].id.label =
"Bedroom";
Locations[n].filespath.models =
"locations\inside\ResBedRoom";
Locations[n].image =
"loading\Bedroom.tga";
//Sound
locations[n].type = "house";
locations[n].fastreload = "Oxbay";
//Models
//Always
Locations[n].models.always.locators
= "bed_l";
Locations[n].models.always.l1 =
"bed";
Locations[n].models.always.window =
"bed_w";
Locations[n].models.always.window.tech
= "LocationWindows";
Locations[n].models.always.window.level
= 50;
//Day
Locations[n].models.day.charactersPatch
= "bed_p";
//Night
Locations[n].models.night.charactersPatch
= "bed_p";
//Environment
Locations[n].environment.weather =
"false";
Locations[n].environment.sea =
"false";
Locations[n].models.back =
"back\redb_";
//Reload map
Locations[n].reload.l1.name =
"reload1";
Locations[n].reload.l1.go =
"Oxbay_mansion_study";
Locations[n].reload.l1.emerge =
"reload2";
Locations[n].reload.l1.autoreload =
"0";
Locations[n].reload.l1.label =
"Study.";
n = n + 1;
Итак, после не очень долгой работы мы получили большой новый особняк – аж 3 комнаты!
Ну думаю что немного разобрались…J. Теперь перейдём к следующему шагу – научимся делать не загружаемые локаторы загружаемыми.
В качестве объекта для опыта будет форт – наша задача сделать дверь с суши в форт.
Ну как включить локатор описывать уже нет нужды – если вы до сих пор не поняли, то дальше читать нет смысла!
Я покажу только описание самого форта(кстати все форты описываются в файле locations\init\boarding.c)
Locations[n].id =
"Oxbay_fake_fort"; //
ID
locations[n].id.label =
"MILITARY AREA. NO TRESPASSING !";
//Info
Locations[n].filespath.models =
"locations\Fort_inside\Fort_1\";
Locations[n].image =
"loading\Fort_01.tga";
//Sound
locations[n].type = "town";
locations[n].fastreload =
"Oxbay";
//Models
//Always
Locations[n].models.always.locators
= "fort1_l";
Locations[n].models.always.l1 =
"fort1";
//Day
Locations[n].models.day.charactersPatch
= "fort1_p";
Locations[n].models.day.fonar =
"fort1_fd";
//Night
Locations[n].models.night.charactersPatch
= "fort1_p";
Locations[n].models.night.fonar =
"fort1_fn";
//Environment
Locations[n].environment.weather =
"true";
Locations[n].environment.sea =
"false";
Locations[n].reload.l1.name =
"character_3";
Locations[n].reload.l1.go =
"Oxbay_suburb";
Locations[n].reload.l1.emerge =
"Falaise_de_fleur_location_02_perechod";
Locations[n].reload.l1.autoreload =
"0";
Locations[n].reload.l1.label =
"Oxbay.";
Locations[n].locators_radius.rld.character_3 = 2;
n = n + 1
ВНИМАНИЕ! Reload Map работает только если вы разрешили группы rld!
Теперь займёмся следующим – попытаемся появиться в локаторах, которые для этого не предназначены!
Итак хотя мы уже сделали локацию форта, но работа ещё не завершена. Вы можете попробовать зайти в новую локацию и увидите что ваш персонаж не может ходить! Это происходит потому что телепортация между двумя локациями происходит по локаторам группы RELOAD, а в форте эта группа называется RLD. Что бы всё заработало как надо, необходимо объявить эти локаторы. Заходим в файл characters_login.c:
Ищем функцию void LoginCharacter(aref chr, string locID). После чего в участке:
if((CheckAttribute(chr,
"index") != false) &&
(GetMainCharacterIndex() == sti(chr.index)))
Пишем следующий текст:
if(chr.location.locator=="loc0")
chr.location.group = "rld";
TeleportCharacterToLocator(chr,
chr.location.group, chr.location.locator);
Если вам необходимо разрешить другие локаторы то их тоже
необходимо описать здесь же. Например так:
if(chr.location.locator=="goto2")
chr.location.group = "goto";
else
{
if(chr.location.locator=="loc0") chr.location.group = "rld";
}
Else
{
chr.location.group = "monsters";
}
Теперь всё работает! Но учтите что загружать перса надо именно в тот локатора который вы объявили!
Так, загрузить то мы загрузили, а вот как выйти? Локаторы выхода то там тоже нет…
Нам опять надо объявить наши локаторы в locations\locations_loader.c в секции
//Main character options=========================
Добавьте в описание локаторов строку:
AddCharacterLocatorGroup(mainCharacter, "rld");
Следующее изменению будет в файле characters\characters_events.c. Найдите в нём функцию chrCharacterEntryToLocator.
Вот эта функция после редактирования:
void
chrCharacterEntryToLocator()
{
aref loc = GetEventData();
....
ref mc = GetMainCharacter();
int result;
// Если мы
в локации Oxbay_fake_fort и локатор character_3 то переносим его в
группу reload
if(mc.location ==
"Oxbay_fake_fort" && locator == "character_3"){
group = "reload"; }
switch(group)
{
case "reload":
chrWaitReloadIsNoLink
= false;
И на последок нам необходимо отредактировать функцию
void chrCharacterExitFromLocator()
Сделайте следующие изменения:
void
chrCharacterExitFromLocator()
{
aref loc = GetEventData();
....
float timeInLocator =
GetEventData();
ref mc = GetMainCharacter();
if(mc.location == "dungeon
1" && locator == "box3"){ group = "reload"; }
if(mc.location ==
"Oxbay_cave" && locator == "randitem1"){ group =
"reload"; }
if(mc.location ==
"Oxbay_fake_fort" && locator == "character_3"){
group = "reload"; }
switch(group)
{
case "reload":
ну вот и всё что я хотел рассказать…теперь вы умеете управлять локациями и локаторами…можно даже сделать минное поле…J