Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Город Мастеров _ Neverwinter Nights 2 Obsidian Toolset _ Скрипты: Все вопросы

Автор: Lex Apr 2 2006, 19:41

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

>> просьбы написать скрипт не в эту тему, а сюда: http://www.wrg.ru/forums/index.php?showtopic=2578
>> выкладывать готовые и отлаженные скрипты не в эту тему, а сюда: http://www.wrg.ru/forums/index.php?showtopic=2581
Тут только вопросы и обсуждение проблем и методов их решения, а так же все непонятки с "должно работать, но не работает".


___

http://www.city-of-masters.ru/forums/index.php?showtopic=5
http://www.city-of-masters.ru/forums/index.php?showtopic=1612
http://www.city-of-masters.ru/forums/index.php?showtopic=889
http://www.city-of-masters.ru/forums/index.php?showtopic=123
Так как скриптинг не сильно изменился, то большая часть вещей, написаная под НВН1 нормально работает и в НВН2. Посмотрите в этих темах, вполне возможно вы найдете интересующую вас информацию.

Автор: Gloom Nov 29 2006, 07:28

Нужно найти игрока по имени в определенной локации...
И еще интересно почему не работает такая

NSS
object oPlayer = GetFirstObjectInArea(GetArea(GetObjectByTag("gds_wpt")));
  icheck=0;
  while(icheck==0)
    { 
      string sCName = GetName(oPlayer);
      if (sCName == sName)
      {
        oTarget=oPlayer;
        icheck=1;
      }
    object oPlayer = GetNextObjectInArea(GetArea(GetObjectByTag("gds_wpt")));
    }

sName - имя игрока

Автор: Vanes Nov 29 2006, 08:24

предпоследняя строка
object oPlayer = GetNextObjectInArea(GetArea(GetObjectByTag("gds_wpt")));

замени на
oPlayer = GetNextObjectInArea(GetArea(GetObjectByTag("gds_wpt")));

Автор: dumbo Nov 29 2006, 08:38

QUOTE(Gloom @ Nov 29 2006, 07:28) [snapback]99455[/snapback]
Нужно найти игрока по имени в определенной локации...

