Игроделу | Встречи | Neverwinter Nights Основной Список созданий Письмена Улучшенный
По сайту
Главная
Рыцарская сага
Файлы
Neverwinter Nights
Гостевая книга
Форум сайта

По теме
Игроделу
Редактор фракций
Редактор журнала
Редактор диалога
Редактор скрипта
Модуль и области
Двери
Монстры
Встречи
Предметы
Торговцы
Объекты
Триггеры
Звуки
Тайлы
Хак файлы
Скриптинг
Neverwinter NightsвстречиИгроделу
Встречи - Neverwinter Nights


Внимание! Рисунок интерактивный, можно кликать по обведенным секторам.

Встречи

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

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

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

Скрипты:

  1. OnEnter – событие при входе
  2. OnExhausted – событие при уничтожение последнего монстра
  3. OnExit – событие при выходе
  4. OnHeartbeat – циклическое событие т.е. через 6 секунд
  5. OnUserDefined – событие при подаче сигнала

На вход можно повесить какие-либо реплики героя или монстров, визуальный эффект или просто локалку на посещение этого района. Примеры приводить не буду, это уж дело вкуса…

Панелька “Улучшенный” на верхнем рисунке, довольно важна при настройке. Фракция монстров может быть любая из стандартных или ваших настроенных. Следует помнить о том, что если в данный момент фракция не враждебна к герою, или если галка “Срабатывает только для игрока” не проставлена, то к тому кто войдет в этот триггер, то никакой встречи не будет! “Респаун встреч” – это повтор встречи через определенное ниже время, также можно проставить сколько раз эта встреча состоится. А если поставить галку “Бесконечные Восстановления”, то будут бесконечные встречи. Если отключит галку “Активный”, то встреч не будет. Это нужно для активации встречи посредством скриптов. Вот функция включения выключения, если TRUE, то включен:

SetEncounterActive(TRUE, GetObjectByTag("VOLKI"));

Нарисовав триггер встречи, и кликнув правой кнопкой мыши, можно выбрать “Добавить Точку Входа”, тогда мы зададим определенную точку появления монстров, причем монстры будут появляться лицом в ту сторону, в которую направлена точка. Точку можно вращать, переставлять и удалять при необходимости, как обычную точку маршрута, только закончив операцию с триггером и точкой, она пропадет из поля зрения. Чтобы опять ее увидеть, щелкните по триггеру…

Некоторые бесконечные встречи, бывает необходимость отключить, например, после выполнения определенного задания. Как это сделать? Тут есть пара нюансов… триггер встреч нельзя удалить! К тому же сработав, он переходит в глухую оборону, и к нему не достучатся, пока не выйдет время респауна. Остается вариант повесить на его OnHeartbeat скрипт, и отследить событие и время зарядки. Сам скрипт:

///////////////////////////////
//:: Слот: OnHeartbeat
//:: File name: end_encounter
///////////////////////////////
void main()
{
object oSelf = OBJECT_SELF;
if(GetEncounterActive()==FALSE || GetLocalInt(oSelf, "LOC")==0) return;
SetEncounterActive(FALSE);
}

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

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

//:://////////////////////////////////////////////
//::  ТРИГГЕР ВСТРЕЧ С МОНСТРАМИ ПО ЗАДАННЫМ ТОЧКАМ
//:: Created By: Gennady    Name:  vstrecha_point
//:: Created On: 11.10.2006
//:://////////////////////////////////////////////
void main()
{
 object oPC = GetEnteringObject();
 object oSelf = OBJECT_SELF;
 int iPoint = 1;
 object oPoint = GetNearestObjectByTag("LOC_"+GetTag(oSelf), oSelf, iPoint);
 string sResRef = GetName(oSelf); // Объект создаваемый
 if(!GetIsPC(oPC)||GetLocalInt(oSelf, "DEACTIVATED")) return;
 while (GetIsObjectValid(oPoint))
  {
   location lLoc = GetLocation(oPoint);
   CreateObject(OBJECT_TYPE_CREATURE, sResRef, lLoc,FALSE);
   iPoint++;
   DestroyObject(oPoint);
   oPoint = GetNearestObjectByTag("LOC_"+GetTag(oSelf), oSelf, iPoint);
  }
    SetLocalInt(oSelf, "DEACTIVATED", TRUE);
    DestroyObject(oSelf, 7.0);
}
/*            Встреча
  Триггер содержит в названии ResRef объкта, который появится.
  Точка, где появится объект LOC_+Тег триггера. 
*/

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

