Помощь - Поиск - Пользователи - Календарь
Полная версия: Скрипты: Все вопросы
Город Мастеров > РЕДАКТОРЫ > Neverwinter Nights 2 Obsidian Toolset
Страницы: 1, 2, 3, 4, 5, 6, 7
Zmeika
Подскажите, пожалуйста, как можно сделать так, чтобы мертвый НПС лежал не в дефолтовой скрюченной позе, а в положении лежа на спине? Пытаюсь делать так:
Код
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
Zmeika, попробуй поэкспериментировать со свойствами NPC, такими как Non permanent death и Lootable corpse. Попробуй выставить второе свойство в true и после применения анимации нанести ему смертельные повреждения.
Лично я бы просто добавил к имени этого НПСа приставку "МЕРТВЫЙ" и успокоился бы. Imho, и так все хорошо, совершенства не бывает.
Zmeika
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
Как можно создавать или менять переменную типа location? Знаю, как ее получить из уже существующего объекта. Но мне надо создать новый объект (существо) на некотором расстоянии от игрока и по событию, которое может спровоцировать сам игрок в любой момент времени (например - вызвать джина из бутылки).
Т.е. locаtion игрока - я определить могу. Но затем мне нужно ее поменять каким-то образом, чтобы нужная тварюка появилась на некотором расстоянии от игрока.
Вопрос - как это сделать?


Update:
Сорри, вопрос снимается - узнала, что есть такой метод Location(....)
Lorendroll
Никто случайно не разобрался как превратить игрока в виспа? (наложить на него fx эффект)
shadowdweller
Пытаюсь написать скрипт, который должен сработать из диалога, но при этом работать еще и в том случае, если перс прекратил этот самый диалог и отошел от собеседника. Получается вот что:

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
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
Дело такое:
Есть необходимость иметь глобальную переменную. Нужно, чтобы эта переменная, в зависимости от действий производимых персонажем, менялась и сохранялась поверх себя, чтобы с уже новым значением скрипты могли взаимодействовать дальше.
В принципе я себе представляю как это сделать, но запоролся в самом начале, видимо что-то с синтаксисом напутал. Вобщем, не могу вызвать глобальную переменную. Перед этим эту переменную я прописал в свойствах модуля. Если не ошибаюсь вызывается она в скриптах при помощи GetGlobalInt()(сейчас тула под рукой нет, точно не вспомню чего я там вчера ваял), но при компиляции тул ругается на эту строчку, так как я очевидно задаю неверные параметры.
Вобщем сама просьба такова - привидите пожалуйста какой-нибудь пример с назначением и последующим вызовом глобальных переменных, разжовывать не надо, сам расковыряю, лишь бы пример рабочий был.
Буду очень признателен.
Lorendroll
KoYuKi, чтобы при компиляции выдавал не какой нибудь бред а реальную ошибку - поставь английский Dialog.tlk и перезапусти тулсет. Иногда скрипты даже не компилируются из за русского диалог.тлк. А уж если русские буквы в код попадут то и весь тулсет бывает падает. Перезапустишь - напиши что за ошибка компиляции выдается.
А SetGlobalInt'ом, кстати, за всю свою нвн-программерскую деятельность мне пользоваться не приходилось. Кстати, почему бы не сохранить эту глобальную переменную на самом персонаже - SetLocalInt(oPC, sIntName, N)?
KoYuKi
Цитата
KoYuKi, чтобы при компиляции выдавал не какой нибудь бред а реальную ошибку - поставь английский Dialog.tlk и перезапусти тулсет. Иногда скрипты даже не компилируются из за русского диалог.тлк. А уж если русские буквы в код попадут то и весь тулсет бывает падает. Перезапустишь - напиши что за ошибка компиляции выдается.

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

Цитата
А SetGlobalInt'ом, кстати, за всю свою нвн-программерскую деятельность мне пользоваться не приходилось. Кстати, почему бы не сохранить эту глобальную переменную на самом персонаже - SetLocalInt(oPC, sIntName, N)?

Lorendroll, этот вариант мне плохо представляется, вероятно в связи с маленьким багажом знаний.
То есть я сохраняю на игроке локальную переменную. Он ходит, взаимодействует с предметами, в связи с чем эта локалка меняется и сохраняется на игроке. Но возможно ли мне при таком подходе сделать так, чтобы значение переменной уменьшалось без каких либо взаимодействий, просто по прошествии времени?
Если не трудно приведи какой-нибудь пример, буду признателен.
Lorendroll
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
Lorendroll спасибо большое, теперь все ясно =) Прийду домой, буду пробовать.

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