странное желание...
NSS
object oArea = GetArea(GetObjectByTag("gds_wpt"));
  object oPC = GetFirstPC();
  while (GetIsObjectValid(oPC))
  {
      if ((oArea == GetArea(oPC) && (sName == GetName(oPC))
        break;
      oPC = GetNextPC();
  }
  if (GetIsObjectValid(oPC))
  {
    // требуемый игрок найден...
  }
  else
  {
    // не найден...
  }


QUOTE(Gloom @ Nov 29 2006, 07:28) [snapback]99455[/snapback]
И еще интересно почему не работает такая

вечный цикл вообще. первичное условие выхода - валидность перечисляемого объекта.


и так, между прочим, для поиска игроков перебирать все объекты в локации - это, я вам скажу...

Автор: Gloom Nov 29 2006, 09:17

Спасибо за помощь good.gif

QUOTE
и так, между прочим, для поиска игроков перебирать все объекты в локации - это, я вам скажу...

это было промежуточное решение, проверка самой возможности...

Автор: Plut Nov 29 2006, 23:08

CODE
object oPC = GetLastUsedBy();

if(GetIsPC(oPC) )
{
    ActionStartConversation(oPC);
}


Так if теперь не работает?

Выдает INVALID DECLARATION TYPE на if

СОРИ, ИЗВИНИТЕ ЗА ВОПРОС...
Не обратил внимания, что имя функции void main() надо писать руками...

Автор: Plut Dec 4 2006, 12:29

Вопрос такой: можно ли на Event плэйсибла, например On Used, навесить скрипт с параметром, т.е. я хочу, чтоб запускалась одна из ветвей, имеющихся в скрипте. Пример:

CODE

void main(int iAction)
{
    switch(iAction)
    {
    case 1:
         object oPC = GetPCSpeaker();
         ActionStartConversation(oPC);
         break;
    case 2:
         .....
         .....
    }
}

Ну а в On Used, понятно, хочется иметь что-то вроде ИмяСкрипта(1)

Автор: Sleeper Dec 4 2006, 12:53

Где брать скрипт на открытие магазина через диалог?biggrin.gif

Автор: -fenix- Dec 4 2006, 13:11

QUOTE(Plut @ Dec 4 2006, 12:29) [snapback]99761[/snapback]
можно ли на Event плэйсибла, например On Used, навесить скрипт с параметром, т.е. я хочу, чтоб запускалась одна из ветвей, имеющихся в скрипте. Пример:

А что тебя останавливает? smile.gif

QUOTE(Sleeper @ Dec 4 2006, 12:53) [snapback]99766[/snapback]
Где брать скрипт на открытие магазина через диалог?

Чтобы не повторяться: http://www.city-of-masters.ru/forums/index.php?s=&showtopic=5&view=findpost&p=31712 .
Там для НВН, но так как скрипты поддаются переносу, то должно работать, может тока какие параметры новые у функций появились.

Автор: Plut Dec 4 2006, 13:16

QUOTE
А что тебя останавливает? smile.gif

То что оно не отрабатывает. Может там синтаксис какой хитрый...

Автор: -fenix- Dec 4 2006, 13:30

Ну, если компилица, но не работает, то вот что может быть:

NSS
void main(int iAction)
{
    switch(iAction)
    {
    case 1:
        object oPC = GetPCSpeaker(); //Это тут откудавы? smile.gif Надо GetLastUsedBy()!
        ActionStartConversation(oPC);
        break;
    case 2:
        .....
        .....
    }
}

Автор: Plut Dec 4 2006, 13:36

QUOTE
Ну, если компилица, но не работает, то вот что может быть:

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

Автор: Lex Dec 4 2006, 13:38

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

Автор: Plut Dec 4 2006, 13:44

QUOTE
Plut, передавать параметр таким образом в скрипт нельзя. Делай через локальные переменные на игроке/объекте или модуле.

Спасибо за кратки и содержательный ответ. А жаль, все-таки...

Автор: -fenix- Dec 4 2006, 13:46

Эээ, ну это, не мешало бы увидеть пациента целиком. smile.gif А на теории я хз че там как отрабатывает, я в НВН 2 не играл и Обсидиановский Тулсет не видел.
Но есть еще момент. В case низя объявлять или инициализировать переменные, делай это до него.

QUOTE(Lex @ Dec 4 2006, 13:38) [snapback]99775[/snapback]
Plut, передавать параметр таким образом в скрипт нельзя. Делай через локальные переменные на игроке/объекте или модуле.

Ой, так вот в чем суть вопроса была. smile.gif

Автор: Lex Dec 4 2006, 14:05

QUOTE(Plut @ Dec 4 2006, 13:44) [snapback]99777[/snapback]
пасибо за кратки и содержательный ответ. А жаль, все-таки...

не знаю, чего тебе жаль то. Там и нет возможности вписать, да и как? Если переменная статичная, то нафиг она тебе не нужна, а если динамическая, то на каком этапе ты собираешься ее формировать? Непосредственно перед запуском эвента ? Никак pardon.gif Единственное место, где параметры бы пригодились - диалоги, чтобы передавать например номер ответа и от него плясать.. но насколько я знаю в новом тулсете что-то по этому поводу сделано.. посмотреть тока не могу.

QUOTE(Plut @ Dec 4 2006, 12:29) [snapback]99761[/snapback]
Вопрос такой: можно ли на Event плэйсибла, например On Used, навесить скрипт с параметром

можно по другому. В локалку плейса вгоняешь параметр. Например "BLOCK" и разные значения туда, а в скрипте
NSS
..
int nBLOCK = GetLocalInt(OBJECT_SELF,"BLOCK");
switch (nBLOCK)
{
case 1: // ---- //
    break;
case 2: // ---- //
    break;
// И так далее
}
...

Автор: Plut Dec 4 2006, 17:30

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

Да, по этому поводу там усе сделано. Даже можно строку выводить или в экшн писать по несколько скриптов... Тут все ок. Можно теперь вообще всю обработку диалогов в 1 скрипт запихать... Чтоб не рыть потом тоннами.

QUOTE
В case низя объявлять или инициализировать переменные, делай это до него.

А я в нем и не пытался инициализировать. Я в него пытался передавать входящий параметр...

Согласен, можно и так написать. Идея была сделать скрипт, в котором хранятся On Used, например, всех плэйсиблов или всех дверей... разных... в зависимости, например, от тега... ну и т.д. Это все к сокращению количества скриптов.

Автор: Lex Dec 4 2006, 18:34

QUOTE(Plut @ Dec 4 2006, 17:30) [snapback]99809[/snapback]
А я в нем и не пытался инициализировать.

пытаешься:
QUOTE(Plut @ Dec 4 2006, 12:29) [snapback]99761[/snapback]
case 1:
object oPC = GetPCSpeaker();

так ни нада. Объявляй object oPC в начале, а в кейсах уже работай с ней.

Автор: Plut Dec 4 2006, 20:51

QUOTE
так ни нада. Объявляй object oPC в начале, а в кейсах уже работай с ней.

Ну нормально! Ты хочешь сказать, что внутри ветвления нельзя объявлять переменные?!?! Это - бред! 8 лет занимаюсь написанием программ - такого еще не видел... Не знаю, видел ли ты второй тулс, но багов с этим пока не замечено...

Господа... Есть проблема. Проблема в файлике http://www.hotfile.ru/30533/ (1,2Мб - модуль для НВН2)
Там есть диалог с лежаком. Если при первом подходе нажать отдохнуть, то следующая фраза этого лежака не выводится... Не понимаю...

Автор: azathoth Dec 5 2006, 00:06

Если очень хочется, то можно:

NSS
...
case 0:
{
      object oPC = GetPCSpeaker();
}
case 1:
...

Автор: Lex Dec 5 2006, 00:56

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

зы: но вот что-то в свичах нельзя делать точно.. а что, я уже и забыл.

Автор: dumbo Dec 5 2006, 06:34

QUOTE(Lex @ Dec 5 2006, 00:56) [snapback]99838[/snapback]
зы: но вот что-то в свичах нельзя делать точно.. а что, я уже и забыл.

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

Автор: Plut Dec 5 2006, 10:09

QUOTE
Господа... Есть проблема. Проблема в файлике http://www.hotfile.ru/30533/ (1,2Мб - модуль для НВН2) Там есть диалог с лежаком. Если при первом подходе нажать отдохнуть, то следующая фраза этого лежака не выводится... Не понимаю...

Поставил патч 1.03 - все исправилось. Так что - это глюк тулса.... был.

Автор: -fenix- Dec 5 2006, 10:55

Хз, как там во втором тулсете, но в первом и правда переменные объявленные в свичах глючили, да и инфа о том, что их объявлять там низя, из Лексекона взята.

Автор: mamuc Dec 5 2006, 12:48

QUOTE
Да, по этому поводу там усе сделано. Даже можно строку выводить или в экшн писать по несколько скриптов... Тут все ок. Можно теперь вообще всю обработку диалогов в 1 скрипт запихать... Чтоб не рыть потом тоннами.

...ммм а пгодробнее об этом можно и в деталях как именно...для тех, кто пока в обсидиановском тулсете не работает....
насколько все удобней.. итд итп ...плз biggrin.gif


Автор: azathoth Dec 5 2006, 14:36

QUOTE(mamuc @ Dec 5 2006, 12:48) [snapback]99860[/snapback]
QUOTE
Да, по этому поводу там усе сделано. Даже можно строку выводить или в экшн писать по несколько скриптов... Тут все ок. Можно теперь вообще всю обработку диалогов в 1 скрипт запихать... Чтоб не рыть потом тоннами.

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


Берешь ветку диалога, выбираешь Экшн -> Добавить и суешь туды скрипт (ну пока как обычно), далее впечатываешь в появившиеся поля переменные для этого скрипта (появляются если он их поддерживает). Если мало - добававить еще таких скриптов к той же ветке, выполнятся они будут по очереди. В игре уже есть пачка простеньких кирпичиков типа "Заставить (таг1) напасть на объект (таг2)", "Забрать итем (таг)" и т.п. Так что можно выстроить комбинацию из них вместо написания отдельного скрипта для каждой ветки.

Автор: mamuc Dec 5 2006, 15:49

azathoth большое спасибо за информацию.... hi.gif
меня больше всего заинтересовал вот такой нюанс

QUOTE
Даже можно строку выводить

это что-то действительно новое и больше не надо будет с SetCustomToken() работать? или это и есть то самое...

...или я чего-то не так понял... pardon.gif

Автор: Vhall Dec 5 2006, 16:20

Мамук, я не в теме, но думаю, строка это "string". Т.е. можно выводить строку в фразу из тлк.

Автор: Gloom Dec 5 2006, 18:26

Вопрос косвенно связанный со скриптами... а сколько спелов(spells) в NWN2?

Griffon: Открой spells.2da и посчитай.

Автор: Plut Dec 6 2006, 11:28

QUOTE
это что-то действительно новое и больше не надо будет с SetCustomToken() работать? или это и есть то самое...

Этого я делать пока не пробовал... попробуем возвращать строку....

Автор: ShadowKeeper Dec 15 2006, 11:53

Народ, а не кто не знает, как поменять расу, пол и класс игрока при входе в локацию и желательно при этом и внешний вид?

Автор: Lex Dec 15 2006, 12:52

если не урезали это в НВН2, то по идее SetCreatureAppearance или что-нить в этом роде. А если урезали - полиморфом тока наверное unknw.gif

Автор: ShadowKeeper Dec 16 2006, 12:14

NSS
void SetCreatureAppearanceType(object oCreature, int nAppearanceType);

Только меняет внешний вид, при этом, если игрок менял при создании персонажа лицо прическу и из-за некоторой одежды персонаж просто исчезает, но все равно спасибо.
Будим исследовать дальше.

Автор: azathoth Dec 16 2006, 12:58

Класс не поменять точно, максимум, что можно сделать - это сбить уровни до 1, а затем пролевелять РС обратно до того уровня, на котором он был нужным классом(см функции SetXP() и LevelUpHenchman()). Т.е, к примеру, если меняем на файтера, то Маг(20) превратится в Маг(1)-Воин(19). Если игрок 1го уровня, то этот трюк, конечно, не даст вообще никаких результатов.

Автор: ShadowKeeper Dec 16 2006, 13:23

Просто по ходу сюжета игрок вспоминает свои прошлые жизни, где он был воином магом и творил великие дела. Попробую обойтись только внешним видом и Cut-Сценами вместо боев sad.gif . Отсюда следует следующая проблема, как запретить ему просмотр персонажа?

Автор: Waromon Dec 16 2006, 13:42

ShadowKeeper, ну для кутсцены ничего делать и не нужно, игроку и так доступен только внешний вид. smile.gif Посему, SetCreatureAppearanceType, будет в самый раз. wink3.gif

Автор: Gloom Jan 5 2007, 19:07

Вопрос следующий
Нужен таг локации в которой находится игрок
и еще интересно почему не работает

NSS
string sCheckTag = GetTag(GetArea(oPC));

он возвращает пустоту

Автор: Lex Jan 5 2007, 19:13

QUOTE(Gloom @ Jan 5 2007, 19:07) [snapback]101568[/snapback]
он возвращает пустоту

хм.. попробуй для начала определить, получается ли там локация. Типа так:
NSS
void main()
{
object oPC = GetFirstPC();
SendMessageToPC(oPC,"Имя: "+GetName(oPC));
object oArea = GetArea(oPC);
SendMessageToPC(oPC,"Локация: "+GetName(oArea));
}

Короче суть в том, чтобы дебажить на всех этапах (определение игрока, определение локации), чтобы понять где именно косяк.
Так как игра только вышла, ни у кого еще нет достаточных знаний об ошибках и подводных камней, так что ищем smile.gif

Автор: Gloom Jan 5 2007, 19:27

Не получается sad.gif
только у меня

NSS
object oPC = GetEnteringObject();

потомучто скрипт oncliententer

Автор: -fenix- Jan 5 2007, 19:33

Что не получается-то?
Возможно возвращается пустота, так как стоит скрипт на КлиентЭнтер. Попробуй проверить на тригере или на ОнЭнтер локи.

Автор: Gloom Jan 5 2007, 19:53

Не получается = возвращает "Локация - " т.е пустоту
он_энтер локи тоже не работает

С он_ентер тригера ситуация та же...
Пустота

Ах да, во всех трех случаях имя игрока показывается правильно

Автор: Narruin Jan 5 2007, 20:36

QUOTE(Gloom @ Jan 5 2007, 20:53) [snapback]101575[/snapback]

Не получается = возвращает "Локация - " т.е пустоту
он_энтер локи тоже не работает

С он_ентер тригера ситуация та же...
Пустота

Предположу, что название локи на русском.
На OnClientEnter не советую вешать. Слабо срабатывает. Лучше на эвенты локации или уж на PC Loaded.
Попробовал у себя только что. Версия 1.03. Работает.
Кинул вещь на землю в локе и дописал этот код в On Acquire Item (чиста ради срабатывания smile.gif )
NSS
object oPC = GetFirstPC ();
object oArea = GetArea (oPC);
string sName = GetName (oArea);
FloatingTextStringOnCreature (sName, oPC);

Автор: Gloom Jan 5 2007, 20:57

Имя локи на английском, версия 1.3, повесил ваш скрипт он_ентер тригера...

NSS
object oArea = GetArea ();

ругается дебагер
NSS
FloatingTextStringOnCreature (sName, oPC);

текст не показывает

Моя ошибка, тепрь показывает имя... у меня DisplayName было пусто

Автор: Lex Jan 5 2007, 21:02

ну потому что там не скрипт в полном понимании, а набросок (с синтаксическими и прочими ошибками типа лишних пробелов)

Если бы глюк был только в onClientEnter, можно было бы списать на то что не успевает грузиться.. но если такая же петрушка на триггере, то похоже возможно не определяет.. возможное те банально GetArea не работает. Эх,, был бы тулс под рукой, поэкспериментировал бы.
зы: попробуй взять локу по тэгу и вывести ее название.
зыы: попробуй взять локу не по oPC, а по триггеру, те oArea = GetArea(OBJECT_SELF).

--------------

э.. а теперь помедленнее, что показывает и где? smile.gif

Автор: Narruin Jan 5 2007, 21:14

QUOTE(Lex @ Jan 5 2007, 22:02) [snapback]101587[/snapback]

те банально GetArea не работает. Эх,, был бы тулс под рукой, поэкспериментировал бы.

GetArea работает.

Автор: Gloom Jan 5 2007, 21:30

Показывает название локации
Тот скрипт который выше

NSS
object oArea = GetArea ();

кстати работает хоть и ругается дебагер
остальные варианты тоже работают

на он_ентер локации проверял

NSS
string sName = GetTag(GetArea(OBJECT_SELF));
FloatingTextStringOnCreature (sName, oPC);

на on_enter локации работает
на oncliententer -нет

Автор: -fenix- Jan 5 2007, 22:10

Ну вот, знач работает. smile.gif
А если на oncliententer не пашет, значит, как гооврил Лекс, не успевает грузиться. Тут вообще многа чего не будет срабатывать. Операции с игроком должны проходить, по идее с вещами на нем, в общем смотреть надо.

Автор: azathoth Jan 6 2007, 20:25

OnClientEnter запускается еще до того, как персонаж попал в какую-либо локацию.

Автор: Gloom Jan 7 2007, 09:35

Всем спасибо за помощь angel.gif

Автор: webkent Jan 8 2007, 05:26

Пытаюсь сделать так: При получении предмета такого-то предмет удаляется и появляется рядом волк и становится хенчманом. При попытке удалить предмет вылетает из игры (НВН2). Сдается мне это изза того что не успевает что-то сделать, да? Профи, подскажите как лучше поправить. Вот мой код в OnAcquireItem:

NSS
int nObjectType = OBJECT_TYPE_CREATURE;
    object oTaker = GetModuleItemAcquiredBy(); 
    object oItem = GetModuleItemAcquired();
    location lLocationOfTaker = GetLocation(GetModuleItemAcquiredBy());
    if (GetResRef(oItem) == "it_dw10") {
    ActionTakeItem(oItem, oTaker); //тут вылетает с ошибкой
    CreateObject(nObjectType, "c_dogwolfdire",lLocationOfTaker, FALSE, "c_dogwolfdire1");
    object oHench = GetObjectByTag("c_dogwolfdire1");
    AddHenchman(oTaker, oHench);

Автор: virusman Jan 8 2007, 10:27

ActionTakeItem - это действие, его можно использовать только от имени существ. Модуль (или даже OBJECT_INVALID), от имени которого вызывается OnItemAcquired, не может взять предмет у игрока.
Вместо этого поставь DestroyObject.
В строчке

NSS
AddHenchman(oTaker, oHench);
используется oHench, но она ранее не объявлена и не установлена.

Автор: gennady Jan 8 2007, 11:38


webkent, слишком много лишнего в твоем коде, для НВН я бы записал так:

NSS
void main()
{
object oTarget = GetModuleItemAcquiredBy();
object oItem = GetModuleItemAcquired();
location Loc = GetLocation(oTarget);
if (GetTag(oItem) == "itm_***") // Лучше определить через тэг
{
  // Сразу определим хенча
  object oHench = CreateObject(OBJECT_TYPE_CREATURE, "c_dogwolfdire", Loc, FALSE, "c_dogwolfdire1");
  AddHenchman(oTarget, oHench);
  DestroyObject(oItem, 3.0); // Удалим с задержкой, чтобы исключить баги
  // На пожарный случай
  DelayCommand(3.0, DestroyObject(GetItemPossessedBy(oTarget, "itm_***")));
}
}


Автор: mamuc Jan 8 2007, 11:56

QUOTE
ActionTakeItem(oItem, oTaker); //тут вылетает с ошибкой

как говорится не в ту степь попали biggrin.gif
кстати- лучше бы сразу не удалять токо что найденый итем, а сделать процесс подлинее biggrin.gif - этот итем делал бы волка на каком нить алтаре, например, или повесить скрипт одноразового юза на сам предмет - тогда появление волка -хенча будет или у алтаря илии после юза спец свойства итема biggrin.gif

CODE

    CreateObject(nObjectType, "c_dogwolfdire",lLocationOfTaker, FALSE, "c_dogwolfdire1");
     object oHench = GetObjectByTag("c_dogwolfdire1");

..и еще ...а почему 2 строчки biggrin.gif ведь можно и одной biggrin.gif
CODE

    object oHench = CreateObject(nObjectType, "c_dogwolfdire",lLocationOfTaker, FALSE, "c_dogwolfdire1");

а то создание обьекта - процесс сравнительно "громоздкий"( как правило лучше на этом процесе действие скрипта и заканчивать biggrin.gif ), а ты уже ищешь обьект (по тэгу), который еще может и не успел досоздатся biggrin.gif

п.с. пока ходил по делам ( пост не завершил писать) gennady уже об этом написал biggrin.gif

Автор: webkent Jan 8 2007, 15:05

QUOTE
как говорится не в ту степь попали
кстати- лучше бы сразу не удалять токо что найденый итем, а сделать процесс подлинее - этот итем делал бы волка на каком нить алтаре, например, или повесить скрипт одноразового юза на сам предмет - тогда появление волка -хенча будет или у алтаря илии после юза спец свойства итема


Да там просто магазин петомцев =)
Ок спасибо всем щас буду править.

Автор: webkent Jan 10 2007, 14:00

И вот что интересно - Я ставлю волка в тулсете, меняю ему некоторые параметры, меняю ТАГ и меняю Тэмплейт. Потом через скрипт хочу создать волка с таким темплейтом(еще одного) а он не создается. Если пробую создать НПЦ со стандартным темплейтом то всё отлично создается. Вот вопрос - что, разве обязательно еще 1 шаблон создавать чтобы потом через скрипт этого НПЦ создать или как-то можно без этого?

Автор: -fenix- Jan 10 2007, 17:25

Все объекты создаются из палитры по их РесРефу. Тобишь, добавляешь в палитру своего волка, делаешь ему уникальный РесРеф и потом по нему создаешь этого волка где тебе надо. В первом НВН была еще возможность создания копии, хз как тут. Но лучше делай через палитру. Еще, если этот непись тебе нужен тока раз, там по квесту он где появляется или еще чего, то можно его для начала кинуть в закрытую локу, а потом просто переместить куда надо.

Автор: webkent Jan 12 2007, 23:16

Тупой вопрос: как скриптами убить объект? =)

Автор: virusman Jan 12 2007, 23:47

Убить или удалить?

Автор: Waromon Jan 13 2007, 13:37

2 webkent:

Самое простое:

NSS
// Destroy oObject (irrevocably).
// This will not work on modules and areas.
void DestroyObject(object oDestroy, float fDelay=0.0f)

Так же, можно ипользовать эффекты. Например дамага/смерти:
NSS
effect EffectDamage(int nDamageAmount, int nDamageType=DAMAGE_TYPE_MAGICAL, int nDamagePower=DAMAGE_POWER_NORMAL)

NSS
effect EffectDeath(int nSpectacularDeath=FALSE, int nDisplayFeedback=TRUE)

Применяюцца, они с помощью функции:
NSS
ApplyEffectToObject.


Ну либа ApplyEffectAtLocation;

Автор: Narruin Jan 13 2007, 15:47

Подскажите кто знает как "ловить" (как эвент) момент, когда по игроку бьют?
Нужно для реализации durability на вещах.

Исользование только On Hit Cast Spell : Unique на мэйн арморе не подходит. Вдруг игрок без армора будет бегать smile.gif Тогда шлем, перчи etc. не будут ломаться.

Автор: azathoth Jan 13 2007, 16:13

Тогда используй On Hit Cast Spell : Unique на оружие.

Еще вариант: на харбите модуля понижать прочность экипировки всем игрокам, находящимся в бою. Не столь реалистично, зато куда менее требовательно к ресурсам, елси игроков много.

Автор: Narruin Jan 13 2007, 17:19

QUOTE(azathoth @ Jan 13 2007, 17:13) [snapback]102185[/snapback]

Тогда используй On Hit Cast Spell : Unique на оружие.

Еще вариант: на харбите модуля понижать прочность экипировки всем игрокам, находящимся в бою. Не столь реалистично, зато куда менее требовательно к ресурсам, елси игроков много.

Вариант уже был рассмотрен. Мне нужно когда по игроку бьют, а не когда он бьет.
На хартбите не хочу, хотя если припрет, то сделаю.

Автор: -fenix- Jan 13 2007, 17:42

Посмотри систему Alternative Core, что лежит на сайте (тока он у меня чет не пашет второй день). На скока помню там отслеживается такой момент.
Тебе для шарда или сингла?

Автор: Narruin Jan 14 2007, 02:17

QUOTE(-fenix- @ Jan 13 2007, 18:42) [snapback]102190[/snapback]

Посмотри систему Alternative Core, что лежит на сайте (тока он у меня чет не пашет второй день). На скока помню там отслеживается такой момент.
Тебе для шарда или сингла?

для pw

Автор: Lazy Ranma Jan 14 2007, 19:54

Драсте. smile.gif

Инетересно, как в NWN2 с поддержкой баз данных для PW? Так же, как и в nwn, SetCampagin*, или добавили поддержку нормальных баз данных через какие-нибудь плагины?

Автор: virusman Jan 14 2007, 20:16

QUOTE(Lazy Ranma @ Jan 14 2007, 19:54) [snapback]102270[/snapback]

Драсте. smile.gif

Инетересно, как в NWN2 с поддержкой баз данных для PW? Так же, как и в nwn, SetCampagin*, или добавили поддержку нормальных баз данных через какие-нибудь плагины?
Какие люди...
Всё то же самое, что и с NWN1, только поддержку сохранения объектов в MySQL ещё не успели прикрутить.

Автор: Gloom Jan 28 2007, 11:56

И сново вопрос...

NSS
AssignCommand(oPC,PlayAnimation(ANIMATION_LOOPING_MEDITATE,1.0f,60.0f));

почему продолжительность анимации - стандартная, а не 60 секунд?

Автор: Lex Jan 28 2007, 13:51

возможно не так применяешь функцию, или в другом скрипте у тебя сбивается анимашка (например в хб). Вся LOOPING анимация проигрывается столько, сколько указывается.
зы: попробуй ActionPlayAnimation и если есть опасность чистки очереди, закрой стек команд.

Автор: Gloom Jan 28 2007, 16:58

ActionPlayAnimation аналогично, в хб врятли... и она не сбивается а именно заканчивается
чтобы быть уверенным на 100% сделал новый модуль, в нем тригер, на он_ентер тригера простой скрипт

NSS
void main()
{
  object oPC =GetEnteringObject();
  AssignCommand(oPC,PlayAnimation(ANIMATION_LOOPING_MEDITATE,1.0f,60.0f));
}

работает, но длительность стандартная...

Автор: Lex Jan 28 2007, 18:20

проверил в Авроре - нормально все работает. В Обси проверить не могу сейчас, но если там и правда такой косяк, эт очень странно.

Автор: Milfes Feb 4 2007, 16:24

Столкнулся с проблемой, надо сделать управляемого хенча. В официальной компании используется функция AddRosterMemberToParty, но у меня не получается присоеденить при помощи нее кого-то. Может кто-то знает как их присоеденять?

Автор: azathoth Feb 4 2007, 20:31

Сначала нужно добавить непись в ростер, например при помощи AddRosterMemberByTemplate.

Насчет длительности анимации: это корявость обсидиана (см. http://www.city-of-masters.ru/forums/index.php?showtopic=4296).

Автор: Milfes Feb 4 2007, 21:01

Спасибо, все получилось. smile.gif

Автор: Milfes Mar 2 2007, 20:01

У меня вопрос. Добавляю на onSpawn НПС строку

NSS
ApplyEffectToObject(DURATION_TYPE_PERMANENT,EffectSleep(),OBJECT_SELF);

Но при проверке, НПС продолжает стоять, как и стоял. Может я что то не правильно делаю? На 1 НВНе этот скрипт вроде работал.

Автор: Narruin Mar 4 2007, 16:38

QUOTE(Milfes @ Mar 2 2007, 21:01) [snapback]105272[/snapback]

У меня вопрос. Добавляю на onSpawn НПС строку
NSS
ApplyEffectToObject(DURATION_TYPE_PERMANENT,EffectSleep(),OBJECT_SELF);

Но при проверке, НПС продолжает стоять, как и стоял. Может я что то не правильно делаю? На 1 НВНе этот скрипт вроде работал.

Этот скрипт кидает кондишен сна на кричу, но не заставляет ее лечь на землю.

Автор: Milfes Mar 4 2007, 17:47

QUOTE
Этот скрипт кидает кондишен сна на кричу, но не заставляет ее лечь на землю.

Ты не прав, он ложится, я выяснил, что он не работает именно на onSpawn. То есть сама функция работает. Странно конечно, что на onSpawn не работает.

Автор: -fenix- Mar 4 2007, 17:56

Попробуй на onSpawn в скрипте поставить небольшую задержку.

Автор: Milfes Mar 4 2007, 18:08

Нет не помогает, но складывается такое ощещение, что на оnSpawn не срабатывает именно анимация, что бы он лег, а сам НПС как бы спит, но стоя.

Автор: -fenix- Mar 4 2007, 18:36

А ты какую задержку ставил? Попробуй поставить две секунды:

NSS
DelayCommand(2.0, ApplyEffectToObject(DURATION_TYPE_PERMANENT,EffectSleep(),OBJECT_SELF));

Если сработает, то уменьшай время, чтобы понять какая задержка нужна, ну а если не получицо. Хм... Не судьба ведать пока. smile.gif

Автор: Milfes Mar 4 2007, 18:42

Я вообще 3 секунды ставил. Да я впринципе на диалоге повесил, меня просто удивляет, что на onSpawn не работает. Наверно обсидан так хорошо сделал.

Автор: azathoth Mar 5 2007, 00:50

Такая задержка может не сработать:

NSS
DelayCommand(2.0, ApplyEffectToObject(DURATION_TYPE_PERMANENT,EffectSleep(),OBJECT_SELF));


Правильно:
NSS
effect eSleep;
DelayCommand(2.0, ApplyEffectToObject(DURATION_TYPE_PERMANENT, eSleep, OBJECT_SELF));


NSS
// Delay aActionToDelay by fSeconds.
// * No return value, but if an error occurs, the log file will contain
//  "DelayCommand failed.".
// It is suggested that functions which create effects should not be used
// as parameters to delayed actions.  Instead, the effect should be created in the
// script and then passed into the action.  For example:
// effect eDamage = EffectDamage(nDamage, DAMAGE_TYPE_MAGICAL);
// DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oTarget);
void DelayCommand(float fSeconds, action aActionToDelay)

Автор: Lex Mar 5 2007, 09:08

а попробовать анимацией положить его не пробовали?

Автор: Ragdaj Mar 5 2007, 18:34

Даже не уверен, возможно ли такое - но как сделать, чтоб при начале кампании, проверялся класс РС, и взависимости от него, грузилась та, или иная область (ну к примеру - выбрал война - начинаешь в казармах, мага - в лаборатории и т.д.)

Автор: Lex Mar 5 2007, 19:04

много раз это обсуждалось, скрипт вынесен в Вопросы и Ответу. (там правда было разделение по расе, но суть одна и та же)

Автор: Ragdaj Mar 5 2007, 19:50

Это разобрался. Спасибо. А вот теперь сложный вопрос - возможно ли как то скриптами прикрутить такую вещь, как использование предметов на объекте.
Не через диалоги!
Перетаскиваешь предмет из инвентаря на НПС\объект и происходит запланированное действие. К примеру порох на костер -> происходит вспышка (пример с потолка).
Диалоговая система не особо устраивает - ибо при обладание нужного предмета его использование становится очевидным - так как появляется необходимая строка в диалоге. Додумываться, как следствие, не надо.

Автор: azathoth Mar 5 2007, 21:02

Просто перетаскивать не выйдет - предмет просто будет выброшен, но можно добавить к свойствам предмета возможность "юзабельности".

Cast Spell -> Unique Power
Результат прописываешь в скрипте "i_ТэгВещи_ac".

Автор: Milfes Mar 6 2007, 11:14

QUOTE
а попробовать анимацией положить его не пробовали?


Анимацией тоже не получается, он ее на onSpawn кажется вообще не воспринимает, так как и у эффекта сна не срабатывает только анимация(НПС не на что не реагирует пока эффект не снять, но стоит).

Автор: diggers Mar 19 2007, 21:36


Nwn2scriptcompiler.exe лежит в корневой папке, но на попытки подсунуть ему .nss не отзывается. Подскажите, как компилировать скрипты без запуска громоздкого тулсета?

Нвн2 скрипты не кеширует, можно править их в оверрайде\модуле сохраненном как папка, перезапускать текущий модуль и смотреть результат.
Вот только делать бы это без тулсета, который ест ресурсов больше чем сам нвн.

Автор: Oranj Mar 30 2007, 20:44

Есть ли возможность при помощи скриптов сделать включение/выключение источника света в определенные время суток?

Автор: Griffon Apr 2 2007, 10:46

Есть система http://nwvault.ign.com/View.php?view=NWN2Scripts.Detail&id=71 источников света.

Цитата
Есть ли возможность при помощи скриптов сделать включение/выключение источника света в определенные время суток?
Может кто из мастеров напишет или выложит уже имеющуюся?

Автор: Oranj Apr 2 2007, 16:28

Предложенный вариант посмотрел, но ничего не понял, так как очень далек от скриптинга и занимаюсь только маппингом smile.gif Было бы хорошо, если кто-то напишет скрипт и объяснит как его применить.

Автор: Sugo77 May 2 2007, 19:27

Привет всем,я новичок в создании и использовании скриптов но в создании модулей уже принимаю участие уже 5 лет начиная с нвн1,а теперь уже и осваиваю нвн2 ,и вот мои первые 2 вопроса,заранее прошу неругать если уже были,
просто я искал на них ответы во многих разделах вашего форума и ненашол(

Как сделать так чтоб монстры респились,ну то есть воскрешались через некоторое время после смерти?
Вот что я испробовал и недобился(
открываю свой модуль скажем Area 1 -далее свойства етой ARea1(Properites) Дальше во всех трех строчках(On_heartbeat On_enter On_dead)повставлял
все найденые поисковиком,етих строчек скрипты с именем respawn их нашлось семь ШТук!(gr_respawn,gui_death_respawn,gui_death_respawn_self,nw_o0_respawn,x0_o0respawn,x0_o0_repawnset,x2_respawn)вот перечислил те что находилис поисковиком,дак я их все на свойствах локации повставлял в строчки:"On_heartbeat On_enter On_dead" и недобился респа,и на свойствах монстров,тоже в строчки:"On_dead,On_heartbeat",вставлял ети семь стандартных скриптов НВН2,но не один из етих семи скриптов невернул неодного монстра к жизни на заданную точку,а ждал я намного больше шести секунд,респа монстров(((
Может не ети скрипты надо выбирать а какой то другой??? или самому прописать?

А второй вопрос: как фракцию сменить?(подхожу к люблму обьекту тыкаю и стаю хостаил как ето сделать?),тоесть чтоб пвп шард создать надо чтоб обязательно кто то один был скажем faction:*comoner*,Другой:*hostile*

Автор: Lex May 3 2007, 08:12

Цитата(Sugo77 @ May 2 2007, 20:27) [snapback]107708[/snapback]
Вот что я испробовал и недобился(
открываю свой модуль скажем Area 1 -далее свойства етой ARea1(Properites) Дальше во всех трех строчках(On_heartbeat On_enter On_dead)повставлял
все найденые поисковиком,етих строчек скрипты с именем respawn их нашлось семь ШТук!(gr_respawn,gui_death_respawn,gui_death_respaw
n_self,nw_o0_respawn,x0_o0respawn,x0_o0_repawnset,
x2_respawn)вот перечислил те что находилис поисковиком,дак я их все на свойствах локации повставлял в строчки:"On_heartbeat On_enter On_dead" и недобился респа,и на свойствах монстров,тоже в строчки:"On_dead,On_heartbeat",вставлял ети семь стандартных скриптов НВН2,но не один из етих семи скриптов невернул неодного монстра к жизни на заданную точку,а ждал я намного больше шести секунд,респа монстров(((
Может не ети скрипты надо выбирать а какой то другой??? или самому прописать?

оригинально. Впервые встречаю такой способ решения поставленной задачи.
Скрипты надо или писать под свои конкретные нужды, или брать готовые и вставлять (возможно модернизируя). Есть специальные уже написанные скриптовые системы для респа монстров. Лучше у шардовиков спросить об этом по подробнее.

Автор: Vanes May 3 2007, 08:49

по поводу спавна мобов была уже тема
см. тут http://www.city-of-masters.ru/forums/index.php?showtopic=287
там вроде и линки какие есть

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

Цитата
А второй вопрос: как фракцию сменить?(подхожу к люблму обьекту тыкаю и стаю хостаил как ето сделать?),тоесть чтоб пвп шард создать надо чтоб обязательно кто то один был скажем faction:*comoner*,Другой:*hostile*

не обязательно...
кричи из одной фракции замечательно могут бить друг друга smile.gif
честно говоря точно не помню функции, но попробуй SetIsEnemy()... если не подойдет, посмотри в лексиконе все что с этой функцией связано, наверняка какие либо смежные с ней функции тебе помогут...

Автор: Sugo77 May 3 2007, 15:27

Vaness,по предложенной тобой ссылке нет ничего конкретного,неодного примера не инструкций(
Единственное что я уяснил для начало надо хотябы заиметь себе програмкуу Ness какуюто,попробовал поискать в интернете ,ссылки на нее битые некачается(

Если у тебя есть рабочие ссылки на ету прогу то вылож плиз или саму прогу скинь плиз на мое мыло если нетрудно

sugo3377@mail.ru

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

Вот нашол всеже сайт от куда Несс качается LRJOnline_net - NESS оно не оно?


Тут вроде для нвн 1 несс или он всем подходит?

Далее куда етот файлик NESS_8_1_3Full.erf нужно устаноить чтоб начать им пользоватся в НВН2 тулсете?

Хотелось бы все поподробнее от вас учителей услышать)

Автор: Vanes May 3 2007, 15:47

щас выложу свой скрипт спавна

суть простая...
в локе ставятся вейпоинты с определенным тегом и именем
имя имеет вид
SP_SGx_SDy_SNz1-z2_SRn_END
где x - принимает значение 0 (спавнить конкретного моба) или 1 (спавнить моба из группы)
y - задержка между спавнами
z1 и z2 - соответственно минимальное и максимальное количество мобов
n - на каком максимальном расстоянии от вейпоинта может появиться моб
в теге вейпоинта указывается либо тег моба, либо тег группы для спавна


это на OnEnter локи
* при входе игрока запускается псевдохарбит

Neverwinter Script Source
void main()
{
    object oArea = GetArea(OBJECT_SELF);
    object oPC = GetEnteringObject();
    if(GetIsDM(oPC)) return;
    if(GetIsPC(oPC)){
        int nCount = GetLocalInt(oArea, "nPlayerCount");
        nCount++;
        SetLocalInt(oArea, "nPlayerCount", nCount);
        if(GetLocalInt(oArea, "bNeedSpawn")==FALSE){
            SetLocalInt(oArea, "bNeedSpawn", TRUE);
            if(GetLocalInt(oArea, "bNeedClear")==FALSE){
                ExecuteScript("vr_spawn_general", oArea);
            }else{
                SetLocalInt(oArea, "bNeedClear", FALSE);
            }
        }
    }
}


это на OnExit локи
* при выходе всех игроков с локи замораживает спавнер, если же выходит моб, то не позволяет ему выйти из локи и возвращает на место спавна
Neverwinter Script Source
void main()
{
    object oArea = GetArea(OBJECT_SELF);
    object oPC = GetExitingObject();
    if(GetIsDM(oPC)) return;
    if(GetIsPC(oPC)){
        int nCount = GetLocalInt(oArea, "nPlayerCount");
        nCount--;
        SetLocalInt(oArea, "nPlayerCount", nCount);

        if(nCount<=0){ // no PC in location
            SetLocalInt(oArea, "bNeedSpawn", FALSE);
            object oWP;
            int nSpawnersCount = GetLocalInt(oArea, "nSpawnersCount");
            int i;
            for(i=1; i<=nSpawnersCount; i++){
                oWP = GetLocalObject(oArea, "Spawner"+IntToString(i));
                if(GetLocalInt(oWP, "nChildCount")>0){ // if any spawner has children
                    SetLocalInt(oArea, "nLastPCExitTime", GetLocalInt(GetObjectByTag("vr_dmhelper"), "nCurrentTime"));
                    SetLocalInt(oArea, "bNeedClear", TRUE);
                    break;
                }
            }
        }
    }else if(GetIsObjectValid(GetLocalObject(oPC, "parent"))){
        //SendMessageToPC(GetFirstPC(), "name="+GetName(oPC));
        object oCreature = CreateObject(OBJECT_TYPE_CREATURE,
                        GetResRef(oPC),
                        GetLocalLocation(oPC, "lHomeLocation"));

        SetLocalLocation(oCreature, "lHomeLocation", GetLocalLocation(oPC, "lHomeLocation"));

        DeleteLocalInt(oPC, "TotalDamage");
        int i;
        for(i=1;i<=GetLocalInt(oPC, "TotalDamagers");i++){
            DeleteLocalObject(oPC, "Damager"+IntToString(i));
            DeleteLocalInt(oPC, "Damage"+IntToString(i));
        }
        DeleteLocalInt(oPC, "TotalDamagers");
        DeleteLocalInt(oPC, "nPreviousHP");
        DeleteLocalObject(oPC, "parent");
        DeleteLocalLocation(oPC, "lHomeLocation");

        DestroyObject(oPC);
    }
}


собственно сам скрипт спавна
*void main() - как раз таки тот самый псевдо харбит, который запускается с частотой, указанной в строках AssignCommand(oArea, DelayCommand(10.0, ExecuteScript("vr_spawn_general", oArea)));
*void CheckWaypoints(object oArea) - проверяет все спавнпоинты в локи и при необходимости их спавнит
*void Spawn(object oWP) - процедура которая непосредственно создает мобов в точках спавна
*void StoreSpawns(object oArea) - срабатывает 1 раз за рестарт... задача его в том, чтобы "расшифровать" тег спавнпоинта и занести все данные в локальные переменные
*void ClearLocationFromCreatures(object oArea) - в случае необходимости деспавна очищает локацию от мобов
Neverwinter Script Source
// SPAWN SYSTEM
// for NWN Shard "Validor 2"
// main script
/* Scripted by Vanes */

#include "vr_spawn_groups"
#include "vr_config"

void CheckWaypoints(object oArea);
void Spawn(object oWP);
void StoreSpawns(object oArea);
void ClearLocationFromCreatures(object oArea);


void main() // psevdo heartbeat
{
    object oArea = OBJECT_SELF;

    if(GetLocalInt(oArea, "bNeedSpawn")==TRUE){
        CheckWaypoints(oArea);
        //SendMessageToPC(GetFirstPC(), "attemting to spawn... "+ GetName(oArea));
        AssignCommand(oArea, DelayCommand(10.0, ExecuteScript("vr_spawn_general", oArea)));
        return;
    }
    if(GetLocalInt(oArea, "bNeedClear")==TRUE){
        //SendMessageToPC(GetFirstPC(), "attemting to clear... "+ GetName(oArea));
        //SendMessageToPC(GetFirstPC(), "nLastPCExitTime = " + IntToString(GetLocalInt(oArea, "nLastPCExitTime")));
        //SendMessageToPC(GetFirstPC(), "nCurrentTime = " + IntToString(GetLocalInt(GetObjectByTag("vr_dmhelper"), "nCurrentTime")));
        if((GetLocalInt(oArea, "nLastPCExitTime")+SPAWN_CLEAR_LOC_DELAY)<=GetLocalInt(GetObjectByTag("vr_dmhelper"), "nCurrentTime")){
            //SendMessageToPC(GetFirstPC(), "clearing... "+ GetName(oArea));
            ClearLocationFromCreatures(oArea);
            SetLocalInt(oArea, "bNeedClear", FALSE);
        }else{
            AssignCommand(oArea, DelayCommand(10.0, ExecuteScript("vr_spawn_general", oArea)));
        }
        return;
    }
}

void CheckWaypoints(object oArea) // check for WP status (waiting for delay end,
                                  // waiting for children death, need pawn now)
{
    if(GetLocalInt(oArea, "bSpawnsStored")==FALSE){
        StoreSpawns(oArea);
        SetLocalInt(oArea, "bSpawnsStored", TRUE);
    }
    object oWP;
    string sName;
    int nPos, nSpawnDelay, nStartDelay, nCurrentTime;
    int i;
    int nSpawnersCount = GetLocalInt(oArea, "nSpawnersCount");
    //SendMessageToPC(GetFirstPC(), "nSpawnersCount="+IntToString(nSpawnersCount));
    for(i=1; i<=nSpawnersCount; i++){
        oWP = GetLocalObject(oArea, "Spawner"+IntToString(i));
        sName = GetName(oWP);
        //SendMessageToPC(GetFirstPC(), "checking WP " + sName);
        if(GetLocalInt(oWP, "nSpawnDelay")==0){ // first check after module started
            nPos = FindSubString(sName, "SG");
            nSpawnDelay = StringToInt(GetSubString(sName, 5, nPos-6))*60;
            //int nTime = GetLocalInt(GetObjectByTag("vr_dmhelper"), "nCurrentTime");
            //if(nTime!=0){
            //SetLocalInt(oWP, "nStartDelay", 60);
            SetLocalInt(oWP, "nSpawnDelay", nSpawnDelay);
            //}
            Spawn(oWP);
        }
        if(GetLocalInt(oWP, "nChildCount")<=0){
            nStartDelay = GetLocalInt(oWP, "nStartDelay");
            //SendMessageToPC(GetFirstPC(), "nStartDelay=" + IntToString(nStartDelay));
            nCurrentTime = GetLocalInt(GetObjectByTag("vr_dmhelper"), "nCurrentTime");
            //SendMessageToPC(GetFirstPC(), "nCurrentTime=" + IntToString(nCurrentTime));
            nSpawnDelay = GetLocalInt(oWP, "nSpawnDelay");
            //SendMessageToPC(GetFirstPC(), "nSpawnDelay=" + IntToString(nSpawnDelay));
            if(nSpawnDelay<(nCurrentTime-nStartDelay)){
                //SendMessageToPC(GetFirstPC(), "delay end, spawning...");
                SetLocalInt(oWP, "bSpawnDisturbed", FALSE);
                Spawn(oWP);
            }else{
                //SendMessageToPC(GetFirstPC(), "waiting for delay end");
            }
        }
    }
}

void Spawn(object oWP)
{
    object oCreature;
    string sTag;
    int nPos1, nPos2;
    int n, n1, n2, i, r, r1;
    int bGroup = FALSE;
    location lLoc;

    sTag = GetLocalString(oWP, "sTag"); // for Lexey's Spawn Table

//---- SG flag ----
    bGroup = GetLocalInt(oWP, "bGroup");

//---- SRn flag ----
    r = GetLocalInt(oWP, "r");
    location lLocation = GetLocation(oWP);
    object oArea = GetAreaFromLocation(lLocation);
    vector vPosition;
    float fOrientation = GetFacingFromLocation(lLocation);

//---- SNn flag ----
    n1 = GetLocalInt(oWP, "nMin");
    n2 = GetLocalInt(oWP, "nMax");
    if(n2!=0){
        n = n1+Random(n2-n1)+1;
    }else{
        n = n1;
    }

    for(i=1; i<=n; i++){
        vPosition = GetPositionFromLocation(lLocation);
        r1 = Random(r+1);
        if(d2()==1) r1 *= -1;
        vPosition.x += r1;
        r1 = Random(r+1);
        if(d2()==1) r1 *= -1;
        vPosition.y += r1;

        lLoc = Location(oArea, vPosition, fOrientation);
        if(bGroup==TRUE) sTag = SpawnGroup(oWP);
        oCreature = CreateObject(OBJECT_TYPE_CREATURE, sTag, lLoc);
        if(oCreature!=OBJECT_INVALID){
            SetLocalInt(oWP, "nChildCount", GetLocalInt(oWP, "nChildCount")+1);
            SetLocalObject(oCreature, "parent", oWP);
            SetLocalLocation(oCreature, "lHomeLocation", lLoc);
        }else{
            i--;
        }
    }
}

void StoreSpawns(object oArea)
{
    object oObject = GetFirstObjectInArea(oArea);
    string sName, s;
    string sTag;
    int nPos1, nPos2;
    int nCount=0;
    while(oObject!=OBJECT_INVALID){
        sName = GetName(oObject);
        if((GetStringLeft(sName, 2)=="SP")&&(GetObjectType(oObject)==OBJECT_TYPE_WAYPOINT)){
            nCount++;
            SetLocalObject(oArea, "Spawner"+IntToString(nCount), oObject);

            SetLocalString(oObject, "sTag", GetTag(oObject));

            //---- SG flag ----
            nPos1 = FindSubString(sName, "SG");
            if((nPos1!=-1)&&(StringToInt(GetSubString(sName, nPos1+2, 1))==1))
                SetLocalInt(oObject, "bGroup", TRUE);

            //---- SRn flag ----
            nPos1 = FindSubString(sName, "SR");
            nPos2 = FindSubString(sName, "END");
            SetLocalInt(oObject, "r", StringToInt(GetSubString(sName, nPos1+2, nPos2-nPos1-3)));

            //---- SNn flag ----
            nPos1 = FindSubString(sName, "SN");
            nPos2 = FindSubString(sName, "SR");
            s = GetSubString(sName, nPos1+2, nPos2-nPos1-3);
            nPos1 = FindSubString(s, "-");
            if(nPos1==-1){
                SetLocalInt(oObject, "nMin", StringToInt(s));
                SetLocalInt(oObject, "nMax", 0);
            }else{
                SetLocalInt(oObject, "nMin", StringToInt(GetSubString(s, 0, nPos1)));
                SetLocalInt(oObject, "nMax", StringToInt(GetSubString(s, nPos1+1, GetStringLength(s)-nPos1-1)));
            }
        }
        oObject = GetNextObjectInArea(oArea);
    }
    SetLocalInt(oArea, "nSpawnersCount", nCount);
}

void ClearLocationFromCreatures(object oArea)
{
    string sName;
    object oWP;
    object oObject = GetFirstObjectInArea(oArea);
    while(oObject!=OBJECT_INVALID){
        sName = GetName(oObject);

        oWP = GetLocalObject(oObject, "parent");
        if(oWP!=OBJECT_INVALID)
            DestroyObject(oObject);

        if((GetStringLeft(sName, 2)=="SP")&&(GetObjectType(oObject)==OBJECT_TYPE_WAYPOINT)){
            if(GetLocalInt(oObject, "nChildCount")>0){
                SetLocalInt(oObject, "nChildCount", 0);
                if(GetLocalInt(oObject, "bSpawnDisturbed")){
                    SetLocalInt(oObject, "nStartDelay", GetLocalInt(GetObjectByTag("vr_dmhelper"), "nCurrentTime"));
                }
            }
            //SendMessageToPC(GetFirstPC(), "b="+IntToString(GetLocalInt(oObject, "bSpawnDisturbed")));
        }

        oObject = GetNextObjectInArea(oArea);
    }
}


ну и последнее... скипт, содержащий таблицу групп мобов...
Neverwinter Script Source
string SpawnGroup(object oWP)
{
    string sTag = GetTag(oWP);

    if(sTag=="vr_lowlvlgrp1"){
        switch(d4()){
            case 1: return "vr_badger";
            case 2: return "vr_rat";;
            case 3: return "vr_direrat";
            case 4: return "vr_bat";
        }
    }

    if(sTag=="vr_bugbeargrp"){
        int nCount = GetLocalInt(oWP, "nChildCount");
        if(nCount<1) return "vr_bugbearhero";
        if(nCount<2) return "vr_bugbearshaman";
        switch(d2()){
            case 1: return "vr_bugbear";
            case 2: return "vr_bugbeararcher";
        }
    }

// ---- !!!! ADD GROUPS OVER THIS LINE !!!! ----
    return "";
}

Автор: Sugo77 May 3 2007, 16:21

Хех пока никак,новичкам тяжкоsmile.gif

а вот в етой твоей фразе нет ошибки?"в *теге моба* указывается либо тег моба, илбо тег группы для спавна"
Может имелось ввиду в теге поинта?
ну тоесть вот так:"в *теге поинта* указывается либо тег моба, илбо тег группы для спавна"

Да а куда собственно вот етот готовы скрипт вставить мне? в какую строчку?

собственно сам скрипт спавна
*void main() - как раз таки тот самый псевдо харбит, который запускается с частотой, указанной в строках AssignCommand(oArea, DelayCommand(10.0, ExecuteScript("vr_spawn_general", oArea)));
*void CheckWaypoints(object oArea) - проверяет все спавнпоинты в локи и при необходимости их спавнит
*void Spawn(object oWP) - процедура которая непосредственно создает мобов в точках спавна
*void StoreSpawns(object oArea) - срабатывает 1 раз за рестарт... задача его в том, чтобы "расшифровать" тег спавнпоинта и занести все данные в локальные переменные
*void ClearLocationFromCreatures(object oArea) - в случае необходимости деспавна очищает локацию от мобов

Neverwinter Script Source
// SPAWN SYSTEM
// for NWN Shard "Validor 2"
// main script
/* Scripted by Vanes */

#include "vr_spawn_groups"
#include "vr_config"

void CheckWaypoints(object oArea);
void Spawn(object oWP);
void StoreSpawns(object oArea);
void ClearLocationFromCreatures(object oArea);

и тд

Автор: Vanes May 3 2007, 16:30

создаешь скрипт с именем vr_spawn_general (именно он запускается в энтере локи, см. ExecuteScript("vr_spawn_general", oArea)wink3.gif и все туда вставляешь

Автор: Sugo77 May 3 2007, 16:32

А еше а как он собственно назватся будет? или просто открываю уже юбой стандартный скрипт нвна и затираю на новый ? а то сам придумал под своим именем шапку Sugo дак несохраняется такое название непринимает его тулсет(

Автор: Vanes May 3 2007, 16:40

так и будет называться - vr_spawn_general...
а в теле скрипта должно быть то, что я выше написал...

Автор: Sugo77 May 3 2007, 20:06

Нет Vanes ты маленько меня недопонял вот последние тобой написаные 2 скрипта куда вставлять в свойства мобов или в свойства локации? и в какие строчки?

а так я разообрался где их имя изменять у меня уже 2 скрипта твои внесены в он Enter и on Exit
под именами: vr_spawn_general 1 и vr_spawn_general 2
но а последнии тобой изобритеные 2 скрита куды вставляются?

Ну тоесть Vanes я шас имею у себя все твои 4 скрипта в тулсете под именами

vr_spawn_general 1
vr_spawn_general 2
vr_spawn_general 3
vr_spawn_general 4

Дак вот с первыми двумя все ясно в строку On Enter Script вставляем vr_spawn_general 1
В строку арейных свойств On Exit Script вставляем vr_spawn_general 2
а куда вставляем оставшиеся два скрипта?vr_spawn_general 3
vr_spawn_general 4

И ето ешо(а вот в етой твоей фразе нет ошибки?"в *теге моба* указывается либо тег моба, илбо тег группы для спавна"
Может имелось ввиду в теге поинта?
ну тоесть вот так:"в *теге поинта* указывается либо тег моба, илбо тег группы для спавна"

Эх пока никак((

А через сколько у тебя запргормаирован респ?

А еше а может мне что то надо изменить в скриптах твоих а то всетаки у меня не валидор модуль а по другому называется? или гдето закралась ошибка или я что то делаю не так(

Проверь плиз ,и раскажи всеже куда еше то 2 скрипта последних вставляем?

Автор: Vanes May 4 2007, 08:45

Цитата
а куда вставляем оставшиеся два скрипта?vr_spawn_general 3
vr_spawn_general 4

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

Цитата
Может имелось ввиду в теге поинта?

уже исправил

Цитата
А через сколько у тебя запргормаирован респ?

задержка респа указывается для каждого конкретного спавна-вейпоинта отдельно, в его имени
т.е. если имя вейпоинта SP_SG0_SD5_SN1_SR5_END и тег vr_goblin
то моб с тегом vr_goblin в количестве одной штуки будет появляться на расстоянии 5 от вейпоинта каждые 5*60 секунд...
зы я кстати ошибся в описании имени спавнпоинта, т.к. по памяти писал... щас поправил...

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

Автор: Sugo77 May 4 2007, 12:51

Хм тоесть надо изменить все нахвания скриттов не генерал 1-2-3-4
а генерал просто ето первый второй будет спавн гроуп по порядку а 3 и 4 ый вообше непонял(
так и непонял что с ними делаем))(
и как ето вставлять их никуда ненадо они что автоматически запустятся ?даже если просто будут сушествовать в тулсете(

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



кстати 2 скритпа с одинаковым именем никак неможетсушествовать тулсет недает их сохранять тогда(
значит каждый твой скритп должен по разному называтся первый и второй уже понял а 3-4 ?

может череез асю пообшаемся на ету тему?)а то весь форум зафлудим сколко непытаюс никак немогу добится респа уже неделю((

просто я обсолютно запутался ответы то несовсем развернутые( а загадками понятными тока мастерам а не новичкам,вот чтоо такое инклуды? я вобше хз(
мнеб все попрастому обьяснить открываем ето вставляем то и тд(

Автор: Lex May 4 2007, 14:04

Цитата(Sugo77 @ May 4 2007, 13:51) [snapback]107767[/snapback]
вот чтоо такое инклуды?

вот это:
Neverwinter Script Source
#include "vr_spawn_groups"
#include "vr_config"

присоединяемые к скрипту библиотеки с дополнительными функциями (такие библиотеки можно самому писать)

Автор: Vanes May 4 2007, 14:41

Цитата
а генерал просто ето первый второй будет спавн гроуп по порядку а 3 и 4 ый вообше непонял(

первый и второй - это не скрипты, а части скриптов, которые тебе нужно вставить в свои скрипты энтера и экзита локи... если таковых нет, то создай 2 скрипта area_enter и area_exit и туда эти части вставь...
третий (который самый большой) - это как раз таки vns_spawn_general
ну и последний - vns_spawn_groups

Автор: Sugo77 May 4 2007, 19:52

Неа все еше никак(
Можно с тобой через асю пообшатся там будет проше вживую ?
потом если что удолиш меня

Собственно что я делал вот что содал с нуля 2 скрипта с названиями: area_enter и area_exit
Вот как выглядят первый:area_enter :

Neverwinter Script Source
// area_enter

void main()
{
    object oArea = GetArea(OBJECT_SELF);
    object oPC = GetEnteringObject();
    if(GetIsDM(oPC)) return;
    if(GetIsPC(oPC)){
        int nCount = GetLocalInt(oArea, "nPlayerCount");
        nCount++;
        SetLocalInt(oArea, "nPlayerCount", nCount);
        if(GetLocalInt(oArea, "bNeedSpawn")==FALSE){
            SetLocalInt(oArea, "bNeedSpawn", TRUE);
            if(GetLocalInt(oArea, "bNeedClear")==FALSE){
                ExecuteScript("vr_spawn_general", oArea);
            }else{
                SetLocalInt(oArea, "bNeedClear", FALSE);
            }
        }
    }
}

// SPAWN SYSTEM
// for NWN Shard "Validor 2"
// main script
/* Scripted by Vanes */

#include "vr_spawn_groups"
#include "vr_config"

void CheckWaypoints(object oArea);
void Spawn(object oWP);
void StoreSpawns(object oArea);
void ClearLocationFromCreatures(object oArea);


void main() // psevdo heartbeat
{
    object oArea = OBJECT_SELF;

    if(GetLocalInt(oArea, "bNeedSpawn")==TRUE){
        CheckWaypoints(oArea);
        //SendMessageToPC(GetFirstPC(), "attemting to spawn... "+ GetName(oArea));
        AssignCommand(oArea, DelayCommand(10.0, ExecuteScript("vr_spawn_general", oArea)));
        return;
    }
    if(GetLocalInt(oArea, "bNeedClear")==TRUE){
        //SendMessageToPC(GetFirstPC(), "attemting to clear... "+ GetName(oArea));
        //SendMessageToPC(GetFirstPC(), "nLastPCExitTime = " + IntToString(GetLocalInt(oArea, "nLastPCExitTime")));
        //SendMessageToPC(GetFirstPC(), "nCurrentTime = " + IntToString(GetLocalInt(GetObjectByTag("vr_dmhelper"), "nCurrentTime")));
        if((GetLocalInt(oArea, "nLastPCExitTime")+SPAWN_CLEAR_LOC_DELAY)<=GetLocalInt(GetObjectByTag("vr_dmhelper"), "nCurrentTime")){
            //SendMessageToPC(GetFirstPC(), "clearing... "+ GetName(oArea));
            ClearLocationFromCreatures(oArea);
            SetLocalInt(oArea, "bNeedClear", FALSE);
        }else{
            AssignCommand(oArea, DelayCommand(10.0, ExecuteScript("vr_spawn_general", oArea)));
        }
        return;
    }
}

void CheckWaypoints(object oArea) // check for WP status (waiting for delay end,
                                  // waiting for children death, need pawn now)
{
    if(GetLocalInt(oArea, "bSpawnsStored")==FALSE){
        StoreSpawns(oArea);
        SetLocalInt(oArea, "bSpawnsStored", TRUE);
    }
    object oWP;
    string sName;
    int nPos, nSpawnDelay, nStartDelay, nCurrentTime;
    int i;
    int nSpawnersCount = GetLocalInt(oArea, "nSpawnersCount");
    //SendMessageToPC(GetFirstPC(), "nSpawnersCount="+IntToString(nSpawnersCount));
    for(i=1; i<=nSpawnersCount; i++){
        oWP = GetLocalObject(oArea, "Spawner"+IntToString(i));
        sName = GetName(oWP);
        //SendMessageToPC(GetFirstPC(), "checking WP " + sName);
        if(GetLocalInt(oWP, "nSpawnDelay")==0){ // first check after module started
            nPos = FindSubString(sName, "SG");
            nSpawnDelay = StringToInt(GetSubString(sName, 5, nPos-6))*60;
            //int nTime = GetLocalInt(GetObjectByTag("vr_dmhelper"), "nCurrentTime");
            //if(nTime!=0){
            //SetLocalInt(oWP, "nStartDelay", 60);
            SetLocalInt(oWP, "nSpawnDelay", nSpawnDelay);
            //}
            Spawn(oWP);
        }
        if(GetLocalInt(oWP, "nChildCount")<=0){
            nStartDelay = GetLocalInt(oWP, "nStartDelay");
            //SendMessageToPC(GetFirstPC(), "nStartDelay=" + IntToString(nStartDelay));
            nCurrentTime = GetLocalInt(GetObjectByTag("vr_dmhelper"), "nCurrentTime");
            //SendMessageToPC(GetFirstPC(), "nCurrentTime=" + IntToString(nCurrentTime));
            nSpawnDelay = GetLocalInt(oWP, "nSpawnDelay");
            //SendMessageToPC(GetFirstPC(), "nSpawnDelay=" + IntToString(nSpawnDelay));
            if(nSpawnDelay<(nCurrentTime-nStartDelay)){
                //SendMessageToPC(GetFirstPC(), "delay end, spawning...");
                SetLocalInt(oWP, "bSpawnDisturbed", FALSE);
                Spawn(oWP);
            }else{
                //SendMessageToPC(GetFirstPC(), "waiting for delay end");
            }
        }
    }
}

void Spawn(object oWP)
{
    object oCreature;
    string sTag;
    int nPos1, nPos2;
    int n, n1, n2, i, r, r1;
    int bGroup = FALSE;
    location lLoc;

    sTag = GetLocalString(oWP, "sTag"); // for Lexey's Spawn Table

//---- SG flag ----
    bGroup = GetLocalInt(oWP, "bGroup");

//---- SRn flag ----
    r = GetLocalInt(oWP, "r");
    location lLocation = GetLocation(oWP);
    object oArea = GetAreaFromLocation(lLocation);
    vector vPosition;
    float fOrientation = GetFacingFromLocation(lLocation);

//---- SNn flag ----
    n1 = GetLocalInt(oWP, "nMin");
    n2 = GetLocalInt(oWP, "nMax");
    if(n2!=0){
        n = n1+Random(n2-n1)+1;
    }else{
        n = n1;
    }

    for(i=1; i<=n; i++){
        vPosition = GetPositionFromLocation(lLocation);
        r1 = Random(r+1);
        if(d2()==1) r1 *= -1;
        vPosition.x += r1;
        r1 = Random(r+1);
        if(d2()==1) r1 *= -1;
        vPosition.y += r1;

        lLoc = Location(oArea, vPosition, fOrientation);
        if(bGroup==TRUE) sTag = SpawnGroup(oWP);
        oCreature = CreateObject(OBJECT_TYPE_CREATURE, sTag, lLoc);
        if(oCreature!=OBJECT_INVALID){
            SetLocalInt(oWP, "nChildCount", GetLocalInt(oWP, "nChildCount")+1);
            SetLocalObject(oCreature, "parent", oWP);
            SetLocalLocation(oCreature, "lHomeLocation", lLoc);
        }else{
            i--;
        }
    }
}

void StoreSpawns(object oArea)
{
    object oObject = GetFirstObjectInArea(oArea);
    string sName, s;
    string sTag;
    int nPos1, nPos2;
    int nCount=0;
    while(oObject!=OBJECT_INVALID){
        sName = GetName(oObject);
        if((GetStringLeft(sName, 2)=="SP")&&(GetObjectType(oObject)==OBJECT_TYPE_WAYPOINT)
){
            nCount++;
            SetLocalObject(oArea, "Spawner"+IntToString(nCount), oObject);

            SetLocalString(oObject, "sTag", GetTag(oObject));

            //---- SG flag ----
            nPos1 = FindSubString(sName, "SG");
            if((nPos1!=-1)&&(StringToInt(GetSubString(sName, nPos1+2, 1))==1))
                SetLocalInt(oObject, "bGroup", TRUE);

            //---- SRn flag ----
            nPos1 = FindSubString(sName, "SR");
            nPos2 = FindSubString(sName, "END");
            SetLocalInt(oObject, "r", StringToInt(GetSubString(sName, nPos1+2, nPos2-nPos1-3)));

            //---- SNn flag ----
            nPos1 = FindSubString(sName, "SN");
            nPos2 = FindSubString(sName, "SR");
            s = GetSubString(sName, nPos1+2, nPos2-nPos1-3);
            nPos1 = FindSubString(s, "-");
            if(nPos1==-1){
                SetLocalInt(oObject, "nMin", StringToInt(s));
                SetLocalInt(oObject, "nMax", 0);
            }else{
                SetLocalInt(oObject, "nMin", StringToInt(GetSubString(s, 0, nPos1)));
                SetLocalInt(oObject, "nMax", StringToInt(GetSubString(s, nPos1+1, GetStringLength(s)-nPos1-1)));
            }
        }
        oObject = GetNextObjectInArea(oArea);
    }
    SetLocalInt(oArea, "nSpawnersCount", nCount);
}

void ClearLocationFromCreatures(object oArea)
{
    string sName;
    object oWP;
    object oObject = GetFirstObjectInArea(oArea);
    while(oObject!=OBJECT_INVALID){
        sName = GetName(oObject);

        oWP = GetLocalObject(oObject, "parent");
        if(oWP!=OBJECT_INVALID)
            DestroyObject(oObject);

        if((GetStringLeft(sName, 2)=="SP")&&(GetObjectType(oObject)==OBJECT_TYPE_WAYPOINT)
){
            if(GetLocalInt(oObject, "nChildCount")>0){
                SetLocalInt(oObject, "nChildCount", 0);
                if(GetLocalInt(oObject, "bSpawnDisturbed")){
                    SetLocalInt(oObject, "nStartDelay", GetLocalInt(GetObjectByTag("vr_dmhelper"), "nCurrentTime"));
                }
            }
            //SendMessageToPC(GetFirstPC(), "b="+IntToString(GetLocalInt(oObject, "bSpawnDisturbed")));
        }

        oObject = GetNextObjectInArea(oArea);
    }
}
вставлял все ето я в On enter в опциях локи а вот второй area_exit :
// area_exit

void main()
{
    object oArea = GetArea(OBJECT_SELF);
    object oPC = GetExitingObject();
    if(GetIsDM(oPC)) return;
    if(GetIsPC(oPC)){
        int nCount = GetLocalInt(oArea, "nPlayerCount");
        nCount--;
        SetLocalInt(oArea, "nPlayerCount", nCount);

        if(nCount<=0){ // no PC in location
            SetLocalInt(oArea, "bNeedSpawn", FALSE);
            object oWP;
            int nSpawnersCount = GetLocalInt(oArea, "nSpawnersCount");
            int i;
            for(i=1; i<=nSpawnersCount; i++){
                oWP = GetLocalObject(oArea, "Spawner"+IntToString(i));
                if(GetLocalInt(oWP, "nChildCount")>0){ // if any spawner has children
                    SetLocalInt(oArea, "nLastPCExitTime", GetLocalInt(GetObjectByTag("vr_dmhelper"), "nCurrentTime"));
                    SetLocalInt(oArea, "bNeedClear", TRUE);
                    break;
                }
            }
        }
    }else if(GetIsObjectValid(GetLocalObject(oPC, "parent"))){
        //SendMessageToPC(GetFirstPC(), "name="+GetName(oPC));
        object oCreature = CreateObject(OBJECT_TYPE_CREATURE,
                        GetResRef(oPC),
                        GetLocalLocation(oPC, "lHomeLocation"));

        SetLocalLocation(oCreature, "lHomeLocation", GetLocalLocation(oPC, "lHomeLocation"));

        DeleteLocalInt(oPC, "TotalDamage");
        int i;
        for(i=1;i<=GetLocalInt(oPC, "TotalDamagers");i++){
            DeleteLocalObject(oPC, "Damager"+IntToString(i));
            DeleteLocalInt(oPC, "Damage"+IntToString(i));
        }
        DeleteLocalInt(oPC, "TotalDamagers");
        DeleteLocalInt(oPC, "nPreviousHP");
        DeleteLocalObject(oPC, "parent");
        DeleteLocalLocation(oPC, "lHomeLocation");

        DestroyObject(oPC);
    }
}
// SPAWN SYSTEM
// for NWN Shard "Validor 2"
// main script
/* Scripted by Vanes */

#include "vr_spawn_groups"
#include "vr_config"

void CheckWaypoints(object oArea);
void Spawn(object oWP);
void StoreSpawns(object oArea);
void ClearLocationFromCreatures(object oArea);


void main() // psevdo heartbeat
{
    object oArea = OBJECT_SELF;

    if(GetLocalInt(oArea, "bNeedSpawn")==TRUE){
        CheckWaypoints(oArea);
        //SendMessageToPC(GetFirstPC(), "attemting to spawn... "+ GetName(oArea));
        AssignCommand(oArea, DelayCommand(10.0, ExecuteScript("vr_spawn_general", oArea)));
        return;
    }
    if(GetLocalInt(oArea, "bNeedClear")==TRUE){
        //SendMessageToPC(GetFirstPC(), "attemting to clear... "+ GetName(oArea));
        //SendMessageToPC(GetFirstPC(), "nLastPCExitTime = " + IntToString(GetLocalInt(oArea, "nLastPCExitTime")));
        //SendMessageToPC(GetFirstPC(), "nCurrentTime = " + IntToString(GetLocalInt(GetObjectByTag("vr_dmhelper"), "nCurrentTime")));
        if((GetLocalInt(oArea, "nLastPCExitTime")+SPAWN_CLEAR_LOC_DELAY)<=GetLocalInt(GetObjectByTag("vr_dmhelper"), "nCurrentTime")){
            //SendMessageToPC(GetFirstPC(), "clearing... "+ GetName(oArea));
            ClearLocationFromCreatures(oArea);
            SetLocalInt(oArea, "bNeedClear", FALSE);
        }else{
            AssignCommand(oArea, DelayCommand(10.0, ExecuteScript("vr_spawn_general", oArea)));
        }
        return;
    }
}

void CheckWaypoints(object oArea) // check for WP status (waiting for delay end,
                                  // waiting for children death, need pawn now)
{
    if(GetLocalInt(oArea, "bSpawnsStored")==FALSE){
        StoreSpawns(oArea);
        SetLocalInt(oArea, "bSpawnsStored", TRUE);
    }
    object oWP;
    string sName;
    int nPos, nSpawnDelay, nStartDelay, nCurrentTime;
    int i;
    int nSpawnersCount = GetLocalInt(oArea, "nSpawnersCount");
    //SendMessageToPC(GetFirstPC(), "nSpawnersCount="+IntToString(nSpawnersCount));
    for(i=1; i<=nSpawnersCount; i++){
        oWP = GetLocalObject(oArea, "Spawner"+IntToString(i));
        sName = GetName(oWP);
        //SendMessageToPC(GetFirstPC(), "checking WP " + sName);
        if(GetLocalInt(oWP, "nSpawnDelay")==0){ // first check after module started
            nPos = FindSubString(sName, "SG");
            nSpawnDelay = StringToInt(GetSubString(sName, 5, nPos-6))*60;
            //int nTime = GetLocalInt(GetObjectByTag("vr_dmhelper"), "nCurrentTime");
            //if(nTime!=0){
            //SetLocalInt(oWP, "nStartDelay", 60);
            SetLocalInt(oWP, "nSpawnDelay", nSpawnDelay);
            //}
            Spawn(oWP);
        }
        if(GetLocalInt(oWP, "nChildCount")<=0){
            nStartDelay = GetLocalInt(oWP, "nStartDelay");
            //SendMessageToPC(GetFirstPC(), "nStartDelay=" + IntToString(nStartDelay));
            nCurrentTime = GetLocalInt(GetObjectByTag("vr_dmhelper"), "nCurrentTime");
            //SendMessageToPC(GetFirstPC(), "nCurrentTime=" + IntToString(nCurrentTime));
            nSpawnDelay = GetLocalInt(oWP, "nSpawnDelay");
            //SendMessageToPC(GetFirstPC(), "nSpawnDelay=" + IntToString(nSpawnDelay));
            if(nSpawnDelay<(nCurrentTime-nStartDelay)){
                //SendMessageToPC(GetFirstPC(), "delay end, spawning...");
                SetLocalInt(oWP, "bSpawnDisturbed", FALSE);
                Spawn(oWP);
            }else{
                //SendMessageToPC(GetFirstPC(), "waiting for delay end");
            }
        }
    }
}

void Spawn(object oWP)
{
    object oCreature;
    string sTag;
    int nPos1, nPos2;
    int n, n1, n2, i, r, r1;
    int bGroup = FALSE;
    location lLoc;

    sTag = GetLocalString(oWP, "sTag"); // for Lexey's Spawn Table

//---- SG flag ----
    bGroup = GetLocalInt(oWP, "bGroup");

//---- SRn flag ----
    r = GetLocalInt(oWP, "r");
    location lLocation = GetLocation(oWP);
    object oArea = GetAreaFromLocation(lLocation);
    vector vPosition;
    float fOrientation = GetFacingFromLocation(lLocation);

//---- SNn flag ----
    n1 = GetLocalInt(oWP, "nMin");
    n2 = GetLocalInt(oWP, "nMax");
    if(n2!=0){
        n = n1+Random(n2-n1)+1;
    }else{
        n = n1;
    }

    for(i=1; i<=n; i++){
        vPosition = GetPositionFromLocation(lLocation);
        r1 = Random(r+1);
        if(d2()==1) r1 *= -1;
        vPosition.x += r1;
        r1 = Random(r+1);
        if(d2()==1) r1 *= -1;
        vPosition.y += r1;

        lLoc = Location(oArea, vPosition, fOrientation);
        if(bGroup==TRUE) sTag = SpawnGroup(oWP);
        oCreature = CreateObject(OBJECT_TYPE_CREATURE, sTag, lLoc);
        if(oCreature!=OBJECT_INVALID){
            SetLocalInt(oWP, "nChildCount", GetLocalInt(oWP, "nChildCount")+1);
            SetLocalObject(oCreature, "parent", oWP);
            SetLocalLocation(oCreature, "lHomeLocation", lLoc);
        }else{
            i--;
        }
    }
}

void StoreSpawns(object oArea)
{
    object oObject = GetFirstObjectInArea(oArea);
    string sName, s;
    string sTag;
    int nPos1, nPos2;
    int nCount=0;
    while(oObject!=OBJECT_INVALID){
        sName = GetName(oObject);
        if((GetStringLeft(sName, 2)=="SP")&&(GetObjectType(oObject)==OBJECT_TYPE_WAYPOINT)
){
            nCount++;
            SetLocalObject(oArea, "Spawner"+IntToString(nCount), oObject);

            SetLocalString(oObject, "sTag", GetTag(oObject));

            //---- SG flag ----
            nPos1 = FindSubString(sName, "SG");
            if((nPos1!=-1)&&(StringToInt(GetSubString(sName, nPos1+2, 1))==1))
                SetLocalInt(oObject, "bGroup", TRUE);

            //---- SRn flag ----
            nPos1 = FindSubString(sName, "SR");
            nPos2 = FindSubString(sName, "END");
            SetLocalInt(oObject, "r", StringToInt(GetSubString(sName, nPos1+2, nPos2-nPos1-3)));

            //---- SNn flag ----
            nPos1 = FindSubString(sName, "SN");
            nPos2 = FindSubString(sName, "SR");
            s = GetSubString(sName, nPos1+2, nPos2-nPos1-3);
            nPos1 = FindSubString(s, "-");
            if(nPos1==-1){
                SetLocalInt(oObject, "nMin", StringToInt(s));
                SetLocalInt(oObject, "nMax", 0);
            }else{
                SetLocalInt(oObject, "nMin", StringToInt(GetSubString(s, 0, nPos1)));
                SetLocalInt(oObject, "nMax", StringToInt(GetSubString(s, nPos1+1, GetStringLength(s)-nPos1-1)));
            }
        }
        oObject = GetNextObjectInArea(oArea);
    }
    SetLocalInt(oArea, "nSpawnersCount", nCount);
}

void ClearLocationFromCreatures(object oArea)
{
    string sName;
    object oWP;
    object oObject = GetFirstObjectInArea(oArea);
    while(oObject!=OBJECT_INVALID){
        sName = GetName(oObject);

        oWP = GetLocalObject(oObject, "parent");
        if(oWP!=OBJECT_INVALID)
            DestroyObject(oObject);

        if((GetStringLeft(sName, 2)=="SP")&&(GetObjectType(oObject)==OBJECT_TYPE_WAYPOINT)
){
            if(GetLocalInt(oObject, "nChildCount")>0){
                SetLocalInt(oObject, "nChildCount", 0);
                if(GetLocalInt(oObject, "bSpawnDisturbed")){
                    SetLocalInt(oObject, "nStartDelay", GetLocalInt(GetObjectByTag("vr_dmhelper"), "nCurrentTime"));
                }
            }
            //SendMessageToPC(GetFirstPC(), "b="+IntToString(GetLocalInt(oObject, "bSpawnDisturbed")));
        }

        oObject = GetNextObjectInArea(oArea);
    }
}

соответствеенно в опции локи в On exit

и что не так?
а с мобами вот что сделал поставил на локу волка стегом c_dogwolfdire и задал для него точку с именемSP_SG0_SD5_SN1_SR5_END и тегом c_dogwolfdire
И что не так????7 ждал около 10 минут респа и недождался(

Помираю хочу научится респу,уже всю ету неделю пробую делать и никак блин(

Автор: diggers May 4 2007, 20:41

Цитата
Помираю хочу научится респу,уже всю ету неделю пробую делать и никак блин(

Напиши свой. Создай пустой модуль, назови его гордо - RespBySugoMod

Соспавни монстра в точке, на пустой локации. Как - см скрипты Vanesа.

Соспавнишь, тогда(И только тогда. На этом этапе уже другие сложности, и с самим спавном у тебя затруднений уже быть не должно. Иначе потонешь в проблемах и забьешь на это дело), соспавнишь несколько монстров, по хитрой системе. Что бы спавнились разные мобы, разное количество и можно было всем этим управлять. Что бы спавнились, нападали, что бы все было нормально в маштабе 1 спавна. Как - посмотришь там же.

Потом подумаешь как переделать систему так, что бы удобно было такие спавны расставлять в больших количествах и управлять ими. На этом этапе, я уверен, у тебя уже закипят свои собственные идеи как что сделать, и будешь спрашивать только об отдельных конкретных технических решениях.

А таким шаманством, тыкая то, незнаю что, незнаю куда, можно и за полгода ничего не сделать.

Автор: r1Stranger May 11 2007, 18:34

Такая штука. Перенес скрипты из 1й версии во вторую.
То что визуальные эффекты почти половина отсутствует или не работает это ладно.
Но как сделать, чтоб неписи ходили по непрерывно по точкам? Была хорошая каманда WalkEayPoints() а тут нету.
Надо снова самому велосипед изобретать?

Автор: Griffon May 11 2007, 20:00

Нет, не надо. Если тебе нужно чтобы нпс строго ходил от 01 до 0..., то выбираешь нпс -> пкм создать wp -> размещаешь wps -> выбираешь все wp через shift лкм и -> пкм create waypoint set

Автор: r1Stranger May 15 2007, 18:01

Спасибо.
Так и сделал. Но оно требует ввести имя группы точек. Дал имя - все равно не ходят по всем.Может надо было вписывать в имя тэг существа?

Автор: Griffon May 16 2007, 09:11

Цитата(r1Stranger @ May 15 2007, 19:01) [snapback]108263[/snapback]
Может надо было вписывать в имя тэг существа?


Именно.

Автор: shadowdweller Jun 26 2007, 12:54

Вот два скрипта, которые делают любого НПС полностью неподвижным (на случай, если нужна статуя, игрушка и т.д.)
Первый ставится на слот OnConversation:

Neverwinter Script Source
// empty to avoid default behaviour

void RemoveEffects(object oObject)
{
    effect eEffect = GetFirstEffect(oObject);
    while(GetIsEffectValid(eEffect))
    {
        RemoveEffect(oObject, eEffect);
        eEffect = GetNextEffect(oObject);
    }
}

void main()
{
    PlaySound("as_cv_winch1");
    /*SetPlotFlag(OBJECT_SELF, FALSE);
    RemoveEffects(OBJECT_SELF);
    ActionPlayAnimation(ANIMATION_LOOPING_PAUSE_DRUNK, 0.5);
    effect eHold = EffectVisualEffect(VFX_DUR_FREEZE_ANIMATION);
    ActionDoCommand(ApplyEffectToObject(DURATION_TYPE_PERMANENT, eHold, OBJECT_SELF));
    ActionDoCommand(SetPlotFlag(OBJECT_SELF, TRUE));*/

}

Второй - на слот OnSpawn:
Neverwinter Script Source
void main()
{
    effect eHold = EffectVisualEffect(VFX_DUR_FREEZE_ANIMATION);
    ApplyEffectToObject(DURATION_TYPE_PERMANENT, eHold, OBJECT_SELF);
    SetLocalInt(OBJECT_SELF, "X1_L_IMMUNE_TO_DISPEL", 10);
}

Оба взяты из SoU, но прекрасно работают и в НВН2.
Наслаждайтесь! rolleyes.gif

ВАЖНО: Чтобы НПС оставался действительно неподвижным, не забудьте убить все остальные скрипты. Должны остаться только эти два. smile.gif

Автор: Griffon Jun 28 2007, 12:02

Скриптование вэйпойнтов:

Neverwinter Script Source
#include "ginc_wp"

void main()
{
    int iCurrentWP = GetCurrentWaypoint();
    int iNextWP;
    switch (iCurrentWP)
    {
        case 1:
            iNextWP = Random(GetNumWaypoints()-1) + 2;
            SetNextWaypoint(iNextWP);
            ActionPlayAnimation(ANIMATION_LOOPING_SIT_CROSS, 1.0, 7.0);
            break;
        case 2:
            SetNextWaypoint(1);
            ActionPlayAnimation(ANIMATION_LOOPING_GET_LOW, 1.0, 4.0);
            break;
        case 3:
            SetNextWaypoint(1);
            break;
    }
}


Neverwinter Script Source
#include "ginc_wp"
     
const int REDIRECTOR_WP = 1;

void main()
{
    int iCurrentWP = GetCurrentWaypoint();// where we are
    int iNextWP;
    switch (iCurrentWP)
    {
        case 1:
// Node 1 should be placed off somewhere out of the way.  This is where the creatures
// will hang out in between reaching the end of the path and starting on a new path.
// Creatures will change their appearance in between travels.

// 1st param is the list of nodes they may reappear at. Must follow the pattern XX,YY,ZZ...
// 2nd param is the length of time to wait before reappearing.
                  StandardRedirectorNode("02,03", 5.0f);
            break;
        case 2:
// Nodes 2 on up define the network the road walkers travel.  They will never return to the node
// they just came from.  When they reach an end node (typically a door or a route out of the area)
// they will be be "redirector node" - typically node 1.

// 1st param is the list of nodes they may travel to. Must follow the pattern XX,YY,ZZ...
//                (end nodes are those with only 1 element in the list)
// 2nd param is the redirector WP
                  StandardRoadNetworkNode("03", REDIRECTOR_WP);
            break;

        case 3:
                  StandardRoadNetworkNode("02", REDIRECTOR_WP);
            break;
    }
}



http://www.nwn2wiki.org/Scripted_waypoints



Автор: Валеско Jul 14 2007, 22:48

В одной из локаций модуля присутствует жаровня. Жаровня - это такая фиговина при нажимании на которую оружие игрока воспламеняется.\
Для действия жаровни был написан скрипт:

Neverwinter Script Source
void main()
{
ActionCastSpellAtObject(SPELL_FLAME_WEAPON,GetLast
sedBy());
}


Однако в работающем скрипте есть недостаток. Воспламенение оружия не прекращается ни через минуту, ни через 2 часа. Что делать?
Воспламенение должно длиться 30-40 секунд.

Автор: Lex Jul 14 2007, 23:05

делать не через магию, а через добавление временного эффекта на предмет.
Что-то типа:

Neverwinter Script Source
void main()
{
object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,GetLastUsedBy());
if (!GetIsObjectValid(oWeapon)) return;
AddItemProperty(DURATION_TYPE_TEMPORARY,ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_FIRE,IP_CONST_DAMAGEBONUS_1d6),oWeapon,40.0);
}

насчет работы под НВН2 не знаю, не могу проверить. Но по идее проблем быть не должно.

Автор: Валеско Jul 15 2007, 09:59

ERROR: UNDEFINED IDENTIFIER

Автор: Dik Morris Jul 15 2007, 13:44

2 Валеско, я подправил:

Neverwinter Script Source
void main()
{
object oWeapon = GetItemInSlot
(INVENTORY_SLOT_RIGHTHAND,
GetLastUsedBy());

if (!GetIsObjectValid(oWeapon)) return;
AddItemProperty(DURATION_TYPE_TEMPORARY,
ItemPropertyDamageBonus
(IP_CONST_DAMAGETYPE_FIRE,IP_CONST_DAMAGEBONUS_1d6)
,oWeapon,40.0);
}


PS: дело было в том, что при абзатце, функции "делились", на несколько частей, соответственно скрипт и не составлялся.

Автор: Drow Jul 18 2007, 20:18

Как лучше всего скриптом сделать непися невидимым. В смысле не эффект невидимости, а чтобы непися не было видно в тру сии.

Автор: Dik Morris Jul 18 2007, 21:15

2 Drow, эх, жаль NWN-2 на компьютере нет (и не горю желанием ее устанавливать) но думаю, EffectVisualEffect и константа VFX_DUR_CUTSCENE_INVISIBILITY, все-таки остались. Так что попробуй использовать их.

Никакие "штатные" средства (ака трусинг или си-инвиз) этот эффект не берут.

Автор: Tomb Jul 23 2007, 23:01

Ребят а кто нить может помочь со скриптом на сундуки для шарда...
Сундук привязан на акк

Автор: gennady Jul 24 2007, 06:05

Tomb, если ты о генерации лута, то можно почитать статью http://remmgen.narod.ru/M_Item.html. Правда там пробиты шмотки для 1 Невера...

Автор: Griffon Jul 24 2007, 08:00

http://nwvault.ign.com/View.php?view=NWN2Scripts.Detail&id=133 - подходит как для модуля, так и для шарда. Правда, он написан на выпадение лута с монстров.

Автор: Tomb Jul 24 2007, 11:46

Неа я про сундуки чтобы хранить свой шмот....

Автор: Lorendroll Jul 24 2007, 12:35

Ну так ты расскажи как именно хочешь чтобы работала твоя система. Если сундук на каждого игрока свой, привязывай SetLocalObject на нужного oPC, а чтобы после рестарта восстанавливать лежащие в сундуке вещи нужно на попадание в сундук вещи запоминать вещь по тегу (StrRef'у? не знаю точно), привязывая SetLocalString на игрока. Но здесь без БД трудно будет, не знаю, есть уже НВНх для НВН2 или нет...
Да или вот пришло в голову интересное решение - завести отдельный модуль-"хранилище". Который просто SaveGame'ить время от времени. Есть ведь возможность переместить игрока в другой модуль скриптом онлайн? Я честно говоря с этим еще не экспериментировал, но должно работать...

Автор: Tomb Jul 24 2007, 13:01

Насколько я помню Ванес писал скрипт с внешней БД
Она работал так
Сундук привязывается к акку шмот по тегу сохраняется во внешней БД
Положил шмот нажал на рычаг и счастье

Автор: FreemanD Aug 10 2007, 11:33

Люди, помогите чайнику... Я тут где-то напоролся на тему где было упоминание про то как посадить перса на стул, к примеру. Но там было сказано, что скрипты x2_am_sit и еще какой-то, x2_plc_sit кажется, короче они кривые, и их надо дорабатывать. Не могли бы вы мне на пальцах объяснить, что именно с ними надо сделать? и желательно с подробными коменнтариями. А то блин, сделал две табуреточки и пенек, повесил скрипт, помучался, а перс, собака такая, не садится! Стоит около него, на панельке действий висит действие "сесть", и все!!! vava.gif

*Ушел в кому*

И такой вопрос: а есть скрипт на действие "Лечь"? Чтобы и на пол, и на кровать, допустим... Я просто сейчас делаю маленький тренировочный модуль, в котором будет все включено, но при этом хочу сделать его максимально качественно и реалистично. Стиль, обстановка, нпсы уже готовы, остались эффекты, диалоги, и вот самая больная тема - скрипты... Хелп... sad.gif

Автор: Aiwan Aug 11 2007, 00:04

Сложно что то говорить если человек не понимает. Тебе надо попробовать с азов самому... Скриптинг нужен всем, если ты не рисуешь локации и больше ничего.

Лечь... Ты видел лежащего НПС в игре?

Автор: NWNmaster Aug 12 2007, 15:13

BAN ME

Автор: Vhall Aug 12 2007, 15:33

Конечно можно.
Только если анимация колеса будет предварительно прописана в максе и подготовлена для обращения через скрипт. biggrin.gif

Автор: Griffon Aug 13 2007, 08:54

Цитата(FreemanD @ Aug 10 2007, 12:33) *
вопрос: а есть скрипт на действие "Лечь

Зачем тебе скрипт если есть анимация смерти и НПС падает на пол.

Автор: FreemanD Aug 13 2007, 11:41

Если бы я знал с чего начинать, то начал бы. А так, никакого руководства под руками нет, чтобы азы какие-нибудь получить... Блин... Нырять то в бездну, не зная что там ох как не хочется...

Автор: NWNmaster Aug 13 2007, 13:10

BAN ME

Автор: FreemanD Aug 16 2007, 10:14

Цитата
Лечь... Ты видел лежащего НПС в игре?


Я специально еще раз прошел игру, чтобы убедиться, что глаза меня не обманули, и понял, что лежащий нпс в игре есть. Обычно это спящие орки и багберы, в пещерах. Скрин сделать не успел, потому что они вскакивают, и хотят меня побить. vava.gif

В редакторе визуальных эффектов обнаружил действие лечь. (LAYDOWN, кажется.) Нпс там берет и реально ложится, правда только на пол, но все равно прогресс. А вот скрипт не нашел. Его реально сделать?

Цитата
Зачем тебе скрипт если есть анимация смерти и НПС падает на пол.


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

Цитата
Если бы я знал с чего начинать, то начал бы. А так, никакого руководства под руками нет, чтобы азы какие-нибудь получить... Блин... Нырять то в бездну, не зная что там ох как не хочется...


Беру свои слова обратно, прочитал вики. prankster2.gif Нырнул в бездну.

Мне кто-нить объяснит, что со скиптом "сесть" делать? shout.gif

Автор: Валеско Aug 23 2007, 20:05

Возможно, тут помогут разобраться. Есть скрипт:

Neverwinter Script Source
#include "mf_hench"
#include "c_animations"

void C_GoDown(object oTarget)
{
      float fTiming;
      fTiming = C_CustomAnimationLength(oTarget, "laydownb");
      PlayCustomAnimation(oTarget, "laydownb", 0, 1.0);
    DelayCommand(fTiming, C_PlayCustomAnimation(oTarget, "proneb", 1, 1.0));
}

void main()
{
object oPoint = GetObjectByTag("WP_RIV_AWAY");
object oBoy = GetObjectByTag("RIV_NPC_YOR");
object oBoy2 = GetObjectByTag("RIV_NPC_DAN");
object oMrin = GetHenchmanByTag("DRW_HEN_MRE01");
effect eEffect = EffectSleep();
if (GetHenchValid("DRW_HEN_MRE01"))
    {
    DestroyObject(GetObjectByTag("T_MISC_TAVERN"));
    int i = 0;
    object oObject = GetObjectByTag("T_ALCO_SLEEP",i);
    while (GetIsObjectValid(oObject))
        {
        DestroyObject(oObject);
        i++;
        oObject = GetObjectByTag("T_ALCO_SLEEP",i);
        }
    }
else
    {
    int i = 0;
    object oObject = GetObjectByTag("RIV_NPC_ALR",i);
    while (GetIsObjectValid(oObject))
        {
        AssignCommand(oObject, ActionDoCommand(ApplyEffectToObject(EFFECT_TYPE_SL
EP, eEffect, oObject,99999.0)));
        C_GoDown(oObject);
        i++;
        oObject = GetObjectByTag("RIV_NPC_ALR",i);
        }
    }
DelayCommand(6.0,SetCutsceneMode(GetFirstPC(),FALS
));
AssignCommand(oBoy2, ClearAllActions());
AssignCommand(oBoy, ClearAllActions());
DelayCommand(0.1,AssignCommand(oBoy2, ActionForceMoveToObject(oPoint)));
DelayCommand(0.1,AssignCommand(oBoy,  ActionForceMoveToObject(oPoint)));
DelayCommand(20.0, DestroyObject(oBoy));
DelayCommand(20.0, DestroyObject(oBoy2));
}


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

Автор: gennady Aug 24 2007, 06:05

Цитата
Возможно, тут помогут разобраться. Есть скрипт:


Уходя – уходи!

Цитата
Я не жалею что потратил столько времени на такое бесперспективное и неблагодарное дело как модульмейкинг на НВН2, но жалею, что потратил его в русском комьюнити.

Оскорбив все русское комьюнити, вылив кучу грязи на модмейкеров и скриптеров - просить о помощи???… Вытри слюни и сопли, и будь мужчиной!
P.S. Западло такому человеку помогать… За 3 года мог бы хоть кодами NSS научиться пользоваться…

Автор: Валеско Aug 24 2007, 06:34

Не волнуйся, милая, буржуям я такой вопрос тоже задал.

Автор: Aiwan Aug 24 2007, 06:58

Поиск сделай через локацию и на ней ищи нужных неписей.

Neverwinter Script Source
object oSelf = OBJECT_SELF; // тут укажи любой объект в нужной локе. Тег уникальный.
    object oObject = GetFirstObjectInArea(GetArea(oSelf));
    while (GetIsObjectValid(oObject))
    {
      if(GetObjectType(oObject)==OBJECT_TYPE_CREATURE)
      {
        if (GetTag(oObject)== "RIV_NPC_ALR")
        {
            AssignCommand(oObject, ClearAllActions(TRUE));
            AssignCommand(oObject, ActionDoCommand(ApplyEffectToObject(EFFECT_TYPE_SL
P, eEffect, oObject,99999.0)));
            C_GoDown(oObject);
        }
      }
        oObject = GetNextObjectInArea(GetArea(oSelf));
    }

Автор: Валеско Sep 4 2007, 10:12

Задумался над таким моментом: как в скриптах менять параметр static у предметов? Допустим есть тайная дверь, которую игрок никак не должен увидеть до момента, когда ей нужно открыться. То есть логично сделать ее до этого static, а после наступления условия - этот static снять... каким образом это сделать?

Автор: Lex Sep 4 2007, 12:23

никак.

Автор: Белатрис Sep 4 2007, 13:19

Я, конечно, скрипты не так хорошо знаю, но на С++ можно изменить, например Visible( виден объект, или нет).
Выглядет все так:
Имя_объекта(в НВН тег или ResRef) -> Visible = true;
Так может, в НВН так:
Тег\ResRef -> static = true/false; ? prankster2.gif

Автор: virusman Sep 4 2007, 13:44

Цитата(Белатрис @ Sep 4 2007, 14:19) *
Я, конечно, скрипты не так хорошо знаю, но на С++ можно изменить, например Visible( виден объект, или нет).
Выглядет все так:
Имя_объекта(в НВН тег или ResRef) -> Visible = true;
Так может, в НВН так:
Тег\ResRef -> static = true/false; ? prankster2.gif
NWScript - не C++. Если уж на то пошло, то больше похоже на C.

Автор: Валеско Sep 4 2007, 13:57

идиотия. Неужто все тайные двери в официальной кампании НВН2 - просто запертые участки стены? о.О

Автор: Dik Morris Sep 4 2007, 14:43

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

Если запертая дверь, будет иметь галочку "Статик", то дверь будет отображаться. Если не будет "статики", объект опять будет видим, тут тоже логики не уловил.

Если не ошибаюсь, в официальной компании НВН1 тайные двери были соответствующим плейсом, со скриптом на onXB, укрытые эффектом прозрачности (невидимки). Скрипт проверял: есть ли игрок в пределах XX метров, если есть, идет проверка его навыка "Spot" - и только в том случае, если игрок обойдет заданное ДЦ, эффект прозрачности удаляется с двери, а сама она открывается. Готовый скрипт, стало быть, нужно искать в компаниях первой или второй части игры (или писать самому).

Автор: azathoth Sep 4 2007, 15:57

Что до статиков, то до них скриптами не добраться. Они вообще хранятся отдельно и загружаются только один раз.

P.S. Эх, а хорошо ведь было бы так: ScriptName "00door" Begin GameMode foreach (object in module as nwn2::placeable) WHERE *$1 IS DOOR with (.pop) { if (Detected(%PC%)) Static = true; } the end.
P.P.S. Надо создать топик: не знаю как тут, но в нвн1 можно сделать так...

Автор: Валеско Sep 4 2007, 16:17

Цитата
Если запертая дверь, будет иметь галочку "Статик", то дверь будет отображаться. Если не будет "статики", объект опять будет видим, тут тоже логики не уловил.
Логика в том, что если объект static -то мы не можем выбрать его курсором и совершить с ним какие-то действия.
Цитата
Что до статиков, то до них скриптами не добраться. Они вообще хранятся отдельно и загружаются только один раз.
Типичная ёпсидиановская идиотия. Я уж решил поступить изящно и двери просто удалить, вместо того чтобы их открывать, но выяснилось что статичные двери даже не удаляются. Придется опускаться до кретинизма вроде "неоткрываемых секретных дверей, про существование которых персонаж догадываться не должен" или дедовским способом перегораживать проходы шкафами, ящиками и камнями.

Автор: Vhall Sep 4 2007, 19:44

У Door State есть вариант "No visible model" (он же Destroyed), которым можно воспользоваться при ситуации:

QUOTE(Валеско @ Sep 4 2007, 11:12) *
Допустим есть тайная дверь, которую игрок никак не должен увидеть до момента, когда ей нужно открыться.

Вопрос в том, можно ли его менять через скрипты.

Автор: Lex Sep 5 2007, 08:22

Цитата(Валеско @ Sep 4 2007, 17:17) *
Логика в том, что если объект static -то мы не можем выбрать его курсором и совершить с ним какие-то действия.
этого же эффекта можно добиться и просто не поставив галочку Статик и Активный. smile.gif
Цитата(Vhall @ Sep 4 2007, 20:44) *
У Door State есть вариант "No visible model" (он же Destroyed), которым можно воспользоваться при ситуации
раньше 100 пудов можно было такое проделывать с плейсами. В нвн2 и с дверьми - я не пробовал.

Автор: Vanes Sep 5 2007, 10:53

Цитата
Если не ошибаюсь, в официальной компании НВН1 тайные двери были соответствующим плейсом, со скриптом на onXB, укрытые эффектом прозрачности (невидимки). Скрипт проверял: есть ли игрок в пределах XX метров, если есть, идет проверка его навыка "Spot" - и только в том случае, если игрок обойдет заданное ДЦ, эффект прозрачности удаляется с двери, а сама она открывается. Готовый скрипт, стало быть, нужно искать в компаниях первой или второй части игры (или писать самому).

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

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

Автор: Griffon Sep 5 2007, 14:38

Цитата(Валеско @ Sep 4 2007, 11:12) *
Задумался над таким моментом: как в скриптах менять параметр static у предметов? Допустим есть тайная дверь, которую игрок никак не должен увидеть до момента, когда ей нужно открыться. То есть логично сделать ее до этого static, а после наступления условия - этот static снять... каким образом это сделать?


В кампании это, вроде сделано предметами - сама секретная дверь и шкаф, который ее закрывает. Так вот этот шкаф имел static - false, collision - true. И поскольку эти двери становились видны только после надевания очков, то почему не сделалать так же?

Автор: audun Dec 7 2007, 20:37

Здравствуйте уважаемые мастера.
Вот наткнулся в скриптах на отладочную функцию:

Neverwinter Script Source

      PrettyDebug( sOut );
      PrettyDebug( "Total influence with " + GetStringByStrRef( GetCompanionNameStringRef( nCompanion )) + " = " + IntToString( nNewInfluence ));


ИМХО понятно, что срабатывает она при включении отладки и выводит текст.

Вопрос:
1.где и как включается этот отладочный режим.
2. куда выводиться отладочная информация(окно сообщений,экран, что нить особое...).

P.S. Сорри, если вопрос нубский или написал не в том топике, прошу не бить больно smile.gif
P.P.S.(поиск юзал sad.gif )

Автор: Aiwan Dec 7 2007, 22:39

Обычно функция описывается. надо навести на нее курсор и в инфопанели внизу будет описание. Но честно, говоря лучше сделать простую дебаг инклюду и пользоваться. Вы собсвенно что хотите увидеть в дебаге? Дебаг НВН-а это место куда идут все сообщения во время игры. Внизу окно такое растягивается.

Автор: audun Dec 8 2007, 17:27

Цитата(Aiwan @ Dec 7 2007, 22:39) *
Обычно функция описывается. надо навести на нее курсор и в инфопанели внизу будет описание.


Как ни печально, но описания этих отладочных функций(PrettyDebug,PrettyError) в инфопанели я не нашел.

Цитата
Но честно, говоря лучше сделать простую дебаг инклюду и пользоваться.


Подключать к рабочему скрипту свой отладочный? Зачем писать свой, если есть уже написанные?

Цитата
Вы собсвенно что хотите увидеть в дебаге?


Давайте попробуем по порядку:

Возьмем глобальный скрипт :
Neverwinter Script Source

// ga_influence( int nCompanion, int nChange )
/* This adjusts the influence rating of the companion to the PC ( the players as a whole technically ).
  The influence rating is based on a scale between -100( worst ) and 100( best ). ( 0 being neutral )

  Parameters:
    int nCompanion  = This is the integer value of the companion to adjust. ( See ginc_companions )
    int nChange    = This is the amount to adjust influence by.

    1    Khelgar
    2    Neeshka
    3    Elanee
    4    Qara
    5    Sand
    6    Grobnar
    7    Casavir
    8    Bishop
    9    ShandraJerro
    10    Construct
    11    Zhjaeve
    12    AmmonJerro
    13  Bevil
*/
// FAB 10/4
// ChazM 5/4/05
// BMA 5/5/05 ginc_companions id look up
// BMA-OEI 8/22/05 added companion id table
// ChazM 12/16/05 added bevil
// ChazM 4/18/06 prepped for adding influence indicator
// ChazM 4/25/06 added string ref constants
// ChazM 5/1/06 fixed "temp text" bug.
// EPF 7/10/06 - added debug strings for balance testing
// BMA-OEI 7/10/06 -- Updated to use GetInfluenceByNumber( )
       
#include "kinc_companion"

const int    STRING_REF_LOST_INFLUENCE     = 178842;
const int    STRING_REF_GAINED_INFLUENCE = 178841;

int GetCompanionNameStringRef( int nCompanion )
{
    // companions str refs are 178843 - 178855
    return ( 178842 + nCompanion );
}

void main( int nCompanion, int nChange )
{
    if ( nChange == 0 )
    {
        PrettyError( "ga_influence: companion " + IntToString( nCompanion ) + " no influence change" );
        return;
    }
   
    int nOldInfluence = GetInfluenceByNumber( nCompanion );
    IncInfluenceByNumber( nCompanion, nChange );
    int nNewInfluence = GetInfluenceByNumber( nCompanion );
   
    string sOut;
    int nDelta = nNewInfluence - nOldInfluence; //nChange; // Actual nDelta may not == nChange
    if ( nDelta > 0 )
        sOut = GetStringByStrRef( STRING_REF_GAINED_INFLUENCE );
    else
        sOut = GetStringByStrRef( STRING_REF_LOST_INFLUENCE );

    sOut += " " + GetStringByStrRef( GetCompanionNameStringRef( nCompanion )) + ": " + IntToString( nDelta );
   
    object oPC = ( GetPCSpeaker( )==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker( ) );
    SendMessageToPC( oPC, sOut );
    PrettyDebug( sOut );
    PrettyDebug( "Total influence with " + GetStringByStrRef( GetCompanionNameStringRef( nCompanion )) + " = " + IntToString( nNewInfluence ));
}


31 строка:
Цитата
// EPF 7/10/06 - added debug strings for balance testing

и далее в теле идут отладочные функции PrettyError и PrettyDebug
Раз авторы их добавлялм ,они ими пользовались.
Значит режим отладки где то должен включаться. Во встроенных функциях этих нет.
Вопросы:
могут эти функции быть только в тулсете, а не в игре?
Возможно ли их как то задействовать в самой игре?
Как вариант , могут ли они после завершения создания модуля удалены из тулсета/игры?
Существует ли в тулсете система отладки скриптов, (которая мне не известна,но может быть известна вам)?


Цитата
Дебаг НВН-а это место куда идут все сообщения во время игры.
Внизу окно такое растягивается.


Мы говорим об окне сообщений, или о чем то другом?

В режиме DebugMode 0 все сообщения в игре отправляются в окно сообщений, в частности строка :
Цитата
SendMessageToPC( oPC, sOut );

А при включенном режиме DebugMode 1 некоторые команды ,например showfps выводятся просто на экран. Значит стандартный вывод
можно менять?
А вэтих строках получается , что выводится 3 сообщения:
Цитата
SendMessageToPC( oPC, sOut ); // вывод в окно сообщений
PrettyDebug( sOut ); // повторение той же строки не понятно куда
PrettyDebug("Total influence with " + GetStringByStrRef(GetCompanionNameStringRef(nCompa
ion)) + " = " + IntToString(nNewInfluence));
// и вывод третьей строки с отладочной информацией


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

Автор: Zmeika Dec 24 2007, 15:27

Здравствуйте уважаемые мастера!
Вот, скопилась целая порция вопросов.

1. Относительно точек приложения скриптов. Пока вижу, что их можно вешать на эвенты (события) из выпадающих списков в пропертях для модуля, для локации, для NPC кажется... И для каждого случая этот набор событий похоже фиксирован. Можно ли его расширить? Можно ли сделать обработку событий с клавиатуры, например? И как можно использовать событие UserDefinеdEvent?

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

3. В готовом игровом модуле nv2 - туториал (это нулевой акт) обнаружила заюзанный скрипт на onRest. Скрипт не принадлежал этому модулю, а был взят из длинного выпадающего списка готовых скриптов. Без проблем загрузила энтот чужой скрипт в редактор, изменила, скомпилила - после чего запущенный модуль вполне себе воспринял эти изменения. И догадываюсь, что если перекомпилить остальные модули, которые его используют, то с ними будет тож самое....
Вопрос - а где все эти готовые скрипты живут на уровне исходных текстов? По другим модулям разложены что ли? Или есть где-то для них общее место?


Автор: Lex Dec 24 2007, 18:06

Цитата(Zmeika @ Dec 24 2007, 15:27) *
1. Относительно точек приложения скриптов. Пока вижу, что их можно вешать на эвенты (события) из выпадающих списков в пропертях для модуля, локации, для NPC кажется... И для каждого случая этот набор событий похоже фиксирован. Можно ли его расширить? Можно ли сделать обработку событий с клавиатуры, например? И как можно использовать событие UserDefinеdEvent?

можно расширить (см систему SSS AC на нашем сайте, как вариант). Другое дело что насколько оно вам необходимо?
С клавиатурой.. так как вы описали - нельзя. Но можно сделать обработку написанного в чат текста. Разбиралось много раз для НВН1, возможно годится для НВН2. Надо экспериментировать.

Цитата(Zmeika @ Dec 24 2007, 15:27) *
2. Пожалуйста, посоветуйте, каким образом лучше и проще делать информационную печать в скрипте? Например, чтобы без перехода в отладочный режим можно было видеть - вызвался ли скрипт и с какими данными вызвался. Другими словами есть ли тут аналог функции printf?

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

Цитата(Zmeika @ Dec 24 2007, 15:27) *
. В готовом игровом модуле nv2 - туториал (это нулевой акт) обнаружила заюзанный скрипт на onRest. Скрипт не принадлежал этому модулю, а был взят из длинного выпадающего списка готовых скриптов. Без проблем загрузила энтот чужой скрипт в редактор, изменила, скомпилила - после чего запущенный модуль вполне себе воспринял эти изменения. И догадываюсь, что если перекомпилить остальные модули, которые его используют, то с ними будет тож самое....

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

Автор: Zmeika Dec 25 2007, 11:39

Цитата(Lex @ Dec 24 2007, 18:06) *
можно расширить (см систему SSS AC на нашем сайте, как вариант). Другое дело что насколько оно вам необходимо?

Пока не знаю. Мне нужно засечь момент, когда солнышко заходит, причем точное время заката (в часах) известно. Такое ощущение, что только на onHeartBeat проверку по времени суток вешать. Пока не уверена, что это оправдано. sad.gif Правда, с другой стороны оч может быть, что сама игра определяет ход небес по этому же самому таймеру

Цитата(Lex @ Dec 24 2007, 18:06) *
я пользуюсь SendMessageToPC - она выдает текст в игровой лог. Мне удобнее в режиме онлайн отслеживать происходящее, чем потом читать текстовой файл с логами. Хотя факт - в таком файле больше полезной инфы относительно некорректной работы скриптов..

ага, мне тоже так удобно, уже подключила, спасип

Цитата(Lex @ Dec 24 2007, 18:06) *
дело в том, что все стандартные скрипты живут в ресурсах игры. Если скрипт меняется - он перекачовывает в модуль. Соотв изменив стандартный скрипт, вы изменили его лишь для данного модуля. Все остальные модули будут работать как работали, сколько бы вы их не перекомпиливали.

Странно, у меня не перекочевывается. Остается на прежнем месте в исправленном состоянии, и все другие модули начинают видеть исправленную версию. Правда, перкомпиляцию не пробовала...

Автор: azathoth Dec 25 2007, 13:15

так и хочется сказать "не знаю как там у вас в нвн2, а в нвн1 было так..." smile.gif

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

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

Автор: Kirald Jan 2 2008, 21:17

Блин хочу написать скрипт для простейшего квеста и не могу sad.gif scratch_one-s_head.gif ктонибудь помогите. хочу поставить локальную переменную ИНТ под названием "deathwolf"

Код
void main()
  {
  SetLocalInt(OBJECT_SELF, "deathWolf", 0);
  }


уверен что делаю что то не так после постановки в нужный слот (Респаун) НПС ставлю скрипт волку

Код
void main()
  {
  SetLocalInt(OBJECT_SELF, "deathWolf", 2);
  }


создаю диалог
Код
Переменная не работает----------------------\
                                             убей волка (deathwolf = 0)-----------------\
                                                                                         молодец (deathwolf = 2)

Плиз ПОМАГИТЕ help.gif help.gif help.gif А то я уже с ума схожу crazy.gif prankster2.gif

Автор: Lex Jan 2 2008, 21:26

проблема у тебя в том, что ты ставишь 2 локалки, а не 1, как ты думаешь.
Ибо deathWolf у НПС и deathWolf у волка - 2 совершенно разные локалки. Мысль ясна? Чтобы это была одна локалка, тебе в скрипте волка (кстати почему в Респаун ты поставил скрипт? А не в Death?) написать не

Neverwinter Script Source
SetLocalInt( OBJECT_SELF, "deathWolf", 2 );

а
Neverwinter Script Source
SetLocalInt( GetObjectByTag( "Тэг НПС, который выдает квест" ), "deathWolf", 2 );

Я тебе в соседней теме не зря советовал использовать SetGlobal*/GetGlobal. Самое незамороченное решение, подходящее для начала smile.gif

Автор: Edwin Jan 3 2008, 08:45

QUOTE
я пользуюсь SendMessageToPC - она выдает текст в игровой лог. Мне удобнее в режиме онлайн отслеживать происходящее, чем потом читать текстовой файл с логами. Хотя факт - в таком файле больше полезной инфы относительно некорректной работы скриптов.. например при проблеме с памятью или кэшэм.


Небольшой оффтоп, про какой именно кэш идет речь?

Автор: Kirald Jan 3 2008, 11:22

Arigato Спасибо Mersi Thenx кое что понял щас попробую rolleyes.gif

Автор: Lex Jan 3 2008, 13:10

Цитата(Edwin @ Jan 3 2008, 08:45) *
про какой именно кэш идет речь?

спроси у шардовиков, я от них это слышал, сам этим логом не пользуюсь smile.gif

Автор: virusman Jan 3 2008, 13:19

Я тоже не понял, что за кэш и память и как они выводятся в лог.

Автор: Lex Jan 3 2008, 13:41

ну раз даже вирь не знает, значит я перепутал НВН с другим приложением smile.gif сам я натыкался только на переполнение стека, деление на 0 и какие-то ошибки с памятью (слово memory было smile.gif )

Автор: Edwin Jan 3 2008, 13:42

Ну если про память еще можно понять (сегментейшен фолт, хоть ни в каких логах ее ессесно не будет), то про кеш меня ввело в ступор, т.к. кеш абсолютно прозрачен для людей и управляется только хардвэйром. Даже через ассамблер в него не влезть.

Автор: virusman Jan 3 2008, 13:58

Цитата(Edwin @ Jan 3 2008, 13:42) *
Ну если про память еще можно понять (сегментейшен фолт, хоть в логах ее не будет), то про кеш меня ввело в ступор, т.к. кеш абсолютно прозрачен для людей и управляется только хардвэйром. Даже через ассамблер в него не влезть.
Кэшей много разных, и в НВНе есть кэш (2da, скриптов и ресурсов), но в лог инфа о нём не выводится (даже через DummyLog).
Ошибки стека в скриптах, TMI, деление на ноль - да, бывает, но это тоже в лог не идёт, насколько я помню.

Автор: Lex Jan 3 2008, 14:19

Цитата(virusman @ Jan 3 2008, 13:58) *
Ошибки стека в скриптах, TMI, деление на ноль - да, бывает, но это тоже в лог не идёт, насколько я помню.

в НВН1 вроде идет и в лог файл и в лог в игре. А иначе очень странный лог получается, никакой инфы по ошибкам? smile.gif А вот в НВН2 мб и не идет, я лог-файлом тут и подавно не пользуюсь.

зы: что-то мы с оффтопом перебрали, пора завязывать ph34r.gif

Автор: Edwin Jan 3 2008, 14:54

А в обычном компиляторе у тебя много информации об ошибках во время экзекуции? stderr, try-catch и руки - все что надо для отладки. Ффс.....

Автор: dumbo Jan 3 2008, 15:12

Цитата(Edwin @ Jan 3 2008, 13:42) *
кеш абсолютно прозрачен для людей и управляется только хардвэйром. Даже через ассамблер в него не влезть.
prefetch/prefetchw/prefetchnta/prefetcht0(1,2) whistle3.gif

Автор: Edwin Jan 3 2008, 17:51

Ок, про асм я загнул. Можно. Но ненужно, т.к. этим вероятнее всего пользуются только в написании мега симуляторов и софта для посадки шаттлов.

Автор: Lex Jan 3 2008, 17:57

Цитата(Edwin @ Jan 3 2008, 17:51) *
софта для посадки шаттлов.

тады уж Бурана, ибо только он садился на автопилоте, Шаттлы - вручную.

завязываем асм, компиляторы и дебагеры. тема не про это. Если хочется всетаки об этом - выделю вам отдельный топик smile.gif А то что выше почищу завтра, чтобы не пугать скриптеров smile.gif

Автор: azathoth Jan 14 2008, 01:10

Есть очень удобная такая вещь: SetGlobalXXX, но только вот когда переменных становится много, то некоторые почему-то тупо игнорируются sad.gif другие можно продолжать добавлять unknw.gif зависимости он имён переменных или их количества установить не удалось, то после 200 начинает корявить, то 5000 спокойно держит. так что предупреждаю и спрашиваю: кто нибудь сталкивался и как с этим бороться?

зы: а чего тема не прикреплена?

Автор: Lex Jan 14 2008, 01:28

у меня пока наверное около 100 глобалок - никаких глюков ниразу не видел.

Цитата(azathoth @ Jan 14 2008, 01:10) *
зы: а чего тема не прикреплена?

тады тут пол раздела будет прикреплено smile.gif

Автор: Ragdaj Jan 20 2008, 22:44

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

И так - можно ли сделать следующее:

при перетаскивании вещи из инвентаря на какой нибудь объект происходило "событие" - открывался диалог, или ещё что - это уже детали.

На вскидку - перетаскиваем факел из инвентаря на стог сена - стог сена заменяется костром (первое пришедшее в голову)

Автор: Lex Jan 21 2008, 01:44

Цитата(Ragdaj @ Jan 20 2008, 22:44) *
На вскидку - перетаскиваем факел из инвентаря на стог сена - стог сена заменяется костром (первое пришедшее в голову)

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

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

Автор: Ragdaj Jan 21 2008, 10:15

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

"Если нужен выбор - предоставлять выбор. или диалогом или гуи окном." в том то и проблема - что предоставляешь выбор, а не делаешь возможность сделать это игроку. Чтоб он сказал " о, я сам догадался!"

Добавлено через 6 минут

хотя - идея сделать объекты помещаемыми в руку и проверку на то ли есть в руки при взаимодействие - самый простой вариант...

спасибо.

Автор: azathoth Jan 21 2008, 23:25

можно добавить предмету "особое свойство" по типу Unique Power или его самого, тогда им можно будет действовать на всё подряд, а уже скриптами проверять и отпускать ядовитые комментарии, когда игрок будет действовать на стог сена неположеными солью и перцем.

однако, игроки не оценят. <_<

--

У SetGlobalXXX тип возвращаемого значения - int (в смысле булеан), что должно наводить на определённые мысли...

Автор: Jadent Mar 24 2008, 17:54

Возможно ли как-то эмулировать событие OnClick для существ?

Или чтобы OnConversation запускался сразу издалека (не заставляя игрока подбегать вплотную к НПЦ).

Автор: gennady Mar 25 2008, 11:41

Цитата(Jadent @ Mar 24 2008, 17:54) *
Возможно ли как-то эмулировать событие OnClick для существ?

Для этого есть по крайней мере 3 варианта:
1. Скрипт OnEnter триггера
2. Скрипт OnHeartbeat НПС или плейса
3. Скрипт OnPerception НПС

Автор: Lex Mar 25 2008, 12:39

Цитата(gennady @ Mar 25 2008, 11:41) *
Для этого есть по крайней мере 3 варианта:
1. Скрипт OnEnter триггера
2. Скрипт OnHeartbeat НПС или плейса
3. Скрипт OnPerception НПС

ни одно из этих не подходит под вариант onClick.
Цитата(Jadent @ Mar 24 2008, 17:54) *
Или чтобы OnConversation запускался сразу издалека (не заставляя игрока подбегать вплотную к НПЦ).

вот в эту сторону можно попробовать подумать, но думаю дистанция разговора зашита в движок.

Автор: Griffon Mar 31 2008, 12:00

Цитата(Lex @ Mar 25 2008, 12:39) *
Цитата(Jadent @ Mar 24 2008, 17:54)
Или чтобы OnConversation запускался сразу издалека (не заставляя игрока подбегать вплотную к НПЦ).

вот в эту сторону можно попробовать подумать, но думаю дистанция разговора зашита в движок.


а разве возможность перебрасывать РС в место диалога с НПС отменили?

Автор: Jadent Mar 31 2008, 13:23

Цитата(Griffon @ Mar 31 2008, 13:00) *
а разве возможность перебрасывать РС в место диалога с НПС отменили?
Диалоги меня в данном случае вообще не интересуют, вопрос был о скриптах.

Автор: Keeper Apr 23 2008, 19:43

Нужна функция, возвращающая школу, на которой специализируется Маг (General, e.t.c.).

Еще вопрос:
Как расширить возможности функции EffectPolymorph()? Для ее функционирования нужно знать ID крича в которого происходит превращение. Оные указаны константами типа POLYMORPH_TYPE_*. Их довольно мало. К примеру, я хочу превратить Духа волка в Тень. Как это сделать?

Автор: azathoth Apr 23 2008, 20:06

Цитата
Как расширить возможности функции EffectPolymorph()? Для ее функционирования нужно знать ID крича в которого происходит превращение. Оные указаны константами типа POLYMORPH_TYPE_*. Их довольно мало. К примеру, я хочу превратить Духа волка в Тень. Как это сделать?

добавить желаемые в .2da таблицы. или использовать функцию SetCreatureAppearanceType.

Автор: Keeper Apr 23 2008, 22:10

Цитата(azathoth @ Apr 23 2008, 20:06) *
добавить желаемые в .2da таблицы. или использовать функцию SetCreatureAppearanceType.

Огромное спасибо! Пойду творить далее. А что по первому пункту?

Закончил писать скрипт для посоха обращения в нежить. Все бы было хорошо, если бы не... если бы не проскакивало за секунду без каких-либо визуальных спецэффектов.
Собственно, вопросы:
1. Почему нет эффектов?
2. Как сделать паузу в выполнении скрипта?
3. Как передать получившееся существо игроку на всегда/на время/не дать создать армию?
Вот скрипт, сыренький, так что не пинайте. Вешается на онитемактивэйт модуля:
Neverwinter Script
object oPC = GetItemActivator();
  object oItem = GetItemActivated();
  object oTarget = GetItemActivatedTarget();
  location lTargetLocation = GetItemActivatedTargetLocation();
  string sPCName = GetName(oPC);
  string sTargetName = GetName(oTarget);
 
  void ItemActivatedPaleStaff();
    string PALE_STAFF_TAG = "EK_STAFF_001";
    int PALE_STAFF_HIT_VS_REFLEX = d20() + 2 * GetAbilityModifier(ABILITY_DEXTERITY, oPC);
    int PALE_STAFF_HIT_VS_FORTITUDE = d20() + 2 * GetAbilityModifier(ABILITY_INTELLIGENCE, oPC);
    int PALE_STAFF_HIT_VS_WILL = d20() + 2 * GetAbilityModifier(ABILITY_WISDOM, oPC);
    float PALE_STAFF_CAST_TIME = 60.0;
    effect PALE_STAFF_POLYMORPH_VISUAL = EffectVisualEffect(VFX_IMP_POLYMORPH);
    effect PALE_STAFF_POLYMORPH_TYPE_1 = EffectPolymorph(POLYMORPH_TYPE_ZOMBIE, TRUE);
 
void main()
{
  if (oItem == GetObjectByTag(PALE_STAFF_TAG))
  {
    ItemActivatedPaleStaff();
  }
}

void ItemActivatedPaleStaff()
{
  if (GetIsObjectValid(oTarget) == FALSE)
  {
    SendMessageToPC(oPC, "<color=red>Некорректная цель для обращения в нежить!</color>");
    return;
  }
  if (GetLocalInt(oTarget, "Undeadable") < 1 || GetPolymorphLocked(oTarget) == TRUE)
  {
    SendMessageToPC(oPC, "<color=red>Выбранная цель не может быть обращена в нежить!</color>");
    return;
  }
  if (GetIsDead(oTarget) == TRUE)
  {
    SendMessageToPC(oPC, "<color=red>Цель мертва, прежде чем обратить в нежить, ее нужно оживить!</color>");
    return;
  }
 

  if (GetReflexSavingThrow(oTarget) > PALE_STAFF_HIT_VS_REFLEX)
  {
    SendMessageToPC(oPC, "<color=blue>"+sPCName+" бросок "+IntToString(PALE_STAFF_HIT_VS_REFLEX)+" против класса сложности "+IntToString(GetReflexSavingThrow(oTarget))+" "+IntToString(GetReflexSavingThrow(oTarget))+" > "+IntToString(PALE_STAFF_HIT_VS_REFLEX)+" *провал*</color>");
    ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectBeam(VFX_BEAM_BLACK, oPC, BODY_NODE_CHEST, TRUE), oTarget);
    return;
  }
  SendMessageToPC(oPC, "<color=blue>"+sPCName+" бросок "+IntToString(PALE_STAFF_HIT_VS_REFLEX)+" против класса сложности "+IntToString(GetReflexSavingThrow(oTarget))+" "+IntToString(GetReflexSavingThrow(oTarget))+" <= "+IntToString(PALE_STAFF_HIT_VS_REFLEX)+" *успех*</color>");
  ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectBeam(VFX_BEAM_BLACK, oPC, BODY_NODE_CHEST), oTarget, PALE_STAFF_CAST_TIME);
  ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectCutsceneParalyze(), oPC, PALE_STAFF_CAST_TIME);
  ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectCutsceneParalyze(), oTarget, PALE_STAFF_CAST_TIME);
  ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectSpellImmunity(), oTarget, PALE_STAFF_CAST_TIME);
  ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectDamageImmunityIncrease(DAMAGE_TYPE_ALL, 100), oTarget, PALE_STAFF_CAST_TIME);
 
  DelayCommand(PALE_STAFF_CAST_TIME/3, ActionWait(0.0));
 
  if (GetFortitudeSavingThrow(oTarget) > PALE_STAFF_HIT_VS_FORTITUDE)
  {
    SendMessageToPC(oPC, "<color=blue>"+sPCName+" бросок "+IntToString(PALE_STAFF_HIT_VS_FORTITUDE)+" против класса сложности "+IntToString(GetFortitudeSavingThrow(oTarget))+" "+IntToString(GetFortitudeSavingThrow(oTarget))+" > "+IntToString(PALE_STAFF_HIT_VS_FORTITUDE)+" *провал*</color>");
    ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_DUR_CONE_EVIL), oTarget);
    RemoveEffect(oTarget, EffectBeam(VFX_BEAM_BLACK, oPC, BODY_NODE_CHEST));
    RemoveEffect(oPC, EffectCutsceneParalyze());
    RemoveEffect(oTarget, EffectCutsceneParalyze());
    RemoveEffect(oTarget, EffectSpellImmunity());
    RemoveEffect(oTarget,EffectDamageImmunityIncrease(
DAMAGE_TYPE_ALL, 100));
    return;
  }
  SendMessageToPC(oPC, "<color=blue>"+sPCName+" бросок "+IntToString(PALE_STAFF_HIT_VS_FORTITUDE)+" против класса сложности "+IntToString(GetFortitudeSavingThrow(oTarget))+" "+IntToString(GetFortitudeSavingThrow(oTarget))+" <= "+IntToString(PALE_STAFF_HIT_VS_FORTITUDE)+" *успех*</color>");
  if (GetLocalInt(oTarget, "Undeadable") == 1)
  {
    ApplyEffectToObject(DURATION_TYPE_INSTANT, PALE_STAFF_POLYMORPH_VISUAL, oTarget);
    ApplyEffectToObject(DURATION_TYPE_PERMANENT, PALE_STAFF_POLYMORPH_TYPE_1, oTarget);
  }
 
  DelayCommand(PALE_STAFF_CAST_TIME/3, ActionWait(0.0));
 
  if (GetWillSavingThrow(oTarget) > PALE_STAFF_HIT_VS_WILL)
  {
    SendMessageToPC(oPC, "<color=blue>"+sPCName+" бросок "+IntToString(PALE_STAFF_HIT_VS_WILL)+" против класса сложности "+IntToString(GetWillSavingThrow(oTarget))+" "+IntToString(GetWillSavingThrow(oTarget))+" > "+IntToString(PALE_STAFF_HIT_VS_WILL)+" *провал*</color>");
    ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_DUR_CONE_EVIL), oTarget);
    RemoveEffect(oTarget, EffectBeam(VFX_BEAM_BLACK, oPC, BODY_NODE_CHEST));
    RemoveEffect(oPC, EffectCutsceneParalyze());
    RemoveEffect(oTarget, EffectCutsceneParalyze());
    RemoveEffect(oTarget, EffectSpellImmunity());
    RemoveEffect(oTarget,EffectDamageImmunityIncrease(
DAMAGE_TYPE_ALL, 100));
    return;
  }
  SendMessageToPC(oPC, "<color=blue>"+sPCName+" бросок "+IntToString(PALE_STAFF_HIT_VS_WILL)+" против класса сложности "+IntToString(GetWillSavingThrow(oTarget))+" "+IntToString(GetWillSavingThrow(oTarget))+" <= "+IntToString(PALE_STAFF_HIT_VS_WILL)+" *успех*</color>");
  ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_BEAM_MIND), oTarget);
  ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectCutsceneDominated(), oTarget);
}

Автор: azathoth Apr 24 2008, 17:41

Функции возвращающей школу не знаю.

объявление переменных вне функции (тем более вперемешку с декларацией функции) - это ахтунг. ИМХО.

Единственное что могу сказать - функция задержки DelayCommand(...), у тебя Delaится Action, а экшн привязан к объекту OBJECT_SELF по умолчанию, не факт, что в отдельной функции он будет тот, что ты хочешь. А самое главное - экшын экшыном, но строчки вне него будут всё равно будут выполнены все сразу в любом случае - то есть сначала сработает скрипт, а затем будут выполняться действия (в т.ч. со своими "кусочками скрипта"). Так что определись, задержку между "чем" и "чем" ты хочешь - и второе заDelay.

Автор: Keeper Apr 24 2008, 18:33

Спасибо!
Хочу, что бы все выполнялось в том порядке, в каком идет в теле скрипта. Значит, надо весь скрипт расписать по секундам в DelayCommand?

Насчет ахтунга - там, если ты не заметил, везде ахтунг - добьюсь работоспособности и оформлю по человечески, заодно оптимизирую.

Автор: Lorendroll May 1 2008, 15:31

Хочу наложить на игрока визуальный эффект такого же типа как накладываются во вкладке "Аppearance (visual effect)" в свойствах существа, а там указаны такие названия как fx_will_o_wisp и подобные, которые не обозначены в глобальных переменных. Возможно ли это? Задача в том чтобы превратить игрока в виспа, при том что SetAppearanceType с APPEARANCE_TYPE_WILL_O_WISP не работает - нет в НВН2 соотвтетсвующей модели, она перекочевала в визуальные эффекты... То есть выход один - превратить игрока в невидимку и наложить на него эффект виспа, который есть только как FX_*, а не VFX_* эффект...

Автор: nitx May 29 2008, 06:25

как сделать реакцию на фразу в чат канала (от плеера)? Только скрипт повесить не в пределах восприятия 1нпц, а на всю локу.

Автор: virusman May 29 2008, 09:04

В 1.69 будет соответствующее событие.
А пока - либо воисами (см. DMFI), либо NWNX Chat (если шард).

Автор: nitx May 29 2008, 12:53

я про нвн2. А нельзя увеличить область восприятия нпс (именно события OnConversation), и поставить его например за пределы локи? Ну или сделать его невидимым для плеера, пробовал ставить апиренс - none и script hidden, так в игре вобще как будето его нету, скрипты так тож неработают.

Автор: virusman May 29 2008, 13:27

Посмотри DMFI, там должны быть невидимые воисы.

Автор: Zmeika Jun 2 2008, 12:02

Можно ли на ходу поменять свойство для уже существующего предмета?
Нужно у готового предмета установить (временно!) свойство из серии Activate, чтобы у предмета появлялась иконка "активировать" и срабатывал нужный скрипт по тэгу. В исходном предмете такого свойства нет. Мне нужно, чтобы оно появилось, и начал срабатывать скрипт.

Временное изменение иконки у предмета - тоже интересует.
Вышла из ситуации временно создавая новый предмет по другому шаблону и незаметно подменяя им старый. Но неудобно это. aggressive.gif


Автор: Lex Jun 3 2008, 01:01

свойство можно.
иконку низя.

Автор: Zmeika Jun 3 2008, 11:01

а какой функцией можно свойство поменять или установить? Хотя бы примерно, как называется?

Автор: Lex Jun 3 2008, 19:52

AddItemProperty
соотв есть или Remove или Delete или какой-нить другой Destroy этой самой ItemProperty.

Автор: Zmeika Jun 5 2008, 16:05

AddItemProperty - работает, спасибо!
Правда, почему-то не работает SetDescription для того же самого предмета. Т.е. свойство - появляется, а описание остается прежним.

Вопрос - можно ли подменять скрипты так же, как диалоги или 2da таблицы, помещая новые компиляции в override? У меня пока не вышло - если есть два скрипта с одинаковым названием, и при этом один находится в моде, другой в override, то в игре берется версия из мода. А хочется, чтобы наоборот.

Автор: virusman Jun 5 2008, 16:07

Цитата(Zmeika @ Jun 5 2008, 17:05) *
AddItemProperty - работает, спасибо!
Правда, почему-то не работает SetDescription для того же самого предмета. Т.е. свойство - появляется, а описание остается прежним.
1.69?

Автор: Zmeika Jun 5 2008, 16:13

версия 1.12
свойство и описание устанавливается в скрипте на взятие предмета (_aq)

Автор: Lex Jun 5 2008, 16:42

Цитата(Zmeika @ Jun 5 2008, 16:05) *
Вопрос - можно ли подменять скрипты так же, как диалоги или 2da таблицы, помещая новые компиляции в override? У меня пока не вышло - если есть два скрипта с одинаковым названием, и при этом один находится в моде, другой в override, то в игре берется версия из мода. А хочется, чтобы наоборот.

можно. Класть в оверрайд нужно скомпилированный скрипт, те nsc. А не nss.

Автор: Zmeika Jun 5 2008, 17:02

Цитата(Lex @ Jun 5 2008, 16:42) *
Класть в оверрайд нужно скомпилированный скрипт, те nsc. А не nss.

Э, так само собой. smile.gif У меня там новые и nss и ncs, но все же срабатывал ncs старый (из мода). Правда, проверяла я запуская мод прямо из тулсета, может это сыграло какую роль... Но по-любому отлично, что в принципе - можно. Тогда, вероятно это у меня где-то косяк.

Автор: Zmeika Jun 12 2008, 00:45

Подскажите, пожалуйста, как можно сделать так, чтобы мертвый НПС лежал не в дефолтовой скрюченной позе, а в положении лежа на спине? Пытаюсь делать так:

Код
object oPC = GetFirstEnteringPC();    

//Здесь непись еще живой    
object oNPC = GetNearestObjectByTag("DEAD_NPC",oPC);

// убиваем его
effect eF1 = EffectDeath();
ApplyEffectToObject( DURATION_TYPE_INSTANT,eF1, oNPC);

// потом пытаемся перевернуть на спину - и не выходит
PlayCustomAnimation(oNPC, "proneB",TRUE, 1.f);


Есть альтернативный вариант - втихую оставить его живым, но симитировать смерть.
Код
// делаем так, чтобы живой НПС совсем не шевелился
effect eF3 = EffectPetrify();
ApplyEffectToObject( DURATION_TYPE_INSTANT,eF3, oNPC);

// переворачиваем на спину  - работает
PlayCustomAnimation(oNPC "proneB", TRUE, 1.f);


Второй вариант выглядит замечательно, пока не навести на НПС курсор - он показывает, что клиент жив! Млжно ли как-то обмануть курсор в этом случае?

Автор: Lorendroll Jun 13 2008, 14:51

Zmeika, попробуй поэкспериментировать со свойствами NPC, такими как Non permanent death и Lootable corpse. Попробуй выставить второе свойство в true и после применения анимации нанести ему смертельные повреждения.
Лично я бы просто добавил к имени этого НПСа приставку "МЕРТВЫЙ" и успокоился бы. Imho, и так все хорошо, совершенства не бывает.

Автор: Zmeika Jun 14 2008, 14:41

Lorendroll, спасибо. После долгих экспериментов с трупами мне все же удалось добиться нужного результата. smile.gif Нужно делать так:

Код
// Создаем эффект смерти.  Внимание - важно, чтобы последний параметр был false!
effect eDeath = EffectDeath(FALSE, FALSE,TRUE, FALSE);

// Создаем эффект неподвижности
effect ePetrify = EffectPetrify();
  
PlayCustomAnimation(oNPC, "proneB",TRUE, 1.f);
ApplyEffectToObject(DURATION_TYPE_INSTANT, ePetrify, oNPC);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eDeath, oNPC);


Т.е. перед смертью нужно применить неподвижность, и эффект смерти должен быть соответствующе настроен. Но это еще не все. Надо удалить у NPC скрипты, которые выполняются по дефолту на различные события. Разумеется не все, но какие именно я пока сама не знаю. Какой-то из них все портит. on Conversation или on Spawn In точно можно оставить.

Только при соблюдении всех этих условий тушка после смерти остается в нужной позе. rolleyes.gif

Автор: Zmeika Jun 27 2008, 12:38

Как можно создавать или менять переменную типа location? Знаю, как ее получить из уже существующего объекта. Но мне надо создать новый объект (существо) на некотором расстоянии от игрока и по событию, которое может спровоцировать сам игрок в любой момент времени (например - вызвать джина из бутылки).
Т.е. locаtion игрока - я определить могу. Но затем мне нужно ее поменять каким-то образом, чтобы нужная тварюка появилась на некотором расстоянии от игрока.
Вопрос - как это сделать?


Update:
Сорри, вопрос снимается - узнала, что есть такой метод Location(....)

Автор: Lorendroll Jul 27 2008, 12:00

Никто случайно не разобрался как превратить игрока в виспа? (наложить на него fx эффект)

Автор: shadowdweller Aug 6 2008, 14:29

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

Neverwinter Script
void main();
{

object oPC = GetPCSpeaker();

ClearAllActions();
          ActionPlayAnimation(ANIMATION_LOOPING_DANCE02, 1.0, 4,0);
          ActionPlayAnimation(ANIMATION_LOOPING_DANCE03, 1.0, 4.0);
          ActionPlayAnimation(ANIMATION_LOOPING_DANCE02, 1.0, 4.0);
          ActionPlayAnimation(ANIMATION_FIREFORGET_BOW);
}


Не срабатывает. При компиляции выдает какой-то бред - название, путь сохранения и неизвестно что еще. Причем, непонятно, на какую строчку плюется и где непосредственно ошибка... Подскажите, плз, что с этим делать... sad.gif

Автор: Zirrex Aug 6 2008, 17:53

shadowdweller, я в свое время делал различные эффекты, которые нельзя было бы снять простым действием, и вот что получилось. Можешь отсюда использовать скрипт танца:

Neverwinter Script
// Персонаж танцует
void ChatDance(object oPC, int n, float fTime);

void main()
{
    object oPC = GetPCSpeaker();
    object oTarget = GetItemActivatedTarget();
    int nDialogLine = GetLocalInt(oPC, "DIALOGSTMLINE");
    int nAnimation;
    float fTime = 999999.0;

    SetCommandable(TRUE, oTarget);
    AssignCommand(oTarget, ClearAllActions());

    SetLocalInt(oTarget, "DIALOGSTMLINE", nDialogLine);

    switch (nDialogLine)
    {
        case 1: nAnimation = ANIMATION_LOOPING_SIT_CROSS;  break; // Сесть
        case 2: nAnimation = ANIMATION_LOOPING_MEDITATE;    break; // Медитация
        case 3: nAnimation = ANIMATION_LOOPING_WORSHIP;    break; // Молитва
        case 4: nAnimation = ANIMATION_LOOPING_DEAD_BACK;  break; // Упасть назад
        case 5: nAnimation = ANIMATION_LOOPING_DEAD_FRONT;  break; // Упасть вперед
        case 6: nAnimation = ANIMATION_LOOPING_SPASM;      break; // Спазм
        case 7: ChatDance(oTarget, 1, fTime);              break; // Танец
    }
    DeleteLocalInt(oPC, "DIALOGSTMLINE");
    DelayCommand(0.2, SetCommandable(FALSE, oTarget)); // убери эту строчку, если нужно, чтобы эффект был снимаемым

    if (nDialogLine < 7)
    {
        DelayCommand(0.1, AssignCommand(oTarget, ActionPlayAnimation(nAnimation, 1.0, fTime)));
    }
    else if (nDialogLine == 8) // Парализация
    {
        effect eDur = EffectVisualEffect(VFX_DUR_PARALYZED);
        effect eLink = EffectLinkEffects(eDur, EffectCutsceneParalyze());
        DelayCommand(0.1, AssignCommand(oTarget, ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(eLink), oTarget)));
    }
    else if (nDialogLine == 9) // Ошеломление
    {
        effect eMind = EffectVisualEffect(VFX_DUR_MIND_AFFECTING_DOMINATE
D);
        effect eLink = EffectLinkEffects(eMind, EffectStunned());
        DelayCommand(0.1, AssignCommand(oTarget, ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(eLink), oTarget)));
    }
    else if (nDialogLine == 10) // Окаменение
    {
        DelayCommand(0.1, AssignCommand(oTarget, ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(EffectPetrify()), oTarget)));
    }
    DelayCommand(fTime, SetCommandable(TRUE, oTarget)); // убери эту строчку, если нужно, чтобы эффект был снимаемым
}


void ChatDance(object oPC, int n, float fTime)
{
    int nDialogLine = GetLocalInt(oPC, "DIALOGSTMLINE");

    if (IntToFloat(n) < fTime && nDialogLine == 7)
    {
        object oRightHand = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oPC);
        object oLeftHand =  GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oPC);

        AssignCommand(oPC, ActionUnequipItem(oRightHand));
        AssignCommand(oPC, ActionUnequipItem(oLeftHand));

        AssignCommand(oPC, ActionPlayAnimation(ANIMATION_FIREFORGET_VICTORY2,1.0));
        AssignCommand(oPC, ActionDoCommand(PlayVoiceChat(VOICE_CHAT_LAUGH,oPC
)));
        AssignCommand(oPC, ActionPlayAnimation(ANIMATION_LOOPING_TALK_LAUGHIN
G, 2.0, 2.0));
        AssignCommand(oPC, ActionPlayAnimation(ANIMATION_FIREFORGET_VICTORY1,1.0));
        AssignCommand(oPC, ActionPlayAnimation(ANIMATION_FIREFORGET_VICTORY3,2.0));
        AssignCommand(oPC, ActionPlayAnimation(ANIMATION_LOOPING_GET_MID, 3.0, 1.0));
        AssignCommand(oPC, ActionPlayAnimation(ANIMATION_LOOPING_TALK_FORCEFU
L,1.0));
        AssignCommand(oPC, ActionPlayAnimation(ANIMATION_FIREFORGET_VICTORY2,1.0));
        AssignCommand(oPC, ActionDoCommand(PlayVoiceChat(VOICE_CHAT_LAUGH,oPC
)));
        AssignCommand(oPC, ActionPlayAnimation(ANIMATION_LOOPING_TALK_LAUGHIN
G, 2.0, 2.0));
        AssignCommand(oPC, ActionPlayAnimation(ANIMATION_FIREFORGET_VICTORY1,1.0));
        AssignCommand(oPC, ActionPlayAnimation(ANIMATION_FIREFORGET_VICTORY3,2.0));
        AssignCommand(oPC, ActionDoCommand(PlayVoiceChat(VOICE_CHAT_LAUGH,oPC
)));
        AssignCommand(oPC, ActionPlayAnimation(ANIMATION_LOOPING_GET_MID, 3.0, 1.0));
        AssignCommand(oPC, ActionPlayAnimation(ANIMATION_FIREFORGET_VICTORY2,1.0));

        AssignCommand(oPC, ActionDoCommand(ActionEquipItem(oLeftHand,INVENTOR
Y_SLOT_LEFTHAND)));
        AssignCommand(oPC, ActionDoCommand(ActionEquipItem(oRightHand,INVENTO
RY_SLOT_RIGHTHAND)));
        n++;
        DelayCommand(20.0, ChatDance(oPC, n, fTime));
    }
}

Чтобы скрипт заработал, необходимо вначале на использующего диалог, предмет и т.п. наложить переменную:
Neverwinter Script
void main()
{
    SetLocalInt(GetPCSpeaker(), "DIALOGSTMLINE", 1);
}

Так как у меня эффектов 10, то я использовал 10 мелких скриптов. Можно сделать иначе, но я не стал возиться, чтобы укоротить количество скриптов.

Автор: KoYuKi Aug 7 2008, 23:49

Дело такое:
Есть необходимость иметь глобальную переменную. Нужно, чтобы эта переменная, в зависимости от действий производимых персонажем, менялась и сохранялась поверх себя, чтобы с уже новым значением скрипты могли взаимодействовать дальше.
В принципе я себе представляю как это сделать, но запоролся в самом начале, видимо что-то с синтаксисом напутал. Вобщем, не могу вызвать глобальную переменную. Перед этим эту переменную я прописал в свойствах модуля. Если не ошибаюсь вызывается она в скриптах при помощи GetGlobalInt()(сейчас тула под рукой нет, точно не вспомню чего я там вчера ваял), но при компиляции тул ругается на эту строчку, так как я очевидно задаю неверные параметры.
Вобщем сама просьба такова - привидите пожалуйста какой-нибудь пример с назначением и последующим вызовом глобальных переменных, разжовывать не надо, сам расковыряю, лишь бы пример рабочий был.
Буду очень признателен.

Автор: Lorendroll Aug 8 2008, 10:24

KoYuKi, чтобы при компиляции выдавал не какой нибудь бред а реальную ошибку - поставь английский Dialog.tlk и перезапусти тулсет. Иногда скрипты даже не компилируются из за русского диалог.тлк. А уж если русские буквы в код попадут то и весь тулсет бывает падает. Перезапустишь - напиши что за ошибка компиляции выдается.
А SetGlobalInt'ом, кстати, за всю свою нвн-программерскую деятельность мне пользоваться не приходилось. Кстати, почему бы не сохранить эту глобальную переменную на самом персонаже - SetLocalInt(oPC, sIntName, N)?

Автор: KoYuKi Aug 8 2008, 11:51

Цитата
KoYuKi, чтобы при компиляции выдавал не какой нибудь бред а реальную ошибку - поставь английский Dialog.tlk и перезапусти тулсет. Иногда скрипты даже не компилируются из за русского диалог.тлк. А уж если русские буквы в код попадут то и весь тулсет бывает падает. Перезапустишь - напиши что за ошибка компиляции выдается.

NWN у меня английский, так что мне там вполне конкретную ошибку компилятор выдал, я сейчас просто не помню какую, с работы пишу.

Цитата
А SetGlobalInt'ом, кстати, за всю свою нвн-программерскую деятельность мне пользоваться не приходилось. Кстати, почему бы не сохранить эту глобальную переменную на самом персонаже - SetLocalInt(oPC, sIntName, N)?

Lorendroll, этот вариант мне плохо представляется, вероятно в связи с маленьким багажом знаний.
То есть я сохраняю на игроке локальную переменную. Он ходит, взаимодействует с предметами, в связи с чем эта локалка меняется и сохраняется на игроке. Но возможно ли мне при таком подходе сделать так, чтобы значение переменной уменьшалось без каких либо взаимодействий, просто по прошествии времени?
Если не трудно приведи какой-нибудь пример, буду признателен.

Автор: Lorendroll Aug 8 2008, 12:06

KoYuKi, да меняй ее откуда хочешь, из любого скрипта вызывай функцию SetLocalInt (oPC, sIntName, N) где object oPC = GetFirstPC(); (первый попавшийся PC, ведь ты делаешь сингл?), string sIntName = "имя твоей переменной"; int N = "значение переменной". Это в точности также как и с GlobalInt только Local в отличие от нее надо где то хранить, на каком то объекте. Откуда надо, оттуда и меняй эту переменную. Например как только игрок дергает за рычаг поставь на действии SetLocalInt(oPC, sIntName, GetLocalInt(oPC, sIntName)+N); где N - то значение которое ты хочешь прибавить к старому значению переменной.

Чтобы переменная уменьшалась или увеличивалась, или еще как-нибудь изменялась со временем, нужно написать таймер который будет, опять таки, работать либо на PC, либо еще где-то. Это сложнее. Для этого нужно зациклить скрипт таймера, не помню точно название функции запуска скрипта, кажется ExecuteScript. Скрипт таймера надо запускать раз, допустим, в 6 секунд (игровой раунд) с помощью функции DelayCommand, и вызывать снова этот делэй-команд по окончании работы скрипта-таймера. В скрипте-таймере же нужно написать то что будет происходить каждые 6 секунд. Я так подозреваю, какая-то проверка. Например проверка того, не прошло ли еще 10 минут, или 60 раундов. Для этого нужно в таймер поставить счетчик раундов или проверку текущего времени... Отдельная песня... Я напишу, если не забуду, пример когда приеду домой и включу невер, у меня полно таймеров в модуле для расчета голода, погоды и пр.

Автор: KoYuKi Aug 8 2008, 13:50

Lorendroll спасибо большое, теперь все ясно =) Прийду домой, буду пробовать.

Цитата
Я напишу, если не забуду, пример, когда приеду домой и включу невер, у меня полно таймеров в модуле для расчета голода, погоды и пр.

Обязательно гляну, если напишешь, пример бы не помешал.


Автор: Lorendroll Aug 9 2008, 14:53

Этот скрипт надо вызвать командой ExecuteScript("this_script", oPC) из любого другого. object oPC = GetFirstPC() к примеру.

Neverwinter Script
void main()
{

    int iTime = 10; /*Количество раундов перед тем как переменная изменится*/
    int iTimer = GetLocalInt (OBJECT_SELF, "TIMER"); /*Смотрим сколько раундов уже прошло*/
    SetLocalInt (OBJECT_SELF, "TIMER", iTimer+1); /*Прибавляем к таймеру единичку*/
    if (iTimer+1 >= iTime) /*Проверяем не прошло ли уже достаточно времени*/
    {
        FloatingTextStringOnCreature("Something happened!", OBJECT_SELF);    /*Если условие выполнено то пишем что произошло (сообщаем игроку если надо)*/
        SetLocalInt (OBJECT_SELF, "INTEGER", GetLocalInt(OBJECT_SELF, "INTEGER")+1); /*Выставляем нужную переменную, или увеличиваем ее значение на 1 или еще что угодно. Еще полезно тут же написать второе условие при котором останавливать таймер после того как он становится ненужным, с помощью команды "return;"*/
        SetLocalInt (OBJECT_SELF, "TIMER", 0); /*обнуляем таймер*/
    }
    DelayCommand(6.0, ExecuteScript("this_script", OBJECT_SELF)); /*Перезапускаем скрипт через 6 секунд. */
       
}

Автор: Melshin Oct 15 2008, 15:28

Вот в кои-то веки не обошелся своими силами...

Значит, существует триггер, описанный около блупринта травы, являющегося по факту "Tree". По факту триггер является трапом, процовоцирующим АОЕ спелл. Т.к. с "Tree" спеллы не пускаются, должен создаться другой блупринт, желательно невидимый.

Вариантов решения 3:
1) ActionCastSpellAtObject - не подходит, нормальный кастер лвл он имеет только с криче блупринта, а со скриптхидден кричи не запускается. В ином случае кастер лвл = 0.
2) Эмулировать заклинание собственным псевдо эффектом. АОЕ эффект почему-то мгновенно уничтожается, даже не появившись толком.
3) TriggerProjectileTrap - не удалось заставить работать. Делал путем задания правельного тэга запускающему блупринту. Опять же работает только с кричи. Разницы между моей версией и скриптом проджектил эрроу трапов из ОС нет практически, но мой скрипт не работает... Именно проджектил эрроу пока не делал...

Автор: Jadent Oct 19 2008, 08:09

Цитата(Melshin @ Oct 15 2008, 15:28) *
2) Эмулировать заклинание собственным псевдо эффектом. АОЕ эффект почему-то мгновенно уничтожается, даже не появившись толком.
В Nwn2 AOE-объекты можно создавать только скриптом с существа. Иначе AOE-объект запускает скрипты OnEnter и OnExit для всех попавших в него существ и сразу исчезает.
Пример.
Вот такой скрипт, висящий на каком-нибудь рычаге или триггере, заработает криво (как описано выше).
Neverwinter Script
void main()
{
    effect eEff = EffectAreaOfEffect(AOE_PER_CUSTOM_AOE, "OnEnter", "OnHeartbeat", "OnExit", "tag");
    ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEff, GetFirstPC());
}
А вот так — нормально:
Neverwinter Script
void func()
{
    effect eEff = EffectAreaOfEffect(AOE_PER_CUSTOM_AOE, "OnEnter", "OnHeartbeat", "OnExit", "tag");
    ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEff, GetFirstPC());
}

void main()
{
    object oCreature = GetFirstPC();
    AssignCommand(oCreature, func());
}

Автор: Melshin Oct 19 2008, 08:31

Тогда это актуально для всех 3 пунктов. То есть то, что я хочу сделать - вообще в принципе нереализуемо... Спасибо.

Можно попробовать сделать это с катсцен инвизибилити... Хотя не стоит, слишком много там будет лишних объектов, лучше другое что-нибудь сделать.

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

Хотя стоп, я же не делаю ActionCastSpellAtLocation, можно и с игрока... Но скрипт этот для PW, к слову.

Тогда еще не все потеряно.

Кстати, в случае выше АОЕ эффект будет бегать вместе с игроком, LOL.

Neverwinter Script
void func(location lTarget)
{
    effect eEff = EffectAreaOfEffect(AOE_PER_CUSTOM_AOE, "OnEnter", "OnHeartbeat", "OnExit", "tag");
    DelayCommand *проджектил анимация*
    DelayCommand *ApplyEffectAtLocation(DURATION_TYPE_PERMANENT, eEff, GetFirstPC());* - кхм, жгу, xD.
}

void main()
{
    object oCreature = GetFirstPC();
    location lTarget = GetLocation (oCreature);
    AssignCommand(oCreature, func(lTarget));
}


В общем, никак не получится.

Блин, туплю... А также не могу редактировать посты... Наверное, их мало... В общем, не нужна тут проджектил анимация и т.д. Вполне реально сделать.

Автор: DarkPhoenix Oct 20 2008, 19:20

Есть ли способ намертво прицепить одну модельку к другой - например чтоб над плечем игрока летала фигурка демилича (череп)

Автор: Jadent Oct 20 2008, 21:26

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

Посмотри вот этот хак и сделай по аналогии: http://nwvault.ign.com/View.php?view=NWN2VisualEffects.Detail&id=37

Автор: DarkPhoenix Oct 20 2008, 22:39

Спасибо! А каких нибудь гидов по этому не знаеш?

Автор: Equilibrium Dec 22 2008, 21:53

Очень интересует вопрос - как вернуть Школу магии, на которой специализируется волшебник? Есть мнение, что оная может храниться в локальных переменных персонажа...

Автор: virus_found Dec 23 2008, 01:04

да
в файле *.bic (персонажа) есть переменная School типа byte (которая находится в ветке ClassList)
значения переменной:

Цитата
0: General
1: Abjuration
2: Conjuration
3: Divination
4: Enchantment
5: Evocation
6: Illusion
7: Necromancy
8: Transmutation


а вот как попасть в этот файл персонажа через скрипты - это уже не ко мне wacko.gif

Автор: Equilibrium Dec 23 2008, 18:09

Спасибо!
Вопрос логически продолжается: кто знает - как добыть эту школу из файла персонажа через скрипты? ^_^

Автор: virusman Dec 23 2008, 18:28

Сингл или шард? Если сингл, то никак, если шард, то можно, но сложно.

Автор: Equilibrium Dec 23 2008, 21:42

Вообще, желательно, сингле... А почему нельзя? Вернее, почему можно на шарде? И как?

Автор: virusman Dec 23 2008, 22:04

Цитата(Equilibrium @ Dec 23 2008, 21:42) *
Вообще, желательно, сингле... А почему нельзя? Вернее, почему можно на шарде? И как?
Потому что в сингле доступны только стандартные функции НВН, которыми нельзя получить школу магии. На шардах же возможно использование NWNX с плагином NWNX-Leto, который позволяет редактировать файлы персонажей.

Автор: Equilibrium Dec 24 2008, 23:44

Эх... ясно, пасиб... Но буду иметь ввиду на всякий случай.

Автор: RebOOter Jan 3 2009, 11:46

Народ, не могу разобраться в некоторых вещах.
1) Пытаюсь написать скрипт, что бы один НПС атаковал другова.

Neverwinter Script
void main()
{
object oVoin = GetObjectByTag("BOEC1");
object oVoin2 = GetObjectByTag("BOEC2");

AssingCommand(oVoin, ActionAttack(oVoin2));
}


Компилятр выдаёт мне:
4000_tboi_os.nss(6): ERROR: UNDEFINED INDENTIFIER

2) В Вики был самоучитель из 4-х уроков. Там был приведён пример скрипта, что-бы НПС пел:

