virusman
Jan 2 2005, 20:03
Neverwinter Script Source |
oTemp = GetFirstObjectInArea(OBJECT_SELF); while(GetIsObjectValid(oTemp)) { if(GetTag(oTemp)=="vir_dw_snow") { CreateObject(OBJECT_TYPE_PLACEABLE, "x0_snowdrift", GetLocation(oTemp)); DestroyObject(oTemp); oTemp = GetNextObjectInArea(OBJECT_SELF); } } |
Выполнение этого куска скрипта приводит к многократному созданию плейсебла в одной точке + подвисанию и таймауту скрипта. ГДЕ здесь бесконечный цикл создания объекта?!
Lukas Addon
Jan 2 2005, 20:42
Возможно надо сделать так чтобы этот скрипт выполнялся 1 раз
то есть добавить переменную
ВИРЬ, ну ты даешь!!
Neverwinter Script Source |
oTemp = GetFirstObjectInArea(OBJECT_SELF); while(GetIsObjectValid(oTemp)) { if(GetTag(oTemp)=="vir_dw_snow") { CreateObject(OBJECT_TYPE_PLACEABLE, "x0_snowdrift", GetLocation(oTemp)); DestroyObject(oTemp); } oTemp = GetNextObjectInArea(OBJECT_SELF); } |
надеюсь, объяснять не надо, почему так, а не так, как ты написал? (примерно неделю назад ТОЧНО ТАКОЙ ЖЕ случай зацикливания кто-то выложил. Я там расписал, почему так, а не иначе. )
2GoDoom
Jan 2 2005, 21:17
И что не понятного?
пока oTemp = GetFirstObjectInArea(OBJECT_SELF); - будет "совпадать" - будет выполняться условие...
может стоит сделать for (правда не помню я - есть ли он в НВНе)
Ну или в While вписать другие условия...
А вообще - что требуется от скрипта?
virusman
Jan 2 2005, 21:24
Брр. Опять не тот исходник выложил.
У меня и:
Neverwinter Script Source |
oTemp = GetFirstObjectInArea(OBJECT_SELF); while(GetIsObjectValid(oTemp)) { if(GetTag(oTemp)=="vir_dw_snow") { CreateObject(OBJECT_TYPE_PLACEABLE, "x0_snowdrift", GetLocation(oTemp)); DestroyObject(oTemp); } oTemp = GetNextObjectInArea(OBJECT_SELF); } |
Действовал абсолютно аналогично.
Эх..ладно, что-то меня совесть замучила. Сейчас объясню для тех, кто не понял еще раз и тему закрою. (Твин, можно это в ФАК занести потом будет)
Neverwinter Script Source |
oTemp = GetFirstObjectInArea(OBJECT_SELF); while(GetIsObjectValid(oTemp)) { if(GetTag(oTemp)=="vir_dw_snow") { CreateObject(OBJECT_TYPE_PLACEABLE, "x0_snowdrift", GetLocation(oTemp)); DestroyObject(oTemp); oTemp = GetNextObjectInArea(OBJECT_SELF); } } |
Идея скрипта такова: замещение одного объекта другим. Те цикл, который перебирает все объекты локации, и если тэг объекта совпадает с тэгом заменяемого объекта (тут это "vir_dw_snow") то мы создаем новый объект, а старый удаляем.
А теперь что НА САМОМ деле тут происходит.
Первый же объект в локации, который будет иметь тэг не "vir_dw_snow" повесит скрипт. ТАК КАК ПЕРЕОБОЗНАЧЕНИЕ ПЕРЕМЕННОЙ oTemp ПРОИСХОДИТ ВНУТРИ УСЛОВИЯ ПРОВЕРКИ ТЭГА. Другими словами, если тэг не "vir_dw_snow" то этот объект и будет вечно бегать по циклу, другой не берется.
Что делать?
Правильно, перенести переобозначение объекта (oTemp = GetNextObjectInArea(OBJECT_SELF)
в тело цикла. Те получаем вот это:
Neverwinter Script Source |
oTemp = GetFirstObjectInArea(OBJECT_SELF); while(GetIsObjectValid(oTemp)) { if(GetTag(oTemp)=="vir_dw_snow") { CreateObject(OBJECT_TYPE_PLACEABLE, "x0_snowdrift", GetLocation(oTemp)); DestroyObject(oTemp); } oTemp = GetNextObjectInArea(OBJECT_SELF); } |
Добавлено в [mergetime]1104690570[/mergetime]
Вирь, да не может такого быть. У меня такие скрипты работают как часы.
virusman
Jan 2 2005, 21:37
Да я знаю, в чем баг скрипта, который в первом посте. Это я просто криво его восстановил после различных безуспешных попыток что-то другое намудрить. Первоначальный вариант был как у тебя. И он виснет.
Такая же проблема и у меня сегодня возникла. Но я только создаю объекты в таком цикле.
Причина возможно кроется в том что, в цикле по всем объекта в локе нельзя создавать и, возможно, удалять объекты, находящиеся в этой же локе. Похоже меняются указатели на след. объект.
я писал скрипты отчистки локации от мусора. Все работает. А это удаление объектов в цикле.
virusman
Jan 2 2005, 22:33
QUOTE |
Такая же проблема и у меня сегодня возникла. Но я только создаю объекты в таком цикле. Причина возможно кроется в том что, в цикле по всем объекта в локе нельзя создавать и, возможно, удалять объекты, находящиеся в этой же локе. Похоже меняются указатели на след. объект. |
Я пробовал так:
Neverwinter Script Source |
oTemp = GetFirstObjectInArea(OBJECT_SELF); while(GetIsObjectValid(oTemp)) { if(GetTag(oTemp)=="vir_dw_snow") { CreateObject(OBJECT_TYPE_PLACEABLE, "x0_snowdrift", GetLocation(oTemp)); DestroyObject(oTemp); oTemp = GetFirstObjectInArea(OBJECT_SELF); } else { oTemp = GetNextObjectInArea(OBJECT_SELF); } } |
Результат: игра уже не виснет, но при каждом вызове создается куча плейсеблов в одной точке, после чего скрипт вылетает с таймаутом (при след. вызове скрипт все-таки переходит на другую точку).
Neverwinter Script Source |
oTemp = GetFirstObjectInArea(OBJECT_SELF); while(GetIsObjectValid(oTemp)) { if(GetTag(oTemp)=="vir_dw_snow") { CreateObject(OBJECT_TYPE_PLACEABLE, "x0_snowdrift", GetLocation(oTemp)); DestroyObject(oTemp); oTemp = GetFirstObjectInArea(OBJECT_SELF); // может сюда надо oTemp = GetNextObjectInArea(OBJECT_SELF); } else { oTemp = GetNextObjectInArea(OBJECT_SELF); } } |
virusman
Jan 2 2005, 22:35
QUOTE |
я писал скрипты отчистки локации от мусора. Все работает. А это удаление объектов в цикле. |
Да у меня тоже.. Даже отложенные вызовы и вложенные циклы в некоторых местах применялись. Но именно в этом скрипте почему-то все виснет. Может, потому что он висит на heartbeat локации? Я с этим уже не в первый раз сталкиваюсь: чуть раньше у меня один модуль вообще вызывал синий экран и зависание всего компа, когда heartbeat локации посылал команды NPC.
virusman
Jan 2 2005, 22:43
QUOTE (Lex @ Jan 2 2005, 22:35) |
Neverwinter Script Source | oTemp = GetFirstObjectInArea(OBJECT_SELF); while(GetIsObjectValid(oTemp)) { if(GetTag(oTemp)=="vir_dw_snow") { CreateObject(OBJECT_TYPE_PLACEABLE, "x0_snowdrift", GetLocation(oTemp)); DestroyObject(oTemp); oTemp = GetFirstObjectInArea(OBJECT_SELF); // может сюда надо oTemp = GetNextObjectInArea(OBJECT_SELF); } else { oTemp = GetNextObjectInArea(OBJECT_SELF); } } |
|
Результат тот же. Виснет.
Neverwinter Script Source |
string sName, sTag; int nNum = 0;
object oTemp = GetFirstObjectInArea(OBJECT_SELF); while (oTemp != OBJECT_INVALID) { sName = GetName(oTemp); if (GetStringLeft(sName, 2) == "SP") { nNum++; SetLocalObject(OBJECT_SELF,"SP"+IntToString(nNum),oTemp); } oTemp = GetNextObjectInArea(OBJECT_SELF); }
int i; for (i=1; i <= nNum; i++) { oTemp = GetLocalObject(OBJECT_SELF, "SP"+IntToString(i)); if (oTemp != OBJECT_INVALID) { CreateObject(OBJECT_TYPE_CREATURE, GetTag(oTemp), GetLocation(oTemp), FALSE, GetTag(oTemp)); } } |
Сделал в 2 этапа. Первый цикл проходит, но при включении 2го - повисание. Этот скрипт висит на OnEnter локи. Или у меня во втором цикле ошибка?
я не работаю с for в скриптах почти никогда.
i=1;
while (i<=nNum)
{
....
i++;
}
virusman
Jan 3 2005, 00:02
Кстати, юзайте Script Debugger.
Завтра гляну, что он напишет про мой скрипт.
Вариант рабочий:
Neverwinter Script Source |
void main() { int nCount = 0; location lTemp;
object oTemp = GetFirstObjectInArea(GetObjectByTag("AREA001"));
while ( GetIsObjectValid(oTemp) ) { if ( GetTag(oTemp) == "StatueDefaced" ) { SetLocalLocation(OBJECT_SELF, "TEMP_CreDelItems_"+ IntToString(nCount), GetLocation(oTemp) ); nCount++;
DestroyObject(oTemp); }
oTemp = GetNextObjectInArea(GetObjectByTag("AREA001")); }
for ( ; nCount >= 0; nCount-- ) { lTemp = GetLocalLocation(OBJECT_SELF, "TEMP_CreDelItems_"+ IntToString(nCount) ); DeleteLocalLocation(OBJECT_SELF, "TEMP_CreDelItems_"+ IntToString(nCount) );
CreateObject(OBJECT_TYPE_PLACEABLE, "plc_impledcrpse1", lTemp); } } |
OBJECT_SELF - в данном случае это модуль.
Остается только проблема с созданием новых плейсов на месте старых статичных. Статичеые плейсы не удаляются и в _первом_ цикле участвуют (но потом куда-то из цикла пропадают, странно
). В общем, если девелоппер гарантирует, что все плейсы, заменяемые в цикле будут не статичными, то всё окей. Имхо.
Да, Твин верно заметил, что для уничтожаемых плэйсов надо ОБЯЗАТЕЛЬНО снимать галку Static. Не забывайте!
Neverwinter Script Source |
void VoidCreateObject(int nType, string sResRef, location lLoc) { CreateObject(nType, sResRef, lLoc); }
void main() { object oTemp = GetFirstObjectInArea(OBJECT_SELF); location lLoc; while(GetIsObjectValid(oTemp)) { if(GetTag(oTemp)=="vir_dw_snow") { lLoc = GetLocation(oTemp); ActionDoCommand(DestroyObject(oTemp)); // вот так правильнее ActionDoCommand(VoidCreateObject(OBJECT_TYPE_PLACEABLE, "x0_snowdrift", lLoc)); } oTemp = GetNextObjectInArea(OBJECT_SELF); } } |
вот это должно работать...
DBColl: Чуток исправлю...
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста,
нажмите сюда.