//:://////////////////////////////////////////////
//:: Created By: Gennady ТРИГГЕР ВСТРЕЧ С МОНСТРАМИ
//:: Created On: 27.04.2006
//:://////////////////////////////////////////////
void main()
{
 object oPC = GetEnteringObject();
 object oSelf = OBJECT_SELF;
 object oPlc = GetNearestObjectByTag("LOC_"+GetTag(oSelf));
 location lLoc = GetLocation(oPlc);
 string sResRef = GetName(oSelf); // Объект создаваемый
 string sNewTag = GetTag(oSelf);  // Тег созданиЯ
 int iN = StringToInt(GetLockKeyTag(oSelf)); // Количество созданий
 int iNN = StringToInt(sNewTag); // Количество встреч
 int iNM = 0;
 effect eEffect1 = EffectVisualEffect(VFX_IMP_LIGHTNING_M);
 effect eEffect2 = EffectVisualEffect(VFX_IMP_DISPEL);
 string sNum = GetStringRight(sNewTag, 2);
 float fTime = 360.0; // ВРЕМЯ ЗАРЯДКИ

 if(!GetIsPC(oPC)||GetLocalInt(oSelf, "DEACTIVATED")) return;
   SetLocalInt(oSelf, "DEACTIVATED", TRUE);
  while (iN != iNM)
  {
   if (GetIsObjectValid(oPlc))
   CreateObject(OBJECT_TYPE_CREATURE, sResRef, lLoc,FALSE,sNewTag);
   else
   CreateObject(OBJECT_TYPE_CREATURE, sResRef, GetLocation(oSelf),FALSE,sNewTag);
   iNM++;
  }
 if (GetIsObjectValid(oPlc))
 {
  ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eEffect1, GetLocation(oPlc));
  DelayCommand(1.5, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eEffect2, 
  GetLocation(oPlc)));
 }
 else
 {
  ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eEffect1, GetLocation(oSelf));
  DelayCommand(1.5, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eEffect2, 
  GetLocation(oSelf)));
 }
 if (GetStringLeft(sNum, 1) == "_")
 {
  sNum = GetStringRight(sNewTag, 1);
  int iTime = StringToInt(sNum); // Множитель времени
  fTime *= iTime;
 }
    DelayCommand(fTime, SetLocalInt(oSelf, "DEACTIVATED", FALSE));
 if (iNN < 1)return; // Если первый символ тэга буква
    SetLocalInt(oSelf, "NUM", GetLocalInt(oSelf, "NUM") + 1);
    if (GetLocalInt(oSelf, "NUM") >= iNN)
    DestroyObject(oSelf, 2.0);
}
/*            Встреча
  Триггер содержит в названии ResRef объкта, который появится.
  Точка, где появится объект LOC_+Тег триггера, если точки нет - то к триггеру.
  Поле триггера KeyTag - Количество созданий
  Если тег триггера 1, то встреча только один раз, если другой,
  то повтор через 360 секунд, если цифра, то это количество встреч.
  Если в теге после "_" стоит цифра - то это множитель времени
*/

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