Neverwinter Script
void main()
  {
  ClearAllActions();
  ActionSpeakString(&#39;This is the song that never ends.&#39wink3.gif;
  ActionWait(1.5);
  ActionSpeakString(&#39;Yes it goes on and on, my friends.&#39wink3.gif;
  ActionWait(1.5);
  ActionSpeakString(&#39;Some people started singing it not knowing what it was.&#39wink3.gif;
  ActionWait(1.5);
  ActionSpeakString(&#39;And now they&#39;ll keep on singing it forever, just because:&#39wink3.gif;
  }


Компилятор так-же выдал ошибку: Script2.nss(4): ERROR: UNDEFINED IDENTIFIER

Может это правила написания для 1-го NWN? Возможно я чего-то не понял?
Если по 1-му вопросу, то я задаю 2 объекта которые определяются по тэгам и отдаю команду (т.е. oVoin c тэгом BOEC1 атакует oVoin2 c тэгом BOEC2).
По втрому вообще понять не могу. Может мне нужно именно задать объект?

Зарание спасибо!


Простите за мультипост, допустил гругую ошибку в предыдущем посте и не могу найти кнопку для редактирования vava.gif

Neverwinter Script
void main()
  {
  ClearAllActions();
  ActionSpeakString(&#39;This is the song that never ends.&#39wink3.gif
  ActionWait(1.5);
  ActionSpeakString(&#39;Yes it goes on and on, my friends.&#39wink3.gif
  ActionWait(1.5);
  ActionSpeakString(&#39;Some people started singing it not knowing what it was.&#39wink3.gif
  ActionWait(1.5);
  ActionSpeakString(&#39;And now they keep on singing it forever, just because&#39wink3.gif
  }


Опять... редактор заменил символ " ' " на "&#39 wink3.gif "

Автор: greye Jan 3 2009, 12:36

В первом скрипте ошибка, должно быть AssignCommand(последние две буквы assign). Ну и чтобы совсем хорошо было, надо добавить перед этим AssignCommand(oVoin, ClearAllActions());
Во втором - кавычки должны быть двойные: не ('), а ("), надо не забывать закрывать скобки и ставить в конце строки ;

Neverwinter Script
void main()
{
    ClearAllActions();
    ActionSpeakString("This is the song that never ends.");
    ActionWait(1.5);
    ActionSpeakString("Yes it goes on and on, my friends.");
    ActionWait(1.5);
    ActionSpeakString("Some people started singing it not knowing what it was.");
    ActionWait(1.5);
    ActionSpeakString("And now they'll keep on singing it forever, just because...");
}


Автор: RebOOter Jan 3 2009, 14:57

Цитата(greye @ Jan 3 2009, 15:36) *
В первом скрипте ошибка, должно быть AssignCommand(последние две буквы assign). Ну и чтобы совсем хорошо было, надо добавить перед этим AssignCommand(oVoin, ClearAllActions());
Во втором - кавычки должны быть двойные: не ('), а ("), надо не забывать закрывать скобки и ставить в конце строки ;


По первому компилятор "дал добро". Спасибо!)

А по второму, ковычки я ставлю двойные и точку с зяпятой тоже ставлю, но компилятор всё равно в той-же строке ошибку выдаёт sad.gif

Автор: RebOOter Jan 4 2009, 06:25

Второй скрип запахал!)) В ковычках дело было... а в примере одна была smile.gif

А второй скрипт без ошибок, но не рабочий... не хотят они друг друга атаковать.

Автор: Marta Jul 25 2009, 12:59

Чувствуется, у админов и у всех остальных летние каникулы. Но все же, вдруг кто зайдет. Не могу написать скрипт одевания брони на ГГ через диалог. Поможите, люди добрые, подскажите, что здесь не так:

Neverwinter Script
// Проба. Одеть вещь в слот.

void main()
{
    object oPC = GetPCSpeaker();
    object oItem = GetObjectByTag("NW_CLOTH018");
   

  AssignCommand( oPC, ActionEquipItem(oItem, INVENTORY_SLOT_CHEST) );


}


И почему у меня эта долбаное действие ActionEquipItem вообще не работает, вплоть до того, что не работает стандартный скрипт ga_equip_slot ? Может быть, кто-то знает, какой командой в этом случае можно заменить ActionEquipItem?

Автор: azathoth Jul 25 2009, 20:20

Neverwinter Script
object oItem = GetObjectByTag("NW_CLOTH018");

может быть дело в том, что таких объектов много, и берётся объект не в инвентаре героя; тогда лучше использовать функцию:
Neverwinter Script
object GetItemPossessedBy(object oCreature, string sItemTag)

ещё может быть стоит попробовать добавить перед одеванием ActionPauseConversation(), а после ActionResumeConversation()...

Автор: Marta Jul 25 2009, 23:40

Ух. Спасибо, что вообще ответил, но я, к сожалению, ничего не поняла. Я же не скриптер, а полный ламер. Вместо object oItem = GetObjectByTag мне надо написать object GetItemPossessedBy? Так у меня не компилируется, или как там... И непонятно, куда писать тег вещи. (object oCreature, string sItemTag("NW_CLOTH018") )? Тогда что за oCreature?

ActionPauseConversation() - это

Neverwinter Script
void    ActionPauseConversation();

?
Так все равно не компилируется.

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

Автор: azathoth Jul 26 2009, 05:16

объясню, но вряд ли кому-то это ещё пригодится, т.к. каждому нужны объяснения для себя отдельно.

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

oCreature и sItemTag - это параметры функции GetItemPossessedBy, чтобы её запустить, надо вместо них записать что нам надо, в данном случае нам нужен предмет с тегом у игрока, сделовательно oCreature - игрок, sItemTag - тэг

Neverwinter Script
object oItem = GetItemPossessedBy(oPC, "NW_CLOTH018");

Автор: Marta Jul 26 2009, 13:23

Вах, сработало! Спасибо огромное, - а то я уже неделю бъюсь!

Но стандартный скрипт ga_equip_slot у меня не работает точно, я ничего не напутала. Поэтому кладу сюда получившийся скриптик имени azathoth для счастья будущих поколений, - вдруг у кого-то еще возникнут такие проблемы. Скрипт одевает броню на ГГ через диалог, и только после того, как через ga_give_item добавляешь эту самую броню в инвентарь ГГ на предыдущей фразе.

Neverwinter Script
//::    Проба. Одеть броню на ГГ.

void main()
{
    object oPC = GetPCSpeaker();
    object oItem = GetItemPossessedBy(oPC, "NW_CLOTH018");
   
  AssignCommand( oPC, ActionEquipItem(oItem, INVENTORY_SLOT_CHEST) );
 
}


azathoth, спасибо. Ты мне просто весь сценарий спас.

Автор: Marta Jul 27 2009, 13:56

Еще вопрос, - к azathoth, или еще к кому-нибудь.

Мне надо написать скрипт - расовую проверку, - объединить дварфов, гномов и хоббитов как бы в одну расу, чтобы не вешать на одну фразу три проверки сразу (у меня там еще проверки висят, некрасиво получится, если на одной фразе штук десять скриптов будет висеть, да и не уверена, что это возможно.)

Я попыталась приравнять гномов и хоббитов к дварфам, чтобы можно было в окошке sRase(String) выставить единицу, и не париться. Но, что ни напишу, все компилируется, но ни хрена не работает.

Сначала я просто написала

Neverwinter Script
else if(sRace == "gnome" || nRace == 1)


Не сработало. Оно и понятно, - выше по списку числятся дварфы, у которых тоже прописана цифра 1. Тогда я переписала:
Neverwinter Script
else if (sRace == "halfling" || nRace == 3)
    {
    return (nRacialType == 1 || nRacialType == 11);
    }

Опять не сработало. Пишу другой вариант:

Neverwinter Script
else if(sRace == "gnome" || nRace == 3)
    {
        nRacialType = GetRacialType(oPC);
        nCheck = RACIAL_TYPE_GNOME;
        return (nRacialType == 1 || nRacialType == 11);
    }

Не работает. Если я пишу гномам nRace == 1, это не влияет. Я думаю, может дело в субрасах. Пишу:
Neverwinter Script
else if(GetStringLeft(sRace, 13) == "lightfoothalf" || nRace == 15)
    {
    return (nRacialType == 1 || nRacialType == 11);
    }

И опять, блин, не работает. Вопрос, - что бы тут еще можно было написать, чтобы заработало, а то этот скрипт видит одних дварфов, как и стандартный скрипт gc_check_race_pc, и толку с него нет никакого. Почему не срабатывает return? Неясно. Если бы я разбиралась в скриптах, я бы, конечно, не мучила бы стандартный скрипт, а написала бы что-то вроде "дварфы, гномы, хоббиты == True, все остальные == False", но я вообще без понятия как и в какой форме такое пишут. Со стандартными скриптами иногда хоть что-то путное выходит. Так что, - в очередной раз, помогите, плиз, кто-нибудь.

Автор: Lex Jul 28 2009, 11:48

должно быть что-то такое:

Neverwinter Script
int nRacialType = GetRacialType(oPC);
return (nRacialType==RACIAL_TYPE_GNOME || nRacialType==RACIAL_TYPE_DWARF || nRacialType==RACIAL_TYPE_HALFLING);

эта конструкция вернет TRUE, если раса игрока одна из трех. А на какие условия втыкать работу этого блока - тебе виднее. Можно замутить что-то универсальное, чтобы из диалога передавался символьный код, например GDH, который понимался бы скриптом как гномы/дварфы/халфлинги. Но имхо под конкретный модуль проще сделать несколько общих скриптов. Если у тебя всегда такая комбинация карликов, то проще сделать для этого отдельный скрипт и не париться.

зы: не уверен в правильности расовых констант, пишу по памяти.

Автор: Marta Jul 28 2009, 14:30

Lex, прости, но вообще не поняла. Я же говорю, - я не скриптер, не программер, - я сценарист.

Мне что, писать

Neverwinter Script
// gc_check_race_PC_correct

int StartingConditional(string sRace)
{
    object oPC = GetPCSpeaker();
    int nRacialType = GetRacialType(oPC);
    return (nRacialType==RACIAL_TYPE_GNOME || nRacialType==RACIAL_TYPE_DWARF || nRacialType==RACIAL_TYPE_HALFLING);
}

?

Но если я пишу (string sRace), это предполагает, что будет окно sRase(String), - и что мне в это окно писать? А если я не пишу (string sRace), то что вместо него написать-то?

Или мне по-прежнему основываться на стандартном скрипте, и расписывать все расы, типа if(sRace == "dwarf" || nRace == 1) , но как? Какой смысл возвращать расу гномов к "RACIAL_TYPE_GNOME", уж не говоря о том, что в стандартном скрипте не int nRacialType = GetRacialType(oPC); , а int nRacialType = GetSubRace(oPC); . На этом мысль останавливается.

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

Автор: Lex Jul 28 2009, 15:38

а ты не пиши (string sRace). И вместо него ничего не пиши. Для данного скрипта тебе вводные параметры из диалога не нужны.

Neverwinter Script
int StartingConditional()
{
    int nRacialType = GetRacialType(GetPCSpeaker());
    return (nRacialType==RACIAL_TYPE_GNOME || nRacialType==RACIAL_TYPE_DWARF || nRacialType==RACIAL_TYPE_HALFLING);
}


Цитата(Marta @ Jul 28 2009, 14:30) *
А что касается таких замороченных заклинаний, как "символьный код GDH", так на нашем болоте об этой темной некромантии и не слыхивали, и я таких словов вообще не знаю. Ты уж, пожалуйста, будь проще с народом.

я лишь имел ввиду передачу из диалога данных в виде строки "GHD", которая бы скриптом расценивалась как: "TRUE, если игрок Gnone, Halfling или Dwarf". Но сейчас я еще раз над этим подумал - плохая идея. Получится большой скрипт (разбор сторки на символы, анализ символов, формирование результата бинарным сложением для упрощения проверки и собственно сама проверка), и нужно будет каждый раз верно ставить буквы. Имхо проще несколько более простых скриптов без внешних параметров.

Автор: Marta Jul 28 2009, 17:30

Ес-с, работает. Не знала, что после int StartingConditional надо скобки оставлять :-). Может быть, в итоге я чему-то выучусь, и перестану уже тупить, но пока до этого далеко.
Спасибо огромное.


Автор: Chimeric Aug 3 2009, 15:46

Общий вопрос. Известно, что Обсидиан отличается от Авроры интерфейсом и некоторыми функциями - я слышал про cutscenes и ActionSit. Я здесь не говорю про маппинг, который может отличаться сильно. Меня интересуют основные, традиционные функции скриптов Авроры. Годны ли они в целом? Иными словами, если я возьму типичный, средней сложности скрипт для Авроры с проверками пола, времени суток и т.п., или скрипт со spawn и уничтожением объектов, с установкой глобальных переменных, такого рода вещами, сколько из этого придется менять?


Автор: Griffon Aug 3 2009, 16:14

В целом скрипты не отличаются и их можно использовать в обоих редакторах. Полный список неработающих функций должен быть на офф форумею К слову, ActionSit одна из них. Более подробно расскажет комадна шарда БГ или Ванес, он тож активно переносил все на НВН2.

http://nwvault.ign.com/View.php?view=NWN2Articles.Detail&id=156#_Toc146633941


Автор: Chimeric Aug 6 2009, 16:56

Спасибо.

Еще вопрос: задавался ли кто-нибудь системой скриптов для изучения заклинаний (spell research)?


Автор: Georgus Aug 25 2009, 14:57

Приветствую уважаемых мастеров. У меня такой вопрос - как сделать, чтобы после смерти персонаж возрождался не в месте гибели, а в указанном мною. Вопрос второй - как сделать чтобы после смерти персонаж вообще не воскрешался, а вылетала табличка из НВН2 (игра окончена, все свободны: загрузка или выход). Заранее спасибо.


З.Ы Да да, я уже знаю. Я НУБ и ламер=)

Автор: Griffon Aug 26 2009, 15:25

Neverwinter Script
V1.1                  l  Ќ                                                                                                                          gui_death_respawn_self              Щ  mod_onplayerdeath                Щ  mod_onplayerrespawn              Щ  0  Ц    ?  E  †  // gui_death_respawn_self
/*
    NWN2 Default Death Screen 'Respawn' callback
*/

// BMA-OEI 7/20/06
// BMA-OEI 11/08/06 -- Close SCREEN_DEATH_DEFAULT
/*
  You can place your real respawn script in here or
  you can use it like I did and execute it on the player.
*/



#include "ginc_death"


void main()
{
    //ResurrectCreature( OBJECT_SELF );
    ExecuteScript("mod_onplayerrespawn",OBJECT_SELF);
    CloseGUIScreen( OBJECT_SELF, "SCREEN_DEATH_DEFAULT" );
}/*
    mod_onplayerdeath
*/

const string GUI_DEFAULT_DEATH_SCREEN = "SCREEN_DEATH_DEFAULT";

// Display death pop-up to oPlayer
void ShowDefaultDeathScreen( object oPlayer );

void main()
{
    object oPlayer = GetLastPlayerDied();   
    DelayCommand( 2.5f, ShowDefaultDeathScreen( oPlayer ) );
}

// Display death pop-up to oPlayer
void ShowDefaultDeathScreen( object oPlayer )
{
    DisplayGuiScreen( oPlayer, GUI_DEFAULT_DEATH_SCREEN, FALSE );
    //DisplayMessageBox( oPlayer, 0, GetStringByStrRef(181408), "gui_death_respawn_self", "", FALSE, "", 6603, "", 0, "" );
}/*
    mod_onplayerrespawn
*/

#include "nw_i0_plot"
#include "ginc_death"
#include "x0_i0_transport"

//::  Applies an XP and GP penalty
//::    to the player respawning
//::  object oDead - Player who died.
void ApplyPenalty(object oDead);
//::  Gets the tag of the destination waypoint
//::  object oDead - Player who died.
string GetDestinationTag(object oDead);
//::  Gets the respawning player
object GetRespawningPlayer();
//::  Gets the respawn point, if any
//::  sDestTag - tag of the destination waypoint
//::  oDead - Player who died
object GetRespawnPoint(string sDestTag, object oDead);

void main()
{
    //Create initial variables
    object oRespawner = GetRespawningPlayer();
    object oArea = GetArea(oRespawner);
    string sDestTag = GetDestinationTag(oRespawner);
    object oRespawnPoint = GetRespawnPoint(sDestTag, oRespawner);
    location lDeathSpot = GetLocation(GetLastRespawnButtonPresser());
    location lRespawnPoint;
   
    //Apply effects to PC
    ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectRe
surrection(),oRespawner);
    ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectHe
al(GetMaxHitPoints(oRespawner)), oRespawner);
    RemoveEffects(oRespawner);
   
    //Apply death penalty
    ApplyPenalty(oRespawner);
   
    //Transport PC
    if (GetIsObjectValid(oRespawnPoint))
    {
        lRespawnPoint = GetLocation(oRespawnPoint);
        TransportToLocation(oRespawner,lRespawnPoint);
    }
   
    //Bring PC back to life
    DelayCommand(1.5,ResurrectCreature(oRespawner));
}

void ApplyPenalty(object oDead)
{
    location lDeathSpot = GetLocation(oDead);
    int nXP = GetXP(oDead);
    int nPenalty = 50 * GetHitDice(oDead);
    int nHD = GetHitDice(oDead);
    // * You can not lose a level with this respawning
    int nMin = ((nHD * (nHD - 1)) / 2) * 1000;

    int nNewXP = nXP - nPenalty;
    if (nNewXP < nMin)
      nNewXP = nMin;
    SetXP(oDead, nNewXP);
    int nGoldToTake =    FloatToInt(0.10 * GetGold(oDead));
    // * a cap of 10 000gp taken from you
    if (nGoldToTake > 10000)
    {
        nGoldToTake = 10000;
    }
    AssignCommand(oDead, TakeGoldFromCreature(nGoldToTake, oDead, TRUE));
    DelayCommand(4.0, FloatingTextStrRefOnCreature(58299, oDead, FALSE));
    DelayCommand(4.8, FloatingTextStrRefOnCreature(58300, oDead, FALSE));
}

string GetDestinationTag(object oDead)
{
    //You can go about determining where the respawn waypoint
    //is located a number of ways.  In here I have two examples.
    //    Determined by setting a string variable on the area called sRespawn
    //    Manually set it.
    string sTag = "";
    object oArea = GetArea(oDead);
    //Get tag based on area level variable
    sTag = GetLocalString(oArea,"sRespawnTag");
    //Check for tag and default to a module level variable
    if(sTag == "")
    {
        sTag = GetLocalString(GetModule(),"sRespawnTag");
    }
    //Manually set tag
    //sTag = "";
    return sTag;
}

object GetRespawningPlayer()
{
    //This should be OBJECT_SELF, however if not then
    //we can use the player that last pressed the respawn
    //button.
    object oPlayer = OBJECT_INVALID;
    oPlayer = OBJECT_SELF;
    //Make sure this is a PC
    if(!GetIsPC(oPlayer))
    {
        oPlayer = GetLastRespawnButtonPresser();
    }
    return oPlayer;
}

object GetRespawnPoint(string sDestTag, object oDead)
{
    //Get the waypoint object by using the destination
    //tag.  First we try for one in the current area by
    //using GetNearestObjectByTag, otherwise we jsut get
    //an object with that tag.
    object oRespawnPoint = OBJECT_INVALID;
    oRespawnPoint = GetNearestObjectByTag(sDestTag,oDead);
    if(!GetIsObjectValid(oRespawnPoint))
    {
        oRespawnPoint = GetWaypointByTag(sDestTag);
    }
    return oRespawnPoint;
}

Автор: Lex Aug 27 2009, 08:40

Грифон, ты опасен!
Подумай над своей реакцией, если бы я на твои ранние вопросы по скриптам так бы отвечал smile.gif

Автор: Aiwan Aug 27 2009, 11:15

Lex, тогда парня надо отправлять сразу в тему по обучению скриптам. Через месяц выкладывать даваемое по кускам smile.gif

Автор: Georgus Aug 27 2009, 12:46

Хех, спасиб . Попробую разобраться в данном скрипте.

Автор: Griffon Aug 27 2009, 13:35

Lex, я на то и рассчитывал, что гуру скриптинга сразу же прокомментируют, выкинут лишнее и вынесут вердикт. biggrin.gif

Автор: Lex Aug 27 2009, 14:45

Цитата(Griffon @ Aug 27 2009, 13:35) *
Lex, я на то и рассчитывал, что гуру скриптинга сразу же прокомментируют, выкинут лишнее и вынесут вердикт. biggrin.gif

я вердикт выше вынес: ты опаcен smile.gif)

по теме: если нужно ТОЛЬКО респ в какой-то точке (без штрафов и прочей фигни) или вообще его убрать - то 3/4 скрипта можно выкинуть.
А вот если планируется еще куча мелких фич, динамическое изменение места респауна и тд - то выкидывать придется не так уж и много.

Но в любом случае, чтобы скрипт заработал - нужно еще понаставить доп. объектов и переменные задать.

Автор: Melshin Dec 15 2009, 06:00

Реализую не стакающиеся бонусы к атаке разноименных типов (ДнД 3.5, ем буквы).

Вариант 1:

Код
effect MoraleBonus (effect eEffect)
{
    eEffect = SetEffectSpellId (eEffect, 1600);
    return eEffect;
}



Вариант 2 - хранение переменных/массивов на объекте-цели или в БД.

Вопрос - как сделать все так, чтобы и диспелл был меньше, чем на 20 страниц кода и длительность нескольких разных спеллов с одноименными эффектами выверялась нормально?

P.S. только что задумался о создании динамического списка на модуле...

Если что, у нас есть еще вот такой список своих функций:

void AppendArrayInt(object obj,string bufName,int value);
int GetArrayInt(object obj,string bufName,int index);
void SetArrayInt(object obj,string bufName,int index,int value);

void AppendArrayLoc(object obj,string bufName,location value);
location GetArrayLoc(object obj,string bufName,int index);
void SetArrayLoc(object obj,string bufName,int index,location value);

void AppendArrayString(object obj,string bufName,string value);
string GetArrayString(object obj,string bufName,int index);
void SetArrayString(object obj,string bufName,int index,string value);

void AppendArrayFloat(object obj,string bufName,float value);
float GetArrayFloat(object obj,string bufName,int index);
void SetArrayFloat(object obj,string bufName,int index,float value);


void AppendArrayObject(object obj,string bufName,object value);
object GetArrayObject(object obj,string bufName,int index);
void SetArrayObject(object obj,string bufName,int index,object value);


void DestroyArray(object obj,string bufName,int type=tINT);
int IsArraySet(object obj,string bufName);
int GetArrayIdxCount(object obj,string bufName);
void DestroyArrayIdx(object obj,string bufName,int index,int type=tINT);
int Split(object obj,string str,string bufName,int type=tSTR,string separator=",");
int SplitCount(string str,string separator=",");
void OutputArray(object obj,string bufName,int type,object oPC=OBJECT_INVALID);

void CreateMatrix(object obj,string bufName,int width,int height);
void DeleteMatrix(object obj,string bufName,int type=tINT);
void ExpandMatrix(object obj,string bufName,int xcount,int ycount);
int GetMatrixInt(object obj,string bufName,int x,int y);
string GetMatrixString(object obj,string bufName,int x,int y);
float GetMatrixFloat(object obj,string bufName,int x,int y);
object GetMatrixObject(object obj,string bufName,int x,int y);
void SetMatrixInt(object obj,string bufName,int x,int y,int value);
void SetMatrixString(object obj,string bufName,int x,int y, string value);
void SetMatrixFloat(object obj,string bufName,int x,int y,float value);
void SetMatrixObject(object obj,string bufName,int x,int y,object value);

Автор: Melshin Dec 16 2009, 15:14

Цитата
P.S. только что задумался о создании динамического списка на модуле...


Начал. Вопрос к опытным мастерам: стоит ли? Будет ли у этого нормальная производительность?

Смысл вышенаписанного: при загрузке в модуль первого персонажа инициализируется рекурсивная (6 секунд) ProcessEffects (). На модуле хранится массив, в котором каждый элемент - объект, на котором находится эффект какого-то заклинания или еще чего. На каждом объекте хранится массив, в котором каждый элемент - какой-то SpellId. Для каждого существующего SpellId берутся локальные интеджеры: кастер лвл, длительность в раундах, ДЦ (если нужно, еще можно весь дамаг для ДОТ-ов сразу рассчитать, т.к. всякие эмповерд нехорошие). Если длительность не закончилась - держим на объекте эффект заклинания 6 секунд до следующего выполнения ProcessEffects. Если длительность закончилась - стираем нафиг спелл из массива и всю информацию о нем. Если объект подвергся диспеллу - работаем с соответствующим массивом.

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

Так вот собственно объектов в модуле много, на каждом может быть несколько спеллов, а в каждом спелле разные эффекты...

Автор: Merkuta Feb 22 2010, 00:33

Извините если не по теме, но есть ли русскоязычные статьи по основам скриптинга для nwn2? Я недавно взялся за тулсет. Освоил практически всё кроме скриптов и не знаю как к ним подступиться. С использованием готовых скриптов в диалогах вроде разобрался, но дальше никак.

Вот например, нужны такие скрипты:

1) Если переменная Local Int "XXXXX" принимает значение 1, начинается отсчёт времени, после которого переменная возвращается в значение 0.

2) Если игрок покидает локацию, все открытые двери в этой локации закрываются.

