Форумы онлайн-игры "Сфера Миров"

Форумы посвящены онлайн-игре MUD "Сфера Миров", ее игровому миру и просто общению игроков.
Текущее время: 25-04, 01:25

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 75 ]  На страницу 1, 2, 3, 4, 5  След.
Автор Сообщение
 Заголовок сообщения: Вопросы по написанию триггеров
СообщениеДобавлено: 21-09, 20:46 
Не в сети
хайлевел
Аватара пользователя

Зарегистрирован: 18-07, 14:31
Сообщения: 478
Откуда: Home.Saratov.Russia
Тема открыта для тех, кто действительно хочет писать скрипты, у кого есть вопросы по реализации и кому не хватает опыта в области работы с кодом. Большая просьба не устраивать тут флудильню и не вносить офтоп (заниматься модерированием у меня нету желания)

Здесь я буду делиться опытом написания скриптов, который накопил почти за год занятия этой проблеммой.

Оформлять свои знания в виде какого то руководства мне просто лень, поэтому в этой теме я буду работать по принципу: вопрос - ответ.

_________________
не суйте пальцы в разетку


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 21-09, 20:47 
Не в сети
хайлевел
Аватара пользователя

Зарегистрирован: 18-07, 14:31
Сообщения: 478
Откуда: Home.Saratov.Russia
Вопрос 1. Что такое скрипты?
Ответ:

Скрипты - это некоторая программа, которая срабатывает в момент возниконвения некоторого события. Например, персонаж вошел в комнату - это событие. Если для этого события написан скрипт, то он сработает.

Скрипты пишутся на языке С++ и компилируются в dll файл. Этот файл автоматически подключается во время запуска сервера и для всех скриптов делаются необходимые установки.

Для написания и компиляции скриптов обычно используется среда Visual Studio 6.0 и более поздних версий. Скомпилированный dll файл работает совместно с ядром мада и без него не может исполняться.

_________________
не суйте пальцы в разетку


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 21-09, 21:01 
Не в сети
ньюб
Аватара пользователя

Зарегистрирован: 10-08, 13:53
Сообщения: 46
Откуда: Чудесная страна
повторюсь
вопрос:
нужен ли мне этот самый редактор с++ для написания скриптов, или я смогу это сделать в обычном блокноте и скомпилить уже средствами самого сервера. всегда было интересно для чего там файлик sowkit.exe.

_________________
Хорошо там где нас нет...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 21-09, 21:06 
Не в сети
хайлевел
Аватара пользователя

Зарегистрирован: 18-07, 14:31
Сообщения: 478
Откуда: Home.Saratov.Russia
Вопрос 2. С чего начать?
1. Прежде всего надо знать синтаксис языка программирования С++ и иметь представление о программировании (хотя бы процедурном).

2. Надо установить Visual Studio 6.0 или более поздних версий для компиляции триггеров. Так же среда Visual Studio предоставляет достаточно удобный редактор для работы с кодом.

3. Скачать файлы с ядром сервера с официального сайта игры из раздела файлы. Так же скачать примеры.

Теперь у вас есть все, что бы начать писать триггеры.
Евли вы совершенно ничего не понимаете в процедуре создания проекта на Visual Studio, то следующие пункты специально для вас:
1. Сделайте папку sow.
2. Скопируйте в нее папку Kernel из архива sowkit с официального сайта.
3. В папке sow сделайте папку Zones.
4. В папку Zones скопируйте папку School из примеров триггеров с официального сайта.
5. В папке Zones создайте новую папку для скриптов к вашей зоне и дайте ей название, соответсвующее зоне (желательно на английском)
6. Скопируйте файл school.dsp в созданую вами папку и переименуйте его в соответсвии с названием папки.
7. Запустите проект. У вас получиться проект с готовыми настройками и неправильно подключенным файлом school.cpp. Удалите school.cpp из проекта и создайте свой cpp файл.

Детали работы с Visual Studio я опускаю, потому что вам все равно придется разбираться с работой с этой программой. Настройка проекта - процесс достаточно сложный, поэтому я рекомендую не тратить на наге время и воспользоваться копией с примера.

_________________
не суйте пальцы в разетку


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 21-09, 21:08 
Не в сети
хайлевел
Аватара пользователя