//:://////////////////////////////////////////////
//::  ТРИГГЕР ВСТРЕЧ С МОНСТРАМИ С УЧЕТОМ УРОВНЯ ГЕРОЯ
//:: File Name: vstrecha_n_level
//:://////////////////////////////////////////////
void LevelMonster(object oPC, object oNPC)
{
 int iLevPC = GetHitDice(oPC)/2+GetHitDice(oPC);
 int iLevNPC = GetHitDice(oNPC);

if (GetLevelByClass(CLASS_TYPE_WIZARD, oNPC)==1) // Класс маг
{
 while (iLevPC > iLevNPC)
 {
  LevelUpHenchman(oNPC, CLASS_TYPE_WIZARD, TRUE);
  iLevNPC++;
 }
 return;
}
if (GetLevelByClass(CLASS_TYPE_SORCERER, oNPC)==1) // Класс колдун
{
 while (iLevPC > iLevNPC)
 {
  LevelUpHenchman(oNPC, CLASS_TYPE_SORCERER, TRUE);
  iLevNPC++;
 }
 return;
}
if (GetLevelByClass(CLASS_TYPE_CLERIC, oNPC)==1) // Класс СВЯЩЕННИК
{
 while (iLevPC > iLevNPC)
 {
  LevelUpHenchman(oNPC, CLASS_TYPE_CLERIC, TRUE);
  iLevNPC++;
 }
 return;
}
 while (iLevPC > iLevNPC)
 {
  LevelUpHenchman(oNPC, CLASS_TYPE_FIGHTER); // Класс воин
  iLevNPC++;
 }
}
////////////////////////////////////////////////////////////////////////////////
void main()
{
 object oPC = GetEnteringObject();
 object oSelf = OBJECT_SELF;
 object oPlc = GetNearestObjectByTag("LOC_"+GetTag(oSelf));
 location lLoc = GetLocation(oPlc);
 string sResRef = GetName(oSelf); // Объект создаваемый
 string sNewTag = GetTag(oSelf);  // Тег созданиЯ
 string sStrL = GetStringLeft(sNewTag, 2);  // 2 первых левых символа
 string sEff = GetStringLeft(sNewTag, 3);  // 3 первых левых символа
 string sDay = GetStringLeft(sNewTag, 4);  // 4 первых левых символа
 int iN = StringToInt(GetLockKeyTag(oSelf)); // Количество созданий
 int iNN = StringToInt(GetStringLeft(sNewTag, 1)); // Количество встреч
 int iNM = 0;
 effect eEffect1 = EffectVisualEffect(VFX_IMP_LIGHTNING_M);
 effect eEffect2 = EffectVisualEffect(VFX_IMP_DISPEL);
 string sNum = GetStringRight(sNewTag, 2);
 float fTime = 360.0; // ВРЕМЯ ЗАРЯДКИ

 if(GetStringRight(sDay, 1)== "N" && GetIsDay()) return; // если день
 if(!GetIsPC(oPC)||GetLocalInt(oSelf, "DEACTIVATED")) return;
 if(GetStringRight(sStrL, 1)== "_")
 {
  int iEnd = GetStringLength(sNewTag)-2; // количество знаков в надписи
  sStrL = GetStringRight(sNewTag, iEnd);
  if (GetLocalInt(oPC, sStrL) == 0) return; // Проверить локалку
 }
  SetLocalInt(oSelf, "DEACTIVATED", TRUE);
 if(GetStringRight(sEff, 1)== "A") // Красный круг
    eEffect1 = EffectVisualEffect(VFX_FNF_LOS_EVIL_20);
 if(GetStringRight(sEff, 1)== "B") // Желтый круг
    eEffect1 = EffectVisualEffect(VFX_FNF_LOS_HOLY_20);
 if(GetStringRight(sEff, 1)== "C") // Воронка синего тумана
    eEffect1 = EffectVisualEffect(VFX_FNF_DISPEL_GREATER);
 if(GetStringRight(sEff, 1)== "N") // Нет эффектов
  {
    eEffect1 = EffectVisualEffect(-1);
    eEffect2 = EffectVisualEffect(-1);
  }

  while (iN != iNM)
  {
   if (GetIsObjectValid(oPlc))
   {
    object oNPC = CreateObject(OBJECT_TYPE_CREATURE, sResRef, lLoc,FALSE);
    LevelMonster(oPC, oNPC);
   }
   else
   {
    object oNPC = CreateObject(OBJECT_TYPE_CREATURE, sResRef, 
    GetLocation(oSelf),FALSE);
    LevelMonster(oPC, oNPC);
   }
   iNM++;
  }
 if (GetIsObjectValid(oPlc))
 {
  ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eEffect1, GetLocation(oPlc));
  DelayCommand(1.5, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eEffect2, 
  GetLocation(oPlc)));
 }
 else
 {
  ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eEffect1, GetLocation(oSelf));
  DelayCommand(1.5, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eEffect2,
  GetLocation(oSelf)));
 }
 if (GetStringLeft(sNum, 1) == "_")
 {
  sNum = GetStringRight(sNewTag, 1);
  int iTime = StringToInt(sNum); // Множитель времени
  fTime *= iTime;
 }
    DelayCommand(fTime, SetLocalInt(oSelf, "DEACTIVATED", FALSE));
  if (iNN < 1)return; // Если первый символ тэга буква
    SetLocalInt(oSelf, "NUM", GetLocalInt(oSelf, "NUM") + 1);
    if (GetLocalInt(oSelf, "NUM") >= iNN)
    DestroyObject(oSelf, 2.0);
}
/*            Встреча
  Триггер содержит в названии ResRef объкта, который появится.
  Точка, где появится объект LOC_+Тег триггера, если точки нет - то к триггеру.
  Поле триггера KeyTag - Количество созданий
  Если первый символ тэга цифра, то это количество встреч.
  Если первый символ тэга буква, то будут бесконечные встречи.
  Если в конце тэга после "_" стоит цифра, то это множитель ЗАРЯДКИ (360 секунд)
  Третий символ тэга сменит эффект молнии при появлении монстров (А, В, С, N)
  Если другой символ, то эффект молния, если буква N, то нет эффектов.
  Уровень монстров равен 150% от уровня героя.
  Если в тэгe 2 символ "_", то дальше в тэге идет имя локалки на ПС.
  Если эта локалка равна нулю, то встречи не будет.
  Если 4 символ тэга "N" то встреча только ночью.
*/
Обновление: Rambler's Top100