3) Если в сундуке А есть вещи, они переносятся в сундук Б.

Автор: Lorendroll Feb 22 2010, 15:31

Merkuta,
1) Для этого переменная твоя должна быть локальной, и где-то храниться. Например на игроке. Для этого задавай ее так:

Neverwinter Script
object oPC = GetFirstPC(); //будет брать первого игрока в модуле. Если игрок один это сработает. Иначе придумай как нам найти нужного (зависит от того, откуда запускается скрипт)

SetLocalInt(oPC, "A", 1); //А = 1


В другом месте, где надо ее проверять и запускать таймер, пиши:

Neverwinter Script
object oPC = GetFirstPC();

int A = GetLocalInt(oPC, "A"); //берем с первого попавшегося игрока переменную А

if (A == 1)
{
float fTime = 10.0; //через сколько секунд занулять будем?
DelayCommand(fTime, SetLocalInt(oPC, "A", 0));
}


2) Это намного сложнее.

3) Здесь нужно организовать цикл перебора всех вещей в сундуке А и копирования их в сундук Б.

Напиши мне в аську/пм, подскажу по ходу дела, если нужно.


Melshin, думаю если воспользуешься NWNX и подрубишь внешнюю БД, то производительность будет норм. Если юзать стандартные скрипты для работы с массивами - загрузишь его серьезно. Но наверняка не могу говорить.