Обязательно гляну, если напишешь, пример бы не помешал.

Lorendroll
Этот скрипт надо вызвать командой 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
Вот в кои-то веки не обошелся своими силами...

Значит, существует триггер, описанный около блупринта травы, являющегося по факту "Tree". По факту триггер является трапом, процовоцирующим АОЕ спелл. Т.к. с "Tree" спеллы не пускаются, должен создаться другой блупринт, желательно невидимый.

Вариантов решения 3:
1) ActionCastSpellAtObject - не подходит, нормальный кастер лвл он имеет только с криче блупринта, а со скриптхидден кричи не запускается. В ином случае кастер лвл = 0.
2) Эмулировать заклинание собственным псевдо эффектом. АОЕ эффект почему-то мгновенно уничтожается, даже не появившись толком.
3) TriggerProjectileTrap - не удалось заставить работать. Делал путем задания правельного тэга запускающему блупринту. Опять же работает только с кричи. Разницы между моей версией и скриптом проджектил эрроу трапов из ОС нет практически, но мой скрипт не работает... Именно проджектил эрроу пока не делал...
Jadent
Цитата(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
Тогда это актуально для всех 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
Есть ли способ намертво прицепить одну модельку к другой - например чтоб над плечем игрока летала фигурка демилича (череп)
Jadent
DarkPhoenix, это вполне реально, но практически не относится к скриптингу. Делается через кастомный vfx.

Посмотри вот этот хак и сделай по аналогии: http://nwvault.ign.com/View.php?view=NWN2V...etail&id=37
DarkPhoenix
Спасибо! А каких нибудь гидов по этому не знаеш?
Equilibrium
Очень интересует вопрос - как вернуть Школу магии, на которой специализируется волшебник? Есть мнение, что оная может храниться в локальных переменных персонажа...
virus_found
да
в файле *.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
Спасибо!
Вопрос логически продолжается: кто знает - как добыть эту школу из файла персонажа через скрипты? ^_^
virusman
Сингл или шард? Если сингл, то никак, если шард, то можно, но сложно.
Equilibrium
Вообще, желательно, сингле... А почему нельзя? Вернее, почему можно на шарде? И как?
virusman
Цитата(Equilibrium @ Dec 23 2008, 21:42) *
Вообще, желательно, сингле... А почему нельзя? Вернее, почему можно на шарде? И как?
Потому что в сингле доступны только стандартные функции НВН, которыми нельзя получить школу магии. На шардах же возможно использование NWNX с плагином NWNX-Leto, который позволяет редактировать файлы персонажей.
Equilibrium
Эх... ясно, пасиб... Но буду иметь ввиду на всякий случай.
RebOOter
Народ, не могу разобраться в некоторых вещах.
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
В первом скрипте ошибка, должно быть 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
Цитата(greye @ Jan 3 2009, 15:36) *
В первом скрипте ошибка, должно быть AssignCommand(последние две буквы assign). Ну и чтобы совсем хорошо было, надо добавить перед этим AssignCommand(oVoin, ClearAllActions());
Во втором - кавычки должны быть двойные: не ('), а ("), надо не забывать закрывать скобки и ставить в конце строки ;


По первому компилятор "дал добро". Спасибо!)

А по второму, ковычки я ставлю двойные и точку с зяпятой тоже ставлю, но компилятор всё равно в той-же строке ошибку выдаёт sad.gif
RebOOter
Второй скрип запахал!)) В ковычках дело было... а в примере одна была smile.gif

А второй скрипт без ошибок, но не рабочий... не хотят они друг друга атаковать.
Marta
Чувствуется, у админов и у всех остальных летние каникулы. Но все же, вдруг кто зайдет. Не могу написать скрипт одевания брони на ГГ через диалог. Поможите, люди добрые, подскажите, что здесь не так:

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
Neverwinter Script
object oItem = GetObjectByTag("NW_CLOTH018");

может быть дело в том, что таких объектов много, и берётся объект не в инвентаре героя; тогда лучше использовать функцию:
Neverwinter Script
object GetItemPossessedBy(object oCreature, string sItemTag)

ещё может быть стоит попробовать добавить перед одеванием ActionPauseConversation(), а после ActionResumeConversation()...
Marta
Ух. Спасибо, что вообще ответил, но я, к сожалению, ничего не поняла. Я же не скриптер, а полный ламер. Вместо object oItem = GetObjectByTag мне надо написать object GetItemPossessedBy? Так у меня не компилируется, или как там... И непонятно, куда писать тег вещи. (object oCreature, string sItemTag("NW_CLOTH018") )? Тогда что за oCreature?

