Помощь - Поиск - Пользователи - Календарь
Полная версия: случайная генерация локаций
Город Мастеров > РЕДАКТОРЫ > Neverwinter Nights Aurora Toolset
Milfes
Помогите пожалуйсто с решением проблемы. Предположим у меня 20 жилых домов (не играющих большой роли в игре), обязательно ли делать для каждого отдельную локацию? Или может быть возможно чтобы на одной локации происходила случайная генерация?
Aiwan
Опыт подсказывает что лучше чделать 10 уникальных запоминающихся интерьеров. Чем 30 разных генераций одного и того же. Это ИМХО.
helvene
QUOTE(Milfes @ Jul 20 2006, 23:30) [snapback]88085[/snapback]
Или может быть возможно чтобы на одной локации происходила случайная генерация?

Возможно на патче 1.67
Но для домов - совершенно не нужно.
Milfes
QUOTE
Опыт подсказывает что лучше чделать 10 уникальных запоминающихся интерьеров. Чем 30 разных генераций одного и того же. Это ИМХО.


То есть ты имееш ввиду, что предположим 2 каких-то двери преведут в одну локацию, а две других в другую?
virusman
QUOTE(helvene @ Jul 20 2006, 23:47) [snapback]88088[/snapback]
Возможно на патче 1.67
Можно меня просветить? Не знал о такой возможности.
Aiwan
QUOTE(virusman @ Jul 21 2006, 03:44) [snapback]88099[/snapback]
Можно меня просветить? Не знал о такой возможности.

И мну!!! yes3.gif
Клемент Астилон
Да вообще полезный патч вроде сделали smile.gif

Список Изменений довольно внушительный.
virusman
QUOTE(Клемент Астилон @ Jul 21 2006, 04:49) [snapback]88107[/snapback]

Да вообще полезный патч вроде сделали smile.gif

Список Изменений довольно внушительный.
Не сомневаюсь. Но в patch notes о генерации локаций ничего не сказано.
helvene
Пользуйтесь
virusman
QUOTE(helvene @ Jul 21 2006, 10:05) [snapback]88115[/snapback]
Какое это имеет отношение к локациям (в смысле area, а не location)?
helvene
Очевидно, никакого...
virusman
А жаль, я бы от динамических лок не отказался. wink3.gif
В общем-то, сгенерить локацию (особенно такую простую, как дом) можно. Поставить на все входы скрипты, задающие номер дома, а при входе в локу дома - скрипт, который будет создавать плейсеблы и NPC, соответствующие этому дому. Правда, тут появится несколько проблем с сохранением (например, если в комнате стоит ящик, то с ним придётся разбираться отдельно), да и задавать точки, куда ставить объекты, проблематично (цифрами в скрипте - неудобно, вейпоинтами - будет нагромождение).
Естественно, это только для сингла. В мультиплеере это исключено.

Наконец, самый простой и доступный вариант, без всяких генераций и скриптов - сделать одну большую локу "дом" и разместить там кучу комнат, не связанных друг с другом.
Nymor
ну генерацию обьектов можно сделать, но не тайлов
maximal_up
QUOTE(Milfes @ Jul 20 2006, 23:56) [snapback]88090[/snapback]
То есть ты имееш ввиду, что предположим 2 каких-то двери преведут в одну локацию, а две других в другую?

Нет, Айван имеет ввиду, что на каждый дом надо сделать собственную локу. А что так сложно? На одну локу интерьера уходит 30 мин максимум (у меня) и это при детальной проработке.

С генерацией у меня были идеи, но ничего толкового так в ум и не пришло.

К примеру можно сделать 16 плейсов на комнату. Далее написать скрипт (а можно ли?), чтобы при загрузке модельки этих плейсов СЛУЧАЙНО выбирались из заданного автором списка. Также можно поставить ограничение на не более 2х одинаковых плейсов.

НО ИМХО это слишком муторно и совсем не нужно.
Milfes
QUOTE
Наконец, самый простой и доступный вариант, без всяких генераций и скриптов - сделать одну большую локу "дом" и разместить там кучу комнат, не связанных друг с другом.