Автор: Kcapra May 26 2010, 15:15

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

Neverwinter Script
#include "inc_array_system"

void main()
{
object oPC = GetFirstPC(1);
//if (!GetIsPC(oPC)) return;
int nInt; int nDay; int nMin; int nHr;
nInt = array_get_int(oPC, "timer", 3);
nInt = nInt + 3; //изменяется в зависимости от текущего таймскейла
array_set_int(oPC, "timer", 3, nInt);
/*if (array_get_int(oPC, "timer", 4) == 60)     //seconds into minutes
    {
        nMin = array_get_int(oPC, "timer", 3);
        nMin = nMin + 1;
        array_set_int(oPC, "timer", 3, nMin);
        array_set_int(oPC, "timer", 4, 0);
    }*/

if (array_get_int(oPC, "timer", 3) == 60)     //minutes into hours
    {   
        nHr = array_get_int(oPC, "timer", 2);
        nHr = nHr + 1;
        array_set_int(oPC, "timer", 2, nHr);
        array_set_int(oPC, "timer", 3, 0);
    }
if (array_get_int(oPC, "timer", 2) == 24)    //hours into days
    {   
        nDay = array_get_int(oPC, "timer", 1);
        nDay = nDay + 1;
        array_set_int(oPC, "timer", 1, nDay);
        array_set_int(oPC, "timer", 2, 0);
    }
}


