Город Мастеров
IPB

Здравствуйте, гость ( Вход | Регистрация )

> Крафт для мультика, да чтоб не лагал
_kaa_
сообщение Jun 17 2004, 11:06
Сообщение #1


Level 9
Иконки Групп

Класс: Волшебник
Характер: Chaotic Good
Раса: Дракон
NWN: Скриптинг [PW]



Вопрос для обсуждения - как сделать крафтовый движок, достаточно гибкий, удобный в обновлении и, самое главное, не приводящий к лагам.

Самый распространенный вариант - делать все рецепты для крафта через .2da файлы. И обновлять удобно (достаточно на сервер выложить новую версию файлов и )желательно) перегрузить модуль). Но есть и проблемы. 2да таблицы хороши, пока число строк в ней невелико. С ростом файла задержки становяться просто недопустимыми и нужно придумывать что-то другое.

Хороший вариант - использовать внешнюю БД (mySQL например) и делать через нее. Будет быстрее и довольно гибко (обновлять рецепты можно даже через веб-интерфейс, не перегружая модуль).
Только есть свои "если". Если хостер прикрутит поддержку mySQL и поставит саму mySQL.

Хочу предложить другой вариант, в чем-то менее удобный, но заметно более быстрый.

Идея простая. Пусть все рецепты хранятся в тех-же 2да файлах (не важно в чем соб-но). Пишется простой скрипт (программа) (я использовал perl), который преобразует таблицу в .nss скрипт, готовый для компиляции. Его можно вставить в модуль, а для обновления можно просто класть новую версию в папку override на сервере, не меняя сам модуль.

Что должен делать такой скрипт, на примере.

Вот кусок реальной 2da-таблицы (список ресурсов-спавнов, с Мидгарда)

Код

2DA V2.0

  Name   FullName             FullName2          ResRef         Price Spawn TTL   Radius Search Spot MaxValue MaxCount DC Desc                                                                
0  min020 "Торф"               "торфа"            "_res_min020"  1     2     6000  5      6      **** 5        48       8  "Торф._Применяется_для_выплавки_слитков_и_сплавов_из_руды."          
1  min022 "Уголь"              "угля"             "_res_min022"  15    1     6000  4      12     **** 7        25       12 "Каменный_уголь._Применяется_для_выплавки_слитков_и_сплавов_из_руды."
2  min013 "Болотное_железо"    "железа"           "_res_min013"  1     2     6000  2      10     **** 8        30       10 "Железная_руда_невысокого_качества"                                  

[...skip...]



Описывается имя резурса, русское имя, имя в падеже, ресреф, шансы на спавн, место спаван (поверхность\подземелье\везде), время жизни спавна, радиус обнаружения ресурса, DC на search, spot, на добычу, максимальное качество и количество ресурса в спавне и описание.

После работы скрипта получаем вот такой скрипт

Код


string _res_i()
{
   object oI = GetWaypointByTag("mg_wp_i");
   if (GetIsObjectValid(oI))
       return GetName(oI);
   else
       return "Я";
}

//return count of resources
int _cra_GetMaxRes();

struct stRes
{
   string Name,FullName,FullName2,ResRef, Desc;
   int Price, Spawn, TTL, Radius, Search, Spot, MaxValue, MaxCount, DC, Result;
};