Но игрок помоему всё равно будет видеть все комнаты, даже если они не связаны.
-fenix-
А как на счет того, что все это будет криейтица при загрузки локи?
ИМХО могут быть всякие лаги и баги. Чем больше плейсов, тем больше вероятность.
Zirrex
Берем большую локацию, делаем в ней 10 комнат, запускаем в момент входа на такую локацию затирание карты, и довольствуемся своей комнатой. Генерировать случайную комнату можно в одиночной игре, но не стоит делать в многопользовательской, ибо всегда может произойти что-то не то, что хотелось изначально добиться.
virusman
QUOTE(Milfes @ Jul 21 2006, 18:39) [snapback]88135[/snapback]

Но игрок помоему всё равно будет видеть все комнаты, даже если они не связаны.
Только те, в которых он уже был.
denis0k
QUOTE(maximal_up @ Jul 21 2006, 16:09) [snapback]88130[/snapback]
К примеру можно сделать 16 плейсов на комнату. Далее написать скрипт (а можно ли?), чтобы при загрузке модельки этих плейсов СЛУЧАЙНО выбирались из заданного автором списка. Также можно поставить ограничение на не более 2х одинаковых плейсов.

НО ИМХО это слишком муторно и совсем не нужно.
А если так. Ставим 16 вэйпоинтов в комнате, далее лезем в скрипт и пишем цикл. Внутри цикла рандомом выбираем плейс (через свитч) и создаем на вэе с номером шага. Результат - 16 относительно случайных плейсеблов.

Но действительно муторно и все равно тайл выдаст подставу smile.gif

Зиррекс прав, у него самый идеальный (и часто используемый имхо) вариант. А главное - безглючный.
Milfes
А как делать затирание карты?
Zirrex
Milfes, в последних патчах появилась доработка к функции:

NSS
// Expose/Hide the entire map of oArea for oPlayer.
// - oArea: The area that the map will be exposed/hidden for.
// - oPlayer: The player the map will be exposed/hidden for.
// - bExplored: TRUE/FALSE. Whether the map should be completely explored or hidden.
void ExploreAreaForPlayer(object oArea, object oPlayer, int bExplored=TRUE)

Используй флажок "bExplored", чтобы затереть карту у игрока. В наборе тайлов "Микросет" можно вообще этой функцией выключить карту, на других наборах придется проверять.
Milfes
Проблема в том, что у меня нет пока последнего патча и у этой функции отсутствует последний параметр.

И ещё никто не знает где можно найти описание функций на русском языке, а то в Lexicone на английском не совсем разбираюсь?
Aiwan
Invisible Object - генерирует PLC объекты.
Скрипт спавнящий разных PLC объекты на локациях.
AM_PLC_SP_[+ TAG_OBJECT_SELF] - наши объекты.
UserDefinedEventNumber() == 7000 - Сигнал скрипту
Если установить на скрытый объект LocalFloat == "RandomLocation"
то ее значение будет радиусом на которм будет пояляться объект.
Если поставить один объект в точку, то все следующие будут появляться на его месте.
Если не ставить НИЧЕГО, то все бъекты будут создаваться на этом невидимом объекте.

Все объекты что должны появиться должны быть присовены на стринг невидимого объекта ResRef_PLC_1, ResRef_PLC_2 и т.д. ресрефом.
NSS
//:://////////////////////////////////////////////
//:: OnUserDefaine  am_cud_spawn
//:: Copyright © 2005 WRG!
//:://////////////////////////////////////////////
/*
    СКРИПТ НЕПОСРЕДСТВЕННО ИСПОЛНЯЕТ ОБМЕН PLC_
    ОБЪЕКТОВ В ЛОКАЦИЯХ В СЛУЧАЕ РАЗРУШЕНИЯ И
    В СЛУЧАЕ ВХОДА РС В ЛОКАЦИЮ ПО СИГНАЛУ

  Скрипт спавнящий разных PLC объекты на локациях.
  AM_PLC_SP_[+ТАГ OBJECT_SELF] - наши объекты.
*/

//:://////////////////////////////////////////////
//:: Created By: Aiwan
//:: Created On: 28.11.2005
//:://///////////////////////////////////////////
void Debug(string message)
{
    object oPC = GetFirstPC();
    if (!GetLocalInt(GetModule(), "DEBAG_PC"))
    {
      SendMessageToPC(oPC, "Debag message: "+message);
    }
    if (!GetLocalInt(GetModule(), "DEBAG_DM"))
          {
            SendMessageToAllDMs("Debag message to DMs: "+message);
          }
}