в качестве inc_array_system используется http://nwvault.ign.com/View.php?view=Scripts.Detail&id=129 скрипт.

Проблема в том, что нифига это ненадежно и недостоверно. Из-за фаст тревелов/возможных кастомных системах отдыхов и прочего. Может быть есть какой-нибудь более простой способ/функции о которых я даже не подозреваю?
Использоваться это будет в сингл модуле.

Автор: Lex May 26 2010, 16:17

самый простой способ работы с игровым временем, имхо, это его пересчет в игровые секунды. Те текущий месяц, день и час пересчитывается в секунды и сравнивается с контрольным для определения, прошло ли нужное количество времени или нет. Этим решается проблема временных скипов в скриптах. Проверять можно не каждые 6 секунд, а лишь когда нужно (в диалоге, в скрипте и тд), что экономит ресурсы. И тд.

Автор: Kcapra May 26 2010, 17:01

Цитата(Lex @ May 26 2010, 21:17) *
самый простой способ работы с игровым временем, имхо, это его пересчет в игровые секунды. Те текущий месяц, день и час пересчитывается в секунды и сравнивается с контрольным для определения, прошло ли нужное количество времени или нет. Этим решается проблема временных скипов в скриптах. Проверять можно не каждые 6 секунд, а лишь когда нужно (в диалоге, в скрипте и тд), что экономит ресурсы. И тд.