Зарегистрирован: 18-07, 14:31
Сообщения: 478
Откуда: Home.Saratov.Russia
klezar писал(а):
повторюсь
вопрос:
нужен ли мне этот самый редактор с++ для написания скриптов, или я смогу это сделать в обычном блокноте и скомпилить уже средствами самого сервера. всегда было интересно для чего там файлик sowkit.exe.


Редактор для написания скриптов можно использовать любой, и компилировать скрипты можно из командной строки, но для этого надо знать достаточно много.

Файл sowkit - это архив с ядром сервера и примерами скриптов. Компилировать скрипты средствами сервера нельзя.

_________________
не суйте пальцы в разетку


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 21-09, 21:22 
Не в сети
хайлевел
Аватара пользователя

Зарегистрирован: 18-07, 14:31
Сообщения: 478
Откуда: Home.Saratov.Russia
Шаблон создания скриптов: (в качестве примера используется часть кода зоны "Городская больница Элендора")
Код:
// Описание файла.
// К какой зоне триггеры и кем написано
// Что бы СоВа знала своих героев

#include "Main.h"
// И другие подключаемые файлы
#include "DB\CharMob.h"
#include "DB\CharPlayer.h"
#include "DB\Room.h"


// Номер зоны и ее модификатор
const int ZONE_ID               = 150;
const int ZID                   = ZONE_ID * 1000;

// Константы
const int CLERIC_ROOM_ID        = ZID + 21; // Кабинет тераперта
const int TEMP_ROOM_ID          = ZID + 45; // Техническая комната

const int RAT_TAIL_OBJ_ID       = ZID + 17; // Хвост крысы

const int MEDICINAL1_OBJ_ID     = ZID + 1;  // Микстура из лекарственных трав (легкое исцеление)
const int MEDICINAL13_OBJ_ID    = ZID + 25; // Микстура из драконих слез (полное лечение всего)

const int CLERIC_MOB_ID         = ZID + 17; // Терапевт

// Переменные
static CCharMob*    s_RatMob;               // Крыса
static CCharMob*    s_ClericMob;            // Терепевт

static CRoom*       s_LiftRoom;             // Лифт
static CRoom*       s_TempRoom;             // Техническая комната
static CRoom*       s_MordRoom;             // Морг

// Таймеры
static int lift_move_timer      = 0;        // Таймер движения лифта

// Описание триггеров
int RoomTrigger_StoreRoom(CRoomTriggerData* date) {
// текст триггера для комнаты
}

int MobTrigger_StoreMan(CMobTriggerData *data) {
// текст триггера моба
}

int ObjTrigger_SomeObj(CObjTriggerData *data) {
// текст триггера для предмета
}

// Дейсвия пульса
void PerformPulse() {
// Этот метод вызывается каждый пульс.
// В нем обычно обрабатываются таймеры и некоторые постоянные дейсвия.
// В больнице здесь обрабатываются таймеры квестов и движения лифта.
}

// Загрузка триггеров и инициализация переменных.
extern "C" void _declspec(dllexport) LoadTriggers()  {
// Сообщение в лог
g_log.SystemLog("Loading Bolnica.dll triggers...");

// Поиск мобов
s_RatMob = g_db.FindMob(RAT_MOB_ID);

// Поиск комнат
s_TempRoom = g_db.FindRoom(TEMP_ROOM_ID);

// Уставнока триггеров
// Тригеры завхоза
g_trgMng.LoadMobTrigger(STORE_MAN_MOB_ID, MTRG_INCOMING_LEADER | MTRG_SPEAK | MTRG_GIVE_OBJ, MobTrigger_StoreMan);

// Обработчик пульсов
g_trgMng.LoadPulseHandler(PerformPulse);
}

// Версия (всегда именно такой код)
extern "C" int _declspec(dllexport) Version()
{
    return APP_VERSION;
}

_________________
не суйте пальцы в разетку


Последний раз редактировалось Roko 22-09, 13:56, всего редактировалось 2 раз(а).

Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 21-09, 21:24 
Не в сети
ньюб
Аватара пользователя