location CreateRandomLocation(object oTarget, float fRadius, int bOnLine = TRUE)
{
if(!bOnLine)
fRadius=IntToFloat(Random(FloatToInt(fRadius)));

float iXO=VectorMagnitude(GetPosition(oTarget))*cos(VectorToAngle(GetPosition(oTarget)));
float iYO=VectorMagnitude(GetPosition(oTarget))*sin(VectorToAngle(GetPosition(oTarget)));
float fRndomAngle=IntToFloat(Random(360));
location lNEW=Location(GetArea(oTarget),Vector(iXO+fRadius*cos(fRndomAngle),iYO+fRadius*sin(fRndomAngle)),360.0);
return lNEW;
}


void main()
{

  int nEvent = GetUserDefinedEventNumber();
  if (GetLocalInt(OBJECT_SELF, "STOP")) return; // Отключаем, если надо
  if (GetLocalInt(OBJECT_SELF, "DAYS_WAITING")>0) return;
//======================== USER DEFINED EVENT===================================
    if (nEvent == 7000)
  // nEvent == 7000 - сигнализируем скриптом.
    {
    if (GetLocalInt(OBJECT_SELF, "STOP"))
      return;

      object oSelf = OBJECT_SELF;
      string sTag = GetTag(oSelf); // Таг невидимого объекта (Общий таг группы)
      object oPlc = GetNearestObjectByTag("AM_PLC_SP_"+sTag);
      int i=1;
      string sResRef = GetLocalString(oSelf, "ResRef_PLC_"+IntToString(i));
      location lLoc; // Место где появляется наш объект

      // Задержка для стандартных объектов, зависит от имени OBJECT_SELF
      if(GetName(oSelf)=="Spawn PLC System")
      SetLocalInt(oSelf, "DAYS_WAITING", Random(6)+1);

      float f = GetLocalFloat(oSelf, "RandomLocation");
      if(f!=0.0)lLoc = CreateRandomLocation(oSelf, f);
      // Если установить на скрытый объект LocalFloat == "RandomLocation"
      // то ее значение будет радиусом на которм будет пояляться объект.
      // Если поставить один объект в точку, то все следующие будут
      // появляться на его месте. Если не ставить НИЧЕГО, то все объекты
      // будут создаваться на этом невидимом объекте.

      if(f==0.0)
      {
            if(!GetLocalInt(oSelf, "DO_THIS"))
            {
              if(oPlc != OBJECT_INVALID)
              {
                SetLocalLocation(oSelf, "SPAWN", GetLocation(oPlc));
              }
              else
                  {
                    SetLocalLocation(oSelf, "SPAWN", GetLocation(oSelf));
                  }
              SetLocalInt(oSelf, "DO_THIS", TRUE);
            }
          lLoc = GetLocalLocation(oSelf, "SPAWN");
        }

      while(sResRef!="")
      {
        i++;
        sResRef=GetLocalString(oSelf, "ResRef_PLC_"+IntToString(i));
      }
      // Так, как вверху, условие было для первого пустого значения
      // то один порядковый номер мы отнимаем из результата
      i = i-1;
      Debug("Общее число объектов - "+IntToString(i));
      int iNext = Random(i)+1;
      sResRef = GetLocalString(oSelf, "ResRef_PLC_"+IntToString(iNext));
      Debug("Следующий - "+IntToString(iNext));

      //----------------------------------------------------------------------
      //  Если выпал тот же ResRef, что стоит здесь
      //----------------------------------------------------------------------
        if(sResRef == GetResRef(oPlc))
        {
            Debug(IntToString(iNext)+" - этому PLC выпало опять быть здесь.");
            iNext++; // Увеличиваем его номер на еденицу
            if(iNext > i) iNext = 1;
            // Если номер больше общего кол-ва PLC, то начинаем с первого.
            Debug(IntToString(iNext)+" - сменим номер на еденицу больше.");
        }
        // Следующий объект на это место
        object oNext = CreateObject(OBJECT_TYPE_PLACEABLE, GetLocalString(oSelf, "ResRef_PLC_"+IntToString(iNext)), lLoc,0, "AM_PLC_SP_"+sTag);

      //----------------------------------------------------------------------
      //  Если мы открывали ящик и в нем уже есть лут
      //----------------------------------------------------------------------
        if (GetHasInventory(oPlc))
        {
          object oItem = GetFirstItemInInventory(oPlc);
          while (GetIsObjectValid(oItem))
          {
            string sTag = GetTag(oItem); // Debag message
            Debug("Destroy Item - "+sTag);
            DestroyObject(oItem);
            oItem = GetNextItemInInventory(oPlc);
          }
        }
        DestroyObject(oPlc);

    }
//------------------------------------------------------------------------------
}


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