Не, для меня это не подходит, нужно чтобы все юзер-френдли было crazy.gif

Можно допустим сделать такой костыль: при первой загрузки модуля (самой-самой первой) создается массив, в который записывается день, час, минута, секунда (последнее можно и не использовать), затем на хардбит вешается скрипт который создает другой массив, записывает в него текущую день, час, минуту, секунду затем эти массивы между собой вычитает и получается вполне себе достоверный таймер

Только топорно все это, и, ввиду малого опыта работы с большими модами, спрашиваю скажется ли это негативно на перфомансе?

Автор: denis0k May 26 2010, 23:43

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

Автор: Lex May 27 2010, 09:29

Цитата(Kcapra @ May 26 2010, 18:01) *
Не, для меня это не подходит, нужно чтобы все юзер-френдли было crazy.gif

для юзерфрендлиности нужно все расчеты спрятать внутрь инклуда, оставив снаружи несколько управляющих функций. Например:
* SetTimer(string sTimerName); - запоминаем текущее время и привязываем число к sTimerName для последующей работы с ним пользователя
* CheckTimer(string sTimerName, int nTimeHour, int nTimeMinute = 0); - проверемя разницу между текущим временем и запомненым по идентификатору. Тру - если прошло больше времени, чем указано в nTimeHour/nTimeMinute
* DeleteTimer(string sTimerName); - удалить таймер