Зарегистрирован: 10-08, 13:53
Сообщения: 46
Откуда: Чудесная страна
согласен, попутал (
файлик там висит SowService.exe его предназначение интересно, но так понял что не для компиляции, хотя в обычной версии его вроде нету, косяк что нужна среда с++, уж лучше из командной строки делать, комп не потянет графическую среду(

_________________
Хорошо там где нас нет...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 21-09, 21:30 
Не в сети
хайлевел
Аватара пользователя

Зарегистрирован: 18-07, 14:31
Сообщения: 478
Откуда: Home.Saratov.Russia
Вопрос: (от Мекора)
Как в скриптах юзать глобальные переменные? Типа там запомнить имя, или какой-нить счетчик. Т.е. такие переменные которые используются не в одном триггере, а во многих. И главное на какое событие их обнулять? ) Поскольку зоны в Сфере репопяцо не полностью, а по мобам, я не могу придумать как обнулить переменную которая зависит от репопа именно ВСЕЙ зоны, или какой-нить ее части, а не отдельного моба.

Ответ:
Примером глобальных переменных являются s_TempRoom (временная или техническая комната) или lift_move_timer (таймер движения лифта). Эти переменные используются более чем в одном триггере зоны. Обрабатывать переменные можно в методе PerformPulse() если они носят переодический характер или в других триггерах, если эпизодических характер.

В существующих триггера игры (тех, которые я видел) синхронизация квеста происходит либо по таймеру, либо по репопу конкретного моба.
У моба можно сделать событие на репоп, и синхронизировать по этому событию, про таймер уже написал.

Как правило, для хорошо продуманного квеста нет необходимости проверять репоп всей зоны, если все же условие полного репопа обязательно, то читай следующее сообщение.

_________________
не суйте пальцы в разетку


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 21-09, 21:39 
Не в сети
хайлевел
Аватара пользователя

Зарегистрирован: 18-07, 14:31
Сообщения: 478
Откуда: Home.Saratov.Russia
Проверка полного репопа:
Код:
// Список id всех мобов, которые должны репопнуться
const int MOB1_ID = ZID + 1;
// ...

// Количество всех мобов, которые должны репонуться
const int MOB_COUNT = 10;

// Массив всех этих мобов
static CCharMob* mobs[MOB_COUNT];

// Флаг проверки полного репопа
static bool checkRepop = false;

// Функция проверки полного репопа
bool checkFullRepop() {
   if (!checkRepop) return false;

   for (int i =0; i < MOB_COUNT; i++) {
      if (!mobs[i]->inGame()) return false;
   }

   return true;
}

// Действие пульса
void PerformPulse() {
   if (checkFullRepop()) {
      checkRepop = false;
      // Полный репоп, делаем что хотели
   }
}

// Загрузка триггеров и инициализация переменных.
extern "C" void _declspec(dllexport) LoadTriggers()  {
   // Загружаем в массив всех мобов, по которым проверяется полный репоп.
}

_________________
не суйте пальцы в разетку


Последний раз редактировалось Roko 22-09, 13:58, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 21-09, 21:45 
Не в сети
хайлевел
Аватара пользователя

Зарегистрирован: 18-07, 14:31
Сообщения: 478
Откуда: Home.Saratov.Russia
klezar писал(а):
согласен, попутал (
файлик там висит SowService.exe его предназначение интересно, но так понял что не для компиляции, хотя в обычной версии его вроде нету, косяк что нужна среда с++, уж лучше из командной строки делать, комп не потянет графическую среду(


Файл SowService.exe не нашел, это либо сам сервер, сделаный в виде сервиса для Windows либо самораспаковывающийся арихв, либо еще что-то, о чем я не догадываюсь.

Я работал на достаточно старом компьютере, с 256мб оперативки и у меня среда Visual Studio .Net 2003 вполне нормально работала. А начинать написание скриптов с разбора параметров компилятора я не советую.

_________________
не суйте пальцы в разетку


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вопросы по написанию триггеров
СообщениеДобавлено: 22-09, 02:24 
Не в сети
ньюб

Зарегистрирован: 22-09, 01:42
Сообщения: 12
Какое назначение возвращаемого значения функции триггера?
А точнее, какие значения и в каких случаях может возвзращать функция триггера?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вопросы по написанию триггеров
СообщениеДобавлено: 22-09, 12:28 
Не в сети
хайлевел
Аватара пользователя

Зарегистрирован: 18-07, 14:31
Сообщения: 478
Откуда: Home.Saratov.Russia
Серб писал(а):
Какое назначение возвращаемого значения функции триггера?
А точнее, какие значения и в каких случаях может возвзращать функция триггера?


Для большенства триггеров это значение игнорируется (насколько мне известно). Учитывается лишь в некоторых событиях:

1. Если триггер обрабатывает команду (большая группа событий для комнат и предметов), например, "нажать рычаг" или "потрясти погремушку".
Алгоритм строиться следующим образом:
- Если команда написана правильно и обрабатывается, то возвращается не ноль (обычно 1).
- Если команда написана неверно или в данный момент не должна обрабатываться никак, то возвращается 0. В этом случае, персонаж, набравший команду увидит "Хмм?..".

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

Других триггеров, возвращаемое значение которых учитывается я не помню. Если вспомню, то допишу в этом же посте.

Ниже дам общую схему написания одного триггера.

_________________
не суйте пальцы в разетку


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 22-09, 12:51 
Не в сети
хайлевел
Аватара пользователя

Зарегистрирован: 18-07, 14:31
Сообщения: 478
Откуда: Home.Saratov.Russia
Когда триггер устанавливается для какого объекта, то указыватеся идентификатор протатипа этого объекта (предмета, комнаты, моба), события, на которые реагирует триггер и процедура обработки.

Код:
g_trgMng.LoadMobTrigger(STORE_MAN_MOB_ID, MTRG_INCOMING_LEADER | MTRG_SPEAK | MTRG_GIVE_OBJ, MobTrigger_StoreMan);

Здесь:
STORE_MAN_MOB_ID - идентификатор протатипа моба (определяется в разделе с константами).

MTRG_INCOMING_LEADER | MTRG_SPEAK | MTRG_GIVE_OBJ - события, на которые происходит реакция
- MTRG_INCOMING_LEADER - в комнату вошел чар (один или за ним кто-то следует)
- MTRG_SPEAK - персонаж в комнате говорит
- MTRG_GIVE_OBJ - мобу дали предмет

MobTrigger_StoreMan - процедура обработки триггера.

Процедура обработки строиться по следующей схеме:
Код:
int MobTrigger_StoreMan(CMobTriggerData* data) {
   if (data->m_type == MTRG_INCOMING_LEADER) {
      CIncomingLeaderMobTriggerData* _data = (CIncomingLeaderMobTriggerData*) data;
      // Обработка события
   }
   if (data->m_type == MTRG_SPEAK) {
      CSpeakMobTriggerData* _data = (CSpeakMobTriggerData*) data;
      // Обработка события
   }
   if (data->m_type == MTRG_GIVE_OBJ) {
      CGiveObjMobTriggerData* _data = (CGiveObjMobTriggerData*) data;
      // Обработка события
   }
   delete data;
   return 0;
}


Как видно в примере данные приводятся к типу дынных конкретного события. Корректность передаваемых данных гарантируется кодом, передающим эти данные. Здесь можно использовать и более современные средства языка для приведения типов, опытные люди меня поймут, а новичкам хватит и такого "школьного" подхода.

Триггер должен удалять структуру данных события по окончании работы с ней. Исключение составляют некоторые события (например, вход в портал), они описаны в файле kernel/system/TriggerMng.h

Советую внимательно просмотреть этот файл, что бы узнать весь доступный арсенал событий для обработки.

_________________
не суйте пальцы в разетку


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 22-09, 13:23 
Не в сети
хайлевел

Зарегистрирован: 22-09, 13:20
Сообщения: 437
Триггер RTRG_CAST вызывается когда кто угодно произнес заклинание (и моб и чар) или только когда оно произнесено чаром?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 22-09, 13:49 
Не в сети
хайлевел
Аватара пользователя

Зарегистрирован: 18-07, 14:31
Сообщения: 478
Откуда: Home.Saratov.Russia
Мекор писал(а):
Триггер RTRG_CAST вызывается когда кто угодно произнес заклинание (и моб и чар) или только когда оно произнесено чаром?


Триггер должен срабатывать на любую магию (в том числе с напитков и свитков) сотворенную игроком или чармисом. На мобов не действует.

Могу ошибаться, но чармисом при мне никто не пробовал проверять (читать свитки и пить магические напитки).

_________________
не суйте пальцы в разетку


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 75 ]  На страницу 1, 2, 3, 4, 5  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 0


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения

Найти:
Перейти:  
cron
Powered by Forumenko © 2006–2014
Русская поддержка phpBB