NSS
while (oObject != OBJECT_INVALID)
    {
        if (GetObjectType(oObject) == OBJECT_TYPE_PLACEABLE)
        {
          if(GetName(oObject)=="Spawn PLC System")
          {
            int i = GetLocalInt(oObject, "DAYS_WAITING"); // Сколько дней осталось
            if(i!=0)SetLocalInt(oObject, "DAYS_WAITING", i-1);
            Debug(GetTag(oObject)+" - PLC будет в локации "+GetName(GetArea(oObject))
            +" дней: "+IntToString(GetLocalInt(oObject, "DAYS_WAITING")));
          }
        }
        oObject = GetNextObjectInArea(oArea);
    }

Этим скриптом непосредственно меняю плейсы уже на входже в локацию игроком.
NSS
object oObject = GetFirstObjectInArea(OBJECT_SELF);
  while (oObject != OBJECT_INVALID)
    {
        if (GetObjectType(oObject) == OBJECT_TYPE_PLACEABLE)
        {
          if(GetName(oObject)=="Spawn PLC System")
          {
              DelayCommand(f, SignalEvent(oObject, EventUserDefined(7000)));
              f=f+0.2; // Сделай паузу!
              Debug(GetTag(oObject)+" - PLC будет в локации "+GetName(GetArea(oObject))
              +" дней: "+IntToString(GetLocalInt(oObject, "DAYS_WAITING")));
          }
        }
        oObject = GetNextObjectInArea(OBJECT_SELF);
    }


Как все это выгляджит в реале? У меня скажем локация, в ней 10 НПС и у них свои сундуки. Таверна. Прошел день, скрипт хертбита дал отмашку, что день. Пробежался по локе, отметил что были здесь день. У кого это последний день он отметил что пора менять. Как только РС вошел в локу, то скрипт обменял эти объекты.

Для чего это сделано? Например у таверны стоит куча повозок. Каждый день два одна из них меняется. За неделю все меняются. Или на случайных локациях спавнятся деревья, палатки и прочее. Конечно все трудно описать, настроить тоже будет не легко новичку. Но если захзотеть, то можно. Ну и вопросы задавать никто не запрещает. Или в таверне через неделю сменились все НПС постояльцы а с ними и их сундуки wink3.gif
Dik Morris
QUOTE(Milfes @ Jul 23 2006, 01:53) [snapback]88187[/snapback]

И ещё никто не знает где можно найти описание функций на русском языке, а то в Lexicone на английском не совсем разбираюсь?


ЧИТАТЬ.
Milfes
Огромное спасибо! Жаль только немного, но для начала хватит.
Existor
На всякий случай напишу следующую памятку: есть возможности "пропихнуть" чара сквозь дверь, или даже разрушить плотовую запертую дверь(сам я с таким не встречался, сколько не пробовал в .66, пишу это полагаясь на свидетельства очевидцев в версии .62), поэтому все закрытые, важные внутренние переходы между комнатами этой локации оформляйте в качестве дверей трансферов, за которыми тупик. Не используйте двери в качестве перемычек между внутренними комнатами, если боитесь что недобросовестный игрок побывает везде раньше, чем вам бы хотелось...
ReyBrujo
Могу предложить еще один вариант, в котором всего лишь нужно сделать комнату (просто для разных локаций ее копировать), в ней расставить все нужные предметы, создаем триггер, потом в его переменные ставим int "roomclean" = число (сколько раз очищать комнату). Затем на онЕнтер триггера ставим код :
Скрипт просто удаляет рандомно с шансом 1 к 2 предметы. Если нужно несколько таких комнат - просто копируем комнаты(локации) в меню слева.
Триггер поставить перед входом в локацию.
Neverwinter Script
void main()
{
object oArea = GetArea(GetEnteringObject());
int nClean = GetLocalInt(oArea, "roomclean");
while(nClean>0)
{
nClean == nClean -1;
object oClean = GetFirstObjectInArea(oArea);
while(GetIsObjectValid(oClean))
{
if(GetIsPC(oClean) == FALSE)
{
switch(d2())
{
case 1: DestroyObject(oClean); break;
case 2:
}
}
oClean = GetNextObjectInArea(oArea);
}
}
DeleteLocalInt(OBJECT_SELF, "roomclean");
}


Скрипт занёс в базу.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.
Invision Power Board © 2001-2024 Invision Power Services, Inc.