Довольно плотно в свое время работал с внутриигровым временем, по своему опыту скажу: в 90% случаев не нужно в каждый момент знать сколько прошло (те каждые 6 секунд ничего пересчитывать не нужно), проверки прохождения энного количества времени стоят в весьма конкретных местах: вход в локу, фраза диалога и тд. У меня было лишь 2-3 случая, когда пришлось повесить на ХБ, потому что отложенное событие было само по себе. В этой связи завязывать систему на постоянный пересчет считаю не совсем верным, пересчет должен быть вызываемым. И пусть в паре случаев вызов будет в ХБ, ничего страшного.

Автор: Kcapra Jun 5 2010, 06:33

Lex, спасибо, момент с вызовом функции по требованию что-то совсем выпал из головы prankster2.gif

Автор: gennady Jun 5 2010, 11:48

Тут для теста Аз написал скрипт подсчета игрового времени. Цикл вывода инфы 5 минут, подсчета 1 минута. Может пригодится...

Neverwinter Script
//::///////////////////////////////////////////////
//:: Скрип работает при загрузке модуля
//:: FileName: module_load
//:: auth: azathoth
////////////////////////////////////////////////////////////////////////////////
// *****  ПОДСЧЕТ ВРЕМЕНИ ДЛЯ ТЕСТА  *****
////////////////////////////////////////////////////////////////////////////////
void Count(int nTimer)
{
object oPC = GetFirstPC();
object oMod =  GetModule();
int iHB = GetLocalInt(oMod, "HB_TIME");

SetLocalInt(oMod, "HB_TIME", iHB+1);
if(iHB >= 4)
{
  int iTimeGameM = GetLocalInt(oMod, "Time_Game_M"); //минуты
  int iTimeGameH = GetLocalInt(oMod, "Time_Game_H"); //часы
   SetLocalInt(oMod, "HB_TIME", 0);
  if(iTimeGameM > 55)
   {
    iTimeGameH++;
    SetLocalInt(oMod, "Time_Game_H", iTimeGameH); //часы
    SetLocalInt(oMod, "Time_Game_M", 0); //минуты
   }
  else
   {
    iTimeGameM+=5;
    SetLocalInt(oMod, "Time_Game_M", iTimeGameM);
   }
  SendMessageToPC(oPC, "Длительность игры: "+IntToString(iTimeGameH)+" ч. "+IntToString(iTimeGameM)+" мин.");
}
  DelayCommand(60.0, Count(nTimer + 1));
}
////////////////////////////////////////////////////////////////////////////////
void main()
{

// ================= ДЛЯ ТЕСТА ====================
if (GetLocalInt(GetModule(), "START_TIME_TEST") == 0) // Проверить
  {
   SetLocalInt(GetModule(),"START_TIME_TEST",1);
   Count(0);
  }
}

Автор: Merkuta Jun 20 2010, 19:16

Мне нужно было написать скрипт, который перемещает вещи из одного сундука в другой. Решил вопрос так:

Neverwinter Script
void main()

{
object oPC = GetFirstPC(),
      oChest_01 = GetObjectByTag("RC_chest_01"),
      oChest_02 = GetObjectByTag("RC_chest_02"),
      oItem = GetFirstItemInInventory(oChest_01),
      oItem_in;
     
//string sString = "скрипт сработал";

while(GetIsObjectValid(oItem))
  {             
  //FloatingTextStringOnCreature(sString, oPC);
  CopyItem(oItem, oChest_02);
  DestroyObject(oItem);
 
  //sString = "скрипт сработал более одного раза";
  oItem = GetNextItemInInventory(oChest_01);         
  }
 
//FloatingTextStringOnCreature("вещей нет", oPC); 
return
}


Однако выяснилось, что предметы типа контейнера не копируются, если в них что-то есть. Копируется только их содержимое.
Сам контейнер пропадает. Попробовал решить вопрос следующим образом(хотя ясно, что это не совсем то, что нужно):

Neverwinter Script
void main()

{
object oPC = GetFirstPC(),
      oChest_01 = GetObjectByTag("RC_chest_01"),
      oChest_02 = GetObjectByTag("RC_chest_02"),
      oItem = GetFirstItemInInventory(oChest_01),
      oItem_in;
     
//string sString = "скрипт сработал";

while(GetIsObjectValid(oItem))
  {             
  //FloatingTextStringOnCreature(sString, oPC);
 
  while(GetHasInventory(oItem)) 
      {      
      oItem_in =  GetFirstItemInInventory(oItem);
     
      while(GetIsObjectValid(oItem_in))     
        {       
        CopyItem(oItem_in, oChest_02);
        DestroyObject(oItem_in);
        oItem_in = GetNextItemInInventory(oItem);   
        }    
       
      CopyItem(oItem, oChest_02);
      DestroyObject(oItem);
      oItem = GetNextItemInInventory(oChest_01);       
      }   
     
  CopyItem(oItem, oChest_02);
  DestroyObject(oItem);
 
  //sString = "скрипт сработал более одного раза";
  oItem = GetNextItemInInventory(oChest_01);         
  }
 
//FloatingTextStringOnCreature("вещей нет", oPC); 
return
}


Но в этом случае предметы из контейнера копируются дважды, а сам контейнер опять же пропадает. Есть идеи, как скопировать контейнер с вложенными в него вещами?

Автор: denis0k Jun 20 2010, 23:17

Никак. Sad, but true.

Автор: Laajin Jun 21 2010, 07:05

ну по идеи нужно скопировать/создать сначала сам контейнер
а потом скопировать вещи из одного в другой

у тебя во всех скриптах копируются только вещи

Автор: Merkuta Jun 21 2010, 08:13

Цитата(Laajin @ Jun 21 2010, 07:05) *
ну по идеи нужно скопировать/создать сначала сам контейнер

И как это сделать?
Во втором скрипте я исходил из того, что после перебора, копирования и удаления всех вещей в контейнере, он станет пустым и скопируется нормально. Но не получилось.

Автор: denis0k Jun 21 2010, 08:41

Контейнеры вообще зло smile.gif

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

Автор: greye Jun 21 2010, 16:54

Цитата(Merkuta @ Jun 5 2010, 11:48) *
Есть идеи, как скопировать контейнер с вложенными в него вещами?

В первом это можно было сделать при помощи ActionGiveItem, но на втором не проверялось.
Хотя можно и с копированием извратиться при особом желании.

Автор: Merkuta Jun 21 2010, 18:02

Цитата(greye @ Jun 21 2010, 16:54) *
В первом это можно было сделать при помощи ActionGiveItem, но на втором не проверялось.
Хотя можно и с копированием извратиться при особом желании.

Спасибо, контейнер действительно переносится со всеми вложенными вещами.
Neverwinter Script
void main()

{
object oPC = GetFirstPC(),
      oChest_01 = GetObjectByTag("RC_chest_01"),
      oChest_02 = GetObjectByTag("RC_chest_02"),
      oItem = GetFirstItemInInventory(oChest_01),
      oItem_in;
     
//string sString = "скрипт сработал";

while(GetIsObjectValid(oItem))
  {             
  //FloatingTextStringOnCreature(sString, oPC);
  AssignCommand(oChest_01, ActionGiveItem(oItem, oChest_02));
 
 
  //sString = "скрипт сработал более одного раза";
  oItem = GetNextItemInInventory(oChest_01);         
  }
 
//FloatingTextStringOnCreature("вещей нет", oPC); 
return
}


Автор: denis0k Jun 21 2010, 23:42

Эпично smile.gif Помню даже на волте видел когда-то скрипт, где всё копировалось, а вот контейнер уничтожался, и в комментах было типа "так надо, иначе дюп" smile.gif

Автор: Aiwan Jun 22 2010, 04:33

Да, здорово... Сразу вспоминается куча проблем при работе с рюкзаками. smile.gif

Автор: denis0k Jun 22 2010, 08:08

Ну если ActionGiveItem() работает через стек действий, то с игроком может не прокатить (скажем, дроп при смерти, или забитый стек, или дикие лаги). Но вот между сундуками работает smile.gif

Автор: Ilerien Jun 22 2010, 11:03

Если уж так приспичило, сундук всегда можно пересоздать с палитры rolleyes.gif

Автор: greye Jun 22 2010, 11:55

Цитата(denis0k @ Jun 22 2010, 08:08) *
то с игроком может не прокатить (скажем, дроп при смерти, или забитый стек, или дикие лаги)

Разве что дикие лаги, потому что остальное обходится без проблем.=)

Автор: GoodLuc Jun 24 2010, 18:15

Извините, если вопрос не по теме. Я видел, как в обе NWN прикручивали новые навыки (feats). Я понял, что это делали через скрипт, но как?
Кто-нибудь так делал?

Автор: Lex Jun 24 2010, 19:01

нужно 2da таблицы ковырять: feats + spells + еще пара по мелочи, и конечно же скрипты. Все это довольно подробно описано в разделе Кастом Контент в категории тулсета первого НВН (во втором суть та же, мб чуток больше параметров).
Новые фиты могут быть только активными. Пассивные вещи типа (+1 атака всегда) сделать нельзя, к сожалению. Те можно, но коряво и через попу. Или через nwnx - но это только для мультиплеера.

Автор: GoodLuc Jun 24 2010, 23:22

Цитата
Все это довольно подробно описано в разделе Кастом Контент в категории тулсета первого НВН

А где именно?

Автор: Lex Jun 27 2010, 01:21

где-то в этой теме: http://www.city-of-masters.ru/forums/index.php?showtopic=78

Автор: PaiNt Jul 15 2010, 10:20

Хотел поделится скриптом строкового массива, может мне бы его оптимизировали..


Neverwinter Script

Автор: azathoth Jul 15 2010, 18:40

Neverwinter Script
if(GetStringLength(sDevider)!=1) sDevider=",";

Ага, незадокумментированная фича!

Автор: PaiNt Jul 16 2010, 01:53

Цитата(azathoth @ Jul 16 2010, 01:40) *
Neverwinter Script
if(GetStringLength(sDevider)!=1) sDevider=",";

Ага, незадокумментированная фича!

Да, smile.gif вот бы вспомнить как вообще все это работает smile.gif

Поидее функция позволяяет добавлять элемент в конец массива (удлинять массив).
Как и было замечено разделитель предусматривается только односимвольный.

Автор: azathoth Jul 16 2010, 08:35

Цитата
вот бы вспомнить как вообще все это работает

ну уж даже если ты не вспомнишь, то вряд ли тут найдутся добровольцы сами разобраться и ещё оптимизировать.

Автор: liantey Aug 11 2010, 12:51

у меня твердое намеренье, ввести в свою компанию что-то типа замка из офф компании...
если это возмоно силами одного человека ( а в этом я не сомневаюсь) подкиньте идей, а еще лучше подскажите где найти грамотный гайд именно по скриптописанию. все остальный что я встречал, ничего путного на эту тему не говорят.

п.с. я не чужд программированию и т.д. т.п., но синтаксиса тулсета не знаю. И на русском ничего не нашел. (А с английским я провожусь не один месяц...)

Автор: Lex Aug 12 2010, 08:44

на русском есть лишь пара совсем нубских гайдов и пару глав про скрипты в НВН1. Если не чужд программированию, то тебе по сути только функции изучить (циклы, условия, объявление переменных и тд тебе должно быть знакомо, синтаксис си тоже не должен вызвать трудностей). А тут никакой гайд не поможет, только ковыряние.

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

Автор: Lorendroll Aug 12 2010, 17:04

Мне в своё время очень помогли ресурсы www.nwnlexicon.com / nwn1.nwn2lexicon.com и nwn2.wikia.com. Легко переводятся при помощи Google Translate, хотя там довольно просто все написано и так.
А в самом начале мне жутко помогла тулза под названием http://nwvault.ign.com/View.php?view=other.detail&id=625. Разбирая то, как она генерит скрипты, можно быстро научиться приемам работы.

Автор: DilanZendal Aug 14 2010, 15:35

Есть у Священника заклинание 4-го круга, называется "Декламация". Действует на всех союзников, давая бонус к атаке, спасброскам и КЗ +2, если божество у цели то же, что у заклинателя, то +3.
Выглядит так:

Neverwinter Script
#include "nwn2_inc_spells"


#include "x2_inc_spellhook"

void main()
{
    if (!X2PreSpellCastCode())
    {    // If code within the PreSpellCastHook (i.e. UMD) reports FALSE, do not run this spell
        return;
    }

    // Declare major variables
    object oCaster = OBJECT_SELF;
    int nCasterLvl = GetCasterLevel(oCaster);
    float fDuration = RoundsToSeconds(nCasterLvl);
    fDuration = ApplyMetamagicDurationMods(fDuration);
    int nDurType = ApplyMetamagicDurationTypeMods(DURATION_TYPE_TEMPO
RARY);
    location lTarget = GetLocation(oCaster);

    // effects
    effect eAC;
    effect eAttack;
    effect eSave;
    effect eVis = EffectVisualEffect(VFX_DUR_SPELL_RECITATION);
    effect eLink;
   
    // find the first target
    object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_VAST, lTarget, TRUE, OBJECT_TYPE_CREATURE);
   
    while (GetIsObjectValid(oTarget)) {
       if (spellsIsTarget(oTarget, SPELL_TARGET_ALLALLIES, oCaster)) {
      
          //Fire cast spell at event for the specified target
          SignalEvent(oTarget, EventSpellCastAt(oCaster, GetSpellId(), FALSE));
         
          int nBonus = 2;
          if (GetStringLowerCase(GetDeity(oTarget)) == GetStringLowerCase(GetDeity(oCaster))) {
             nBonus = 3;
          }
          eAC = EffectACIncrease(nBonus, AC_DODGE_BONUS, AC_VS_DAMAGE_TYPE_ALL);
          eAttack = EffectAttackIncrease(nBonus);
          eSave = EffectSavingThrowIncrease(SAVING_THROW_ALL, nBonus, SAVING_THROW_TYPE_ALL);
          eLink = EffectLinkEffects(eAC, eAttack);
          eLink = EffectLinkEffects(eLink, eSave);
          eLink = EffectLinkEffects(eLink, eVis);
      
          RemoveEffectsFromSpell(oTarget, GetSpellId());
      
             //Apply the VFX impact and effects
             ApplyEffectToObject(nDurType, eLink, oTarget, fDuration);
       }
       oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_VAST, lTarget, TRUE, OBJECT_TYPE_CREATURE);
    }      
}



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

Автор: Alian REXis Aug 14 2010, 19:44

Цитата(DilanZendal @ Aug 14 2010, 16:35) *
Помогите поправить, пожалуйста. Нужно чтобы под действие заклинания попадали только дружественные аутсайдеры, плюс чтобы не было бонуса для них, если божество совпадает с божеством заклинателя. Как это сделать?

вроде так
Neverwinter Script
#include "nwn2_inc_spells"


#include "x2_inc_spellhook"

void main()
{
    if (!X2PreSpellCastCode())
    {    // If code within the PreSpellCastHook (i.e. UMD) reports FALSE, do not run this spell
        return;
    }

    // Declare major variables
    object oCaster = OBJECT_SELF;
    int nCasterLvl = GetCasterLevel(oCaster);
    float fDuration = RoundsToSeconds(nCasterLvl);
    fDuration = ApplyMetamagicDurationMods(fDuration);
    int nDurType = ApplyMetamagicDurationTypeMods(DURATION_TYPE_TEMPO
RARY);
    location lTarget = GetLocation(oCaster);

    // effects
    effect eAC;
    effect eAttack;
    effect eSave;
    effect eVis = EffectVisualEffect(VFX_DUR_SPELL_RECITATION);
    effect eLink;
   
    // find the first target
    object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_VAST, lTarget, TRUE, OBJECT_TYPE_CREATURE);
   
    while (GetIsObjectValid(oTarget)) {
      if (spellsIsTarget(oTarget, SPELL_TARGET_ALLALLIES, oCaster)) {
     
          //Fire cast spell at event for the specified target
          SignalEvent(oTarget, EventSpellCastAt(oCaster, GetSpellId(), FALSE));
         
          int nBonus = 2;
          /*if (GetStringLowerCase(GetDeity(oTarget)) == GetStringLowerCase(GetDeity(oCaster))) {
            nBonus = 3;
          } */

          eAC = EffectACIncrease(nBonus, AC_DODGE_BONUS, AC_VS_DAMAGE_TYPE_ALL);
          eAttack = EffectAttackIncrease(nBonus);
          eSave = EffectSavingThrowIncrease(SAVING_THROW_ALL, nBonus, SAVING_THROW_TYPE_ALL);
          eLink = EffectLinkEffects(eAC, eAttack);
          eLink = EffectLinkEffects(eLink, eSave);
          eLink = EffectLinkEffects(eLink, eVis);
     
          RemoveEffectsFromSpell(oTarget, GetSpellId());
     
            //Apply the VFX impact and effects
          if ((GetRacialType(oTarget)==RACIAL_TYPE_OUTSIDER)&&(!GetIsEnemy(oTarget)))
            ApplyEffectToObject(nDurType, eLink, oTarget, fDuration);
      }
      oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_VAST, lTarget, TRUE, OBJECT_TYPE_CREATURE);
    }     
}

Автор: DilanZendal Sep 9 2010, 12:54

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

Neverwinter Script
void main()
{
    int nWisdomBonus  = GetAbilityModifier(ABILITY_WISDOM);
    int nDuration = 5 + GetAbilityModifier(ABILITY_WISDOM);
    int nBonus = nWisdomBonus;

    effect eBonAttack = EffectAttackIncrease(nBonus);
    effect eBonDamFire = EffectDamageIncrease(nBonus, DAMAGE_TYPE_FIRE);
    effect eDodgeAc = EffectACIncrease(nBonus, AC_DODGE_BONUS)
    effect eFists = EffectVisualEffect(VFX_DUR_SACRED_FLAMES);
    effect eBody = EffectVisualEffect(VFX_DUR_INNER_ARMOR);

    effect eLink = EffectLinkEffects(eBonAttack, eBonDamPhysic);
    eLink = EffectLinkEffects(eLink, eDodgeAc);
    eLink = EffectLinkEffects(eLink, eFists);
    eLink = EffectLinkEffects(eLink, eBody);

    ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, OBJECT_SELF, RoundsToSeconds(nDuration));
}

Автор: Merkuta Sep 9 2010, 14:03

А у тебя редактор разве не указывает строчку, в которой допущена ошибка? Всего-то точки с запятой нет вот здесь: effect eDodgeAc = EffectACIncrease(nBonus, AC_DODGE_BONUS)

Автор: DilanZendal Sep 9 2010, 21:18

блин, точно. Вот это называется "невнимательность". Кажется, пора выспаться.
Merkuta, спасибо.

Автор: Orochi Sep 19 2010, 15:07

Где в 2d прописывать свои названия расс и классов?

Автор: Orochi Sep 21 2010, 13:03

А? shout.gif

Автор: Ghost Sep 21 2010, 13:18

http://www.city-of-masters.ru/forums/index.php?showtopic=4227. Когда же вы научитесь искать по форуму, писать в соответствующих темах и не флудить? sad.gif

Автор: Orochi Sep 22 2010, 15:02

Чувак,ответь на все мои вопросы и я больше не буду писать не в тему,ОК? rolleyes.gif

Автор: denis0k Sep 22 2010, 18:55

Извините, не удержался. "Чувак" - это кастрированный баран. А "чувиха" - "проститутка" на воровском жаргоне начала 20го века.

Автор: Ghost Sep 22 2010, 19:11

Цитата(Orochi @ Sep 22 2010, 16:02) *
Чувак,ответь на все мои вопросы и я больше не буду писать не в тему,ОК? rolleyes.gif

Ооо... На "все"(!) ваши вопросы отвечать это дело неблагодарное. И дело даже не в том что я и сам многого не знаю. Вы задали вопрос не по теме, я указал нужную тему где "возможно" эта проблема уже обсуждалась, но Вам мало... Разжевать и в рот положить? Уж пардон за слегка резкий тон... Хотя если честно вообще не вижу с чего вдруг мне оправдываться.
Цитата(denis0k @ Sep 22 2010, 19:55) *
Извините, не удержался...

Забавно. smile.gif Не знал этого. Но так уж и быть, разрешаю администрации и модераторам не бить банхаммером товарища за оскорбление меня. smile.gif

Автор: Lex Sep 23 2010, 15:14

Цитата(Orochi @ Sep 22 2010, 15:02) *
Чувак,ответь на все мои вопросы и я больше не буду писать не в тему,ОК? rolleyes.gif

Не, чувак, все немного не так. Будешь писать не в тему (или в такой же нагловатой манере, как сейчас) - схлопочешь пред.

Автор: Kcapra Sep 23 2010, 16:40

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

Neverwinter Script
void main()

{

if (GetLocalInt(OBJECT_SELF, "script_fired") != TRUE)
    {
        SetLocalInt(OBJECT_SELF, "script_fired", TRUE);
       
        ClearAllActions();
       
        //AssignCommand(OBJECT_SELF, (ActionWait(2.0)));
       
        AssignCommand(OBJECT_SELF, (ActionSpeakString("строка1")));
       
        AssignCommand(OBJECT_SELF, (ActionWait(120.0)));
       
        AssignCommand(OBJECT_SELF, (ActionSpeakString("строка2")));
       
        AssignCommand(OBJECT_SELF, (ActionWait(120.0)));
       
        AssignCommand(OBJECT_SELF, (ActionSpeakString("строка3")));
       
        SetLocalInt(OBJECT_SELF, "script_fired", FALSE);
       
    }


}

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

Автор: denis0k Sep 23 2010, 18:47

Wait-ы тормозят непися, а не исполнение скрипта. Флаг запуска скидывается сразу же после установки, поэтому через 6 сек скрипт срабатывает по новой.

Автор: Kcapra Sep 24 2010, 05:31

Ну и как же мне тогда поступить?
А то я хз вообще.

Автор: PaiNt Sep 24 2010, 06:15

Делай удаление переменной таймера с какии-то периодом. Типа

Neverwinter Script
void main()
{
if(GetLocalInt(OBJECT_SELF, "TIMEOUT"))  return;
SetLocalInt(OBJECT_SELF, "TIMEOUT", TRUE);
DelayCommand(3600.0, DeleteLocalInt(OBJECT_SELF, "TIMEOUT"));


...Твой код
}


Правда проверки сердцебиения проводятся раз в 6с так что действия не кратные этому промежутку сделать проблематично.

Русская версия Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)