ActionPauseConversation() - это
Neverwinter Script
void    ActionPauseConversation();

?
Так все равно не компилируется.

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

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

oCreature и sItemTag - это параметры функции GetItemPossessedBy, чтобы её запустить, надо вместо них записать что нам надо, в данном случае нам нужен предмет с тегом у игрока, сделовательно oCreature - игрок, sItemTag - тэг

Neverwinter Script
object oItem = GetItemPossessedBy(oPC, "NW_CLOTH018");
Marta
Вах, сработало! Спасибо огромное, - а то я уже неделю бъюсь!

Но стандартный скрипт 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
Еще вопрос, - к 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
должно быть что-то такое:

Neverwinter Script
int nRacialType = GetRacialType(oPC);
return (nRacialType==RACIAL_TYPE_GNOME || nRacialType==RACIAL_TYPE_DWARF || nRacialType==RACIAL_TYPE_HALFLING);

эта конструкция вернет TRUE, если раса игрока одна из трех. А на какие условия втыкать работу этого блока - тебе виднее. Можно замутить что-то универсальное, чтобы из диалога передавался символьный код, например GDH, который понимался бы скриптом как гномы/дварфы/халфлинги. Но имхо под конкретный модуль проще сделать несколько общих скриптов. Если у тебя всегда такая комбинация карликов, то проще сделать для этого отдельный скрипт и не париться.

зы: не уверен в правильности расовых констант, пишу по памяти.
Marta
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
а ты не пиши (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
Ес-с, работает. Не знала, что после int StartingConditional надо скобки оставлять :-). Может быть, в итоге я чему-то выучусь, и перестану уже тупить, но пока до этого далеко.
Спасибо огромное.

Chimeric
Общий вопрос. Известно, что Обсидиан отличается от Авроры интерфейсом и некоторыми функциями - я слышал про cutscenes и ActionSit. Я здесь не говорю про маппинг, который может отличаться сильно. Меня интересуют основные, традиционные функции скриптов Авроры. Годны ли они в целом? Иными словами, если я возьму типичный, средней сложности скрипт для Авроры с проверками пола, времени суток и т.п., или скрипт со spawn и уничтожением объектов, с установкой глобальных переменных, такого рода вещами, сколько из этого придется менять?

Griffon
В целом скрипты не отличаются и их можно использовать в обоих редакторах. Полный список неработающих функций должен быть на офф форумею К слову, ActionSit одна из них. Более подробно расскажет комадна шарда БГ или Ванес, он тож активно переносил все на НВН2.

http://nwvault.ign.com/View.php?view=NWN2A...6#_Toc146633941

Chimeric
Спасибо.

Еще вопрос: задавался ли кто-нибудь системой скриптов для изучения заклинаний (spell research)?

Georgus
Приветствую уважаемых мастеров. У меня такой вопрос - как сделать, чтобы после смерти персонаж возрождался не в месте гибели, а в указанном мною. Вопрос второй - как сделать чтобы после смерти персонаж вообще не воскрешался, а вылетала табличка из НВН2 (игра окончена, все свободны: загрузка или выход). Заранее спасибо.


З.Ы Да да, я уже знаю. Я НУБ и ламер=)
Griffon
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
Грифон, ты опасен!
Подумай над своей реакцией, если бы я на твои ранние вопросы по скриптам так бы отвечал smile.gif
Aiwan
Lex, тогда парня надо отправлять сразу в тему по обучению скриптам. Через месяц выкладывать даваемое по кускам smile.gif
Georgus
Хех, спасиб . Попробую разобраться в данном скрипте.
Griffon
Lex, я на то и рассчитывал, что гуру скриптинга сразу же прокомментируют, выкинут лишнее и вынесут вердикт. biggrin.gif
Lex
Цитата(Griffon @ Aug 27 2009, 13:35) *
Lex, я на то и рассчитывал, что гуру скриптинга сразу же прокомментируют, выкинут лишнее и вынесут вердикт. biggrin.gif

я вердикт выше вынес: ты опаcен smile.gif)

по теме: если нужно ТОЛЬКО респ в какой-то точке (без штрафов и прочей фигни) или вообще его убрать - то 3/4 скрипта можно выкинуть.
А вот если планируется еще куча мелких фич, динамическое изменение места респауна и тд - то выкидывать придется не так уж и много.

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