struct stRes _cra_GetRes(int nNumber)
{
   struct stRes stResult;
   if (!nNumber || nNumber > _cra_GetMaxRes())
   {
       stResult.Result = 0;
       return stResult;
   }

 
   switch (nNumber)
   {

   case 1:
       stResult.Name      = "min020";
       stResult.FullName  = "Торф";
       stResult.FullName2 = "торфа";          
       stResult.ResRef    = "_res_min020";        
       stResult.Price     = 1;
       stResult.Spawn     = 2;
       stResult.TTL       = 6000;
       stResult.Radius    = 5;
       stResult.Search    = 6;
       stResult.Spot      = 0;
       stResult.MaxValue  = 5;
       stResult.MaxCount  = 48;
       stResult.DC        = 8;
       stResult.Desc      = "Торф. Примен"+_res_i()+"етс"+_res_i()+" дл"+_res_i()+" выплавки слитков и сплавов из руды.";
       stResult.Result    = 1;
       break;


   case 2:
       stResult.Name      = "min022";
       stResult.FullName  = "Уголь";
       stResult.FullName2 = "угл"+_res_i()+"";          
       stResult.ResRef    = "_res_min022";        
       stResult.Price     = 15;
       stResult.Spawn     = 1;
       stResult.TTL       = 6000;
       stResult.Radius    = 4;
       stResult.Search    = 12;
       stResult.Spot      = 0;
       stResult.MaxValue  = 7;
       stResult.MaxCount  = 25;
       stResult.DC        = 12;
       stResult.Desc      = "Каменный уголь. Примен"+_res_i()+"етс"+_res_i()+" дл"+_res_i()+" выплавки слитков и сплавов из руды.";
       stResult.Result    = 1;
       break;


   case 3:
       stResult.Name      = "min013";
       stResult.FullName  = "Болотное железо";
       stResult.FullName2 = "железа";          
       stResult.ResRef    = "_res_min013";        
       stResult.Price     = 1;
       stResult.Spawn     = 2;
       stResult.TTL       = 6000;
       stResult.Radius    = 2;
       stResult.Search    = 10;
       stResult.Spot      = 0;
       stResult.MaxValue  = 8;
       stResult.MaxCount  = 30;
       stResult.DC        = 10;
       stResult.Desc      = "Железна"+_res_i()+" руда невысокого качества";
       stResult.Result    = 1;
       break;

[...skip...]
return stResult;
}

int _cra_GetMaxRes()
{
   return 3;
}


Данный вариант - инклуд (можно делать и вызываемый скрипт), возвращает структуру по номеру и количество ресурсов.

Вставляем этот файл в папку с открытым модулем, компилим. Скорость работы - выше сложнее придумать, ведь мегабайтные файлы с АИ мобов выполняются шустро, а тут объемы гораздо меньше и все данные статичны.

Аналогично можно поступить с любой 2да-таблицей.
Как уже говорил - не обязаетельно делать вариант с инклудом полученного скрипта в другой, можно создавать полноценный скрипт с main() функцией и передавать в него параметры через SetLocalInt(GetModule()...), ExecuteScript("..",) и потом так-же получать результат - GetLocalInt(GetModule()...)

В моем случае все скрипты писались под определенные 2да-таблицы, но легко можно сделать унифицированный скрипт, который будет работать очень похоже на функцию чтения данных из 2да-файла.

Что в итоге:
минусы:
* дополнительный этап при сборке модуля, если изменились таблицы - компиляция 2да-таблиц в скрипты.
* меньшая гибкость по сравнению с mySQL -вариантом в плане обновления
плюсы:
* скорость. выше - сложнее придумать, а для шарда это очень важно
* не нужны спец. условия для хостинга
* простота и универсальность (хоть и проигрывает в этом простому варианту с 2да-файлами)

Предлагаю обсудить другие варианты и отвечу на вопросы - если будут (IMG:style_emoticons/kolobok_light/smile.gif)

Сообщение отредактировал _kaa_ - Jun 17 2004, 11:07
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения
 
Открыть новую тему
Ответов
Valleo
сообщение Aug 3 2004, 08:41
Сообщение #2


Level 4
**

Класс: Друид
Характер: Neutral Evil
Раса: Эльф
NWN: Скриптинг [PW]



Да у меня крафт такой, что нельзя сделать из там металла+дерева топор.
У меня можно из этого топора забабахать +1 энчант, +2 урон кислотой и т.п. =) Смотря какие рецепты...
И кончно же этот энчант +1 можно сделать +2 и +3 и т.п....
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения

Сообщений в этой теме


Ответить в эту темуОткрыть новую тему
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 



Текстовая версия Сейчас: 23rd June 2024 - 10:26