Для программистов, вопросы по скриптам ПКМ |
Здравствуйте, гость ( Вход | Регистрация )
Для программистов, вопросы по скриптам ПКМ |
igor_pol |
Aug 24 2005, 21:00
Сообщение
#1
|
боцман Группа: форумчанин Сообщений: 140 Регистрация: 3-December 04 Пользователь №: 169 |
Первое что я хотел написать "АДМИНЫ!!!!" НЕ ЗВЕРЕЙТЕ ЗА "НЕНУЖНУЮ ТЕМУ"
************************************************** на вопрос зачем создал эту тему отвечу так "Я например НЕ ПРОСТО ЮЗВЕРЬ А КОЕ ЧТО И САМ НАПИСАТЬ МОГУ. И хотел бы чтобы на форуме была тема для тех кто сам хочет что-то добавить в игру. На сайте аддона Алекс вікинул ссылку на описание скриптов ПКМ на английском. Я хотел бы узнать где можно нарыть больше инфы по этом скриптам. И кстати на каком языке они пишуться. Если кто-то знает ----- пишите. И вообще всем програмерам на форуме нужна своя тема. так что ГОСПОДА ПРОГРАМЕРЫ ВАЛИТЕ СЮДА !!!! Может из этого что небудь интересное выйдет!!!!!!(Если тему не УТРУТ) Жду сообщений (может у когот есть идеи на эту тему ) Сообщение отредактировал Догева - Apr 24 2006, 13:36 |
Black Angel |
Jul 13 2010, 23:42
Сообщение
#461
|
боцман Группа: форумчанин Сообщений: 252 Регистрация: 19-August 06 Из: Павлово(Нижегородская обл.) Пользователь №: 3,985 |
|
Pirat-Blad5 |
Jul 19 2010, 16:11
Сообщение
#462
|
юнга Группа: форумчанин (*) Сообщений: 15 Регистрация: 22-March 10 Пользователь №: 22,484 |
Кто знает как проверять залез ли ГГ в определенный сундук, после того квест?
|
Black Angel |
Jul 19 2010, 23:09
Сообщение
#463
|
боцман Группа: форумчанин Сообщений: 252 Регистрация: 19-August 06 Из: Павлово(Нижегородская обл.) Пользователь №: 3,985 |
Кто знает как проверять залез ли ГГ в определенный сундук, после того квест? Вот пример кода Код //при залезании в сундук срабатывает следующий квест по номеру PChar.quest.BP_17.win_condition.l1 = "location"; PChar.quest.BP_17.win_condition.l1.location = "Terks_Grot"; pchar.quest.BP_17.win_condition.l1.locator_group = "box"; pchar.quest.BP_17.win_condition.l1.locator = "box1"; pchar.quest.BP_17.function = "BP_17"; Работает только в кгпк 1.2 и выше |
Pirat-Blad5 |
Jul 22 2010, 19:18
Сообщение
#464
|
юнга Группа: форумчанин (*) Сообщений: 15 Регистрация: 22-March 10 Пользователь №: 22,484 |
Вот еще вопрос такой.
Как починить корабли ГГ, включая всех компаньонов. Я знаю только как просто только корабль ГГ починить Вот так я это делал Код DeleteAttribute(pchar, "ship.sails");// убрать дыры на парусах DeleteAttribute(pchar, "ship.blots"); DeleteAttribute(pchar, "ship.masts");// вернуть сбитые мачты SetBaseShipData(pchar); |
Black Angel |
Jul 22 2010, 23:15
Сообщение
#465
|
боцман Группа: форумчанин Сообщений: 252 Регистрация: 19-August 06 Из: Павлово(Нижегородская обл.) Пользователь №: 3,985 |
|
Pirat-Blad5 |
Jul 25 2010, 00:31
Сообщение
#466
|
юнга Группа: форумчанин (*) Сообщений: 15 Регистрация: 22-March 10 Пользователь №: 22,484 |
Не нашел в коде, может там как-то циклом по компаньонам ГГ пройтись.
---- Как забрать оружие ГГ и положить в определенный box? |
Black Angel |
Jul 25 2010, 02:04
Сообщение
#467
|
боцман Группа: форумчанин Сообщений: 252 Регистрация: 19-August 06 Из: Павлово(Нижегородская обл.) Пользователь №: 3,985 |
Не нашел в коде, может там как-то циклом по компаньонам ГГ пройтись. ---- Как забрать оружие ГГ и положить в определенный box? тебе надо сначало найти компаньенов и проделать с ними тоже самое. --- TakeItemFromCharacter(pchar, item); //забрать предмет у гг на счет этой реализации посмотри как это сделано в аддоне к к3 тдм. ЗЫ.старайся внимательнее читать код там все эти простые вещи есть. |
sasha108 |
Jul 26 2010, 12:53
Сообщение
#468
|
юнга Группа: форумчанин (*) Сообщений: 12 Регистрация: 15-July 10 Пользователь №: 23,069 |
Подскажите пожалуйста, что осуществляет программа в момент вызова
PostEvent("a",30); Event("a", "1",30); Еще маленький вопросик rand(15) это генерация случайного целого числа от 0 до 15, а что делает frnd()?? И еще вопрос. Если GetAttributesNum возвращает количество типов атрибутов у атрибута, то что возвращает GetAttributeValue?? Прошу помощи. Заранее благодарен. |
Black Angel |
Jul 26 2010, 15:53
Сообщение
#469
|
боцман Группа: форумчанин Сообщений: 252 Регистрация: 19-August 06 Из: Павлово(Нижегородская обл.) Пользователь №: 3,985 |
Почитай учебник по си,смотри примеры в коде,включи мозги и будет тебе счастье.
Вообще,прежде чем задавать вопросы надо подумать и задаться вопросом "а оно тебе надо?"Потом мыслить надо логически,желательно как комп. |
sasha108 |
Jul 26 2010, 16:27
Сообщение
#470
|
юнга Группа: форумчанин (*) Сообщений: 12 Регистрация: 15-July 10 Пользователь №: 23,069 |
Почитай учебник по си,смотри примеры в коде,включи мозги и будет тебе счастье. Вообще,прежде чем задавать вопросы надо подумать и задаться вопросом "а оно тебе надо?"Потом мыслить надо логически,желательно как комп. Да это фссе понятно. Я ж сперва погуглил, а потом спросил. Надо оно, надо. Я когда в 1С начинал писать, тоже на примерах, да на интуиции. А оно не всегда помогает, благо книжки под лапками усегда были. А потом пришло осознание, что прежде чем тырить куски кода нуно разобраться в них. Вот теперь прежде, чем что-то написать, хочу полностью разобрать код отвественный за часть, которую хочу изменить. А там, кое-где не понятно. Точнее понятно интуитивно, но хочется уверенности. Подскажите ссылочку хотя бы на литру по синтаксису си. |
ALexusB |
Jul 26 2010, 16:48
Сообщение
#471
|
Разработчик ВМЛ-КВЛ Группа: Admin Сообщений: 16,242 Регистрация: 2-November 04 Пользователь №: 3 |
Подскажите пожалуйста, что осуществляет программа в момент вызова PostEvent("a",30); Event("a", "1",30); Еще маленький вопросик rand(15) это генерация случайного целого числа от 0 до 15, а что делает frnd()?? И еще вопрос. Если GetAttributesNum возвращает количество типов атрибутов у атрибута, то что возвращает GetAttributeValue?? Прошу помощи. Заранее благодарен. Евенты - это вызвать свой евент принудительно с таймаутом, нужно прпедварительно повесить слушателя на евент, а потом его снять. Система такая многозадачная на прерываниях - это в любом нормальном языке есть. с рандом нужно эксперементить, тк в отличие от книжек - тут свои тараканы Пиши код, вызывай его кнопкой или в дебугпанели и см в логе результат Точно не помню уже вроде 0 15 (включая) будет См мой краткий мауаль по коду тут в темах или в папке с ГПК. фрнд - это от 0 до 1 действительное число, токо в скриптах это вроде эмулянт ранд (32к)/32к GetAttributeValue - его значение, ищи по коду переборы циклами - на этом у мя вся логика унификации была построена. Вообще, повторяю, структура Пчар иерархическая (дерево) - это первый шаг на пути к экспертным системам в построении алгоритмов. Это не плоская таблица, в ней можно хранить разрозненные данные, которые дают в сборе знания. Так же устроена система прерываний квестов - имхо оч удачно. |
sasha108 |
Jul 26 2010, 17:10
Сообщение
#472
|
юнга Группа: форумчанин (*) Сообщений: 12 Регистрация: 15-July 10 Пользователь №: 23,069 |
Евенты - это вызвать свой евент принудительно с таймаутом, нужно прпедварительно повесить слушателя на евент, а потом его снять. Система такая многозадачная на прерываниях - это в любом нормальном языке есть. с рандом нужно эксперементить, тк в отличие от книжек - тут свои тараканы Пиши код, вызывай его кнопкой или в дебугпанели и см в логе результат Точно не помню уже вроде 0 15 (включая) будет См мой краткий мауаль по коду тут в темах или в папке с ГПК. фрнд - это от 0 до 1 действительное число, токо в скриптах это вроде эмулянт ранд (32к)/32к GetAttributeValue - его значение, ищи по коду переборы циклами - на этом у мя вся логика унификации была построена. Вообще, повторяю, структура Пчар иерархическая (дерево) - это первый шаг на пути к экспертным системам в построении алгоритмов. Это не плоская таблица, в ней можно хранить разрозненные данные, которые дают в сборе знания. Так же устроена система прерываний квестов - имхо оч удачно. Блин, не догнал про евенты, ранее с ними не работал(((((. Можно поподробней, пожалуйста. Механизм работы этого оператора. Или ссылку. Про frnd я так и думал (float random). goodName = Goods[sti(GetAttributeValue(GetAttributeN(arCurType,j)))].name; Здесь я и не понял GetAttributeValue. Остально-то понятно. sti - преобразование типа строка-целое GetAttributeN(arCurType,j)) - получить атрибут числящийся за группой атрибутов arCurType под j-тым номером. Возращается строковое значение. Так вот и не понятно, что делает GetAttributeValue со строковым значением, что получается значение, которое приводясь в данном контексте к числовому совпадает со значением объекта Товары. Хотя изначально работа осуществлялась кучкой атрибутов, принадлежащих этой группе. Более менее разобрался с кодом экономической части Корсаров:ГПК. Автору скриптов респект. Написано все более менее ясно. Понял, как сделана добыча и потребление товаров. Супер))). |
Warship |
Jul 27 2010, 05:42
Сообщение
#473
|
Гроза морей Группа: бета-тестер Сообщений: 441 Регистрация: 29-April 07 Из: Прим. край г. Находка Пользователь №: 9,103 |
По евентам:
Логика поведения объектов в скриптах Storm 2.* отчасти основана на событиях Основная идея (если забить на Википедию): При совершении какого-то действия приложение рассылает определенное событие, после чего оно (событие) попадает в т.н. "Event pool" (из уровня скриптов эта куча недоступна). Вот в этой куче находятся все необработанные, но разосланные события. При обработке каждого события (т.е. через определенное время) оно удаляется из пула событий и происходит вызов процедуры, связанной с событием - слушателя события. Теперь о логике поведения PostEvent: Синтаксис процедуры: Код void PostEvent(string _event, int _delay, [string _pattern, ... _params]); Т.е. _pattern и _params опциональны. Вызов этой процедуры разошлет событие _event через _delay миллисекунд с указанными набором параметров (_pattern, строкой перечисляются типы параметров) и собственно с перечисленными параметрами. Т.е. Код PostEvent("someEvent", 1000); Разошлет событие "someEvent" без параметров через 1 секунду. Код PostEvent("anotherEvent", 100, "sl", "hello", 123); Разошлет событие "anotherEvent" через 100 миллисекунд со строковым параметром "hello" и целочисленным параметром 123. Доступные сокращения для шаблона параметров: "s" - строка (string). "l" - целочисленное (int). "f" - с плавающей точкой (float). "i" - ссылка (aref, кто бы мог подумать!). Для того, чтобы скриптами отловить вот такое разосланное событие, нужно установить слушателя ("подписаться на событие"). Это делается директивой препроцессора #event_handler, например: Код #event_handler("someEvent","onSomeEvent"); В этом примере идет подписка на событие "someEvent" (которое мы рассылали выше с секундной задержкой), при появлении которого будет вызвана процедура "onSomeEvent". Процедура должна быть описана без параметров. Теперь о том, как выуживать параметры из события: Напрмер, мы разослали событие anotherEvent с двумя параметрами - строкой "hello" и целочисленным 123. Для того, чтобы получить следующий параметр события, используется функция GetEventData(), возвращающая значение того-же типа, что и указано в параметрах события. Ну и пример рассылки и обработки события: Код #event_handler("anotherEvent","onAnotherEvent"); // Регистрирует для события anotherEvent процедуру-обработчик onAnotherEvent() void someProc() { // ... PostEvent("anotherEvent", 100, "sl", "hello", 123); // Разошлет событеи anotherEvent через 100 миллисекунд // ... } // Обработчик события anotherEvent void onAnotherEvent() { string str = GetEventData(); // "hello" int num = GetEventData(); // 123 // ... } Вот так вот. Директиву препроцессора можно заменять вызовом процедуры SetEventHandler(string, string, int); Первый параметр у этой процедуры - событие, которое нужно обрабатывать, второй параметр - процедура-обработчик, третий - хзчто, везде 0 (наверное, приоритет). Слушателя события, который установлен процедурой SetEventHandler, можно снять, вызвав процедуру DelEventHandler(string, string), первый параметр у которой - название события, второй - название процедуры-слушателя (если событие установлено с помощью директивы препроцессора, отписаться от него невозможно). Ну а процедура Event(string _event, [string _pattern, ...params]); выполняет тоже самое, что и PostEvent, только без задержки. В общем, надеюсь, с евентами разобрались === Терь поговорим о функциях работы с атрибутами (в дополнение к сказанному Алексом) Что имеем (из хелпа по скриптам): Код void DeleteAttribute(aref _objRef, string _attr); int GetAttributesNum(aref _objRef); aref GetAttributeN(aref _objRef, int _num); string GetAttributeName(aref _objRef); void DumpAttributes(ref _obj); int CheckAttribute(aref _objRef, string _attr); string GetAttributeValue(aref _objRef); Процедура DeleteAttribute(aref _objRef, string _attr); удаляет у указанного объекта атрибут с указанным именем. Функция GetAttributesNum(aref _objRef); возвращает количество атрибутов у указанного объекта (или атрибута объекта). Функция GetAttributeN(aref _objRef, int _num); возвращает ссылку на такой атрибут указанного объекта, который находится по указанному индексу (нумерация с нуля). Функция GetAttributeName(aref _objRef); возвращает название указанной атрибута объекта. Далее. Процедура DumpAttributes(ref _obj); выполняет трассировку в compile.log (вроде) значений (или названий, уже не помню) всех корней и листьев (атрибутов) указанного дерева. Функция CheckAttribute(aref _objRef , string _attr); возвращает булево-значение, показывающее, содержит-ли указанный корень или лист еще один корень или лист с указанным названием. Функция GetAttributeValue(aref _objRef); возвращает значение указанного корня или листа (не забываем, что все значения - это строки). === По рандому: Есть две двиговые функции: int rand(int _max); float frnd(); Первая возвращает псевдослучайное целое число в диапазоне 0 ... _max, вторая - псевдослучайное число с плавающей запятой в диапазоне 0 ... 1. Над ними есть несколько надстроек в скриптах: float FRAND(float _x) - псевдослучайное число с плавающей запятой в диапазоне 0 ... _x (rand(32768) / 32768.0 * _x). float frandSmall(float _x); - что и выше, только rand(32) / 32.0 * _x (актуальна для ГПК). float Random(); - псевдослучайное с плавающей запятой 0 ... 1 (rand(32768) / 32768.0) (актуальна для ГПК) |
sasha108 |
Jul 28 2010, 10:17
Сообщение
#474
|
юнга Группа: форумчанин (*) Сообщений: 12 Регистрация: 15-July 10 Пользователь №: 23,069 |
Ничего понять не могу
файл characters/init/tortuga.c //sasha108 - старший офицер флота (тест) makeref(ch,Characters[n]); ch.name = "Джон"; ch.lastname = "Льюис"; ch.id = "Tortuga_NavyOfficer"; ch.model = "off_fra_2"; ch.sex = "man"; ch.City = "Tortuga"; ch.location = "Tortuga_tavern"; ch.location.group = "sit"; ch.location.locator = "sit_front1"; ch.Dialog.Filename = "Smuggler Agent_dialog.c"; ch.nation = FRANCE; LAi_SetLoginTime(ch, 0.0, 24.0); LAi_SetSitType(ch); LAi_RemoveLoginTime(ch); LAi_group_MoveCharacter(ch, "FRANCE_CITIZENS"); LAi_SetImmortal(ch, false); ch.AlwaysSandbankManeuver = true; ch.Ship.Type = GenerateShip(13 + rand(3), 1); SetBaseShipData(ch); SetCrewQuantityFull(ch); Fantom_SetCannons(ch, "war"); //fix Fantom_SetBalls(ch, "pirate"); Fantom_SetGoods(ch, "war"); ch.Ship.Name = "Elisabett"; SetFantomParamHunter(ch); //крутые парни SetCaptanModelByEncType(ch, "war");// Group_AddCharacter("PGGQuest", ch.id); ch.AlwaysEnemy = true; Group_SetGroupCommander("PGGQuest", "Tortuga_NavyOfficer"); Group_SetAddress("PGGQuest", "Tortuga", "Quest_Ships", "Quest_Ship_" + (3+ rand(4))); Group_SetTaskNone("PGGQuest"); int iTask = rand(1); float x, z; if (iTask == 0) { x = rand(1000000); z = rand(1000000); Group_SetTaskMove("PGGQuest", x, z); } else { Ship_SetTaskDrift(SECONDARY_TASK, Ch); Group_SetTaskNone("PGGQuest"); } ch.Ship.Mode = "war" ch.AlwaysSandbankManeuver = true; // тупым запрет тонуть об берег ch.AnalizeShips = true; //анализить вражеские корабли ch.location.from_sea = colonies[8].from_sea; SetCaptanModelByEncType(ch, ch.Ship.Mode); Персонаж в таверне появляется. С берега его корабль виден. Выходим в море - корабля нет. Я уже голову сломал. Делал генерацию корабля и по аналогии с механизмом заложенном в PSHERO и IslandShips. Фигня какая-то. При правке Scripts/IslandShips.c можно генерить какое угодно количество кораблей. При правке characters/init/tortuga.c максимум достигнутого описан выше. Объясните в чем не прав. Еще маленький вопросец. Pchar, в случае обращения из различных функций это главный герой ?? |
Warship |
Aug 2 2010, 12:27
Сообщение
#475
|
Гроза морей Группа: бета-тестер Сообщений: 441 Регистрация: 29-April 07 Из: Прим. край г. Находка Пользователь №: 9,103 |
Сложно что-то сказать... С кораблем ничего не понятно вообще. Прописывать таск движения или ничегонеделанья так неправильно точно, хотя-бы эстетически. Попробуй для начала изменить название группы - возможно, зарезервировано или что-нибудь подобное. И глянь файл characters/init/StoryCharacters.c - можно попробовать сделать генерацию корабля на примере Генри Моргана (у тебя ведь ГПК? ).
Вообще, если персонаж используется "пару раз", его нужно генерить динамически в момент, когда нужно, а не забивать массив с начала игры PСhar - да, это ГГ. Первый (не нулевой) элемент массива Characters, в файле global.c в функциях где-то есть присвоение. |
sasha108 |
Aug 2 2010, 14:16
Сообщение
#476
|
юнга Группа: форумчанин (*) Сообщений: 12 Регистрация: 15-July 10 Пользователь №: 23,069 |
"Сложно что-то сказать... С кораблем ничего не понятно вообще. Прописывать таск движения или ничегонеделанья так неправильно точно, хотя-бы эстетически. Попробуй для начала изменить название группы - возможно, зарезервировано или что-нибудь подобное. И глянь файл characters/init/StoryCharacters.c - можно попробовать сделать генерацию корабля на примере Генри Моргана (у тебя ведь ГПК? )."
Не получится(((. Я именно с этого и начинал. Команды движения и команды ничегонеделания я уже от безысходности пихал. Смена названия группы ничего не дала. Смотрел в locations_loader, там для загрузки корабля в порт треба нужны атрибуты locators.ships, которые больше нигде не фигурируют (искал блокнотом++). Роюсь в ПГГ. Пока ничего не нарыл. Точнее могу попробовать создать корабль, через клонфантом, а иначе не получается((. "Вообще, если персонаж используется "пару раз", его нужно генерить динамически в момент, когда нужно, а не забивать массив с начала игры ." В этом то и дело, что нужен с самого начала. Вместе с отображением корабля. "PСhar - да, это ГГ. Первый (не нулевой) элемент массива Characters, в файле global.c в функциях где-то есть присвоение." спасибо, что учите)) |
Warship |
Aug 3 2010, 00:46
Сообщение
#477
|
Гроза морей Группа: бета-тестер Сообщений: 441 Регистрация: 29-April 07 Из: Прим. край г. Находка Пользователь №: 9,103 |
В общем, попробуй сделать так:
Прописать корабль как Код ch.Abordage.Enable = false; ch.Ship.Name = "Elisabett"; ch.Ship.Type = GenerateShipExt(SHIP_FRIGATE, true, ch); ch.Ship.Stopped = true; ch.Ship.Cannons.Type = CANNON_TYPE_CANNON_LBS48; SetCrewQuantityFull(ch); Fantom_SetBalls(ch, "pirate"); Имею ввиду, по-аналогии + названия некоторых методом могут отличаться, т.к. не знаю, какая у тебя версия ГПК. Это просто пропишет ему корабль без локации и таска. И все, в ИНИТах больше ничего не писать Потом, в нужный момент (когда нужно его корабль поставить в море, хоть сразу после загрузки ГГ в стартовый город, но не в ИНИТах) делать Код Group_FindOrCreateGroup("NavyOfficerGroup"); Group_AddCharacter("NavyOfficerGroup", "Tortuga_NavyOfficer"); Group_SetType("NavyOfficerGroup", "war"); Group_SetGroupCommander("NavyOfficerGroup", "Tortuga_NavyOfficer"); Group_SetTaskAttack("NavyOfficerGroup", PLAYER_GROUP); Group_LockTask("NavyOfficerGroup"); Group_SetAddress("NavyOfficerGroup", "Tortuga", "", ""); Group_SetPursuitGroup("NavyOfficerGroup", PLAYER_GROUP); Собственно, это создаст группу с этим персом, поставит корабль рядом с кораблем ГГ (при выходе в море) и заставить атаковать. Хотя, я могу и ошибаться, что скорее-всего и делаю Подобный способ генерации персожаней с кораблями почти никогда не использовал... Да и на скриптах уже с год как не кодил ничего |
sasha108 |
Aug 3 2010, 11:13
Сообщение
#478
|
юнга Группа: форумчанин (*) Сообщений: 12 Регистрация: 15-July 10 Пользователь №: 23,069 |
а что означает вот этот кусочек кода?
pchar.quest.(sQuest).win_condition.l1 = "Character_Capture"; pchar.quest.(sQuest).win_condition.l1.character = chref.id; pchar.quest.(sQuest).function= "CaptureMerchant"; Такое ощущение, что это что-то очень важное. В части win_condition.l1 и function, такое ощущение, что это зарезервированные имена атрибутов. |
Black Angel |
Aug 3 2010, 16:28
Сообщение
#479
|
боцман Группа: форумчанин Сообщений: 252 Регистрация: 19-August 06 Из: Павлово(Нижегородская обл.) Пользователь №: 3,985 |
а что означает вот этот кусочек кода? pchar.quest.(sQuest).win_condition.l1 = "Character_Capture"; pchar.quest.(sQuest).win_condition.l1.character = chref.id; pchar.quest.(sQuest).function= "CaptureMerchant"; Такое ощущение, что это что-то очень важное. В части win_condition.l1 и function, такое ощущение, что это зарезервированные имена атрибутов. на этой странице есть мой пост, в нем есть ответ на твой вопрос. |
Warship |
Aug 4 2010, 04:30
Сообщение
#480
|
Гроза морей Группа: бета-тестер Сообщений: 441 Регистрация: 29-April 07 Из: Прим. край г. Находка Пользователь №: 9,103 |
Ответа на этой странице нету точно, есть такой же кусок кода с отсылом "догадайся, как работает"
См. тута: === В общем, приведенный тобой кусок кода - это установка прерывания. Прерывание - пожалуй, один из важнейших механизмов в скриптах и является чем-то вроде события (грубо говоря). Применяется при разработке квестов. Как работает: В определенный момент вешается вот такое прерывание, например, на выход на глобальную карту. В нем указывается некая функция, которая будет вызвана после того, как мы окажемся на глобальной карте. После отработки прерывания (т.е. в нашем примере - после того, как мы вышли на глобальную карту) оно автоматически снимается (если не указано иного). Разберем структуру, которая содержит информацию о прерывании: Прежде всего, все это хранится в PChar.Quest. Далее идет ветка самого прерывания, называться она может как угодно, главное, чтобы не было совпадения имен. На эту ветку вешается: 1) Тип прерывания. Обязательная ветка, которая указывает, какое собственно прерывание мы будем обрабатывать. 2) Кейс в структуре switch() процедуры QuestComplete() (файл Quests/quest_reaction.c). При срабатывании прерывания будет выполнен код, указанный в этом кейса. Опциональная ветка, альтернатива ей - в пункте ниже. 3) Процедура, которая будет вызвана при срабатывании прерывания. Является альтернативой пункту выше. Причем, лучше использовать именно процедуру - выигрышь в производительности. 4) Ветка "again". Ее присутствие указывает на то, что прерывание не будет снято при отработке - снять можно будет только ручками. 5) Различные параметры для конкретного прерывания. Как это все выглядит: Код PChar.Quest.(sQuest).win_condition.l1 = Строка_Типа_Прерывания; [Ветки с параметрами прерывания - win_condition.l1.*] PChar.Quest.(sQuest).win_condition = Строка_Кейса; [PChar.Quest.(sQuest).function = Строка_Процедуры;] [PChar.Quest.(sQuest).again = true;] И пример, для того, чтобы было лучше понятно: Код PChar.Quest.InBridgetownLocation.win_condition.l1 = "location"; PChar.Quest.InBridgetownLocation.win_condition.l1.location = "Bridgetown_town"; PChar.Quest.InBridgetownLocation.function = "InBridgetownLocation"; Расшифровываем: Первая строка - как помним, она указывает на тип прерывания. На данном примере указано прерывание на вход в определенную локацию (и на нахождение в этой локации вообще). Вторая строка - это параметр прерывания. Указывает на ID локации, заход в которую мы проверяем. Третья строка - функция, которая будет вызвана после того, как ГГ зашел в указанную локацию. Прерывания обладают одним важным свойством: один могут быть многоуровневыми. Т.е., к примеру, нам нужно, чтобы указанная нами в прерывании функция отработала не просто тогда, когда мы зайдем в локации, а тогда, когда мы зайдем в локацию с определенным предметом и перед этим еще убьем некоего непися. Как видно, тут нужно проверять целых три условия (и ставить трехуровненое прерывание). Делается это очень просто, пример: Код PChar.Quest.InBridgetownLocation.win_condition.l1 = "location"; PChar.Quest.InBridgetownLocation.win_condition.l1.location = "Bridgetown_town"; // ID локации PChar.Quest.InBridgetownLocation.win_condition.l2 = "item"; PChar.Quest.InBridgetownLocation.win_condition.l2.item = "blade28"; // ID предмета PChar.Quest.InBridgetownLocation.win_condition.l3 = "NPC_Death"; PChar.Quest.InBridgetownLocation.win_condition.l3.character = "badEnemy"; // ID персонажа PChar.Quest.InBridgetownLocation.function = "InBridgetownLocation"; Ну, собсна, вотъ. Как можно снять прерывание, которое больше не нужно: Код PChar.Quest.InBridgetownLocation.over = "yes"; После выполнение такого кода прерывание проверяться уже не будет, а ветка "InBridgetownLocation" вообще удалится при следующей проверке. Основные типы прерываний и параметры для них смотреть в файле Quests/quest_check.c в функции ProcessCondition(). Там-же можно добавить свое собственное, если нужно Забыл сказать, чем отличается событие от прерывания: 1) Способом установки 2) Способом обработки: события обрабатываются движком и слушатель события вызывается моментально после наступления события. Прерывания же проверяются на уровне скриптов в процедуре QuestsCheck(), которая вызывается только при определенных действиях (закрытие диалога, начало диалога, выход на карту и куча прочего). 3) Пул событий очищается при выходе из игры/заходе в игру. Не сохраняется при сохранении игры. Прерывания-же описываются в структуре PChar, которая при сохранении игры полностью сохраняется в файл-сохранение и может быть успешно восстановлена после загрузке. Поэтому для квестов применяются только прерывания. События - это интерфейс, и остальное, что есть событие по логике. Прошу прощения, если получилось сумбурно. Я старался донести суть. === Да, отвечу на вопрос, что означает приведенный кусок кода. В нем устанавливается прерывание на абордажевое потопление корабля указанного персонажа. |
Текстовая версия | Сейчас: 28th April 2024 - 22:52 |