Цитата
Я сам в скриптах не очень
Основываясь на весьма посредственных знаниях (!)паскаля, лексиконе, в/о с данного сайта вообще и в/о со страниц 136, 137 и 138 (а так же стр. 133, но тогда я еще по нулям был даже в паскале) данной темы я получил весьма неплохие знания (по моему мнению, ес-сно. На данной странице писали как минимум пять человек, по сравнению с которыми я, имхо, нуб и позорюсь

) нвскрипта.
Цитата
Можешь такой подкинуть или нет?
Все еще не вижу смысла в использовании ХБ. Если нужно заставить NPC вечно ходить открывать-закрывать сундуки, то первое, что пришло в голову: OnSpawn непися дописывается/ставится скрипт, заставляющий идти к первому сундуку и открыть его. На OnOpen сундука идет проверка, кто открыл, и если это нужный нам непись, то заставляем открывшего закрыть и пойти к другому сундуку, на котором повторяется то же, но учитывая, что сундук другой. Писать за тебя не буду, но попробую понятно привести лексику, что тут понадобится.
Основа
Neverwinter Script
void main() //обозначение, гхм, начала скрипта (на самом деле - процедура, но это сейчас совсем не нужно)
{ //совсем начало скрипта, только после которого можно записывать то, что скрипт делает
} //обозначает конец скрипта (в данном случае)
Переменные, их объявление и математика (возможно, страшно звучит, но пугаться не стоит: все донельзя легко)
Neverwinter Script
//Переменная - буквоциферный идентификатор чего-то (например: цифре, букве, фразе), при помощи которого можно использовать это что-то
//Объявление переменной - "говорим" скрипту, что существует такой-то идентификатор, принадлежащий к такому-то типу (см. ниже)
//Тип переменной - что может идентифицировать переменная (например, целое число). Переменная, принадлежащая к целочисленному типу не может
//обозначать, например, букву.
//Общий вид объявления переменных
/*
[тип переменной] [идентификатор1];
//или
[тип переменной] [идентификатор1] = [значение1];
//или
[тип переменной] [идентификатор1], [идентификатор2];
[другой тип переменной] [идентификатор3], [идентификатор4];
//можно комбинировать, например:
[тип переменной] [идентификатор1] = [значение1], [идентификатор2];
[другой тип переменной] [идентификатор3], [идентификатор4] = [значение2];
*/
//Список типов переменных (возможно, неполный, максимальные и минимальные значения для каждого типа описывал где-то по соседству)
/*
int - целые числа (-1; 0; 1; 2 и т.д.)
float - рациональные числа (-1.0; -0.5; 0.0; 0.5; 1.0 и т.д.)
string - буквы и строки ("a"; "abc"; "abcdefg"; "aaanbhdjfjkdfsljfh" и т.п.)
vector - координаты в трехмерном пространстве. Можно получить при помощи Vector([координата x], [координата y], [координата z]). x, y и z принадлежат float, но не обязательно являются переменными (по сути - использование переменных не обязательно и можно использовать запись Vector(1.0, 3.0, 7.5) (обращаю внимание на большую букву (регистр играет роль): с маленькой буквы получится объявление переменной типа вектор, с большой - получение значения типа вектор из трех координат), но с переменными удобнее.) Далее принадлежность переменной к какому-либо типу буду обозначать [тип] [идентификатор]
location - подробное описание местоположения чего-либо. Аналогично вектору, можно получить при помощи Location(object oArea (об объектах речь далее), vector vPosition, float fOrientation (поворот по градусам, где север - 90 градусов (см. Лексикон SetFacing)));
object - вероятно, наиболее часто используемый в нвскрипте тип. Включает в себя созданий (creature, в т.ч. и игроков), вещи, плэйсы и т.д. За подробностями - в Лексикон, OBJECT_TYPE (кроме того, что включает в себя тип object там еще можно узнать, как обозначить тот или иной подтип объекта для специфических функций, этого требующих (пока не надо))
*/
//Пример объявления переменных и примитивных мат. действий
void main()
{
int nNum = 7, nN = 5, nNumber = 4; //создаем переменные и присваиваем им значения. Т.е. создели целочисленную переменную nNum и задали
int nResult; //(присвоили) ей значение 7
nResult = nNum - nN; //присвоили переменной nResult значение разности переменных nNum и nN, т.е. nResult = nNum - nN = 7 - 5 = 2
nResult = nResult * nNumber; //присвоили переменной nResult собственное значение, умноженное на nNumber, т.е. nResult = nResult * 4 = 2 * 4 = 8
nResult = nResult * nNumber; //повторяем предыдущее действие. НО после предыдущего действия значение переменной nResult изменилось, стало
//равным восьми. Следовательно, теперь nResult = nResult * nNumber = 8 * 4 = 32
//предположим, что это скрипт, стоящий на OnOpen плэйса-контейнера
object oPC = GetLastOpenedBy(); //в таком случае GetLastOpenedBy() будет работать, ее значением будет являться (далее: он(а) возвращает
//значение) объект (наиболее вероятно, что это будет существо, но да не суть важно), открывший контейнер.
object oArea = GetArea(oPC); //GetArea(object oObj) возвращает объект-арию (локацию в плане продукта работы маппера), в которой находится
//объект oObj, в данном случае арию, где находится существо, открывшее контейнер
float fX = 6.0, fY = 7.0 - 1.0, fZ = 16.0/16.0 - 2.0; //да, значением может являться результат математического действия.
vector vPos = Vector(fX, fY, fZ); //три вышеописанных числа были использованы для создания вектора
vPos = GetPosition(oPC); //а теперь мы записали в переменную vPos координаты существа, открывшего контейнер, тем самым удалив предыдущее
vector vPos2 = Vector(fX, fY, fZ); //значение. Но в данном случае его нетрудно восстановить, что только что мы и сделали
location lLoc = Location(oArea, vPos, 90.0); //А теперь, воспользовавшись вышеполученными арией и вектором мы получили из них локацию,
location lLoc2 = GetLocation(oPC); //совпадающую с локацией открывшего, только с ориентацией на север. А сейчас мы присвоили некой переменной
lLoc = lLoc2; //lLoc2 локацию открывшего контейнер, без изменений. И приравняли к ней переменную lLoc.
}
Условия и логика
Neverwinter Script
/*
Если (на что я очень надеюсь) известны неравенства, то с примитивными условиями и такой же логикой проблем возникнуть не должно.
Как выглядит условие в нвскрипте? Очень просто:
if([условие])
{
[часть скрипта, которая будет выполнена, если условие верно и проигнорирована в противном случае]
}
else
{
[часть скрипта, которая будет выполнена, если условие неверно]
}
Так выглядит условие в полном виде (т.н. полный условный оператор)
Так же можно использовать краткую его версию:
if([условие])
{
[часть скрипта, которая будет выполнена, если условие верно и проигнорирована в противном случае]
}
Теперь: как получить логическое выражение, которое должно быть использовано как условие? Есть несколько вариантов:
1) использовать 0 и 1 как логические выражения (0 - неверное условие (в любом случае), 1 - верное)
2) использовать "неравенства", например, nNum<nN (данное условие будет верно, если переменная nNum меньше, чем nN, следовательно nNum и nN
должны быть обе одного типа: или int, или float. Ес-сно сравнить локацию и целое число не получится)
Список для неравенств:
> строго больше
< строго меньше
<= нестрого меньше
>= нестрого больше
== равно
!= не равно
*/
//Сложные условия
/*
А что, если нам надо выполнение одновременно нескольких условий? А делать нужно вот что:
if([условие][логическая операция][условие1] ...[логическая операция][условиеN])
{}
Логические операции
|| или
&& и
== равно //логические выражения тоже можно сравнивать, но только при помощи "равно" или "не равно"
!= не равно
Что же это означает? Пример:
условие || условие1
будет считаться верным, если верно только одно из условий. Пример1:
условие && условие 1
будет считаться верным, если верны оба условия одновременно. Пример2:
(условие && условие1) || условие2
будет считаться верным, только если ЛИБО первые два условия будут одновременно верны, ЛИБО если верно ТОЛЬКО третье условие
! считается знаком отрицания, т.е. логическое выражение !(условие) будет верным, только если условие будет неверным. Пример3:
(условие || условие1) && !(условие2)
будет считаться верным, если верно ТОЛЬКО ОДНО из первых двух условий И ОДНОВРЕМЕННО С ЭТИМ НЕ будет верно третье условие
*/
//Пример сложных и не очень условий
void main()
{
int bFlag = FALSE, nN; //0 и 1 можно записывать как FALSE и TRUE соответственно
if(!bFlag)
{
nN = 100;
if(nN<100)
{nN = 100;}
else
{nN = 0;}
}
if((nN == 0) && (nN != 1) && !(nN == 1)) //тут написан бред. Достаточно ограничиться лишь nN == 0, т.к. если nN равно нолю, то в любом случае она не
//равна единице. А так же условия nN != 1 и !(nN == 1) - одно и то же.
{nN = 0;} //Бессмысленное действие, т.к. нету смысла приравнивать nN к нолю, если она уже равна нолю (см. пред. условие)
}
Агась, а теперь домашнее задание: посмотреть в
Лексиконе функции, названия которых написаны ниже и понять как их использовать
GetLastOpenedBy
GetTag
GetObjectByTag
GetNearestObjectByTag
AssignCommand
ActionMoveToObject
ActionLockObject
ActionUnlockObject
Эти функции понадобятся тебе для твоих хождений по сундукам. Если поймешь, как их использовать (если при этом понял, что я писал выше, хех), то сможешь эти хождения по сундукам написать сам. Если хочешь, чтобы ходящий по сундукам, например, оглядывался по сторонам, перед тем, как открыть сундук, то посмотри ActionPlayAnimation. Если хочешь еще и всяких ништяков вроде свечений и прочего, посмотри effect (это тип, тут, скорее всего, понадобится английский), EffectVisualEffect и ApplyEffectToObject.
Как-то так