![]() |
Здравствуйте, гость ( Вход | Регистрация )
![]() ![]() |
![]() |
![]()
Сообщение
#66
|
|||||||
Level 5 ![]() Класс: Обыватель Характер: Lawful Neutral Раса: Человек NWN: Модмейкер Проклятие Левора Порядок Времени ![]() |
СЕРИЯ "СКРИПТЫ СТАРОЙ БАЗЫ" ЦИКЛ "СКРИПТЫ EXICUTIONER'A" автор::::::::::::NightElf-Sniper aka Executioner:::::::::::::::::::: Заняляс я тут немного скриптованием и вот что из этого получилось:
Универсальный скрипт открытия магазинов, что бы все работало делаете так: создаете непися с тегом m_weapons, после чего создаете рядом с ним магазин и даете ему тег m_weapons_store, после чего скрипт ставится на нужную ветвь диалога... И вот это:
Для полной работоспособности надо создать еще 1 плейсейбл и 1 итем и поставить вейпойн куда надо бросать после смерти(фуга\храм) плейсейбл: tag: Mod_DeathCorpse resref: mod_deathcorpse ставим галку напротив Usable и Has Inventory так же на OnClose ставим скрипт OnClse_DthCorpse, а на OnOpen соответственно OnOpen_DthCorpse итем: tag: Mod_BagOfGold resref: mod_bagofgold Что мы получаем в итоге: после смерти убирается хенча, снимается 10% экспы. Все вещи которые были на нем и деньги отбираются и бросаются в лут, который появляется на месте смерти. После бросаем нашего чара туда, куда надо ) там можете с ним делать все. что захотите А зачем вешать на лут скрипты - а затем, что бы нам говорили кто умер, и после что бы не валялись они по всему модулю... ************************************************************************************ КОНЕЦ ЦИКЛА "СКРИПТЫ EXICUTIONER'A" СЕРИИ "СКРИПТЫ СТАРОЙ БАЗЫ" |
||||||
![]()
Сообщение
#67
|
|||||
Level 5 ![]() Класс: Обыватель Характер: Lawful Neutral Раса: Человек NWN: Модмейкер Проклятие Левора Порядок Времени ![]() |
СЕРИЯ "СКРИПТЫ СТАРОЙ БАЗЫ" ЦИКЛ "СКРИПТЫ (MOF)DARTH_NICK'A" автор::::::::::::[MoF]Darth_Nick:::::::::::::::::::: Jul 3 2004 получение лвла по алайменту
************************************************************************************ автор::::::::::::[MoF]Darth_Nick:::::::::::::::::::: Jul 3 2004 веселая ловушка
************************************************************************************ КОНЕЦ ЦИКЛА "СКРИПТЫ (MOF)DARTH_NICK'A" СЕРИИ "СКРИПТЫ СТАРОЙ БАЗЫ" |
||||
![]()
Сообщение
#68
|
|||||
Level 5 ![]() Класс: Обыватель Характер: Lawful Neutral Раса: Человек NWN: Модмейкер Проклятие Левора Порядок Времени ![]() |
СЕРИЯ "СКРИПТЫ СТАРОЙ БАЗЫ" ЦИКЛ "СКРИПТЫ RED DEVIL'A" автор::::::::::::Red Devil:::::::::::::::::::: Jul 31 2004 Значит так крафтинг. Крафт осущетсвляется при разговоре с неписем. Крафт брони +1 к АС.
************************************************************************************ автор::::::::::::Red Devil:::::::::::::::::::: Jul 31 2004 Крафт оружия +1энчант бонус, либо елси это лук или арбалет +1 атак бонус.
************************************************************************************ КОНЕЦ ЦИКЛА "СКРИПТЫ RED DEVIL'A" СЕРИИ "СКРИПТЫ СТАРОЙ БАЗЫ" КОНЕЦ СЕРИИ "СКРИПТЫ СТАРОЙ БАЗЫ" |
||||
![]()
Сообщение
#69
|
|||||||||
Level 5 ![]() Класс: Обыватель Характер: Lawful Neutral Раса: Человек NWN: Модмейкер Проклятие Левора Порядок Времени ![]() |
СЕРИЯ "СКРИПТЫ ПРОКЛЯТИЯ ЛЕВОРА" ЦИКЛ "СКРИПТЫ ДЯДЮШКИ BAAL'A" Скриптовая система из "Проклятия Левора", предназначенная для переноса вещей хенчмана в следующий модуль. Работает только с одним хенчманом! Скрипт bm_inv_transit1 запускаеться перед переходом в новый модуль. Скрипт bm_inv_transit3 запускаеться в новом модуле, уже после того как присоединен хенчман(хенч должен быть с пустыми слотами и инвентарем). На закрытой локе должны находиться 2 монстра с пустым инвентарем и с тагами SECOND_PC и SECOND_HENCH в палитре должны быть 3 сумки с одинаковым тагом и ресрефом transit_cont1, transit_cont2 и transit_cont3
|
||||||||
![]()
Сообщение
#70
|
|||||
Level 3 ![]() Класс: Некромант Характер: Neutral Evil Раса: Человек ![]() |
скрипт чтобы NPC шел за игроком. Будет идти даже после окончания боя. 1создаёте диалог. на вкладке ACTION TAKEN пишите команду
cтавьте на ветку диалога. 2теперь в скрипте OnSpawn надо раскомментировать строчку SetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT); раскомментировать значит убрать вот такой знак // т.е просто стираете эти слэши.У меня в скрипте подобной комадны сразу не было я вставил сразу ту о которой говорил выше 3 теперь в скрипте OnUserDefined пишите
не забудьте сохранить стандартный скрипт OnUserDefined,а новый скрипт под другим именем вот вроде и всё. |
||||
![]()
Сообщение
#71
|
|||||||||||||||||||||||||||||
Level 5 ![]() Класс: Страж Тьмы Характер: Chaotic Neutral Раса: Дракон NWN: Скриптинг [PW] ![]() |
СЕРИЯ "СКРИПТЫ ДЛЯ ШАРДА" ЦИКЛ "СКРИПТЫ RIPPER'a" Я написал пару простых, но очень полезный скриптов для шардов, на них "нанизываются" все остальные примочки. Что я сделал:
pl_onlogon.nss (поставить в OnClientEnter модуля)
pl_on_logoff.nss (поставить в OnClientLeave модуля)
default.nss
main_spirit.nss (просто инклуд)
main_active_item.nss
m_def_loc_enter.nss (ставить на OnEnter _всех_ локаций, _кроме_ стартовой)
m_loc_saver.nss Сделать локацию 2х2. Туда поставить таким образом триггеры:
= - Тригеры для перехода * - Тригер с этим скриптом В центре тригера со скриптом поставить стартовый вэйпоинт.
dm_ban_boot.nss
dm_ban_info.nss
dm_ban_minus.nss
dm_ban_plus.nss
dm_w_return.nss
Для работы скриптов ДМ-посоха нужно: Создать любой итем с рес-реф'ом "dm_wand" и Уник Повером. Создать диалог dm_wand_pl_list Структура диалога:
Это чисто пример по созданию посоха, можно легко модернизировать во что-то оч. хорошее :). Дерзайте Кроме того обязательно нужно создать в палитре новый итем с тагом "Spirit", ResRef'ом "spirit", Undropable p.s. у кого проблемы с установкой пишите в приват. МОДУЛЬ МОЖНО СКАЧАТЬ ТУТ Сообщение отредактировал RiPPeR - Apr 30 2005, 07:49 |
||||||||||||||||||||||||||||
![]()
Сообщение
#72
|
|||||||
Миловидный Бегрюссунг ![]() Класс: Воин Характер: Chaotic Good Раса: Человек NWN: Модмейкер Проклятие Левора Порядок Времени ![]() |
Тут мне понадобились факела включаемые. Помнится кто-то из молодежи спрашивал как сделать. Вот скрипт и демка в виде файла.
Добавлено в [mergetime]1118299586[/mergetime]
Добавлено в [mergetime]1118299909[/mergetime]
|
||||||
![]()
Сообщение
#73
|
|||
Level 5 ![]() ![]() Класс: Мастер Оружия Характер: Chaotic Neutral Раса: Полуорк ![]() |
Пришла мне в голову такая идея, а что если сделать такой тригер перехода, который бы перекидывал игрока не в какую то определенную точку, а ровно в то место, в которое игрок входит, с той разницей, что если выходит игрок из локации с востока, то войдет в локацию назначения с запада, ну или с севера на юг, так жн и наоборот. И вылилась идейка вот в такой скрипт:
Подготовка местности: - В ЦЕНТР (и чем точнее тем лучше) нужной локации помещаем вейпоинт и задаем ему уникальный тэг. - В локации из которой будем выходить помещаем тригер со скриптом, в поле для тэга точки назначения помещаем тэг размещенного в центре целевой локации вэйпоинта. Ограничения: - Тригер перехода должен размещаться по краю локации и не вылезать по ширине (или высоте, смотря с какой стороны находится) за пределы одной клетки. - Не размещайте тригер в угловых клетках, будет глючить. - Ширина (высота) тригера не должна превышать ширины (высоты) локации назначения. |
||
![]()
Сообщение
#74
|
|||
Миловидный Бегрюссунг ![]() Класс: Воин Характер: Chaotic Good Раса: Человек NWN: Модмейкер Проклятие Левора Порядок Времени ![]() |
Функция для библиотеки. Выдает любому уровню процент ХР заданный вами. К примеру у вас квестов 10. Зашел РС 30 левелом или 5 -м, всеравно выполнив 10 квестов он наберет 1 левел...
|
||
![]()
Сообщение
#75
|
|||||
Level 5 ![]() ![]() Класс: Рейнджер Характер: Neutral Good Раса: Человек ![]() |
Вот маленький инклюд с функцией makeTrace изображает дымную трассу (типа как от ракеты) между двумя точками, с помощью виз. эффектов (н.п. VFX_FNF_SMOKE_PUFF). Что-то похожее было в первом модуле СоУ в подземелье с плохой эльфой.
Функции, устанавливают заданное числовое значение аляймента:
Вдруг кому-нибудь пригодится. |
||||
![]()
Сообщение
#76
|
|||
Level 3 ![]() Класс: Паладин Характер: Chaotic Evil Раса: Человек ![]() |
Нет проблем. Итак, вот он, скрипт:
Спасибо, Aiwan. Этот скрипт и вправду лучше - не загружает систему и более обширней в применении. Ставить на OnHeartbeat локации или триггера. ЗЫ: Сорри за опечатки |
||
![]()
Сообщение
#77
|
|||||||
Level 9 ![]() Класс: Вор Характер: True Neutral Раса: Эльф NWN: Скриптинг [PW] ![]() |
альтернатива стандартному отдыху с возможностью ставить свою анимацию, выставлять время реста, проверки до/после/во время реста и т.п.
в модульный onEnter:
Добавлено в 15:18 позволяет получать разницу во времени между действиями..
Сообщение отредактировал 2_advanced - Aug 30 2005, 15:24 |
||||||
![]()
Сообщение
#78
|
|||
Миловидный Бегрюссунг ![]() Класс: Воин Характер: Chaotic Good Раса: Человек NWN: Модмейкер Проклятие Левора Порядок Времени ![]() |
Скрипт запрещает классы в модуле. Годится для сингла. Для шардов надо придумать как описать РС. Ставится это добро на OnPlayerLevelUp модуля.
|
||
![]()
Сообщение
#79
|
|||
Level 9 ![]() Класс: Вор Характер: True Neutral Раса: Эльф NWN: Скриптинг [PW] ![]() |
скрипт, усаживающий на стулья и т.п., не запарывает стул после выхода сидящего из игры (хоть это и древняя недоработанная бетка, однако работает) зы. необходим неразрушимый невидимый объект sittingsurface
для доработки: выкидывать игрока с *объекта посадки* при уничтожении стула, профиксить баг с высотой посадки для разных расс (было такое на 1.29 о_О), сделать возможным усаживаться нескольким персонажам на 1 большой объект (диван =)) с автораспределением свободных сидячих мест.
<сделаю позже :swoon: > |
||
![]()
Сообщение
#80
|
|||
Миловидный Бегрюссунг ![]() Класс: Воин Характер: Chaotic Good Раса: Человек NWN: Модмейкер Проклятие Левора Порядок Времени ![]() |
Скрипт вешается на строку диалога НПС. Если он загородил нам проход, просим отойти в сторону. Очень актуально для сингла. Когда НПС стоит поперек выхода и нет сил его обойти...
|
||
![]()
Сообщение
#81
|
|||||
Миловидный Бегрюссунг ![]() Класс: Воин Характер: Chaotic Good Раса: Человек NWN: Модмейкер Проклятие Левора Порядок Времени ![]() |
Скрипт активирует на локации енкаучеры ночные и дневные. Соответсвенно одни выключает, другие включает. Все работает как часы и оптимизировано Лексом. За шо ему гранд респект. :good:
Добавлено в [mergetime]1131452068[/mergetime] А, забыл! :scratch: Первый на хертбит арены. Второй на юзерДеф ей же. |
||||
![]()
Сообщение
#82
|
|||||||||||
Миловидный Бегрюссунг ![]() Класс: Воин Характер: Chaotic Good Раса: Человек NWN: Модмейкер Проклятие Левора Порядок Времени ![]() |
Выкладываю скрипт+заготовку ERF триггера, что бы вы не мучались с настройкой. Давно я использую на триггерах три своих темповых скрипта, для присвоения каких-нибудь локалок на игрока, для проверки того или иного диалога, строки, действия и прочее. Очень меня задолбало это. Писать каждый раз новый скрипт и я написал триггер для теста. Что он делает? Он присваивает до 5 уникальных локалок на игрока и НПС, может отправить НПС в точку которую вы укажите. Например, НПС в другой локе, вы наступили на триггер, он спавнился рядом и повесили на него три локалки, повесили на РС две локалки и можно быть в середине вашего сюжета. Еще он (скрипт) может запускать другие скрипты на НПС, РС и OBJECT_SEL, соответсвенно. Как он настраивается: DEACTIVATED == 1 отключает триггер после первого раза. Например, вы насупили раз, прошли одну ветку диалога. Подошли, наступили второй, прошли заново диалог и т.д. Надо? Ставьте 0 и будет бесконечно приваивать ваши локалки. LOCAL_NPC_01 - Присваивает переменную на НПС. Пример: ПЕРЕМЕННАЯ_01
LOCAL_PC_01 - Присваивает переменную на PС. Пример: ПЕРЕМЕННАЯ_01
RUN_SCRIPT - ИМЯ_СКРИПТА - запускает на OBJECT_SELF
RUN_SCRIPT_ON_NPC - ИМЯ_СКРИПТА - запускает на oNpc
На игрока понятное дело так же. TAG_NPC - Таг нашего НПС. TAG_WP_TO_JUMP - ТАГ нашего вейпоинта. НПС прыгнет на него, если только вы укажете ТАГ точки. Ну вот и все. Все локалки работают до пяти штук на РС и НПС.
|
||||||||||
![]()
Сообщение
#83
|
|||||||
Level 19 ![]() Класс: Воин Характер: Lawful Good Раса: Человек NWN: Скриптинг [Sn] ![]() |
Вот тут решил написать скрипты, которые может кому, пригодятся, но лично мне они пока не нужны. Зачем написал? Просто так. :crazy: Что эти скрипты делают? Они дают процент экспы за убийство/разрушение объекта равное проценту нанесенного ущерба. Пример: Есть бочка, у нее 10 хитов. За разрушение назначено 100 опыта. Если вы снимите 100% хитов(10), то получите 100% опыта(100). Если вы снимете 50% хитов(5), то получите 50% опыта(50). Остальной опыт либо пропадет (если кроме вас объект лупили только НПС), либо поделится между другими ПС лупившими объект, либо поделится между всеми ПС и часть пропадет, от лупивших НПС. ХМ, надеюсь, идея ясна. Приступим к скриптам. Для реализации нам нужно два скрипта: один на OnDamaged объекта, другой на OnDeath объекта. Скрипты универсальные и ограничений по атакующим у них нет. Дома я проверил, как смог, но так как шарда у меня дома нет, то данный аспект проверить не смог. Но по идее все работает нормально, если заметите баг, обязательно сообщите. Еще, на шарде ни когда не играл, поэтому может это и не идеальный код для него, но думаю, что знающим людям поправить будет не сложно. :) И так, сами скрипты. На OnDamaged объекта
Второй скрипт ставется на OnDeath объекта. Этот скрипт раздает опыт.
Ну и еще их маленький брат - скрипт считающий отдельно урон ПС и урон всех остальных. Иногда бывает очень нужно узнать урон нанесенный объекту ПС. Скрипт для сингла.
З.Ы Сорри, что порвал страницу :oops: Aiwan: вообще-то некоторые строки можно делить и переносить. :this: -fenix-: просто мне как-то неудобно так ориентироваться %) Но впредь, на форуме, буду строки делить и переносить:yes: Сообщение отредактировал -fenix- - Nov 17 2005, 13:09 |
||||||
![]()
Сообщение
#84
|
|||
Level 5 ![]() Класс: Обыватель Характер: Lawful Neutral Раса: Человек NWN: Модмейкер Проклятие Левора Порядок Времени ![]() |
|
||
![]()
Сообщение
#85
|
|||
Level 4 ![]() ![]() Класс: Маг Характер: Chaotic Evil Раса: Человек ![]() |
Скрипт мой, все совпадения с другими скриптами случайны. Скрипт для управления группой NPC в реальном времени, без создания waypoint-ов. Позволяет группировать NPC в любые построения(к примеру в Каре, Свинью, Шеренгу,Полк и т д.и т п на Ваш вкус) и перемещать их в таком построении. Можно использовать при построении масштабных баталий с участием большого количества неписей(причем под управлением игрока)
Построение можно регулировать с помощью двух параметров a и b. a отвечает за то как удален будет NPC от игрока, а b - за смещение NPC вправо или влево. Для использования необходимо: 1) Создать предмет со свойством "активировать предмет:дальнее расстояние" и тагом "panel" 2)Поставить группу из семи NPC с тагоми:NPC1 , NPC2 , NPC3 , NPC4 , NPC5 , NPC6 , NPC7 При желании количество неписей и их построение можно поменять произвольным образом Сообщение отредактировал justshurik - Feb 4 2006, 01:52 |
||
![]()
Сообщение
#86
|
|
Level 12 ![]() Класс: Оборотень Характер: Chaotic Neutral Раса: Нежить NWN: Скриптинг [Sn] ![]() |
Библиотечка нескольких функций для работы со строками, фактически написана ради одной функции. Насколько оптимален алгоритм не знаю, но годится для обычных проверок на нужные тэги.
NSS // name: i_string // type: Библиотека // desc: Строковые функции // autor: Nightwalker Sorcerer // date: 4.01.2006 // modified: 11.01.2006 //////////////////////////////////////////////////////////////////////////////// // INFO //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /* Contains: int FindFirstOf(string sString, string sPattern, int nFrom = 0, int bSymbols = TRUE); int FindLastSubString(string sString, string sSubString); int FindSubStringFrom(string sString, string sSubString, int nCount = 0); int Match(string sString, string sPattern); */ //////////////////////////////////////////////////////////////////////////////// // CONSTANTS /////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// const string ANY_SYMBOL = "?"; const string ANY_SEQUENCE = "*"; const string P_BEGIN = "["; // открывающая скобка (1 символ) const string P_END = "]"; // закрывающая скобка (1 символ) const string P_OR = "|"; // ИЛИ выражение внутри скобок (1 символ) const string SYMBOL_NOT = "!"; //////////////////////////////////////////////////////////////////////////////// // FUNCTION DEFINITIONS //////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Нахождение первого вхождение в строку sString символов из набора sPattern. // - sString: строка для поиска; // - sPattern: набор символов; // - nFrom: позиция символа, с которого начинается поиск; // - bSymbols: Зарезервировано, используйте умолчание, чтобы в следующих // версиях библиотеки функция работала как предполагалось. // * Возвращает позицию в строке или отрицательное значение, если // позиция не найдена. // --> Например: // > FindFirstOf("a", "abc") - возвращает 0; // > FindFirstOf("word", "ro") - возвращает 1; // > FindFirstOf("word", " _[](),.-") - возвращает отрицательное значение; // > FindFirstOf("wоw", "w", 1) - возвращает 2; // > FindFirstOf("string", "some", 1) - возвращает отрицательное значение. int FindFirstOf(string sString, string sPattern, int nFrom = 0, int bSymbols = TRUE); // Нахождение последнего вхождения строки sSubString в строку sString. // - sString: строка для поиска; // - sSubString: искомая подстрока. // * Возвращает позицию в строке или отрицательное значение, если позиция // не найдена. int FindLastSubString(string sString, string sSubString); // Нахождение позиции подстроки sSubstring внутри строки sString, // начиная поиск с позиции nCount. // - sString: строка, в которой ищем; // - sSubString: что ищем; // - nCount: ищем начиная с этой позиции. // * Возвращает позицию подстроки или отрицательное значение, если подстрока // не найдена. int FindSubStringFrom(string sString, string sSubString, int nCount = 0); // Провека совпадения сторки sString с шаблоном sPattern: // '?' считается любым символом; // '*' cчитается любой последовательностью символов, // в том числе пустой (без символов); // '!' совпадение считается, если остаток строки не подходит к шаблону, // испольйте только в начале шаблона или скобочного выражения, // иначе за результат не ручаюсь; // [..|..|..] один из вариантов, допускается вложенность. // - sString: строка для проверки; // - sPattern: правильная палитра. // * Возвращает TRUE, если строки совпадают, и FALSE, если нет. // --> Например: // > "?*" - любая непустая последовательность; // > "itm_*" - все строки, начинающиеся с "itm_"; // > "i_*_gold" - строки вида "i_25_gold", "i_pi_gold", а также "i__gold"; // > "*a*" - строки, в которых есть хоть одна буква а; // > "[X|N]*" - тэги всех стандарнтых вещей NWN и дополнений; // > "[|?[|?]]" - пустая строка или 1-2 символа; // > "!wrong" - любая строка, кроме "wrong". int Match(string sString, string sPattern); //////////////////////////////////////////////////////////////////////////////// // IMPLEMENTATION ////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// int FindFirstOf(string sString, string sPattern, int nFrom = 0, int bSymbols = TRUE) { int nResult = -1; int nCounter, nPosition, nLengthPattern = GetStringLength(sPattern); for (nCounter = 0; nCounter < nLengthPattern; nCounter++) { nPosition = FindSubStringFrom(sString, GetSubString(sPattern, nCounter, 1), nFrom); if (nResult < 0) nResult = nPosition; else if ((nPosition >= 0) && (nResult > nPosition)) nResult = nPosition; } return nResult; } int FindLastSubString(string sString, string sSubString) { int nSubStrLength, nResult, nNext; if ((nSubStrLength = GetStringLength(sSubString)) == 0) return -1; if ((nNext = (nResult = FindSubString(sString, sSubString))) < 0) return nResult; while ((nNext = FindSubString((sString = GetStringRight(sString, GetStringLength(sString) - nNext - nSubStrLength)), sSubString)) >= 0) { nResult += (nNext + nSubStrLength); } return nResult; } int FindSubStringFrom(string sString, string sSubString, int nCount = 0) { int nResult = FindSubString(GetStringRight(sString, GetStringLength(sString) - nCount) , sSubString); if (nResult < 0) return nResult; return (nResult + nCount); } int Match(string sString, string sPattern) { // DEBUG //SendMessageToPC(GetFirstPC(), "Сравнение '"+sString+"' с '"+sPattern+"'."); int nS, nPhB, nPhE; int nLengthString = GetStringLength(sString); int nLengthPattern = GetStringLength(sPattern); if (GetStringLeft(sPattern, 1) == SYMBOL_NOT) { return (!Match(sString, GetStringRight(sPattern, nLengthPattern - 1))); } if ((nPhE = (nPhB = FindSubString(sPattern, P_BEGIN))) >= 0) // обработка ИЛИ выражений { int nNest = 1; // текущая вложенность while ((nPhE >= 0) && (nNest > 0)) { nPhE = FindFirstOf(sPattern, P_BEGIN + P_END, nPhE + 1); if (GetSubString(sPattern, nPhE, 1) == P_BEGIN) nNest++; else nNest--; } if (nNest != 0) return FALSE; // неправильно расставлены скобки int nPhS, nPhF = nPhB; // начало и конец подстроки string sSymbol = ""; while ((sSymbol != P_END) && (nPhF >= 0)) { nPhS = nPhF + 1; sSymbol = ""; while ((((sSymbol != P_OR) || (nNest > 0)) && ((sSymbol != P_END) || (nNest >= 0))) && (nPhF >= 0)) { nPhF = FindFirstOf(sPattern, P_BEGIN + P_OR + P_END, nPhF + 1); sSymbol = GetSubString(sPattern, nPhF, 1); if (sSymbol == P_BEGIN) nNest++; else if (sSymbol == P_END) nNest--; } if (Match(sString, GetStringLeft(sPattern, nPhB) + GetSubString(sPattern, nPhS, nPhF - nPhS) + GetStringRight(sPattern, nLengthPattern - nPhE - 1))) return TRUE; } return FALSE; } if ((nS = FindSubString(sPattern, ANY_SEQUENCE)) > 0) // строки, содержащие ANY_SEQUENCE, но не вначале { if (!Match(GetStringLeft(sString, nS), GetStringLeft(sPattern, nS))) return FALSE; // упрощаем в "*..." return Match(GetStringRight(sString, nLengthString - nS), GetStringRight(sPattern, nLengthPattern - nS)); } if (nS == 0) // теперь ANY_SEQUENCE вначале { string sPattern2 = GetStringRight(sPattern, nLengthPattern - 1); if ((nS = (FindLastSubString(sPattern2, ANY_SEQUENCE) + 1)) > 0) // есть второй ANY_SEQUENCE { // конечные кусочки после последнего ANY_SEQUENCE должны "совпадать" string sPatternAfterSeq = GetStringRight(sPattern, GetStringLength(sPattern) - nS - 1); int nLengthAfterSeq = GetStringLength(sPatternAfterSeq); if (!Match(GetStringRight(sString, nLengthAfterSeq), sPatternAfterSeq)) return FALSE; // упрощаем в "*...*" nLengthString = GetStringLength(sString = GetStringLeft(sString, nLengthString - nLengthAfterSeq)); nLengthPattern = GetStringLength(sPattern = GetStringLeft(sPattern, nS + 1)); // DEBUG: //SendMessageToPC(GetFirstPC(), "тупой подбор '"+sString+"' к '"+sPattern+"'"); int nCounter1, nCounter2; for (nCounter1 = 1; (nCounter1 < nLengthString); nCounter1++) { for (nCounter2 = 1; (nCounter2 < nLengthPattern); nCounter2++) { if (Match(GetStringLeft(sString, nCounter1), GetStringLeft(sPattern, nCounter2))) if (Match(GetStringRight(sString, nLengthString - nCounter1), GetStringRight(sPattern, nLengthPattern - nCounter2))) return TRUE; } } return FALSE; } // только один ANY_SEQUENCE вначале; осталось сравнить конец строки с палитрой return Match(GetStringRight(sString, GetStringLength(sPattern2)), sPattern2); } // теперь строка и палитра должны быть одинакового размера if (nLengthString != nLengthPattern) return FALSE; if ((nS = FindSubString(sPattern, ANY_SYMBOL)) >= 0) // в палитре присутствует ANY_SYMBOL { return Match(GetStringLeft(sString, nS), GetStringLeft(sPattern, nS)) && Match(GetStringRight(sString, nLengthString - nS - 1), GetStringRight(sPattern, nLengthPattern - nS - 1)); } return (sString == sPattern); } //void main(){} Библиотека функций для работы с инвентарем, используя предыдущий инклюд. Основные функции: CreateItemList HasItemList и RemoveItemList, остальные функции тоже полезны в тех или иных ситуациях. NSS // name: i_inv // type: Библиотека // desc: Функции для работы с инвентарем. // autor: Nightwalker Sorcerer // date: 11.01.2005 // modified: 13.01.2005 //////////////////////////////////////////////////////////////////////////////// // INFO //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /* Contains: void CreateItemList(string sList, object oTarget = OBJECT_SELF); int GetNumItems(object oTarget = OBJECT_SELF, string sTag = "*", int bCreatureSlots = FALSE); int GetNumItemsInInventory(object oInventory = OBJECT_SELF, string sTag = "*"); int GetNumItemsInSlot(object oTarget, int nSlot, string sTag = "*"); int HasItemList(object oTarget, string sList, int bCreatureSlots = FALSE); void RemoveItemList(object oTarget, string sList, int bCreatureSlots = FALSE); int RemoveItemsFromInventory(object oInventory = OBJECT_SELF, string sTag = "*", int nNum = -1); int RemoveItemsFromSlot(object oTarget, int nSlot, string sTag = "*", int nNum = -1); int RemoveItemsFromSlots(object oTarget = OBJECT_SELF, string sTag = "*", int nNum = -1, int bCreatureSlots = FALSE) */ //////////////////////////////////////////////////////////////////////////////// // INCLUDES //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// #include "i_string" //////////////////////////////////////////////////////////////////////////////// // CONSTANTS /////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// const string SYMBOL_AND = "&"; const string SYMBOL_EQU = "="; //////////////////////////////////////////////////////////////////////////////// // FUNCTION DEFINITIONS //////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Создание вещей из заданого списка в инвентаре oTarget // - sList: список вещей в виде "вещь1=кол-во1&вещь2=кол-во2&вещь3=кол-во3", // при опускании "=колво", количество считается 1; // - oTarget: в чьем инвентаре создаем? // --> Например: // > CreateItemList("single_item"); // > CreateItemList("first_item&second_item&one_arrow=99", oTreasure); // ? Примечание: если символ '&' плохо видно в списке, можно использовать '&&'. void CreateItemList(string sList, object oTarget = OBJECT_SELF); // Нахождение количества вещей с тэгом sTag у персонажа oTarget (в инвентаре // и слотах) // - oInventory: персонаж, в имуществе которого ищем; // - sTag: палитра для проверки тэга; // - bCreatureSlots: искать ли в невидимых слотах? // * Возвращает количество найденых вещей. int GetNumItems(object oTarget = OBJECT_SELF, string sTag = "*", int bCreatureSlots = FALSE); // Нахождение количества вещей с заданым тэгом sTag в инвентаре oInventory, // предметы в слотах не учитываются. // - oInventory: целевой инвентарь // - sTag: палитра для проверки тэга // * Возвращает количество найденых вещей, тэг которых подходит под палитру // --> Например: // > GetNumItemsInInventory(oChest, "itm_sword*") - количество вещей с тэгом, // начинающимся с "itm_sword" у объекта oChest; // > GetNumItemsInInventory(oPC, "eda") - количество вещей с тэгом "eda" у oPC. int GetNumItemsInInventory(object oInventory = OBJECT_SELF, string sTag = "*"); // Нахождение количества вещей с заданым тегом sTag в слоте инвентаря nSlot // существа oTarget. // - oTarget: существо, у которого ищем; // - nSlot: слот инвентаря; // - sTag: тэг. // * Возвращает количество найденых вещей. int GetNumItemsInSlot(object oTarget, int nSlot, string sTag = "*"); // Нахождение количества вещей с заданым тегом sTag в слотах инвентаря // существа oTarget. // - oTarget: существо, у которого ищем; // - sTag: тэг; // - bCreatureSlots: считать ли вещи в невидимых слотах? // * Возвращает количество найденых вещей. int GetNumItemsInSlots(object oTarget = OBJECT_SELF, string sTag = "*", int bCreatureSlots = FALSE); // Проверка, имеет ли oTarget cписок вещей sList. // - sList: список вещей в виде "вещь1=кол-во1&вещь2=кол-во2&вещь3=кол-во3", // при опускании "=колво", количество считается 1; // - oTarget: у кого проверяем; // - bCreatureSlots: проверять ли вещи в невидимых слотах? // * Возвращеет TRUE, если объект имеет вещи из списка, иначе FALSE. // --> Например: // > НasItemList(oPC, "quest&gem[1|2]=6") - проверка, есть ли у персонажа вещь // c тэгом "quest" и шесть вещей с тэгом gem1 или gem2 // ? Примечание: если символ '&' плохо видно, можно использовать '&&'. int HasItemList(string sList, object oTarget = OBJECT_SELF, int bCreatureSlots = FALSE); // Удаление у оTarget списка вещей sList. // - sList: список вещей в виде "вещь1=кол-во1&вещь2=кол-во2&вещь3=кол-во3", // при опускании "=колво", количество считается 1; // - oTarget: у кого удаляем; // - bCreatureSlots: удалять ли вещи из невидимых ячеек? // --> Например: // > RemoveItemList(oPC, "fragile=-1&extra") - удаление всех вещей с // тэгом "fragile" и одной вещи с тэгом "extra". // ? Примечание: если символ '&' плохо видно, можно использовать '&&'. void RemoveItemList(string sList, object oTarget = OBJECT_SELF, int bCreatureSlots = FALSE); // Удаление заданого количества вещей с тэгом sTag у персонажа. // - oTarget: персонаж; // - sTag: палитра для проверки тэга; // - nNum: количество вещей, коророе нужно удалить, при отрицательном // значении будут удалены все вещи; // - bCreatureSlots: удалять ли вещи из невидимых ячеек? // * Возвращает количество вещей, коророе осталось удалить. // --> Например: // > RemoveItems(oTarget) - удалить все вещи у цели; // > RemoveItems(oPC, "flower", 2) - удалить у oPC две вещи с тэгом "flower". int RemoveItems(object oTarget, string sTag = "*", int nNum = -1, int bCreatureSlots = FALSE); // Удаление вещей из инвентаря с заданым тэгом, вещи в слотах не удаляются // - oInventory: целевой инвентарь // - sTag: палитра для проверки тэга // - nNum: количество удаляемых вещей, при -1 удалятся все вещи, // подходящие под палитру // * Возвращает количество вещей, которые осталось удалить, т.е 0, если удалено // столько вещей, сколько указано или большее число, если найдено меньше вещей, // c подходящим тэгом. Возвращает -1, если указано удалять все вещи. // Количество удаленных вещей можно получить = nNum - RemoveItemsFromInventory(,, nNum) // --> Например: // > int nNoFood = RemoveItemsFromInventory(oPC, "itm_food", 1) - удаляет 1 еду, // nNoFood = 1, если у oPC нет еды; // > RemoveItemsFromInventory(oPC, "x*") - удаляет из вещмешка oPC вещи из дополнений. int RemoveItemsFromInventory(object oInventory = OBJECT_SELF, string sTag = "*", int nNum = -1); // Удалить nNum вещей из слота nSlot существа oTarget, // если тэг вещи подходит к sTag. // - oTarget: существо, у которого удаляем вещи; // - nSlot: ячейка, из которой удаляем; // - sTag: палитра тэга; // - nNum: количество вещей, которое нужно удалить, при отрицательном значении // удалять все вещи. // * Возвращает количество вещей, которые осталось удалить, или отрицательное // значение, если указано удалять все вещи. int RemoveItemsFromSlot(object oTarget, int nSlot, string sTag = "*", int nNum = -1); // Удалить nNum вещей из ячеек инвентаря существа oTarget с заданным тэгом. // - oTarget: цель; // - sTag: палитра тэга; // - nNum: количество вещей, которое нужно удалить, при отрицательном значении // удалять все вещи; // - bCreatureSlots: удалять ли вещи из невидимых ячеек. // * Возвращает количество вещей, которые осталось удалить, или отрицательное // значение, если указано удалять все вещи. int RemoveItemsFromSlots(object oTarget = OBJECT_SELF, string sTag = "*", int nNum = -1, int bCreatureSlots = FALSE); //////////////////////////////////////////////////////////////////////////////// // IMPLEMENTATION ////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// void CreateItemList(string sList, object oTarget = OBJECT_SELF) { int nDiv, nNum; string sResRef; while (sList != "") { if ((nDiv = FindSubString(sList, SYMBOL_AND)) < 0) { nDiv = GetStringLength(sList); } sResRef = GetStringLeft(sList, nDiv); sList = GetStringRight(sList, GetStringLength(sList) - nDiv - 1); nNum = 1; if ((nDiv = FindSubString(sResRef, SYMBOL_EQU)) >= 0) { nNum = StringToInt(GetStringRight(sResRef, GetStringLength(sResRef) - nDiv - 1)); sResRef = GetStringLeft(sResRef, nDiv); } for ( ; nNum > 0; nNum--) CreateItemOnObject(sResRef, oTarget); // лучше ничего не придумал } } int GetNumItems(object oTarget = OBJECT_SELF, string sTag = "*", int bCreatureSlots = FALSE) { return GetNumItemsInInventory(oTarget, sTag) + GetNumItemsInSlots(oTarget, sTag, bCreatureSlots); } int GetNumItemsInInventory(object oInventory = OBJECT_SELF, string sTag = "*") { int nNum = 0; object oItem = GetFirstItemInInventory(oInventory); while (GetIsObjectValid(oItem)) { if (Match(GetTag(oItem), sTag)) { nNum += GetItemStackSize(oItem); } oItem = GetNextItemInInventory(oInventory); } return nNum; } int GetNumItemsInSlot(object oTarget, int nSlot, string sTag = "*") { object oItem = GetItemInSlot(nSlot, oTarget); if (Match(GetTag(oItem), sTag)) return GetItemStackSize(oItem); return 0; } int GetNumItemsInSlots(object oTarget = OBJECT_SELF, string sTag = "*", int bCreatureSlots = FALSE) { int nNum = 0; nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_ARMS, sTag); nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_ARROWS, sTag); nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_BELT, sTag); nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_BOLTS, sTag); nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_BOOTS, sTag); nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_BULLETS, sTag); //nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_CARMOUR, sTag); nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_CHEST, sTag); nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_CLOAK, sTag); //nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_CWEAPON_B, sTag); //nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_CWEAPON_L, sTag); //nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_CWEAPON_R, sTag); nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_HEAD, sTag); nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_LEFTHAND, sTag); nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_LEFTRING, sTag); nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_NECK, sTag); nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_RIGHTHAND, sTag); nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_RIGHTRING, sTag); if (bCreatureSlots) { nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_CARMOUR, sTag); nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_CWEAPON_B, sTag); nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_CWEAPON_L, sTag); nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_CWEAPON_R, sTag); } return nNum; } int HasItemList(string sList, object oTarget = OBJECT_SELF, int bCreatureSlots = FALSE) { int nDiv, nNum; string sTag; while (sList != "") { if ((nDiv = FindSubString(sList, SYMBOL_AND)) < 0) { nDiv = GetStringLength(sList); } sTag = GetStringLeft(sList, nDiv); sList = GetStringRight(sList, GetStringLength(sList) - nDiv - 1); if ((nDiv = FindSubString(sTag, SYMBOL_EQU)) >= 0) { nNum = StringToInt(GetStringRight(sTag, GetStringLength(sTag) - nDiv - 1)); sTag = GetStringLeft(sTag, nDiv); } else { nNum = 1; } if (sTag != "") if (GetNumItems(oTarget, sTag, bCreatureSlots) < nNum) return FALSE; } return TRUE; } void RemoveItemList(string sList, object oTarget = OBJECT_SELF, int bCreatureSlots = FALSE) { int nDiv, nNum; string sTag; while (sList != "") { if ((nDiv = FindSubString(sList, SYMBOL_AND)) < 0) { nDiv = GetStringLength(sList); } sTag = GetStringLeft(sList, nDiv); sList = GetStringRight(sList, GetStringLength(sList) - nDiv - 1); if ((nDiv = FindSubString(sTag, SYMBOL_EQU)) >= 0) { nNum = StringToInt(GetStringRight(sTag, GetStringLength(sTag) - nDiv - 1)); sTag = GetStringLeft(sTag, nDiv); } else { nNum = 1; } RemoveItems(oTarget, sTag, nNum, bCreatureSlots); } } int RemoveItems(object oTarget, string sTag = "*", int nNum = -1, int bCreatureSlots = FALSE) { nNum = RemoveItemsFromInventory(oTarget, sTag, nNum); return RemoveItemsFromSlots(oTarget, sTag, nNum, bCreatureSlots); } int RemoveItemsFromInventory(object oInventory = OBJECT_SELF, string sTag = "*", int nNum = -1) { int nStack; object oItem = GetFirstItemInInventory(oInventory); while (GetIsObjectValid(oItem) && (nNum != 0)) { if (Match(GetTag(oItem), sTag)) { if (nNum < 0) DestroyObject(oItem); else if ((nStack = GetItemStackSize(oItem)) > nNum) { SetItemStackSize(oItem, nStack - nNum); return 0; } else { DestroyObject(oItem); nNum -= nStack; } } oItem = GetNextItemInInventory(oInventory); } return nNum; } int RemoveItemsFromSlot(object oTarget, int nSlot, string sTag = "*", int nNum = -1) { if (nNum == 0) return nNum; object oItem = GetItemInSlot(nSlot, oTarget); if (GetIsObjectValid(oItem)) if (Match(GetTag(oItem), sTag)) { int nStack; if (nNum < 0) DestroyObject(oItem); else if ((nStack = GetItemStackSize(oItem)) > nNum) { SetItemStackSize(oItem, nStack - nNum); return 0; } else { DestroyObject(oItem); nNum -= nStack; } } return nNum; } int RemoveItemsFromSlots(object oTarget = OBJECT_SELF, string sTag = "*", int nNum = -1, int bCreatureSlots = FALSE) { nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_ARMS, sTag, nNum); nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_ARROWS, sTag, nNum); nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_BELT, sTag, nNum); nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_BOLTS, sTag, nNum); nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_BOOTS, sTag, nNum); nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_BULLETS, sTag, nNum); //nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_CARMOUR, sTag, nNum); nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_CHEST, sTag, nNum); nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_CLOAK, sTag, nNum); //nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_CWEAPON_B, sTag, nNum); //nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_CWEAPON_L, sTag, nNum); //nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_CWEAPON_R, sTag, nNum); nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_HEAD, sTag, nNum); nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_LEFTHAND, sTag, nNum); nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_LEFTRING, sTag, nNum); nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_NECK, sTag, nNum); nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_RIGHTHAND, sTag, nNum); nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_RIGHTRING, sTag, nNum); if (bCreatureSlots) { nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_CARMOUR, sTag, nNum); nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_CWEAPON_B, sTag, nNum); nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_CWEAPON_L, sTag, nNum); nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_CWEAPON_R, sTag, nNum); } return nNum; } //void main(){} Примеры использования (судя по всему маст би): - Проверка в диалоге на наличие у персонажа игрока необходимого количества (пусть 3) предметов с заданым тэгом (пусть "quest_item") NSS #include "i_inv" int StartingConditional() { object oPC = GetPCSpeaker(); int n = GetNumItems(oPC, "quest_item"); return (n >= 3); } - Забрать необходимое кол-во предметов у игрока (пусть те же 3 "quest_item") NSS #include "i_inv"
void main() { object oPC = GetPCSpeaker(); RemoveItems(oPC, "quest_item", 3); } Сообщение отредактировал azathoth - Jul 9 2006, 02:47 |
![]()
Сообщение
#87
|
|
Миловидный Бегрюссунг ![]() Класс: Воин Характер: Chaotic Good Раса: Человек NWN: Модмейкер Проклятие Левора Порядок Времени ![]() |
Эта функция копирует инвентарь объекта, если необходимо, то и все надетые вещи на существо.
NSS // // КОПИРУЕТ ВЕСЬ ИНВЕНТАРЬ oMaster=OBJECT_SELF В ИНВЕНТАРЬ oNewMaster // iDel = TRUE - удаляет копируемый объект из инвентаря хозяина, FALSE - нет // iUnequip = TRUE - раздевает объект, снимая с него все в инвентарь void CopyInventory(object oNewMaster, object oMaster=OBJECT_SELF, int iDel=TRUE, int iUnequip=FALSE); void CopyInventory(object oNewMaster, object oMaster=OBJECT_SELF, int iDel=TRUE, int iUnequip=FALSE) { if(iUnequip==TRUE) { int i=0; while(i<14) { if(GetItemInSlot(i, oMaster)!= OBJECT_INVALID) CopyItem(GetItemInSlot(i, oMaster), oNewMaster, TRUE); if(iDel==TRUE) DestroyObject(GetItemInSlot(i, oMaster)); i++; } } object oItem = GetFirstItemInInventory(oMaster); while(GetIsObjectValid(oItem)) { if(GetBaseItemType(oItem) == BASE_ITEM_LARGEBOX) { CreateItemOnObject(GetResRef(oItem), oNewMaster, 1); if(iDel==TRUE) DestroyObject(oItem, 0.5); } else { CopyItem(oItem, oNewMaster, TRUE); if(iDel==TRUE) DestroyObject(oItem); } oItem = GetNextItemInInventory(oMaster); } } Тут все просто. Имеем 25 бутылочек, удаляем из них 3 или одну. NSS // ВОЗВРАЩАЕТ КОЛИЧЕСТВО ПРЕДМЕТОВ В СТЕКЕ В ИНВЕНТАРЕ ОБЪЕКТА int GetItemStackNumber(string sTagItem, object oTarget=OBJECT_SELF); // УДАЛЯЕТ iNum КОЛИЧЕСТВО ПРЕДМЕТОВ В СТЕКЕ В ИНВЕНТАРЕ ОБЪЕКТА void RemoveItemStackNumber(string sTagItem, int iNum = 1, object oTarget=OBJECT_SELF); //------------------------------------------------------------------------------ int GetItemStackNumber(string sTagItem, object oTarget=OBJECT_SELF) { object oItem = GetFirstItemInInventory(oTarget); int iNum = 0; while (GetIsObjectValid(oItem)) { if (GetTag(oItem) == sTagItem) { iNum = iNum+GetItemStackSize(oItem); } oItem = GetNextItemInInventory(oTarget); } return iNum; } //------------------------------------------------------------------------------ void RemoveItemStackNumber(string sTagItem, int iNum = 1, object oTarget=OBJECT_SELF) { object oItem = GetFirstItemInInventory(oTarget); while (GetIsObjectValid(oItem) && (iNum != 0)) { if (GetTag(oItem) == sTagItem) { int i = GetItemStackSize(oItem); if (i > iNum) { SetItemStackSize(oItem, GetItemStackSize(oItem)-iNum); iNum = 0; } else { DestroyObject(oItem); iNum = iNum-i; } } oItem = GetNextItemInInventory(oTarget); } } Определяем лучший класс мультикласса. NSS //
// ЛУЧШИЙ КЛАСС МУЛЬТИКЛАССОВОГО СОЗДАНИЯ int GetCreatureBestClass(object oCr=OBJECT_SELF); int GetCreatureBestClass(object oCr) { int class1 = GetClassByPosition(1, oCr); int class2 = GetClassByPosition(2, oCr); int class3 = GetClassByPosition(3, oCr); int classlev1, classlev2, classlev3; classlev1 = GetLevelByClass(class1, oCr); if (class2 != CLASS_TYPE_INVALID) classlev2 = GetLevelByClass(class2, oCr); if (class3 != CLASS_TYPE_INVALID) classlev3 = GetLevelByClass(class3, oCr); int BestClass = class1; if (classlev1 < classlev2) BestClass = class2; if (classlev2 < classlev3) BestClass = class3; return BestClass; } |
![]()
Сообщение
#88
|
|
Level 8 ![]() Класс: Некромант Характер: Chaotic Evil Раса: Дракон NWN: Скриптинг [PW] ![]() |
Скрипт "резервирования" нескольких мест на сервере под DM'ов
Бывает, что сервер полностью забит и зайти DM'ом не получается. Теперь несколько мест будут забиты для ДМов P.S. Возможно где-то уже есть, если так то сорри onClientEnter NSS int nMaxPlayers = 30; // Макс. число игроков в настройке сервера минус число зарезервированных мест void main() { object oPC = GetEnteringObject(); object oMod = GetModule(); int nCurrPC = GetLocalInt(oMod, "CurrPC"); if(nCurrPC >= nMaxPlayers && !GetIsDM(oPC)) { BootPC(oPC); return; } SetLocalInt(oMod, "CurrPC", nCurrPC+1); // нормальный oncliententer // ... OnClientExit NSS void main() {
object oMod = GetModule(); SetLocalInt(oMod, "CurrPC", GetLocalInt(oMod, "CurrPC")-1); // нормальный onclientexit // ... |
![]()
Сообщение
#89
|
|
Level 9 ![]() Класс: Друид Характер: True Neutral Раса: Эльф NWN: Скриптинг [PW] Амен ![]() |
Скрипт резервирования мест для ДМ-ов.
Аналогичный скрипт. Только чуть эффективней и проще. В момент входа игрока, а не ДМ-а, пересчитывается количество игроков, и если их больше указанной цифры, то входящий игрок бутится. В скрипте, что выше, есть недостатки. Если клиент "отвалится" от сервера, т.е. у него произойдет дисконнект, то скрипт изменения переменной не выполнится. Далее, ДМ-ы занимают места игроков. Это не очень хорошо. Учитывая то, что максимально клиентов может быть только 30. В настройках сервера надо сделать 35 мест, а игроков ограничить 30-ю местами, используя подобный скрипт. Т.е. изменение переменной необходимо включить в условие, которое игнорирует Дм. И соответственно на выходе с модуля тоже ограничить условие игроком. NSS void main() { object oMod = GetModule(); //--------------------------------------------------// // Данные записываются в отдельный скрипт, а потом // // считываются во время загрузки модуля через // // действие 'OnModuleLoad'. // int DMRESERVE = 30; // Для примера - 30 человек SetLocalInt(oMod, "DMRESERVE", DMRESERVE); //--------------------------------------------------// object oClient = GetEnteringObject(); if (GetIsDM(oClient) == FALSE) { int nReserve = GetLocalInt(oMod, "DMRESERVE"); if (nReserve == TRUE) { int nPlayer; object oPlayer = GetFirstPC(); while (GetIsObjectValid(oPlayer)) { nPlayer++; oPlayer = GetNextPC(); } if (nPlayer > nReserve) { BootPC(oClient); return; } } } } З.Ы. kreon, если не сложно, доработай скрипт. |
![]()
Сообщение
#90
|
|
Level 2 ![]() Класс: Обыватель Характер: Lawful Good Раса: Человек ![]() |
Вообщем я хотела вот что,у меня была такая идея...нужно было разделить отдых и процесс подготовки заклинаний кастующем классом. Это все нужно было все, чтобы клерик мог молиться Богу о заклинаниях только в определенные часы времени суток....ну перепало и магу конечно.(IMG:style_emoticons/kolobok_light/smile.gif) )
NSS ////////////////////////////////////////////////////////////////////////////////
/////Эта функция каждые 3 секунды проверяет подготавливает ли персонаж магию./// //////////////////////////////////////////////////////////////////////////////// void Examen(object oPC = OBJECT_SELF) { if(!GetLocalInt(oPC,"Rest")) { ForceRest(oPC);//востановление магии ActionMoveToLocation(GetLocation(oPC));//встаем FloatingTextStringOnCreature( "Вы успешно подготовили магию.",oPC); //удаление локалок if(GetIsObjectValid(GetLocalObject(oPC,"GodLay"))) { DestroyObject(GetLocalObject(oPC,"GodLay")); DeleteLocalObject(oPC,"GodLay"); } DeleteLocalLocation(oPC, "RestLocation"); return; } if(GetLocation(oPC) != GetLocalLocation(oPC, "RestLocation")) { ActionMoveToLocation(GetLocation(oPC)); FloatingTextStringOnCreature("Вам неудалось подготовить магию.",oPC); //удаление локалок if(GetIsObjectValid(GetLocalObject(oPC,"GodLay"))) { DestroyObject(GetLocalObject(oPC,"GodLay")); DeleteLocalObject(oPC,"GodLay"); } DeleteLocalInt(oPC,"Rest"); DeleteLocalLocation(oPC, "RestLocation"); return; } else { AssignCommand(oPC, DelayCommand(3.0f, Examen(oPC))); AssignCommand(oPC,ActionPlayAnimation(ANIMATION_LOOPING_MEDITATE,1.0,3.0)); } } //////////////////////////////////////////////////////////////////////////////// ///Это начало подготовки заклинаний для божественных заклинателей/////////////// //////////////////////////////////////////////////////////////////////////////// void BeginGodMagic(object oPC =OBJECT_SELF) { object oLay;//тут я сделала луч, с неба как бы, впрочем необязательно. Так что можно убрать(IMG:style_emoticons/kolobok_light/smile.gif) //проверка айламента if(GetAlignmentGoodEvil(oPC)==ALIGNMENT_EVIL) {oLay = CreateObject(OBJECT_TYPE_PLACEABLE,"plc_solred",GetLocation(oPC));} else if (GetAlignmentGoodEvil(oPC)==ALIGNMENT_NEUTRAL) {oLay = CreateObject(OBJECT_TYPE_PLACEABLE,"plc_solblue",GetLocation(oPC));} else oLay = CreateObject(OBJECT_TYPE_PLACEABLE,"plc_solwhite",GetLocation(oPC)); //вешаем нужные локалки на Чара и плэйсебл SetLocalLocation(oPC, "RestLocation", GetLocation(oPC)); SetLocalInt(oPC,"Rest",TRUE); SetLocalObject(oPC,"GodLay",oLay); AssignCommand(oPC,ActionPlayAnimation(ANIMATION_LOOPING_MEDITATE,1.0,3.0)); AssignCommand(oPC, DelayCommand(3.0, Examen())); DelayCommand(1.0,FloatingTextStringOnCreature("Подготовка магии.",oPC)); DelayCommand(30.0,DeleteLocalInt(oPC,"Rest")); } //////////////////////////////////////////////////////////////////////////////// //Это проверка у божественных заклинателей наличия бога///////////////////////// //если есть, то все нормально,нет-не подготовить заклинаний.//////////////////// //и времени, в которое можно помолиться этому богу.///////////////////////////// //Закоментировала.////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /*void ExsamenGod(object oPC = OBJECT_SELF) { object oGodLatander,oGodMysrta; int nTime = GetTimeHour(); oGodLatander = GetItemPossessedBy(oPC,"i_latander_sign"); oGodMysrta = GetItemPossessedBy(oPC,"i_mystra_sign"); // Latander if(GetIsObjectValid(oGodLatander)) { if((nTime>=6)&&(nTime<13)){BeginGodMagic(oPC);return;} else return; } //Mystra else if(GetIsObjectValid(oGodMysrta)) { if((nTime>=23)&&(nTime<4)){BeginGodMagic(oPC);return;} else return; } else{FloatingTextStringOnCreature("Вам не кому молитьсЯ относительно заклинаний.",oPC);} }*/ //////////////////////////////////////////////////////////////////////////////// /// Это начало подготовки заклинаний для арканных заклинателей ///////////////// //////////////////////////////////////////////////////////////////////////////// void BeginArcaneMagic(object oPC =OBJECT_SELF) { SetLocalLocation(oPC, "RestLocation", GetLocation(oPC)); SetLocalInt(oPC,"Rest",TRUE); AssignCommand(oPC,ActionPlayAnimation(ANIMATION_LOOPING_MEDITATE,1.0,3.0)); DelayCommand(3.0,AssignCommand(oPC,ActionPlayAnimation(ANIMATION_FIREFORGET_READ,1.0,10.0))); AssignCommand(oPC, DelayCommand(3.0, Examen())); DelayCommand(1.0,FloatingTextStringOnCreature("Подготовка магии.",oPC)); DelayCommand(30.0,DeleteLocalInt(oPC,"Rest")); } //////////////////////////////////////////////////////////////////////////////// ///// Проверка. Есть ли у персонажа кастующий класс? ////////////////////////// //////////////////////////////////////////////////////////////////////////////// void ExamenCastClass(object oPC = OBJECT_SELF) { int iu = 1,iClass; while(iu <=3) { iClass=GetClassByPosition(iu,oPC); if(iClass == CLASS_TYPE_CLERIC){BeginGodMagic(oPC);return;} else if(iClass == CLASS_TYPE_DRUID){BeginGodMagic(oPC);return;} else if(iClass == CLASS_TYPE_PALADIN){BeginGodMagic(oPC);return;} else if(iClass == CLASS_TYPE_RANGER){BeginGodMagic(oPC);return;} else if(iClass == CLASS_TYPE_WIZARD){BeginArcaneMagic(oPC);return;} else if(iClass == CLASS_TYPE_SORCERER){BeginArcaneMagic(oPC);return;} else if(iClass == CLASS_TYPE_BARD){BeginArcaneMagic(oPC);return;} iu++ ; } } //////////////////////////////////////////////////////////////////////////////// /// Удаление восстановленных при отдыхе заклинаний ///////////////////////////// //////////////////////////////////////////////////////////////////////////////// void SpellDelete(object oPC = OBJECT_SELF) { int nSpell, nKSpell; for (nSpell = 0; nSpell < 1000; nSpell++) { nKSpell = GetHasSpell(nSpell, oPC); if (nKSpell) { while (nKSpell > 0) { DecrementRemainingSpellUses(oPC, nSpell); nKSpell--; } } } } //////////////////////////////////////////////////////////////////////////////// ////////////////// Отдых /////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// void main() { object oPC = GetLastPCRested(); object oItem,oItem1; switch(GetLastRestEventType()) { case REST_EVENTTYPE_REST_STARTED: { //Необходимые эффекты,проверки и тд.. break; } case REST_EVENTTYPE_REST_CANCELLED: { break; } case REST_EVENTTYPE_REST_FINISHED: { SpellDelete(oPC); DelayCommand(1.5,ExamenCastClass(oPC)); break; } } } |
![]() ![]() |
Текстовая версия | Сейчас: 28th April 2025 - 20:34 |