Помощь - Поиск - Пользователи - Календарь
Полная версия: База скриптов
Город Мастеров > РЕДАКТОРЫ > Neverwinter Nights Aurora Toolset
Страницы: 1, 2, 3
Lex
СЕРИЯ "СКРИПТЫ СТАРОЙ БАЗЫ"
ЦИКЛ "СКРИПТЫ ДЯДЮШКИ MILEZ'А"

Автор:::::::::::::::::Milez::::::::::::::::::::::::::::::
May 22 2003
Cкрипт для смерти.
Вешать на OnPlayerDying модуля.
+ скрипта в том, что он не использует хартбит.
Это бета-версия скрипта предложена as is, автор не несет ответственности за материальный и моральные ущерб, который этот скрипт может кому-то принести!
Neverwinter Script Source
void DyingTicker(object oPC)
{
   int iHP=GetCurrentHitPoints(oPC);
   if (iHP>0) {
       RemoveEffect(oPC,EffectBlindness());
       DeleteLocalInt(oPC,"DyingDC");
       DeleteLocalInt(oPC,"STvsDeathSucceed");
       return;
   }
   int iDC;
   int iDam;
   int iSuc;
   if (iHP<-9) { ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectDeath(TRUE,TRUE),oPC); }
   else {
       iDam=d4();
       iDC=GetLocalInt(oPC,"DyingDC");
       if (FortitudeSave(oPC,iDC)>0) {
           iDam=iDam/2;
           iSuc=GetLocalInt(oPC,"STvsDeathSucceed")+1;
           SetLocalInt(oPC,"STvsDeathSucceed",iSuc);
           if (iSuc>2) {
               FloatingTextStringOnCreature("Кровотечение прекратилось",oPC,FALSE);
               return;
           }
       }
       AssignCommand(oPC,DelayCommand(6.0,DyingTicker(oPC)));
       ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(iDam), oPC);
       ApplyEffectToObject(DURATION_TYPE_TEMPORARY,EffectBlindness(),oPC,6.0);
       SetLocalInt(oPC,"DyingDC",iDC+1);
   }
}

void main()
{
   object oPC=GetLastPlayerDying();
   if (!GetIsPC(oPC)) return;
   SetLocalInt(oPC,"DyingDC",15);
   SetLocalInt(oPC,"STvsDeathSucceed",0);
   FloatingTextStringOnCreature("У менz открылось кровотечение",oPC,FALSE);
   DyingTicker(oPC);
}

Смысл в том, что каждый раунд (6 сек) игрок кидает спасбросок стойкости для половинного дамаджа от 1d4, при этом DC, который надо побить, увеличивается с каждым раундом на 1 (начальное значение 15). При удачном спасбраске 2 раза подряд кровотечение прекращается.
от 0 до -9 - игрок без сознание. От -10 и меньше - смерть без спасброска.

************************************************************************************

Автор:::::::::::::::::Milez::::::::::::::::::::::::::::::
May 24 2003

Вот температурный скрипт, полностью в соответсвии с D&D 3ed согласно разделам HEAT и COLD в DMG. Писан мной, любые совпадения в реализации с другими подобными скриптами являются чисто случайными. За общую идею создать нечто подобное спасибо ДБколлу. Подробнее об общем алгоритме работы см DMG (Температура, в отличие от DMG, приведена не в иноземных Фаренгейтах, а в старых добрых Цельсиях).
Всяческое использование, модификация, дебаггинг приветствуются! Никакой ответственности за причиненный моральный/материальный ущерб в результате работы скрипта автор не несет!

Вешать на OnEnter местности.
Neverwinter Script Source
void DealTemperatureDamage(object oPC)

{
   // Игрок без сознания
   if (GetCurrentHitPoints(oPC)<1) return;
   // Где находится игрок?
   object oArea=GetArea(oPC);
   // И какая там температура?
   int iT=GetLocalInt(oArea,"Temperature");
   // Температура комфортабельна или не установлена
   // (значение 0 рассматривается как неустановленная температура. Вместо 0 ставьте -1)
   if (((iT<=32) && (iT>=4)) || (iT==0)) return;
   // Определяем переменные
   int iDamType;
   int iDamAmount;
   int iSaveType;
   float iInterval;

   object oFire;
   int iFatigue=FALSE;
   int iFortSave;
   int i;
   effect eDam;
   // Носим тяжелую броню и/или плащ?
   int iCloth=(GetItemACValue(GetItemInSlot(INVENTORY_SLOT_CHEST,oPC))>5)
               ||GetIsObjectValid((GetItemInSlot(INVENTORY_SLOT_CLOAK,oPC)));
   // Сколько раз мы уже "стучали" по игроку?
   int iTimes=GetLocalInt(oPC,"TemperatureDamageTimer");
   int iDC=15+iTimes; // Подсчет DC
   if (iT>32) { // Жарко!
       FloatingTextStringOnCreature("Мне жарко!",oPC);
       iDamType=DAMAGE_TYPE_FIRE;
       iSaveType=SAVING_THROW_TYPE_FIRE;
       iDamAmount=d4();
       if (iCloth) iDC+=4; // -4 пенальти к спасброску аналогично +4 к DC (так как спасбросок делается встроенной функцией). При желание спасбросок можно делать вручную, но встроенная функция уж больно красиво пишет о спасброске в логах smile.gif
       if (iT>60) { // Адская жарища!
       // 1d6 дамадж каждые 2 реальные секунды без спасброска
           eDam=EffectDamage(d6(),iDamType);
           ApplyEffectToObject(DURATION_TYPE_INSTANT,eDam,oPC);
           for (i=2;i<10;i+=2)
               AssignCommand(oPC,DelayCommand(IntToFloat(i),
               ApplyEffectToObject(DURATION_TYPE_INSTANT,eDam,oPC)));
           iFatigue=TRUE;
           iInterval=10.0;
       } else if (iT>43) { // Очччень жарко!
           iInterval=20.0;
           iFatigue=TRUE;
       } else { // Просто жарко
           iInterval=120.0;
       }
   } else if (iT<4) { // Холодно!
       // ищем костер
       oFire=GetNearestObjectByTag("ku_campfire",oPC);
       // Если рядом костер, но мы согреемся
       if ((GetIsObjectValid(oFire)) &&
           (GetDistanceBetween(oFire,oPC)<5.0)) {
           iDC=0;
           RemoveEffect(oPC,EffectSlow());
           iInterval=120.0;
       } else {
           iDamType=DAMAGE_TYPE_COLD;
           iSaveType=SAVING_THROW_TYPE_COLD;
           iDamAmount=d6();
           FloatingTextStringOnCreature("Мне холодно!",oPC);
           if (iT<-18) { // Жуткий мороз
               if (iCloth) iInterval=120.0; else iInterval=20.0;
               iFatigue=TRUE;
           } else { // Very cold
               if (iCloth) iDC=0; // Мы хорошо одеты и легкий морозец нам не страшен
               iInterval=120.0;
           }
       }
   }
   if (iDC>0){
       iFortSave=FortitudeSave(oPC,iDC,iSaveType);
       if (iFortSave==0) {
           ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectDamage(iDamAmount,iDamType),oPC);
           if (iFatigue) ApplyEffectToObject(DURATION_TYPE_TEMPORARY,EffectSlow(),oPC,iInterval);
       }
   }
   SetLocalInt(oPC,"TemperatureDamageTimer",iTimes+1);
   AssignCommand(oPC,DelayCommand(iInterval,DealTemperatureDamage(oPC)));
}


void main()
{
   object oPC=GetEnteringObject();
   if (GetIsObjectValid(oPC)) {
       DeleteLocalInt(oPC,"TemperatureDamageTimer");
       AssignCommand(oPC,DealTemperatureDamage(oPC));
   }
}

где
ku_campfire - "синька" костра

************************************************************************************

Автор:::::::::::::::::Milez::::::::::::::::::::::::::::::
May 24 2003

Скрипт для "тягловых" животных. Легко переделывается для банка. Писано мной, любые совпадения с чьей-либо реализацией как в деталях так и в общем алгоритме чисто случайны. Всяческие изменения, доработки, дебаггинг приветствуются. За моральный/материальный ущерб в результате работы скрипта автор ответственности не несет!
На "тягловом" НПЦ (я использовал окса, но это может быть и хенчман, и фамильяр) в диалоге ставиться строчка наподобие "Перебрать поклажу". В Action Taken ставиться следующий скрипт:
Neverwinter Script Source
void main()
{
   object oPC=GetPCSpeaker();
   object oPackAnimal=OBJECT_SELF;
   location lLoc=GetLocation(oPC);
   object oContainer=CreateObject(OBJECT_TYPE_PLACEABLE,"inviscont",lLoc);
   object oEnum=GetFirstItemInInventory(oPackAnimal);
   SetLocalObject(oContainer,"LinkedPackAnimal",oPackAnimal);
   while (GetIsObjectValid(oEnum)) {
       CopyObject(oEnum,lLoc,oContainer);
       DestroyObject(oEnum);
       oEnum=GetNextItemInInventory(oPackAnimal);
   }
   AssignCommand(oPC,ClearAllActions());
   AssignCommand(oPC,ActionInteractObject(oContainer));
}

Создается "синька" врменного контейнера (я использовал за образец Invisible Object), на "синьке" ставяться аттрибуты Usable, Plot, Has Inventory. Имя синьки в данном случае "inviscont". В обработчик "синьки" OnClose ставиться следующий скрипт:
Neverwinter Script Source
void main()
{
   object oMaster=GetLocalObject(OBJECT_SELF,"LinkedPackAnimal");
   location lLoc=GetLocation(OBJECT_SELF);
   object oEnum=GetFirstItemInInventory();
   while (GetIsObjectValid(oEnum)) {
       CopyObject(oEnum,lLoc,oMaster);
       DestroyObject(oEnum);
       oEnum=GetNextItemInInventory();
   }
   DelayCommand(1.0,DestroyObject(OBJECT_SELF));
}


************************************************************************************

Автор:::::::::::::::::Milez::::::::::::::::::::::::::::::
May 27 2003
Гильдия Убийц.
(с) Оригинальная идея ONYX'а.
(с) Реализация Milez'а.
Система маленько запутанна, в модуле все взаимосвязано, здесь только основные скрипты, без диалогов и прочего.
Итак, есть айтем Контракт, в св-вах добавлено Cast: Unique Power Unlim Times/Day. Имя синьки contract.
Есть айтем Голова "клиента", в св-вах Cast: Unique Power Self Only Unlim Times/Day. Имя синьки headofclient.
В OnActivateItem модуля следующая бяка:
Neverwinter Script Source
location RandomLocationFrom(location lOrigin)
{
   vector vOrigin=GetPositionFromLocation(lOrigin);
   vOrigin.x+=(Random(11)-5);
   vOrigin.y+=(Random(11)-5);
   return Location(GetAreaFromLocation(lOrigin),vOrigin,GetFacingFromLocation(lOrigin));
}

void SummonKiller(object oClient,object oMaster)
{
   location lClient=RandomLocationFrom(GetLocation(oClient));
   ApplyEffectAtLocation(DURATION_TYPE_INSTANT,
       EffectVisualEffect(VFX_FNF_SMOKE_PUFF),lClient);
   object oKiller=CreateObject(OBJECT_TYPE_CREATURE,"gypsy007",lClient);
   SetLocalObject(oKiller,"MyClient",oClient);
   SetLocalString(oKiller,"MyClientName",GetName(oClient));
   SetLocalString(oKiller,"MyClientTag",GetTag(oClient));
   SetLocalObject(oKiller,"MyMaster",oMaster);
  & nbsp;DelayCommand(IntToFloat(Random(51)+50),AssignCommand(oKiller,ActionAttack(o
Client)));
}

void SummonKillers(object oClient,object oMaster,int iNumKillers)
{
   int i;
   for (i=1;i<=iNumKillers;i++) {
       SummonKiller(oClient,oMaster);
   }
}

void main()
{
   object oOwner=GetItemActivator();
   if (!GetIsPC(oOwner)) return;
   object oSource=GetItemActivated();
   object oTarget=GetItemActivatedTarget();
   string sSourTag=GetTag(oSource);
   if (sSourTag=="contract") {
       int iNumOfKillers=GetLocalInt(oSource,"NumberOfKillers");
       if (iNumOfKillers<1) {
           DestroyObject(oSource);
       } else
       if ((GetObjectType(oTarget)==OBJECT_TYPE_CREATURE) && (!GetIsDM(oTarget)) && (!GetPlotFlag(oTarget)))
      {
           FloatingTextStringOnCreature("The murder have been assigned!",oOwner,FALSE);
           DelayCommand(IntToFloat(Random(51)+50),
               SummonKillers(oTarget,oOwner,iNumOfKillers));
           DestroyObject(oSource);
       } else {
           FloatingTextStringOnCreature("The murder can't be assigned to an item, DM or plot character!",oOwner,FALSE);
       }
   } else if (sSourTag=="headofclient") {
       FloatingTextStringOnCreature("This is the head of "+
           GetLocalString(oSource,"Client"),oOwner,FALSE);

   }
}

Персонажи:
Наемник (типа главарь). В его диалоге уставливается кол-во убийц для задания, забираются деньги у игрока,
дается контракт (CreateItemOnObject("contract",oPC)).
Кол-во убийц-исполнителей должно писаться на контракте (SetLocalInt(oContract,"NumberOfKillers",xxx))
Убийца. Собственно исполнитель. Имя синьки "gypsy007". В OnHeartbeat убийцы такая бяка:
Neverwinter Script Source
void main()
{
   object oClient=GetLocalObject(OBJECT_SELF,"MyClient");
   object oMaster=GetLocalObject(OBJECT_SELF,"MyMaster");
   object oMessenger;
   string sNotifyVar;
   if ((!GetIsObjectValid(oClient)) || GetIsDead(oClient)) {
       if (GetIsObjectValid(oMaster)) {
           sNotifyVar="Notified"+GetLocalString(OBJECT_SELF,"MyClientTag");
           if (GetLocalInt(oMaster,sNotifyVar)!=TRUE) {
               oMessenger=CreateObject(OBJECT_TYPE_CREATURE,"halfmerc002",
                   GetLocation(oMaster),TRUE);
               SetLocalObject(oMessenger,"MyMaster",oMaster);
               SetLocalString(oMessenger,"MyClient",GetLocalString(OBJECT_SELF,"MyClientName"));
               SetLocalString(oMessenger,"NotifyVar",sNotifyVar);
               SetLocalInt(oMaster,sNotifyVar,TRUE);
           }
       }
       DestroyObject(OBJECT_SELF);
   }
}

Вестник Гильдии Убийц. После исполнения задания доставляет заказчику голову жертвы. Имя синьки "halfmerc002".
Диалог длинный, хитрый и может быть любым. Основной скрипт который должен быть для отдавания головы жертвы следующий:
Neverwinter Script Source
void main()
{
   object oPC=GetPCSpeaker();
   object oHead=CreateItemOnObject("headofclient",oPC);
   SetLocalString(oHead,"Client",GetLocalString(OBJECT_SELF,"MyClient"));
   SetLocalObject(oHead,"Master",oPC);
   DeleteLocalInt(oPC,GetLocalString(OBJECT_SELF,"NotifyVar"));
}

Работа скрипта: игрок говорит с Наемником и просит его убрать какого-либо игрока/неписю.
Наемник спрашивает сколько посылать убийц и в зависимости от их кол-ва устанавливает цену,
если игрок согласен и у него хватает денег, то игроку дается контракт и забираются деньги.
Потом контракт используется на том неписе/игроке которого надо "убрать", после чего через 50-100 секунд
(DelayCommand(IntToFloat(Random(51)+50),... Впрочем это можно регулировать) около "клиента" материализуется энное кол-во убийц. Они атакуют жертву (убийцы у меня в спец. фракции Killer, которая нейтральна ко всем, так что атакуют они только намеченную жертву, но это можно менять) и если жертва успешно убивается, то к заказчику направляется гонец (если жертва выживает, то значит убийцы умирают и посылать гонца некому) и убийцы бесследно смываются с места преступления. Игрок говорит с посыльным и получает голову "клиента". Если использовать эту голову, то игроку-заказчику напишет чья это голова.
Вот и все.

************************************************************************************

Автор:::::::::::::::::Milez::::::::::::::::::::::::::::::
May 14 2003
Это система отдыха в моем модуле (модуль пока еще не вышел из стадии первичной разработки поэтому о нем пока ни гу-гу).
Навеяно системой отдыха из Axistown'а но полностью писано мной

kel_rest
Neverwinter Script Source
void DestroyFirecamp(object oCampFire=OBJECT_SELF)
{
// Создаем обгорелое пятно на месте костра и гасим костер
   object oLandMark=CreateObject(OBJECT_TYPE_PLACEABLE,"plc_weathmark",GetLocation(oCampFire));
// Пятно исчезает через 120 секунд (2 реальных минуты, 1 игровой час). Менять по вкусу
   AssignCommand(oLandMark,DelayCommand(120.0,DestroyObject(oLandMark)));
   DestroyObject(oCampFire);
}

void ApplyRestEffect(object oTarget=OBJECT_SELF)
{
// Создаем эффекты сна. Функцию править по вкусу.
   effect eSleep=EffectBlindness();

   if (GetRacialType(oTarget)==RACIAL_TYPE_ELF)
   {
// Эльфы не спят, а впадают в транс (см. описание эльфов в D&D 3ed)
       if (GetGender(oTarget)==GENDER_FEMALE)
           FloatingTextStringOnCreature("Я вошла в транс",oTarget,FALSE);
       else
           FloatingTextStringOnCreature("Я вошел в транс",oTarget,FALSE);
   } else

       eSleep=EffectLinkEffects(eSleep,EffectVisualEffect(VFX_IMP_SLEEP));
// Эффект сна на 30 секунд. Менять по желанию.
   ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eSleep,oTarget,30.0);
}

object FindFood(object oTarget=OBJECT_SELF)
{
   object oEnum=GetFirstItemInInventory(oTarget);
   while (GetIsObjectValid(oEnum) && (GetTag(oEnum)!="KEL_FOOD"))
       oEnum=GetNextItemInInventory(oTarget);
   return oEnum;
}


ku_makecamp (вешать на OnUsed дров)
Neverwinter Script Source
#include "kel_rest"

void main()
{
   object oPC=GetLastUsedBy();
   if (!GetIsPC(oPC)) return;
   object oTorch=GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oPC);
   if (GetIsObjectValid(oTorch) &&
          (GetTag(oTorch) == "NW_IT_TORCH001") &&
// Флаг, висящий на области (например в таверне) и позволяющий отдыхать бесплатно
          (GetLocalInt(GetArea(oPC),"NoCampArea") != TRUE)) {
       object oFire=CreateObject(OBJECT_TYPE_PLACEABLE,"ku_campfire",GetLocation(OBJECT_SELF));
       DestroyObject(OBJECT_SELF);
// Огонь гаснет через 900 секунд (15 реальных минут или 7,5 игровых часов)
// Менять по желаю
       AssignCommand(oFire,DelayCommand(900.0,DestroyFirecamp(oFire)));
   } else {
       CreateItemOnObject("kel_wood",oPC);
       DestroyObject(OBJECT_SELF);
   }
}


kua_dropwood (вешать OnUnAquiredItem модуля)
Neverwinter Script Source
void main()
{
   object oPC=GetModuleItemLostBy();
   if (!GetIsPC(oPC)) return;
   object oItem=GetModuleItemLost();
   if (!GetIsObjectValid(oItem)) return;
   string sResRef=GetTag(oItem);
   if (sResRef=="KEL_WOOD")
   {
// Пропатчено by Milez on 14/05/2003, по намекам некоего Guest
       if (GetIsObjectValid(GetAreaFromLocation(GetLocation(oItem)))) {
           CreateObject(OBJECT_TYPE_PLACEABLE,"ku_woodpile",GetLocation(oItem));
           DestroyObject(oItem);
       }
   }
}


kr_resteffect (вешать на OnRested модуля)
Neverwinter Script Source
#include "kel_rest"
void main()
{
   object oPC=GetLastPCRested();
   if (GetCurrentAction(oPC)!=ACTION_REST) return;
   int iFreeRest=GetLocalInt(GetArea(oPC),"FreeRestArea");
   if (iFreeRest) ApplyRestEffect(oPC);
   else {
       object oCampFire=GetNearestObjectByTag("ku_campfire",oPC);
// нельзя отдыхать дальше 3 метров от костра (расстояние менять по вкусу)
       if (GetIsObjectValid(oCampFire) && (GetDistanceBetween(oPC,oCampFire)<=3.0)) {
           object oFood=FindFood(oPC);
           if (GetIsObjectValid(oFood)) {
               DestroyObject(oFood);
               ApplyRestEffect(oPC);
           } else {
               FloatingTextStringOnCreature("Мне надо перекусить",oPC,FALSE);
               AssignCommand(oPC,ClearAllActions());
           }
       } else {
           FloatingTextStringOnCreature("Я не могу отдыхать далеко от костра",oPC,FALSE);
           AssignCommand(oPC,ClearAllActions());
       }
   }
}


khb_cfire_sfx (на OnHeartbeat костра, исключительно для красоты, можно не использовать в целях повышения скорости работы кода)
Neverwinter Script Source
void main()
{
   PlaySound("al_cv_firecamp1");
}



Используемые "синьки":
KEL_WOOD - дрова как айтем в инвентаре
ku_woodpile - горка дров как плэйсабл айтем на земле
ku_campfire - сам костер
KEL_FOOD - еда

************************************************************************************


Автор:::::::::::::::::Milez::::::::::::::::::::::::::::::
May 29 2003
"Приведем НВН в соответствие с АДиД". На повестке дня скрипт для ветра. Ниже базовый инклуд. Основная функция - ApplyWindEffect.
Параметры:
int iWindForce - сила ветра: 0 - Light wind; 1 - Moderate wind; 2 - Strong wind; 3 - Severe wind; 4 - Windstorm; 5 - Hurricane force wind; 6 - Tornado.
Neverwinter Script Source
float fWindDirection
- направление ветра, угол.
Neverwinter Script Source
object oTarget
- на кого "подуть"
Рекомендуется использовать в Heartbeat'е, перебирая всех игроков, так как по АДиД эти проверки должны проходить каждый раунд. Реально в хартбите использовать можно например так:
Neverwinter Script Source
void main()
{
   object oPC=GetFirstPC();
   while (GetIsObjectValid(oPC)) {
       ApplyWindEffect(4,45.0,oPC);
       oPC=GetNextPC();
   }
}

Работает в соответствии с соответствующим разделом DMG.
Ниже собственно сам инклуд.
Neverwinter Script Source
vector BlowAwayTo(vector vOrigin,float fAngle,float fRange)
{
   float dx=fRange*cos(fAngle);
   float dy=fRange*sin(fAngle);
   return Vector(vOrigin.x+dx,vOrigin.y+dy,vOrigin.z);
}

// "Сдувание". Сбивание с ног + отбрасывание на 1d4*10 футов с 1d4 дамаджа на каждые 10 футов.
void ApplyBlowAwayEffect(float fWindDirection,object oTarget=OBJECT_SELF)
{
   int iRange=d4();
   int iDam=d4(iRange);
   iRange *= 10;
   float fRange=FeetToMeters(IntToFloat(iRange));
   vector vNewPos=BlowAwayTo(GetPosition(oTarget),fWindDirection,fRange);
   AssignCommand(oTarget,ClearAllActions(TRUE));
   AssignCommand(oTarget,JumpToLocation(Location(GetArea(oTarget),vNewPos,GetFacin
g(oTarget))));
   AssignCommand(oTarget,ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
       EffectKnockdown(),oTarget,6.0));
   ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectDamage(iDam),oTarget);
   PrintVector(vNewPos,TRUE);
}

void ApplyWindEffect(int iWindForce,float fWindDirection,object oTarget=OBJECT_SELF)
{
if (iWindForce<1) return;
object oTorch=GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oTarget);

if (GetBaseItemType(oTorch)==BASE_ITEM_TORCH) {
   if (iWindForce==1) { // Moderate wind имеет 50% шанс погасить незащищенный огонь (факел)
       if (d2()==1) ActionUnequipItem(oTorch);
       return;
   } else { ActionUnequipItem(oTorch); } // Stronger winds extinguish fire at 100%
} else if (iWindForce==1) return; // If there's no lit torch moderate wind doesn't do any effect

int iCreatureSize=GetCreatureSize(oTarget);
// Так как мы будем накладывать пенальти на удаленные атаки, мы вызнаем, держит ли чар метательное/стреляющее оружие
int iWpnType=GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oTarget));
int iFeet;
vector vVec;
int bRangeWpn=FALSE;

if (iWpnType!=BASE_ITEM_INVALID) {
   bRangeWpn=(iWpnType==BASE_ITEM_DART)||
             (iWpnType==BASE_ITEM_HEAVYCROSSBOW)||
             (iWpnType==BASE_ITEM_LIGHTCROSSBOW)||
             (iWpnType==BASE_ITEM_LONGBOW)||
             (iWpnType==BASE_ITEM_SHORTBOW)||
             (iWpnType==BASE_ITEM_SHURIKEN)||
             (iWpnType==BASE_ITEM_SLING)||
             (iWpnType==BASE_ITEM_THROWINGAXE);
}

switch (iWindForce) {
case 2: // Strong wind
   if (bRangeWpn)
       ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
       EffectAttackDecrease(2),oTarget,6.0);
   ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
   EffectSkillDecrease(SKILL_LISTEN,2),oTarget,6.0);

   if (iCreatureSize==1) // оч. маленькое существо (Tiny)
       if (FortitudeSave(oTarget,10)==0)
       ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
       EffectKnockdown(),oTarget,3.0);
break;
case 3: // Severe wind
   if (bRangeWpn)
       ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
       EffectAttackDecrease(4),oTarget,6.0);
   ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
   EffectSkillDecrease(SKILL_LISTEN,4),oTarget,6.0);

   if (iCreatureSize<4)
   if (FortitudeSave(oTarget,15)==0)
   switch (iCreatureSize) {
   case 3: // Среднее существо (Medium).
       ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
       EffectEntangle(),oTarget,6.0);
   break;
   case 2: // Маленькое сущ-во (Small)
       ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
       EffectKnockdown(),oTarget,6.0);
   break;
   case 1:
       ApplyBlowAwayEffect(fWindDirection,oTarget);
   }
break;
case 4: // Windstorm
   if (bRangeWpn)
       ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
       EffectAttackDecrease(50),oTarget,6.0);
   ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
   EffectSkillDecrease(SKILL_LISTEN,8),oTarget,6.0);

   if (iCreatureSize<6)
   if (FortitudeSave(oTarget,18)==0)
   switch (iCreatureSize) {
   case 3:
       ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
       EffectKnockdown(),oTarget,6.0);
   break;
   case 4: // Большое (Large)
   case 5: // или огромное сущ-во (Huge)
       ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
       EffectEntangle(),oTarget,6.0);
   break;
   case 2:
   case 1:
       ApplyBlowAwayEffect(fWindDirection,oTarget);
   break;
   }
break;
case 5: // Hurricane force wind
   if (bRangeWpn)
       ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
       EffectAttackDecrease(50),oTarget,6.0);
   ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
   EffectSkillDecrease(SKILL_LISTEN,50),oTarget,6.0);

   if (iCreatureSize<6)
   if (FortitudeSave(oTarget,20)==0)
   switch (iCreatureSize) {
   case 3:
   case 2:
   case 1:
       ApplyBlowAwayEffect(fWindDirection,oTarget);
   break;
   case 4:
       ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
       EffectKnockdown(),oTarget,6.0);
   break;
   case 5:
       ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
       EffectEntangle(),oTarget,6.0);
   break;
   }
break;
case 6: // Tornado (WOW!)
   if (bRangeWpn)
       ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
       EffectAttackDecrease(50),oTarget,6.0);
   ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
   EffectSkillDecrease(SKILL_LISTEN,50),oTarget,6.0);
   if ((iCreatureSize==5) && (FortitudeSave(oTarget,30)==0))
       ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
       EffectKnockdown(),oTarget,6.0);
   else { // Торнадо особый случай. Он не сбивает с ног, а засасывает на 1d10 раундов, давая 6d6 дамаджа за раунд
       iFeet=GetLocalInt(oTarget,"IsInTornado");
       if (iFeet<1)
           if (FortitudeSave(oTarget,30)==0) iFeet=d10();
       if (iFeet>0) {
           iFeet-=1;
// По АДиД жерло торнадо движется с линейной скоростью 30 миль в час.
// В пересчете на реальные для НВН значения получаются астрономические цифры, кроме того летание
// в НВН нормально не сделаешь, поэтому я предположил что торнадо каждый раунд кидает чара в случайное
// место в радиусе 10 метров от текущего местоположения. Садисты это значение могут увеличить
           vVec=GetPosition(oTarget);
           vVec.x+=Random(21)-10;
           vVec.y+=Random(21)-10;
           AssignCommand(oTarget,ClearAllActions(TRUE));
           AssignCommand(oTarget,JumpToLocation(Location(GetArea(oTarget),vVec,GetFacing(o
Target))));
           AssignCommand(oTarget,ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
               EffectKnockdown(),oTarget,6.0));
           ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectDamage(d6(6)),oTarget);
       }
       SetLocalInt(oTarget,"IsInTornado",iFeet);
   }
break;
}
}

Кроме того сила ветра 3 (Severe wind) соответствует спеллу Gust of Wind, так что кому не в терпеж ждать этого спелла в SoU можете заюзать этот скрипт для создание этого спелла вручную
Смотреть spells.2da, там прописаны данные по спеллам, включая скрипты, эти спеллы реализующие.

************************************************************************************


Автор:::::::::::::::::Milez::::::::::::::::::::::::::::::
Jun 8 2003
Как и обещал, скрипт для осадков. Прошу прощения за такую задержку: только начались экзамены, просто не было времени. Писано как всегда мной, теперь уже по готовому шаблону (см. ветер, кстати, этот шаблон очень удобно использовать во многих случаях, может кому пригодиться). Ниже только функция, использовать можно так же, как скрипт на ветер.
Все сделано по DMG AD&D 3ed.
Neverwinter Script Source
int PRECIPITATION_RAIN=1;
int PRECIPITATION_SNOW=2;
int PRECIPITATION_SLEET=3;
int PRECIPITATION_HAIL=4;

void ApplyPrecipitationEffect(int iPrecType,object oTarget=OBJECT_SELF)
{
object oTorch=GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oTarget);
if (GetBaseItemType(oTorch)==BASE_ITEM_TORCH) ActionUnequipItem(oTorch);
int iWpnType=GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oTarget));
int bRangeWpn=FALSE;

if (iWpnType!=BASE_ITEM_INVALID) {
   bRangeWpn=(iWpnType==BASE_ITEM_DART)||
             (iWpnType==BASE_ITEM_HEAVYCROSSBOW)||
             (iWpnType==BASE_ITEM_LIGHTCROSSBOW)||
             (iWpnType==BASE_ITEM_LONGBOW)||
             (iWpnType==BASE_ITEM_SHORTBOW)||
             (iWpnType==BASE_ITEM_SHURIKEN)||
             (iWpnType==BASE_ITEM_SLING)||
             (iWpnType==BASE_ITEM_THROWINGAXE);
}

switch(iPrecType) {
case 3: //PRECIPITATION_SLEET - морось
   ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
   EffectMovementSpeedDecrease(50),oTarget,7.0);
case 1: //PRECIPITATION_RAIN - дождь
   ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
   EffectSkillDecrease(SKILL_SPOT,4),oTarget,7.0);

   ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
   EffectSkillDecrease(SKILL_SEARCH,4),oTarget,7.0);

   ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
   EffectSkillDecrease(SKILL_LISTEN,4),oTarget,7.0);

   if (bRangeWpn)
       ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
       EffectAttackDecrease(4),oTarget,7.0);
break;
case 2: //PRECIPITATION_SNOW - снег
   ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
   EffectMovementSpeedDecrease(50),oTarget,7.0);

   if (bRangeWpn)
       ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
       EffectAttackDecrease(4),oTarget,7.0);

   ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
   EffectSkillDecrease(SKILL_SPOT,4),oTarget,7.0);

   ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
   EffectSkillDecrease(SKILL_SEARCH,4),oTarget,7.0);
break;
case 4: //PRECIPITATION_HAIL - град
   ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
   EffectMovementSpeedDecrease(50),oTarget,7.0);

   ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
   EffectSkillDecrease(SKILL_LISTEN,4),oTarget,7.0);

   if (d100()<=5) {
       ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectDamage(1,DAMAGE_TYPE_BLUDGEONIN
G),oTarget);
       SendMessageToPC(oTarget,"Здороваz градина внезапно стукнула тебz по голове.");
   }
break;
}
}

Это предпоследний скрипт из цикла скриптов, реализующих окружающую среду по АДиД. Последним будет скрипт для штормов, но там уже в принципе все просто: это в основном смесь осадков и ветра.

************************************************************************************
Lex
СЕРИЯ "СКРИПТЫ СТАРОЙ БАЗЫ"
ЦИКЛ "СКРИПТЫ ДЯДЮШКИ MILEZ'А"

Автор:::::::::::::::::Milez::::::::::::::::::::::::::::::
Jun 29 2003
Еще один спавн. Фишка в том, что респавн существ основан на вероятностом законе, а не на времени, через которое спавн должен происходить. Может кому пригодиться.
Основной скрипт на Heartbeat плейсабла, играющего роль спавна:
Neverwinter Script Source
void main()
{
   object oSelf=OBJECT_SELF;
   object oPC=GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR,PLAYER_CHAR_IS_PC);
   if (!GetIsObjectValid(oPC)) return;
   float fActDist=IntToFloat(GetMaxHitPoints()); // расстоЯние, на к-ом должен поЯвитьсЯ игрок от спавна, чтобы тот заработал
   if (GetDistanceBetween(oPC,oSelf)>fActDist) return;
   int iSpawnDist=GetReflexSavingThrow(oSelf); // макс. расст-ие, на к-ом будут поЯвлЯться сущ-ва
   int iSpawnChance=GetWillSavingThrow(oSelf); // вероЯтность поЯвлениЯ существа, %
   int iMaxSpawn=GetFortitudeSavingThrow(oSelf); // макс. кол-во сущ-в, поддерживаемых спавном
   int iSpawned=GetLocalInt(oSelf,"SpawnedCreatures");
   object oMonster;
   string sMonster;
   float fSpawnAngle;
   float fSpawnDist;
   vector vSpawnPlace;
   location lSpawnLoc;
   if (iSpawned<iMaxSpawn) {
       if (d100()<=iSpawnChance) {
           iSpawned++;
           fSpawnDist=IntToFloat(Random(iSpawnDist)+1);
           fSpawnAngle=IntToFloat(Random(360));
           vSpawnPlace=GetPosition(oSelf);
           vSpawnPlace.x+=fSpawnDist*cos(fSpawnAngle);
           vSpawnPlace.y+=fSpawnDist*sin(fSpawnAngle);
           lSpawnLoc=Location(GetArea(oSelf),vSpawnPlace,IntToFloat(Random(360)));
// Здесь вставьте подобным образом список сущ-в, которые будут спавнитьсЯ
           switch (Random(2)) {
           case 0:
               sMonster="nw_skeleton";
           break;
           case 1:
               sMonster="nw_zombie01";
           break;
           }
           oMonster=CreateObject(OBJECT_TYPE_CREATURE,sMonster,lSpawnLoc);
           SetLocalObject(oMonster,"MySpawner",oSelf);
           SetLocalObject(oSelf,"LastMonsterSpawned",oMonster);
       }
   }
   SetLocalInt(oSelf,"SpawnedCreatures",iSpawned);
}


В OnUserDefined стандартного скрипта nw_c2_defaultd добавим обработчик на событие 1007 (смерть), для регистрации смерти существа на мастер-спавне:
Neverwinter Script Source
...
object oSpawnPoint;
switch(iEvent) {
...
case 1007:
       oSpawnPoint=GetLocalObject(OBJECT_SELF,"MySpawner");
       if (GetIsObjectValid(oSpawnPoint)) {
           SetLocalInt(oSpawnPoint,"SpawnedCreatures",GetLocalInt(oSpawnPoint,"SpawnedCreatures")-1);
       }
   break;
...
}


Модификации возможны самые разные. Можно добавить флаг на макс. спавн, чтобы спавн работал только 1 раз, можно внести ограничения по времени. Короче, делайте что хотите
Настраивается спавн до обидног просто:
с св-вах плейсабла-спавна (я использовал невидимый объект) ставите:
Max Hit Points - расстояние, на котором должен появиться игрок, чтобы спавн заработал.
Reflex Save - макс. расст-ие от спавна, на котором будут создаваться сущ-ва.
Fortitude Save - макс. кол-во существ, к-ое будет поддерживаться спавном.
Will Save - вероятность того, что существо будет создано при каждом данном вызове скрипта, в процентах (100 - существа будут спавниться всегда, 0 - спавн отключен. 100 используйте очень осторожно: спавн будет постоянно поддерживать популяцию монстров, игрок просто может не успеть всех прибить!)

************************************************************************************

Автор:::::::::::::::::Milez::::::::::::::::::::::::::::::
Feb 24 2004
Ээээх, давно я тут не писал. Времени скриптовать не было. И вот жизнь подладилась, вышла ХотУ и... Сбылась мечта идиота! Я наконец-то смог сделать нормального призрака!
Вот функция:
Neverwinter Script Source
void SetGhostState(object oPC)
{
   // polymorph, so we can't equip/use things, cast spells etc.
   effect eGhost = EffectPolymorph(POLYMORPH_TYPE_SPECTRE,TRUE);
   // this way we can pass thru other mobs
   eGhost = EffectLinkEffects(EffectCutsceneGhost(),eGhost);
   // ghosts are invisible, you know
   eGhost = EffectLinkEffects(EffectInvisibility(INVISIBILITY_TYPE_DARKNESS),eGhost);
   // ghosts can't attack as well
   eGhost = EffectLinkEffects(EffectDazed(),eGhost);
   // others can't detect ghosts, no way!
   eGhost = EffectLinkEffects(EffectEthereal(),eGhost);
   // these effects can't be dispelled, as well as they can't be removed by rest
   eGhost = SupernaturalEffect(eGhost);

   ApplyEffectToObject(DURATION_TYPE_PERMANENT,eGhost,oPC);
   SetPlotFlag(oPC,TRUE); // ghosts are invincible
   SetLocalInt(oPC,"IAmAGhost",1);
}

Ставим ее на OnDeath, а скрипт ресурректа правим так, чтобы, будучи скастованным на чара, проверял соотв-ую лок. переменную и, если надо, "оживлял" чара, скидывая эффкты.

КОНЕЦ ЦИКЛА "СКРИПТЫ ДЯДЮШКИ MILEZ'А" СЕРИИ "СКРИПТЫ СТАРОЙ БАЗЫ"
Lex
СЕРИЯ "СКРИПТЫ СТАРОЙ БАЗЫ"
ЦИКЛ "СКРИПТЫ ДЯДЮШКИ _kaa_"

Автор:::::::::::::::::_kaa_::::::::::::::::::::::::::::::
Feb 24 2004
По поводу защиты чаров от хака. Вот простая реализация, привязывает конкретный аккаунт и имя персонажа к СД-КЕЮ. Есть возможность ДМ-ом отключить защиту на некоторое время (например сменили СД-КЕЙ и не могут попасть на шард)
Все ключи хранятся в базе данных на сервере.
Neverwinter Script Source
void main()
{
object oPC = GetEnteringObject();
string sCDKEY = GetPCPublicCDKey(oPC);
string sName = GetName(oPC);
string sPCName = GetPCPlayerName(oPC);
//Зачем нужны скобки (или вообще любые символы) - думайте сами.
string sID = "("+sPCName+")"+sName;
int SecurityDisabled = GetLocalInt(GetModule(),"SecurityDisable");
//if (GetIsDM(oPC)) return;
WriteTimestampedLogEntry("Security: "+sName+" :["+sPCName+"]: with key ="+sCDKEY);
string sReadID = GetCampaignString("Security",sID);
// ЕСЛИ НОВЫЙ ИЛИ ПРОВЕРКА ОТКЛЮЧЕНА - ПЕРЕЗАПИСЫВАТЬ КЛЮЧИ
if (sReadID =="" || SecurityDisabled)
   SetCampaignString("Security",sID,sCDKEY);
if (sReadID != sCDKEY && sReadID !="" && !SecurityDisabled)
   {
    BootPC(oPC);
    SendMessageToAllDMs("Security: Error! "+sName+" :["+sPCName+"]: with key ="+sCDKEY+ " != "+sReadID);
    WriteTimestampedLogEntry("Security: Error! "+sName+" :["+sPCName+"]: with key ="+sCDKEY+ " != "+sReadID);
   }
else
   WriteTimestampedLogEntry("Security: Check ok.");
}

Чтобы отключить на время защиту - из ДМ-клиента в консоли набираете:
dm_setmodulevarint SecurityDisable 1
включить обратно :
dm_setmodulevarint SecurityDisable 0

************************************************************************************

Автор:::::::::::::::::_kaa_::::::::::::::::::::::::::::::
Oct 3 2003
Скрипт для магазинов. Проверяет наличие такого товара в магазине, если уже есть - то после продажи удаляет. Нужен на шардах, где мазагины со временем забиваются ловушками, камнями и т.п. - при наличии более 10 страниц ассортимента в магазине начинаются заметные торможения сервера, проверенно.
Только одно требования к самим магазинам. В теге должно содержаться слово "_SHOP" (//Иначе нельзя узнать, магазин это или нет). - Вру ведь и никто не видит wacko.gif
Есть функция узнать тип объекта GetObjectType();
Вызывать из события модуля OnUnAcquireItem
Проще всего добавить в уже существующий обработчки строку:
ExecuteScript("at_check_dupe",OBJECT_SELF);

Сам скрипт:
at_check_dupe
Neverwinter Script Source
void main()
{
object oLostItem = GetModuleItemLost();
object oLostBy = GetModuleItemLostBy();
object oNewPosessor = GetItemPossessor(oLostItem);

if (FindSubString(GetStringUpperCase(GetTag(oNewPosessor)),"_SHOP"))
   {
    int n = 0;
    object oItem = GetFirstItemInInventory(oNewPosessor);
    while (GetIsObjectValid(oItem))
        {
          if (GetTag(oLostItem) == GetTag(oItem)) n++;
          if (n>1)
               {
                 DestroyObject(oLostItem);
                 break;
               }
          oItem = GetNextItemInInventory(oNewPosessor);
        }
   }
}


************************************************************************************

Автор:::::::::::::::::_kaa_::::::::::::::::::::::::::::::
Jan 30 2004
Из нового.
Реализация кольца духа - при надевании игрок становится полупрозрачным и может проходить сквозь других игроков. При снятии - эффект пропадает.
При желании можно добавить и неузвимость (не стал делать, ибо нефиг).
Для эффекта рекомендую добавить DayToNight() при надевании и наоборот.
на событие модуля onPlayerEquipItem()
Neverwinter Script Source
void main()
{
object oPC = GetPCItemLastEquippedBy();
object oItem = GetPCItemLastEquipped();
if (GetTag(oItem) == "mg_it_ringghost")
   {
   effect E = EffectCutsceneGhost();
   E = EffectLinkEffects(EffectEthereal(),E);
   ApplyEffectToObject(DURATION_TYPE_PERMANENT,E,oPC);
   }
}
[/nss

на onPlayerUnEquipItem()
[nss] 
void FindAndRemoveGhostEffect(object O)
{
effect e = GetFirstEffect(O);
while (GetIsEffectValid(e))
   {
   if (GetEffectType(e) == EFFECT_TYPE_CUTSCENEGHOST)
       RemoveEffect(O,e);
   if (GetEffectType(e) == EFFECT_TYPE_ETHEREAL)
       RemoveEffect(O,e);
   e = GetNextEffect(O);
   }
void main()
{
object oPC = GetPCItemLastUnequippedBy();
object oItem = GetPCItemLastUnequipped();
// кольцо духа
if (GetTag(oItem) == "mg_it_ringghost")
   {
   FindAndRemoveGhostEffect(oPC);
   }

где mg_it_ringghost - тег кольца.
написанно вчера для Мидгарда.

************************************************************************************

Автор:::::::::::::::::_kaa_::::::::::::::::::::::::::::::
Mar 25 2004
Расцветка сообщений, выводимых SendMessageToPC()
Работает все примерно так: есть тег <cRGB> и парный ему </c>
RGB - это три символа, ascii код каждого - это значение соответствующей цветовой компоненты.
Посколько многие символы нельзя использовать в скиптах, я взял " " (пробел) (32) и букву "ю" (254) как минимум и максимум.
После использования тега раскраски - закрывайте тег в помощью s_end()
Мне было достаточно 4 цветов, вот самый простейший код:
Neverwinter Script Source
string s_green() 
{     
return "<c ю >"
}   
string s_blue()
{     
return "<c  ю>"
}   
string s_red() 
{     
return "<cю  >"
}   
string s_white() 
{     
return "<cююю>"

string s_end() 
{     
return "</c>"
}


Вроде можно и в диалогах через SetCustomToken

************************************************************************************

Автор:::::::::::::::::_kaa_::::::::::::::::::::::::::::::
Mar 26 204
Простейшая реализация двумерного массива (очень полезен при кэширование .2da таблиц).
Ограничение - размерность, поставил 0..999

Neverwinter Script Source
//Add string S to array O[X,Y]
void _arr_SetStringXY(object O, int X,int Y,string S,string Prefix="_arr");
//Get string S from array O[X,Y]
string _arr_GetStringXY(object O, int X,int Y,string Prefix="_arr");
string _arr_AddNull(int I)
{
   string result = "";
   if (I<10) result+="0";
   if (I<100) result+="0";
   result += IntToString(I);
   return result;
}

void _arr_SetStringXY(object O, int X,int Y,string S,string Prefix="_arr")
{
   SetLocalString(O,Prefix+_arr_AddNull(X)+_arr_AddNull(Y),S);
}

string _arr_GetStringXY(object O, int X,int Y,string Prefix="_arr")
{
   return GetLocalString(O,Prefix+_arr_AddNull(X)+_arr_AddNull(Y));
}


ps. Многие не знают, поэтому добавлю:
Если вы описываете кроме самой функции ее прототип - это дает вам а) право использовать функцию в рекурсивных вызовах б) при дабл клике на функции выдаст описание этой функции (все то, что выше прототипа)

************************************************************************************

КОНЕЦ ЦИКЛА "СКРИПТЫ ДЯДЮШКИ _kaa_" СЕРИИ "СКРИПТЫ СТАРОЙ БАЗЫ"
Lex
СЕРИЯ "СКРИПТЫ СТАРОЙ БАЗЫ"
ЦИКЛ "СКРИПТЫ ДЯДЮШКИ DBCOLL'A"

автор::::::::::::DBColl::::::::::::::::::::
May 7 2003
скрипт на первое использование рычага отпирает и открывает дверь, на второе закрывает и захлопывает ее и тд.
На "OnUsed" рычага
Neverwinter Script Source
void main()
{
object oDoor=GetNearestObjectByTag("ТЭГ_ДВЕРИ");
if(GetIsOpen(oDoor)) // если она открыта
   {
    AssignCommand(OBJECT_SELF,ActionCloseDoor(oDoor));
    // захлопнуть дверь. действие привязанно к рычагу.
    SetLocked(oDoor,TRUE); // запереть дверь
    ActionPlayAnimation(ANIMATION_PLACEABLE_DEACTIVATE);
    // рычаг переходит в другое положение
    }
else if(!GetIsOpen(oDoor)) //иначе, если дверь не открыта
    {
    SetLocked(oDoor,FALSE);// отпереть дверь
    AssignCommand(OBJECT_SELF,ActionOpenDoor(oDoor));
    // открыть дверь.
    ActionPlayAnimation(ANIMATION_PLACEABLE_ACTIVATE);
    // перевод рычага в другое положение
    }
}


************************************************************************************

Автор:::::::::::::::::DBColl::::::::::::::::::::::::::::::
May 8 2003
данный скрипт каждые 18 секунд убавляет хиты, если игрок более, чем на 15 футов от костра.
(эмуляция действия холода)
Neverwinter Script Source
void main()
{
object oPC = GetFirstPC();
object oFlame = GetObjectByTag("тэг пламени");
int nSpeedOfDec = 3
// 3 раунда (за 18 секунд здоровье уменьшиться на 1 единицу)
int nSpeed = GetLocalInt(oPC, "DecHealthSpeed");
// первый раз даже если такая переменная не заведена, значение будет == 0
if (nSpeed == nSpeedOfDec && GetDistanceBetween(oPC, oFlame) > 15.0)
  // проверяем сколько раундов прошло с последнего уменьшения Health
  // и расстояние до костра (15 метров)
  {
  effect eDamage = EffectDamage( 1, DAMAGE_TYPE_MAGICAL, DAMAGE_POWER_NORMAL);
  /// определяется кол-во повреждений и тип
  ApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oPC);
  /// нанесение урона
  AssignCommand(oPC, ActionSpeakString("Блин, холодно однако..."));
  SetLocalInt(oPC, "DecHealthSpeed", 0);
  return;
  }
else if (GetDistanceBetween(oPC, oFlame) < 15.0
        && GetCurrentHitPoints(oPC) <= GetMaxHitPoints(oPC))
  /// если дистанция 15 метров или меньше, то лечить 2 хитпоинта за раунд
  {
  effect eHeal = EffectHeal(2);
  ApplyEffectToObject(DURATION_TYPE_INSTANT, eHeal, oPC);
  return;
  }
SetLocalInt(oPC, "DecHealthSpeed", nSpeed+1);
}


************************************************************************************

Автор:::::::::::::::::DBColl::::::::::::::::::::::::::::::
May 28 2003
Это скрипт командира охраны. Ему все солдаты (его фракции) отдают честь. ставится в UserDefined
Neverwinter Script Source
#include nw_i0_generic
void main()
{
int nEvent = GetUserDefinedEventNumber();
if (nEvent == 1002)
   {
   object oNPC = GetLastPerceived();
   if (GetFactionEqual(oNPC, OBJECT_SELF))
      {
      if (GetLastPerceptionSeen() && GetDistanceToObject(oNPC) < 6.0f &&
      GetLocalInt(oNPC, "GREATED") != 1)
          {
          SetLocalInt(oNPC, "GREATED", 1);
          AssignCommand(oNPC, ClearAllActions());
          AssignCommand(oNPC, ActionDoCommand(SetFacingPoint(GetPosition(OBJECT_SELF))));
          AssignCommand(oNPC, ActionSpeakString("ЗдравиЯ желаю!"));
          AssignCommand(oNPC, ActionPlayAnimation(ANIMATION_FIREFORGET_SALUTE, 0.5f, 1.0f));
          AssignCommand(oNPC, ActionDoCommand(WalkWayPoints()));
          DelayCommand(15.0f, SetLocalInt(oNPC, "GREATED", 0));
          }
      }
   return;
   }
}


************************************************************************************

Автор:::::::::::::::::DBColl::::::::::::::::::::::::::::::
Feb 20 2004
Я вот смотрю-смотрю, жду, но что-то так никто и не догадался, как просто можно сделать всплывающую строку на триггере... Вот мой вариант:
1. Создать триггер в палитре. В ОнЭнтер нужен всего один универсальный скрипт! Этот юзаем мы в Проклятии.
Neverwinter Script Source
//::///////////////////////////////////////////////
//:: Name
//:: Copyright © 2003 WRG!
//:://////////////////////////////////////////////
//:: Created By: DBColl
//:: Created On: 7.09.2003
//:://////////////////////////////////////////////
void main()
{
   object oPC = GetEnteringObject();
   if (!GetIsPC(oPC) || GetLocalInt(OBJECT_SELF, "triggered") > 0)
       return;
   string sStr = GetName(OBJECT_SELF);
   AssignCommand(oPC, SpeakString(sStr));
   if (GetLockKeyTag(OBJECT_SELF) == "")
       SetLocalInt(OBJECT_SELF, "triggered", 1);
}

2. Создаем этот триггер в модуле, заходим в его свойства и в поле Name пишем текст, который должен всплыть над игроком при наступании на него!!!
3. В KeyTag вносим что-то (любое число!) и получаем постоянно всплывающий текст над всеми PC, кто войдет на него.

************************************************************************************

КОНЕЦ ЦИКЛА "СКРИПТЫ ДЯДЮШКИ DBCOLL'A" СЕРИИ "СКРИПТЫ СТАРОЙ БАЗЫ"

Lex
СЕРИЯ "СКРИПТЫ СТАРОЙ БАЗЫ"
ЦИКЛ "СКРИПТЫ ДЯДЮШКИ LAZY RAMN'Ы"

автор::::::::::::Lazy Ramna::::::::::::::::::::
Oct 14 2003
LEX: ИСТОРИЧЕСКИЙ СКРИПТ LAZY. ОКТЯБРЬ 2003 ГОДА!! ВЕСЬ РУНЕТ ПОЛЬЗОВАЛСЯ ЭТОЙ ИДЕЕЙ ДО ВЫХОДА ПАТЧА DUMBO
Скрипт, позволяющий использовать букву "я" в скриптах
В константных строках буковка "я" запрещена, однако в переменных ее никто не запрещал. Посему создаем любой плэсейбл с тэгом ax_letter_ya и именем "я". Потом просто через ya() получаем нашу буковку, либо заменяем в строке все "йа" на "я". pardon.gif
Neverwinter Script Source
string ya(string sMessage = "йа")
   {
    string sYa = GetName(GetObjectByTag("ax_letter_ya"));
    string sResult = "";
    string sSub;
    int i = 0;
    while ((sSub = GetSubString(sMessage, i, 2)) != "")
           {
           if (sSub == "йа")
              {
              sResult += sYa;
              i += 2;
              }
           else
              {
              sResult += GetStringLeft(sSub, 1);
              i++;
              }
           }
    return sResult;
  }


Использование:
1) string sMessage = "Мо"+ya()+" сто"+ya()+"ть как стена";
2) string sMessage = ya("Мойа стойать как стена");
В обоих случаях в sMessage будет "Моя стоять как стена"

************************************************************************************

автор::::::::::::Lazy Ramna::::::::::::::::::::
Mar 15 2004
Не знаю, было или нет (я сюда не сильно заглядываю ), вот элементарнейший скрипт "автоперехода". Телепортирует наступившую на триггер кричу к объекту, тэг которого прописан в KeyTag. Вешается на OnEnter.
Neverwinter Script Source
void main()
{
object oPC = GetEnteringObject();
object oTarget = GetObjectByTag(GetTrapKeyTag(OBJECT_SELF));
if (GetIsObjectValid(oPC) && GetIsObjectValid(oTarget)) {
     AssignCommand(oPC, ClearAllActions());
     AssignCommand(oPC, JumpToObject(oTarget));
}
}

Я его ставлю после городских ворот, или ворот на мосту. Если PC не захочет "входить" в ворота, а решит пройтись чуть дальше к краю локации, то его насильно кинут куда надо.
Добавлено 18:57
Простенький инклюд. Позволяет получать кол-во лет/месяцев/дней/часов/минут/секунд, которое прошло с момента старта модуля. (в стиле UNIX_TIMESTAMP ) AX_LIB_START_YEAR - стартовый год.
Neverwinter Script Source
//© 2003 by Alexander Ponyatikh, aka Lazy Ranma

const int AX_LIB_START_YEAR = 0;

int GetCurrentYear()
{
   return GetCalendarYear() - AX_LIB_START_YEAR;
}

int GetCurrentMonth()
{
   return GetCurrentYear()*12 + GetCalendarMonth();
}

int GetCurrentDay()
{
   return (GetCurrentMonth() - 1)*28 + GetCalendarDay();
}

int GetCurrentHour()
{
   return (GetCurrentDay() - 1)*24 + GetTimeHour();
}

int GetCurrentMinute()
{
   return GetCurrentHour()*FloatToInt(HoursToSeconds(1))/60 + GetTimeMinute();
}

int GetCurrentSecond()
{
   return GetCurrentMinute()*60 + GetTimeSecond();
}


************************************************************************************

КОНЕЦ ЦИКЛА "СКРИПТЫ ДЯДЮШКИ LAZY RAMN'Ы" СЕРИИ "СКРИПТЫ СТАРОЙ БАЗЫ"
Lex
СЕРИЯ "СКРИПТЫ СТАРОЙ БАЗЫ"
ЦИКЛ "СКРИПТЫ ДЯДЮШКИ BAAL'A"

автор::::::::::::Baal::::::::::::::::::::
May 7 2003
данный скрипт забирает у игрока (или любого другого объекта) все вещи и дестроит их.
Neverwinter Script Source
void main()
{
  object oPC = GetFirstPC();
  /// выбирает игрока ( если хотите другой объект то GetObjectByTag("тэг объекта")
  object oInv = GetFirstItemInInventory(oPC);
    /// брать первый предмет из инвентаря игрока
  while(GetIsObjectValid(oInv)) /// пока в инвентаре есть предмет
      {
      DestroyObject(oInv); /// удаляет его
      oInv = GetNextItemInInventory(oPC);
      /// брать следующий предмет из инвентаря игрока
      }
    int i=0;
    while(i<14
      {
      DestroyObject(GetItemInSlot(i, oPC)); /// удаление вещей из слотов
      i++;
      }
}


************************************************************************************

автор::::::::::::Baal::::::::::::::::::::
Aug 18 2003
Вот конечный, работающий скрипт часов, для тех кому интересно. Спасибо ДБу за то, что помог с минутами.
Neverwinter Script Source
void main()
{
int iHour=GetTimeHour();
int iGameHourRealMinutes = 2; // число реальных минут равное 1 игровому часу (в настройках модулЯ)
float fMinute = IntToFloat(GetTimeMinute());
float fSecond = IntToFloat(GetTimeSecond());
float fGameMinute = fMinute*(60/iGameHourRealMinutes)+(fSecond/iGameHourRealMinutes);
int iMinute=FloatToInt(fGameMinute);
string sHour;
string sMinute;
if(iHour>0||iHour==21)
sHour=" Час ";
if(iHour>1||iHour>21)
sHour=" Часа ";
if(iHour>4&&iHour<21)
sHour=" часов ";
if(iHour==0)
sHour=" часов ";
sHour=IntToString(iHour)+sHour;

int iVR=StringToInt(GetStringRight(IntToString(iMinute),1));
if(iVR==0)
sMinute=IntToString(iMinute)+" минут.";
if(iVR>0)
sMinute=IntToString(iMinute)+" минута.";
if(iVR>1)
sMinute=IntToString(iMinute)+" минуты.";
if(iVR>4||(iMinute>10&&iMinute<21))
sMinute=IntToString(iMinute)+" минут.";
if(iMinute<10)
sMinute="0"+sMinute;

AssignCommand(GetFirstPC(),SpeakString("Московское времЯ: "+sHour+sMinute));
PlaySound("as_an_rooster1");//звук можно убрать :-)
}


************************************************************************************

автор::::::::::::Baal::::::::::::::::::::
Этот скрипт подсчитовает сколько у цели предметов с выбранным тегом. oInventory - чей инвентарь. sItemTag - Тег
Neverwinter Script Source
int ItemsAmount(string sItemTag, object oCreature = OBJECT_SELF)
{
int N=0;
object oItem = GetFirstItemInInventory(oCreature);
while (GetIsObjectValid(oItem))
  {
  if(GetTag(oItem) == sItemTag)
      {
      N = N + GetNumStackedItems(oItem);
      }
  oItem = GetNextItemInInventory(oCreature);
  }
return N;
}


************************************************************************************

КОНЕЦ ЦИКЛА "СКРИПТЫ ДЯДЮШКИ BAAL'A" СЕРИИ "СКРИПТЫ СТАРОЙ БАЗЫ"
Lex
СЕРИЯ "СКРИПТЫ СТАРОЙ БАЗЫ"
ЦИКЛ "СКРИПТЫ SMITH'A"

автор::::::::::::Smith::::::::::::::::::::
Sep 24 2003
Мне иногда приходилось сталкиваться с задачей создания случайной локации на заданном растоянии от какого-то объекта. Среди стандартных функций тулсета я такой вещи не нашел (хотя может быть плохо искал ), так, что пришлось написать самому. Может кому и пригодиться:
Neverwinter Script Source
location RandomLocation(object oTarget, float fRadius, int iLine = TRUE)
{
if(!iLine)
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 lNewLoc=Location(GetArea(oTarget),Vector(iXO+fRadius*cos(fRndomAngle),iYO+fRadiu
s*sin(fRndomAngle)),360.0);
return lNewLoc;
}

Скрипт создает случайную локацию на растоянии fRadius метров от объекта oTarget, причем, если задать iLine = FALSE, то локация может быть создана внутри круга на произвольном растоянии от объекта, не превышающем, однако, fRadius.

************************************************************************************

КОНЕЦ ЦИКЛА "СКРИПТЫ SMITH'A" СЕРИИ "СКРИПТЫ СТАРОЙ БАЗЫ"
Lex
СЕРИЯ "СКРИПТЫ СТАРОЙ БАЗЫ"
ЦИКЛ "СКРИПТЫ SELLARY"

автор::::::::::::sellary::::::::::::::::::::
Oct 20 2003
Функция определяет, можно ли надеть указанный армор.
в функцию передаем:
oArmor - объект армора,
oCreature - объект создания, на которое этот армор пытаемся одеть
возвращает TRUE, если одеть можно, FALSE - в обратном случае.
Проверка идет без учета класса создания (возможно, в дальнейшем модифицирую "по просьбам радиослушателей").
Отдельное спасибо Lazy Ranma за идею и spurlos - за мотивацию, DBColl за подсказку с уровнем.
Neverwinter Script Source
int GetIsValidArmor(object oArmor, object oCreature)
{
       // считаем базовую цену армора
       int nPrice = GetGoldPieceValue(oArmor);

       // определяем уровень создания
       int nClass = GetHitDice(oCreature);

       // определяем, может ли создание класса nClass
       // одевать броню стоимостью nPrice
       // (используется таблица #13 из приложения;
       // считаем, что создание более, чем 20 уровня
       // может одеть любой армор)
       int bResult = TRUE;
       switch (nClass) {
               case 1: bResult = (nPrice<=1000);
                       break;
               case 2: bResult = (nPrice<=1500);
                       break;
               case 3: bResult = (nPrice<=2500);
                       break;
               case 4: bResult = (nPrice<=3500);
                       break;
               case 5: bResult = (nPrice<=5000);
                       break;
               case 6: bResult = (nPrice<=6500);
                       break;
               case 7: bResult = (nPrice<=9000);
                       break;
               case 8: bResult = (nPrice<=12000);
                       break;
               case 9: bResult = (nPrice<=15000);
                       break;
               case 10: bResult = (nPrice<=19500);
                       break;
               case 11: bResult = (nPrice<=25000);
                       break;
               case 12: bResult = (nPrice<=30000);
                       break;
               case 13: bResult = (nPrice<=35000);
                       break;
               case 14: bResult = (nPrice<=40000);
                       break;
               case 15: bResult = (nPrice<=50000);
                       break;
               case 16: bResult = (nPrice<=65000);
                       break;
               case 17: bResult = (nPrice<=75000);
                       break;
               case 18: bResult = (nPrice<=90000);
                       break;
               case 19: bResult = (nPrice<=110000);
                       break;
               case 20: bResult = (nPrice<=130000);
                       break;
               default: bResult = (nClass>20);
                       break;
       };

       // возвращаем результат
       return bResult;
}


************************************************************************************

КОНЕЦ ЦИКЛА "СКРИПТЫ SELLARY" СЕРИИ "СКРИПТЫ СТАРОЙ БАЗЫ"
Lex
СЕРИЯ "СКРИПТЫ СТАРОЙ БАЗЫ"
ЦИКЛ "СКРИПТЫ GREEDO BEEFY"

автор::::::::::::Greedo Beefy::::::::::::::::::::
Jan 10 2004
Может кому то пригодится...
Если хотите что бы на вашем сервере, имеются ввиду шарды с PW, время и дата не сбрасывались с рестартом то можно сделать следующее.
Такой вот скриптик вешаем на любой предмет в модуле, лучше в защищенной локе, в слот OnHeartBeat
Neverwinter Script Source
void SaveCurTime (int minutes)
{
  int current = GetLocalInt(GetModule(), "cyclestill");
  if (current < ((minutes * 60) / 6))
  SetLocalInt(GetModule(), "cyclestill", current + 1);
  else
  {
        object oMod = GetModule();
        int iMonth = GetCalendarMonth();
        int iDay = GetCalendarDay();
        int iYear = GetCalendarYear();
        int iHour = GetTimeHour();
        SetCampaignInt("server_time", "CUR_YEAR", iYear, oMod);
        SetCampaignInt("server_time", "CUR_DAY", iDay, oMod);
        SetCampaignInt("server_time", "CUR_MONTH", iMonth, oMod);
        SetCampaignInt("server_time", "CUR_HOUR", iHour, oMod);
        SetLocalInt(GetModule(), "cyclestill", 0);
        WriteTimestampedLogEntry("Save Current Time completed");
  }
return;
}
void main ()
{
SaveCurTime(10);
}

Раз в десять минут (можно поставить любое значение) будет сохранятся текущая дата и время на сервере , игровое конечно же.
А на OnModuleLoad ставим это:
Neverwinter Script Source
void main()
{
object oMod = GetModule();
int iMonthNew = GetCampaignInt("server_time", "CUR_MONTH", oMod);
int iDayNew = GetCampaignInt("server_time", "CUR_DAY", oMod);
int iYearNew = GetCampaignInt("server_time", "CUR_YEAR", oMod);
int iHourNew = GetCampaignInt("server_time", "CUR_HOUR", oMod);
SetCalendar (iYearNew, iMonthNew, iDayNew);
SetTime (iHourNew, 0, 0, 0);
}

Написать скрипт вынудило желание ввести в банковскую систему проценты по вкладам и кредиты с процентами, которые зависят от времени. Ну как в жизни
С уважением Александр Дишке

************************************************************************************

КОНЕЦ ЦИКЛА "СКРИПТЫ GREEDO BEEFY" СЕРИИ "СКРИПТЫ СТАРОЙ БАЗЫ"
Lex
СЕРИЯ "СКРИПТЫ СТАРОЙ БАЗЫ"
ЦИКЛ "СКРИПТЫ DOCFEERT'A"

автор::::::::::::DocFeert::::::::::::::::::::
Feb 10 2004
Вот скрипт для уборщика:
Cтавится на OnHeartBeat уборщика
Как только уборщик увидит валяющийся на земле предмет, он его сразу поднимет.
Neverwinter Script Source
void main()
{
object oItem = GetFirstObjectInArea(GetArea(OBJECT_SELF));
while (GetIsObjectValid(oItem) == TRUE)
ClearAllActions();
{
if (GetObjectType(oItem) == OBJECT_TYPE_ITEM)
{
ActionPickUpItem(oItem);
}
oItem = GetNextObjectInArea(GetArea(OBJECT_SELF));
}
}


************************************************************************************

автор::::::::::::DocFeert::::::::::::::::::::
Feb 24 2004
Скрипт определяет кол-во жизней цели в процентах. oObject - чьи жизни, Возвращает кол-во жизней oObject.
Neverwinter Script Source
int Percent(object oObject)
{
int iCur = GetCurrentHitPoints(oObject);
int iMax = GetMaxHitPoints(oObject);
int iSt = iCur * 100;
int iPercent = iSt / iMax;
return iPercent;
}


************************************************************************************

автор::::::::::::DocFeert::::::::::::::::::::
Feb 24 2004
Скрипт на автооткрывание дверей. Делаем триггер и вешаем на него 2 скрипта. Это на OnEnter Триггера:
Neverwinter Script Source
void main()
{
object oDoor = GetFirstObjectInShape(SHAPE_SPHERE, 3.0, GetLocation(OBJECT_SELF), FALSE, OBJECT_TYPE_DOOR);
if (GetLocked(OBJECT_SELF) == FALSE)
{
ActionOpenDoor(oDoor);
}
}

А это на OnExit Триггера:
Neverwinter Script Source
void main()
{
if (GetLocked(OBJECT_SELF) == FALSE)
{
object oDoor = GetFirstObjectInShape(SHAPE_SPHERE, 3.0, GetLocation(OBJECT_SELF), FALSE, OBJECT_TYPE_DOOR);
ActionCloseDoor(oDoor);
}
}

Триггер просто растягивается под открываемой дверью.

************************************************************************************

автор::::::::::::DocFeert::::::::::::::::::::
Mar 10 2004
А этот код позволяет создать "случайную локацию", как например в БГ или Фаллоут, когда идешь, идешь... И натыкаешься на каких-нибудь рейдеров. Для этого в oArea записываем локацию, в которой будут создоваться обьекты, в Х записываем количество тайлов этой локации по оси Х, в Y записываем количество тайлов этой локации по оси Y, в sObjByResRef пишем тег по ресрефу обьекта, в iObjType пишем тип обьекта (OBJECT_TYPE_*) а в iMaxObjects пишем максимальное количество этих обьектов.
Neverwinter Script Source
void RandomObjectsAtRandomLocation(object oArea, int X, int Y, string sObjByResRef, int iObjType, int iMaxObjects)
{
int iMax = 0;
float fX = IntToFloat(Random(X * 10));
float fY = IntToFloat(Random(Y * 10));
float fZ = 0.0;
float fF = IntToFloat(Random(360));
location lLoc = Location(oArea, Vector(fX, fY, fZ), fF);
while (iMax != iMaxObjects)
{
iMax = iMax + 1;
float fX = IntToFloat(Random(X * 10));
float fY = IntToFloat(Random(Y * 10));
float fZ = 0.0;
float fF = IntToFloat(Random(360));
location lLoc = Location(oArea, Vector(fX, fY, fZ), fF);
if (d2(1) == 2)
{
CreateObject(iObjType, sObjByResRef, lLoc, FALSE);
}
}
}


************************************************************************************

автор::::::::::::DocFeert::::::::::::::::::::
Mar 10 2004
А этот скрипт для переноса всех обьектов (крич, плейсов, итемов) из одной локации в другую. В oAreaFrom записываем локацию ИЗ которой переносим обьекты, в oAreaTo пишим ту локацию В которую переносим обьекты, если iDestroy = TRUE, все обьекты в локации oAreaFrom уничтожаются. Если в локации игрок, то он тоже переностится.
Neverwinter Script Source
void MoveArea(object oAreaFrom, object oAreaTo, int iDestroy=TRUE)
{
object oObject = GetFirstObjectInArea(oAreaFrom);
while (GetIsObjectValid(oObject) == TRUE)
{
location lLoc = Location(oAreaTo, GetPosition(oObject), GetFacing(oObject));
if (GetObjectType(oObject) == OBJECT_TYPE_ITEM)
{
CopyObject(oObject, lLoc, OBJECT_INVALID, GetTag(oObject));
if (iDestroy == TRUE)
{
DestroyObject(oObject);
}
}
if ((GetObjectType(oObject) == OBJECT_TYPE_PLACEABLE))
{
string sTag = GetResRef(oObject);
CreateObject(OBJECT_TYPE_PLACEABLE, sTag, lLoc);
if (iDestroy == TRUE)
{
DestroyObject(oObject);
}
}
if (GetObjectType(oObject) == OBJECT_TYPE_CREATURE)
{
AssignCommand(oObject, JumpToLocation(lLoc));
}
oObject = GetNextObjectInArea(oAreaFrom);
}
}


************************************************************************************

КОНЕЦ ЦИКЛА "СКРИПТЫ DOCFEERT'A" СЕРИИ "СКРИПТЫ СТАРОЙ БАЗЫ"
Lex
СЕРИЯ "СКРИПТЫ СТАРОЙ БАЗЫ"
ЦИКЛ "СКРИПТЫ MALKOR'A"

автор::::::::::::MalkoR::::::::::::::::::::
Sep 13 2003
Идея скрипта такая. Стоит обелиск, вокруг стоят 4 шарика силы. В обелиске по порядку стоят 10 невидимых объекта, мелких. Шарики накладывают на onHeartbeat эффект луча в рэндом из этих 10 невидимых объекта. Получаеться эффект питания обелиска энергией этими шариками.
скрипт ставиться в onHeartbeat шариков
Neverwinter Script Source
void main()
{
object wp_k4 = GetObjectByTag("TWp_KEEPER4"); //WayPoint стояший на месте шарика, это на тот случай, если шарик атакуя кого то отойдет.
AssignCommand(OBJECT_SELF, ActionJumpToObject(wp_k4)); //перемешаеться на свое место
object os = OBJECT_SELF;
effect eff = EffectBeam(VFX_BEAM_LIGHTNING,os,BODY_NODE_CHEST,FALSE); //какой эффект накладывать на обелиск (тут была идея сделать ещё один скрипт, чтоб луч был рэндом, но с первого разане вышло, продолжать не стал из- за своей запарки  )

object c1 = GetObjectByTag("TP_CORPOSE_001"); //определяет невидимый объект в обелиске
object c2 = GetObjectByTag("TP_CORPOSE_002");
object c3 = GetObjectByTag("TP_CORPOSE_003");
object c4 = GetObjectByTag("TP_CORPOSE_004");
object c5 = GetObjectByTag("TP_CORPOSE_005");
object c6 = GetObjectByTag("TP_CORPOSE_006");
object c7 = GetObjectByTag("TP_CORPOSE_007");
object c8 = GetObjectByTag("TP_CORPOSE_008");
object c9 = GetObjectByTag("TP_CORPOSE_009");
object c10 = GetObjectByTag("TP_CORPOSE_010");

int a = d10();

if (a == 1)
{
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eff,c1,6.0f);
return;
}
if (a == 2)
{
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eff,c2,6.0f);
return;
}
if (a == 3)
{
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eff,c3,6.0f);
return;
}
///. . . . . . (а == 4, а ==5 и т.д. до 9) . . . . . . .

if (a == 10)
{
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eff,c10,6.0f);
return;
}
}


************************************************************************************

КОНЕЦ ЦИКЛА "СКРИПТЫ MALKOR'A" СЕРИИ "СКРИПТЫ СТАРОЙ БАЗЫ"
Lex
СЕРИЯ "СКРИПТЫ СТАРОЙ БАЗЫ"
ЦИКЛ "СКРИПТЫ ДЯДЮШКИ VALLEO"

автор::::::::::::Valleo::::::::::::::::::::
Mar 19 2004
Маленький скриптик для реализации болота:
Neverwinter Script Source
void StartBog()
{
object oBog = OBJECT_SELF;
object oArea = GetArea(oBog);
location lLocation = GetLocation(oBog);
location lLoc;
location lLocat;
object oObject = GetFirstObjectInShape(SHAPE_SPHERE,100.0,lLocation,FALSE,OBJECT_TYPE_CREATURE);
while(GetIsObjectValid(oObject))
{
lLoc = GetLocation(oObject);
lLocat = GetLocalLocation(oObject,"BOGLOC");
if(GetIsObjectValid(GetAreaFromLocation(lLocat)))
  {
  float fDist = GetDistanceBetweenLocations(lLoc,lLocat);
  if(fDist < 5.0)
   {
   effect eSlow = EffectMovementSpeedDecrease(75);
   ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eSlow,oObject,70.0);
   FloatingTextStringOnCreature("Вас засасывает в бололто...",oObject,FALSE);
   }
  }
SetLocalLocation(oObject,"BOGLOC",lLoc);
oObject = GetNextObjectInShape(SHAPE_SPHERE,100.0,lLocation,FALSE,OBJECT_TYPE_CREATURE);
}
}
void main()
{
object oBog = OBJECT_SELF;
int iTimer = GetLocalInt(oBog,"TIMER");
if(iTimer <= 9)
{
iTimer = iTimer + 1;
SetLocalInt(oBog,"TIMER",iTimer);
return;
}
SetLocalInt(oBog,"TIMER",0);
StartBog();
}

Ставится на хербит любого объекта на локации болота (главное чтобы объект был плотовый )...

************************************************************************************

автор::::::::::::Valleo::::::::::::::::::::
Mar 19 2004
Мой личный код на проверку скилла Persuade. Используется харизма и ее модификатор, а так же кубики для болей реалестичности...
Использовать:
NPC: Привет!
1) И тебе привет! У тебя же есть работа?
NPC (1) [Проверка удачна] Да, конечно! <-- сюда вставить скрипт проверки Persuade
NPC (2) [Проверка неудачна] С чего ты взял?
2) Извини, обознался...
Neverwinter Script Source
int StartingConditional()
{
object oPC = GetPCSpeaker();
object oNPC = OBJECT_SELF;
object oWinner;
int iCharisma = GetAbilityScore(oPC,ABILITY_CHARISMA);
if(iCharisma < 7)
{
SendMessageToPC(oPC,"У вас харизма ниже 7, вы не можете нормально разговаривать с "+GetName(oNPC));
return FALSE;
}
int iPCPersuade, iNPCPersuade;
int iAddPC, iAddNPC;
int iPCCharModif, iNPCCharModif;
if(GetHasSkill(SKILL_PERSUADE,oPC)) iPCPersuade = GetSkillRank(SKILL_PERSUADE,oPC);
if(GetHasSkill(SKILL_PERSUADE,oNPC)) iNPCPersuade = GetSkillRank(SKILL_PERSUADE,oNPC);
iPCCharModif = GetAbilityModifier(ABILITY_CHARISMA,oPC);
iNPCCharModif = GetAbilityModifier(ABILITY_CHARISMA,oNPC);
iAddPC = d12();
iAddNPC = d12();
SendMessageToPC(oPC,"Проверка на скилл Persuade:");
SendMessageToPC(oPC,"Ваш сккилл равен = "+IntToString(iPCPersuade)+" + "+IntToString(iAddPC)+" (d12) + "+IntToString(iPCCharModif)+" (модификатор харизмы) = " +IntToString(iPCPersuade+iAddPC+iPCCharModif));
SendMessageToPC(oPC,"Скилл вашего оппонента равен = "+IntToString(iNPCPersuade)+" + "+IntToString(iAddNPC)+" (d12)  + "+IntToString(iNPCCharModif)+" (модификатор харизмы) = " +IntToString(iNPCPersuade+iAddNPC+iNPCCharModif));
iPCPersuade = iPCPersuade + iAddPC + iPCCharModif;
iNPCPersuade = iNPCPersuade + iAddNPC + iNPCCharModif;
if(iPCPersuade > iNPCPersuade)
{
SendMessageToPC(oPC,"Вы удачно провели проверку скилла.");
return TRUE;
}
SendMessageToPC(oPC,"Вы провалили проверку.");
return FALSE;
}


************************************************************************************

КОНЕЦ ЦИКЛА "СКРИПТЫ ДЯДЮШКИ VALLEO" СЕРИИ "СКРИПТЫ СТАРОЙ БАЗЫ"
Lex
СЕРИЯ "СКРИПТЫ СТАРОЙ БАЗЫ"
ЦИКЛ "СКРИПТЫ ТЕМНОГО ЛОРДА"

автор::::::::::::Темный лорд::::::::::::::::::::
May 17 2003
Скрипт на то. Чтобы после смерти объекты воскрешали. Я делал его для себя. Подскажу как его еще можно использовать.
Я взял обычных людей. Поставив им тег h01. И вставил в onDeath этот скрипт. В результате получилось, что если убить этого человека.
Он превратится в зомби. Главное не забыть поставить на карте объект Nekrolog01.
Neverwinter Script Source
void Raise()
{
effect eVisDead = EffectVisualEffect(VFX_IMP_HEAD_ACID);///Эффект с которым объект будет воскресать. В данном случае это кислота!
object oNew = CreateObject(OBJECT_TYPE_CREATURE,"ZombieWeak07", GetLocation(OBJECT_SELF)) ;///Тег объекта который будет воскресать.
ApplyEffectAtLocation(DURATION_TYPE_PERMANENT, eVisDead, GetLocation(oNew));

}
void main()
{
object oCleric = GetNearestObjectByTag("Nekrolog01");/// Тег объекта который будет оживлять. И которого надо убить чтобы остальные больше не оживали.

if (GetIsObjectValid(oCleric) == TRUE && GetIsDead(oCleric) == FALSE)
{
AssignCommand(oCleric, ClearAllActions());
AssignCommand(oCleric, ActionPlayAnimation(ANIMATION_LOOPING_WORSHIP, 1.0, 3.0));///Действия которые выполняет "оживитель" как только умирает один из объектов. В данном случае становится на колени.
effect eVisCleric = EffectVisualEffect(VFX_IMP_AURA_NEGATIVE_ENERGY);/// Эффект с которым клирик воскрешает. В данном случае появляется красного цвета аура. Но эффекты можно менять!
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eVisCleric, oCleric);
DelayCommand(3.0, Raise());
DelayCommand(0.2,AssignCommand(oCleric, SpeakOneLinerConversation())) ;
}
}

Самое необходимое я выделил.

************************************************************************************

автор::::::::::::Темный лорд::::::::::::::::::::
May 17 2003
Скрипт моего друга. Он если зайдет то даст его описание. Вообще скрипт на то чтобы после смерти находится в бессознательном состоянии 10 едениц. 1 вставляется в OnHeartbeat. Второй в OnPlayerDying. /// Без пояснений.
Neverwinter Script Source
void loadBehaviors()
{
SetLocalInt(OBJECT_SELF, "DEATH_TARGET", -10);
SetLocalInt(OBJECT_SELF, "PLAYER_ONLY_GRUNTS_WHILE_DYING", FALSE);
}
void bleedCheck(object pc)
{
if (!GetIsPC(pc))
return;
int DEATH_TARGET = GetLocalInt(OBJECT_SELF, "DEATH_TARGET");
int PLAYER_ONLY_GRUNTS_WHILE_DYING = GetLocalInt(OBJECT_SELF, "PLAYER_ONLY_GRUNTS_WHILE_DYING");
int hp = GetCurrentHitPoints(pc);
if ((hp <= 0) && (hp > DEATH_TARGET))
    {
    effect dmg = EffectDamage(1);
    ApplyEffectToObject(DURATION_TYPE_INSTANT, dmg, pc);
    int which = Random(6)+1;
    if (PLAYER_ONLY_GRUNTS_WHILE_DYING)
    switch (which)
        {
        case 1:
              PlayVoiceChat(VOICE_CHAT_PAIN1, pc);
              break;
        case 2:
              PlayVoiceChat(VOICE_CHAT_PAIN2, pc);
              break;
        case 3:
              PlayVoiceChat(VOICE_CHAT_PAIN3, pc);
              break;
        case 4:
              PlayVoiceChat(VOICE_CHAT_HEALME, pc);
              break;
        case 5:
              PlayVoiceChat(VOICE_CHAT_NEARDEATH, pc);
              break;
        case 6:
              PlayVoiceChat(VOICE_CHAT_HELP, pc);
              break;
       }
    }
else if (hp <= DEATH_TARGET)
   {
   effect death = EffectDeath(FALSE, FALSE);
   ApplyEffectToObject(DURATION_TYPE_INSTANT, death, pc);
   }
}

void main()
{
loadBehaviors();
object pc = GetFirstPC();
while (GetIsObjectValid(pc))
   {
   bleedCheck(pc);
   pc = GetNextPC();
   }
}



Neverwinter Script Source
void main()
{
// load up desired behaviors for all OnHeartbeat scripts
loadBehaviors();

// enumerate all PCs, calling bleedCheck on each
// if you want to add more / other scripts that act on all players
// every heartbeat, this is the place to do it ... just put a call
// to them after (or before) bleedCheck, within the while loop.
object pc = GetFirstPC();

while (GetIsObjectValid(pc))
  {
  bleedCheck(pc);
  pc = GetNextPC();
  }
}


************************************************************************************

автор::::::::::::Темный лорд::::::::::::::::::::
Jun 3 2003
Вот еще скрипт из моего модуля. Ставится как правило. На OnUsed
предмета. Что телепортирует игрока на заданный вэйпоинт.
Neverwinter Script Source
void main()
{
object oPC = GetLastUsedBy();
object oTarget = GetObjectByTag("Waypoint"); /// тэг Waypoint-та, на который попадёт игрок.
effect eVis = EffectVisualEffect(VFX_IMP_HEALING_X); /// эффект с которым игрок будет попадать.
location lPC = GetLocation(oPC);
ApplyEffectAtLocation(DURATION_TYPE_PERMANENT, eVis, lPC);
AssignCommand(oPC,JumpToObject(oTarget));
}


************************************************************************************

автор::::::::::::Темный лорд::::::::::::::::::::
Jun 3 2003
На превращение НПC в предмет. Вставляется в Heartbeat!!
(Скрипт взят из гаргульи.)
Neverwinter Script Source
void main()
  {
  object oPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC);
  if ((GetIsObjectValid(oPC) != TRUE) || (GetIsDead(oPC) == TRUE) || GetDistanceToObject(oPC) >= 10.0)
    {
    location l = GetLocation(OBJECT_SELF);
    location lNew = Location( GetAreaFromLocation(l), GetPositionFromLocation(l), GetFacingFromLocation(l) + 180);
    // CreateObject( OBJECT_TYPE_PLACEABLE, "plc_statue3", lNew );
    CreateObject(OBJECT_TYPE_PLACEABLE, "StatueStone", lNew); /// предмет в который НПК будет превращатся.
    DestroyObject(OBJECT_SELF, 0.5);
    }
  }


************************************************************************************

КОНЕЦ ЦИКЛА "СКРИПТЫ ТЕМНОГО ЛОРДА" СЕРИИ "СКРИПТЫ СТАРОЙ БАЗЫ"
Lex
СЕРИЯ "СКРИПТЫ СТАРОЙ БАЗЫ"
ЦИКЛ "СКРИПТЫ NEUROSHOOTA"

автор::::::::::::neuroshoot::::::::::::::::::::
Jun 19 2003
Скрипт смены погоды (таких наверное дофига уже сделали, но ине лень было искать, вот и написал).
Скрипт кладете на хертбит зоны:
Neverwinter Script Source
void main()
{
object oArea = OBJECT_SELF;
int nRain = WEATHER_RAIN;
int nClear = WEATHER_CLEAR;
int nDef = WEATHER_USE_AREA_SETTINGS;
int nHour = GetTimeHour();
if(nHour == 20|| nHour == 21|| nHour == 22|| nHour == 23||
nHour == 24|| nHour == 0 || nHour == 1 || nHour == 2 ||
nHour == 3 || nHour == 4 || nHour == 5 || nHour == 6 &&
!GetLocalInt(oArea, "IsDef") == 1)
{
SetWeather(oArea, nDef);
SetLocalInt(oArea, "IsRaining", 0);
SetLocalInt(oArea, "IsClear", 0);
SetLocalInt(oArea, "IsDef", 1);
}

if(nHour == 7 || nHour == 8 || nHour == 9 || nHour == 10||
nHour == 11|| nHour == 12&&
!GetLocalInt(oArea, "IsClear") == 1)
{
SetWeather(oArea, nClear);
SetLocalInt(oArea, "IsRaining", 0);
SetLocalInt(oArea, "IsClear", 1);
SetLocalInt(oArea, "IsDef", 0);
}

if(nHour == 13|| nHour == 14|| nHour == 15|| nHour == 16||
nHour == 17|| nHour == 18|| nHour == 19&&
!GetLocalInt(oArea, "IsRaining") == 1)
{
SetWeather(oArea, nRain);
SetLocalInt(oArea, "IsRaining", 1);
SetLocalInt(oArea, "IsClear", 0);
SetLocalInt(oArea, "IsDef", 0);
}
}

Вроде все работает. Если хотите, чтобы погода менялась чаще, поменяйте измените время срабатывания. Для полноты картины разместите на карте различные звуки, которые будут появляться в определенное время (например звук грозы и т.д.).

************************************************************************************

КОНЕЦ ЦИКЛА "СКРИПТЫ ТЕМНОГО ЛОРДА" СЕРИИ "СКРИПТЫ СТАРОЙ БАЗЫ"
Lex
СЕРИЯ "СКРИПТЫ СТАРОЙ БАЗЫ"
ЦИКЛ "СКРИПТЫ ДЯДЮШКИ AIWAN'A"

автор::::::::::::Aiwan::::::::::::::::::::
Jan 19 2004
Скрипт лута для класса в после выполнения квеста.
Neverwinter Script Source
//::///////////////////////////////////////////////////////////
//:: Created By: WRG! Aiwan aiwanwrg.ru
//:: Created On: 19.01.2004
//:://////////////////////////////////////////////////////////
/*
Скрипт на OnOpen сундука. Здесь приведены только
два класса, но проверить можно любой, достаточно
скопировать строки кода и кликнув на классе в скрипте
F-2, выбрать нужный класс. Если класс не попал в
проверку, то получаем самую нижнюю вещь.
*/

//:://////////////////////////////////////////////////////////
void main()
{
  object oPC = GetLastOpenedBy();

  if (!GetIsPC(oPC) || GetLocalInt(OBJECT_SELF, "DO_IT") ||
       !GetLocalInt(oPC, "ПЕРЕМЕННАЯ_КВЕСТА"))
      {return;}
     SetLocalInt(OBJECT_SELF, "DO_IT", TRUE);

     if(GetLevelByClass(CLASS_TYPE_CLERIC, oPC) >= 1) // КЛЕРИК выше 1 уров.
       {
       CreateItemOnObject("res-ref предмета", OBJECT_SELF, 1);
         return;
       }
     if(GetLevelByClass(CLASS_TYPE_WIZARD,oPC) >= 1) // МАГ выше 1 уров. итд
       {
       CreateItemOnObject("res-ref предмета ", OBJECT_SELF, 1);
         return;
       }
       CreateItemOnObject("res-ref предмета ", OBJECT_SELF, 1); // все остальные
         return;
}


************************************************************************************

автор::::::::::::Aiwan::::::::::::::::::::
Mar 5 2004
Вот простенький скрипт, ставится на OnOpen сундука, саркофаги и т.д. При проверке скилла поиск, создает в инвентаре объект в зависимости от алигмента. Код не идеален, но работает
Neverwinter Script Source
//:://////////////////////////////////////////////
//:: Created By: WRG! Aiwan aiwane-mail.ru
//:: Created On: 06.12.2003
//:://////////////////////////////////////////////
/*  Скрипт на OnOpen сундука или саркофага.
     у каждого, алигмента свой приз.
    Если поиск прошел, получаем плюшку.
*/

//:://////////////////////////////////////////////
#include "nw_i0_tool"
void main()
{
  object oPC = GetLastOpenedBy();

  if (GetIsPC(oPC) && GetLocalInt(OBJECT_SELF, "DO_IT") != 1 &&
     (AutoDC(DC_HARD, SKILL_SEARCH, oPC))) // ПРОВЕРКА СКИЛЛА ПОИСК
    {
    AssignCommand(oPC, SpeakString("Bам удалось обнаружить предмет."));
    if (GetAlignmentGoodEvil(oPC) == ALIGNMENT_GOOD) // ПЛЮШКА ДЛЯ ГУДА
       {
       CreateItemOnObject("ResRef ОБЪЕКТА", OBJECT_SELF, 1);
       }
       if (GetAlignmentGoodEvil(oPC) == ALIGNMENT_EVIL) // ПЛЮШКА ДЛЯ ЕВИЛА
           {
           CreateItemOnObject("ResRef ОБЪЕКТА", OBJECT_SELF, 1);
           }
    RewardPartyXP(1500, oPC);
    SetLocalInt(OBJECT_SELF, "DO_IT", 1);
    }
  if (GetIsPC(oPC) && GetLocalInt(OBJECT_SELF, "DO_IT") != 1)
  {
  AssignCommand(oPC, SpeakString("Вам не удалось обнаружить ничего."));
  RewardPartyXP(500, oPC);
  SetLocalInt(OBJECT_SELF, "DO_IT", 1);
  }
}


************************************************************************************

автор::::::::::::Aiwan::::::::::::::::::::
Mar 5 2004
Вот еще один скрипт. Короче, создаете в палитре НПС и делаете его с нужными свойствами, что бы он рандомно бродил или еще что. Дальше, в локации где он должен спавниться, на любой объект вешаете скрипт на хербит. И усе, ночью будет приведение, днем все спокойно

Neverwinter Script Source
//:://////////////////////////////////////////////
//:: Copyright © 2004 WRG!
//:://////////////////////////////////////////////
/*
СТАВИМ НЕВИДИМЫЙ ОБЪЕКТ В ЛОКЕ И НА OnHeartBeat
КИДАЕМ СКРИПТ. НОЧЬЮ ПОЯВЛЯЕТСЯ ДУХ ИЗ ПАЛИТРЫ
С НАСТУПЛЕНИЕМ УТРА ДЕСТРОИТЬСЯ. КТО ХОЧЕТ МОЖЕТ
      ДОБАВИТЬ ТОЧНОЕ ВРЕМЯ ДЛЯ СПАВНА
*/

//:://////////////////////////////////////////////
//:: Created By: Aiwan
//:: Created On: 03.02.2004
//:://////////////////////////////////////////////

void main()
{
    object oItm = OBJECT_SELF;
    object oTarget = GetObjectByTag("WP_NIMPHA_GOST"); //ТОЧКА ПОЯВЛЕНИЯ ДУХА
    object oGost = GetObjectByTag("ANDR_GOST");
//=====================  ДЕНЬ  ====================
    if (GetIsDay() && GetLocalInt(OBJECT_SELF, "NIGHT") == 1)
    {
      ApplyEffectAtLocation(DURATION_TYPE_INSTANT,
      EffectVisualEffect(VFX_FNF_SOUND_BURST), GetLocation(oGost));
      ActionWait(1.0);
      ActionDoCommand(DestroyObject(oGost));
      SetLocalInt(OBJECT_SELF, "NIGHT", 0);
    }
    if (!GetIsNight() && GetLocalInt(OBJECT_SELF, "NIGHT") == 0)
    return;
//=====================  НОЧЬ =====================
    {
    if (!GetIsNight() || GetLocalInt(OBJECT_SELF, "NIGHT") == 1)
    return;

      oGost = CreateObject(OBJECT_TYPE_CREATURE, "ResRef_ДУХА", GetLocation(oTarget));
      ApplyEffectAtLocation(DURATION_TYPE_INSTANT,
      EffectVisualEffect(VFX_IMP_DEATH_WARD), GetLocation(oTarget));
      AssignCommand(oGost, ClearAllActions());
      SetLocalInt(OBJECT_SELF, "NIGHT", 1);
     }
}


Перед спавном вашего Духа поставьте строчку, я не проверял. но должно пахать:
Neverwinter Script Source
if (GetTimeHour()==23) // ТУТ УКАЖЕТЕ ВРЕМЯ


************************************************************************************

автор::::::::::::Aiwan::::::::::::::::::::
Mar 8 2004
У меня много дверей в модуле, которые произносят фразу, типа: "Запечатано магией. Открыть нельзя" Ну и в том же духе. Так вот, скриптов-стрингов развелось уже довольно много Сел я тут и написал парачку ну очень простеньких скриптиков для этих нужд. Если вам пригодятся, буду только рад.
Первый, просто скрипт. Если вам не в лом его править под каждую дверь, то ставьте его.
Второй проще для установки, но немного с побочным эффектом в виде вейпоинта. Какой нравится, тот и берите.
Neverwinter Script Source
//:://////////////////////////////////////////////
//:: Copyright © 2004 WRG!
//:: OnFailToOpen
//:://////////////////////////////////////////////
//:: Created By: Aiwan
//:: Created On: 10.01.2004
//:://////////////////////////////////////////////
void main()
{
string oDoor = GetTag(OBJECT_SELF);
string sMesseg = "ОШИБКА! TAG двери НЕПРАВИЛЬНЫЙ!"; // ЕСЛИ ВЫ ОШИБЛИСЬ С ТЭГОМ
{
   if (oDoor == "TAG_ДВЕРИ_01" || oDoor == "TAG_ДВЕРИ_02") // ОДИНАКОВЫЕ ФРАЗЫ ДЛЯ РАЗНЫХ ДВЕРЕЙ
      {sMesseg = "Дверь заперта, ключ украден.";}
   if (oDoor == "TAG_ДВЕРИ_03")
      {sMesseg = "Дверь заперта.";}
SpeakString(sMesseg);
}
}


Neverwinter Script Source
//:://////////////////////////////////////////////
//:: Copyright © 2004 WRG!
//:: OnFailToOpen
//:://////////////////////////////////////////////
/*
  WP_DOOR_TXT - вейп с именем нашего текста.
    Ставим его сразу перед нужной дверью.
*/

//:://////////////////////////////////////////////
//:: Created By: Aiwan
//:: Created On: 10.01.2004
//:://////////////////////////////////////////////
void main()
{
object oWp = GetNearestObjectByTag("WP_DOOR_TXT"); // БЕРЕМ БЛИЖАЙШИЙ
string sDoor = GetName(oWp);

   if (GetIsObjectValid(oWp) && GetDistanceBetween(oWp, OBJECT_SELF) <= 10.0f)
       //  ЕСЛИ ЕСТЬ ТАКОЙ WP И ОН НЕ ДАЛЬШЕ 10 МЕТРОВ
       {
       SpeakString(sDoor); // ПРОИЗНОСИМ ЕГО ИМЯ
        return;
       }
       else
          {
          SpeakString("Ошибка! Не могу найти WP_DOOR_TXT!");// ЕСЛИ МЫ ЗАБЫЛИ ПОСТАВИТЬ
          return;
          }
}


************************************************************************************

автор::::::::::::Aiwan::::::::::::::::::::
Mar 14 2004
Воот ну очень простой скриптик. Рандомный лут в КВЕСТОВЫЙ сундук, плюшка к плотовому предмету или еще куда.
Мне необходимо дать игроку разные вещи но +4, +5 и т.д. Править лут общий из-за пары сундуков не охота
Чем проще тем надежнее Вспомнил как мне нужен был такой скрипт год назад
Neverwinter Script Source
//:://////////////////////////////////////////////
//:: Copyright © 2004 WRG!  www.wrg.ru
//:: OnOpen OBJECT
//:://////////////////////////////////////////////
/*
           РАНДОМНЫЙ ЛУТ ДЛЯ СУНДУКА
*/

//:://////////////////////////////////////////////
//:: Created By: Aiwan    Aiwane-mail.ru
//:: Created On: 14.03.2004
//:://////////////////////////////////////////////
void main()
{
  object oPC = GetLastOpenedBy();
  string sResRef;
if (!GetIsPC(oPC) || GetLocalInt(OBJECT_SELF, "DO_IT"))
      {return;}
{
  SetLocalInt(OBJECT_SELF, "DO_IT", TRUE);
  int iPrize = Random(10);
             switch (iPrize)
             {
                   case 0:
                   {
                        sResRef = "sResRef_itm"; break;
                   }
                   case 1:
                   {
                        sResRef = "sResRef_itm"; break;
                   }
                   case 2:
                   {
                        sResRef = "sResRef_itm"; break;
                   }
                   case 3:
                   {
                        sResRef = "sResRef_itm"; break;
                   }
                   case 4:
                   {
                        sResRef = "sResRef_itm"; break;
                   }
                   case 5:
                   {
                        sResRef = "sResRef_itm"; break;
                   }
                   case 6:
                   {
                        sResRef = "sResRef_itm"; break;
                   }
                   case 7:
                   {
                        sResRef = "sResRef_itm"; break;
                   }
                   case 8:
                   {
                        sResRef = "sResRef_itm"; break;
                   }
                   case 9:
                   {
                        sResRef = "sResRef_itm"; break;
                   }
             }
     CreateItemOnObject(sResRef, OBJECT_SELF, 1); // ЭТО РАНДОМНЫЙ ЛУТ
     CreateItemOnObject("sResRef_itm_2", OBJECT_SELF, 1); // ЭТО ПОСТОЯННЫЙ, т.е. В ЛЮБОМ СЛУЧАЕ ВЕЩЬ №2
   }
}


************************************************************************************

КОНЕЦ ЦИКЛА "СКРИПТЫ ДЯДЮШКИ AIWAN'A" СЕРИИ "СКРИПТЫ СТАРОЙ БАЗЫ"
Lex
СЕРИЯ "СКРИПТЫ СТАРОЙ БАЗЫ"
ЦИКЛ "СКРИПТЫ EXICUTIONER'A"

автор::::::::::::NightElf-Sniper aka Executioner::::::::::::::::::::
Заняляс я тут немного скриптованием и вот что из этого получилось:
Neverwinter Script Source
//:: Dlg_Open_Store :: Executioner :://

void main()
{
string sNPSTag = GetTag(OBJECT_SELF);
object oStore = GetNearestObjectByTag(sNPSTag+"_store");

if(GetObjectType(oStore) == OBJECT_TYPE_STORE)
OpenStore(oStore, GetPCSpeaker());

else
ActionSpeakStringByStrRef(53090, TALKVOLUME_TALK);
}

Универсальный скрипт открытия магазинов, что бы все работало делаете так:
создаете непися с тегом m_weapons, после чего создаете рядом с ним магазин и даете ему тег m_weapons_store, после чего скрипт ставится на нужную ветвь диалога...
И вот это:
Neverwinter Script Source
/******************************
Name: _On_Pl_Death
Autor: Executioner
*******************************/


void main()
{
object oDied = GetLastPlayerDied();
object oHenchman = GetHenchman(oDied);
object oKiller = GetLastAttacker(oDied);
object oMod = GetModule();

string sName = GetName(oDied);
string sID = GetName(oDied)+GetPCPublicCDKey(oDied); //ID умершего, ибо скрипт писался для мультика...

int iGold = GetGold(oDied);

location lDiedHere = GetLocation(oDied);

object oDeathCorpse=CreateObject(OBJECT_TYPE_PLACEABLE,"mod_deathcorpse",lDiedHere,FALSE,"DeathCorpse"+sID);
object oBag = CreateItemOnObject("mod_bagofgold",oDeathCorpse);


//убираем хенчу
if (GetIsObjectValid(oHenchman))
RemoveHenchman(oDied, oHenchman);


//Воскрешаем
ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectResurrection(),oDied);
ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectHeal(GetMaxHitPoints(oDied)), oDied);
AssignCommand(oDied, ActionJumpToObject(GetObjectByTag("wp_death"))); &#092;&#092; Туда, куда должен прыгать чар после смерти(храм&#092;фуга)


//Снимаем 10% экспы
int iDeadXP = 10;
int iXP = GetXP(oDied);
int iNewXP = iXP-iXP*iDeadXP/100;

SetXP(oDied, iNewXP);

//Отнимаем деньги и вещи и кидаем их в лут
SetLocalString(oDeathCorpse,"oDiedName",sName);
SetLocalInt(oBag,"Gold",iGold);

int i;
for(i=0;i<15;i++)
AssignCommand(oDeathCorpse, ActionTakeItem(GetItemInSlot(i, oDied), oDied));

AssignCommand(oDeathCorpse, TakeGoldFromCreature(iGold,oDied,TRUE));
}
[nss]

[nss]
//:: OnOpen_DthCorpse :: Executioner :://
void main()
{
SpeakString("Corpse of "+GetLocalString(OBJECT_SELF,"oDiedName"),TALKVOLUME_TALK);
}


Neverwinter Script Source
//:: OnClse_DthCorpse :: Executioner :://
void main()
{
if(GetIsObjectValid(GetFirstItemInInventory(OBJECT_SELF))==FALSE)
DelayCommand(3.0,DestroyObject(OBJECT_SELF));
}

Для полной работоспособности надо создать еще 1 плейсейбл и 1 итем и поставить вейпойн куда надо бросать после смерти(фуга\храм)

плейсейбл:
tag: Mod_DeathCorpse
resref: mod_deathcorpse
ставим галку напротив Usable и Has Inventory
так же на OnClose ставим скрипт OnClse_DthCorpse, а на OnOpen соответственно OnOpen_DthCorpse
итем:
tag: Mod_BagOfGold
resref: mod_bagofgold

Что мы получаем в итоге: после смерти убирается хенча, снимается 10% экспы. Все вещи которые были на нем и деньги отбираются и бросаются в лут, который появляется на месте смерти. После бросаем нашего чара туда, куда надо ) там можете с ним делать все. что захотите
А зачем вешать на лут скрипты - а затем, что бы нам говорили кто умер, и после что бы не валялись они по всему модулю...

************************************************************************************

КОНЕЦ ЦИКЛА "СКРИПТЫ EXICUTIONER'A" СЕРИИ "СКРИПТЫ СТАРОЙ БАЗЫ"
Lex
СЕРИЯ "СКРИПТЫ СТАРОЙ БАЗЫ"
ЦИКЛ "СКРИПТЫ (MOF)DARTH_NICK'A"

автор::::::::::::[MoF]Darth_Nick::::::::::::::::::::
Jul 3 2004
получение лвла по алайменту
Neverwinter Script Source
/*
Created By: [MoF]Darth_Nick
Data Of Creating: 02.07.2004 11:03
Discription: So, this script is do following - when you have a level up, after up
script founding your alignment(GOOD, EVIL, NEUTRAL) and doing something visual effects
for you. Also effects maybe change if you change Constans...Sample:
VFX_FNF_SUMMON_EPIC_UNDEAD - this is first constant of evil leveling, delete that and
enter something yours in the list of constants, an example - VFX_FNF_IMPLOSION.
*/


void main()
{
object oPC = GetPCLevellingUp();

if(GetAlignmentGoodEvil(oPC) == ALIGNMENT_EVIL)
{
DelayCommand(1.0, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_SUMMON_EPIC_UNDEAD), oPC));
DelayCommand(1.0, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_HARM), oPC));
}
else if(GetAlignmentGoodEvil(oPC) == ALIGNMENT_GOOD)
{
DelayCommand(1.0, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_HOLY_AID), oPC));
DelayCommand(1.0, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_SUNBEAM), oPC));
}
else if(GetAlignmentGoodEvil(oPC) == ALIGNMENT_NEUTRAL)
{
DelayCommand(1.0, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_SOUND_BURST), oPC));
DelayCommand(1.0, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_HEALING_X), oPC));
}
}


************************************************************************************

автор::::::::::::[MoF]Darth_Nick::::::::::::::::::::
Jul 3 2004
веселая ловушка
Neverwinter Script Source
/*
Created By: [MoF]Darth_Nick
Data Of Creating: 11:37
Discription: Script is stand on a OnEnter of Generic Triger, you also can use it in the
trap, but unexpectandlly is be very other!
*/


void main()
{
object oPC = GetEnteringObject();
effect eBall = EffectVisualEffect(VFX_FNF_FIREBALL);

if (GetIsPC(oPC) == GetCurrentHitPoints(oPC) < 70)
{
DelayCommand(0.5, ApplyEffectToObject(DURATION_TYPE_INSTANT, eBall, oPC));
DelayCommand(0.5, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDeath(), oPC));
}
else if (GetIsPC(oPC) == GetCurrentHitPoints(oPC) > 70)
{
FloatingTextStringOnCreature("Heh...This trick is not for me!", oPC);
}
}


************************************************************************************

КОНЕЦ ЦИКЛА "СКРИПТЫ (MOF)DARTH_NICK'A" СЕРИИ "СКРИПТЫ СТАРОЙ БАЗЫ"
Lex
СЕРИЯ "СКРИПТЫ СТАРОЙ БАЗЫ"
ЦИКЛ "СКРИПТЫ RED DEVIL'A"

автор::::::::::::Red Devil::::::::::::::::::::
Jul 31 2004
Значит так крафтинг. Крафт осущетсвляется при разговоре с неписем.
Крафт брони +1 к АС.
Neverwinter Script Source
#include "x2_inc_itemprop"
void main()
{
int iBonus;
object oPC=GetPCSpeaker();
object oArmor=GetItemInSlot(INVENTORY_SLOT_CHEST,oPC);
itemproperty ipHasAC=GetFirstItemProperty(oArmor);
GetItemPropertyType(ipHasAC)==ITEM_PROPERTY_AC_BONUS;
if (!GetIsObjectValid(oArmor)) return;
if (GetBaseItemType(oArmor)!=BASE_ITEM_ARMOR) return;
   {
   iBonus=GetItemPropertyCostTableValue(ipHasAC);
   if (iBonus<0) iBonus=0;
   iBonus++;
   itemproperty ipAddAC=ItemPropertyACBonus(iBonus);
   IPSafeAddItemProperty(oArmor,ipAddAC);
   }
}


************************************************************************************

автор::::::::::::Red Devil::::::::::::::::::::
Jul 31 2004
Крафт оружия +1энчант бонус, либо елси это лук или арбалет +1 атак бонус.
Neverwinter Script Source
#include "x2_inc_itemprop"
void main()
{
object oPC=GetPCSpeaker();
object oWeap=GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oPC);
int iBonus;
int bType=GetBaseItemType(oWeap);
if (!GetIsObjectValid(oWeap)) return;
if ((bType == BASE_ITEM_BASTARDSWORD) ||
(bType == BASE_ITEM_BATTLEAXE) ||
(bType == BASE_ITEM_CLUB) ||
(bType == BASE_ITEM_DAGGER) ||
(bType == BASE_ITEM_DIREMACE) ||
(bType == BASE_ITEM_DOUBLEAXE) ||
(bType == BASE_ITEM_DWARVENWARAXE) ||
(bType == BASE_ITEM_GREATAXE) ||
(bType == BASE_ITEM_GREATSWORD) ||
(bType == BASE_ITEM_HALBERD) ||
(bType == BASE_ITEM_HANDAXE) ||
(bType == BASE_ITEM_HEAVYFLAIL) ||
(bType == BASE_ITEM_KAMA) ||
(bType == BASE_ITEM_KATANA) ||
(bType == BASE_ITEM_KUKRI) ||
(bType == BASE_ITEM_LIGHTFLAIL) ||
(bType == BASE_ITEM_LIGHTHAMMER) ||
(bType == BASE_ITEM_LIGHTMACE) ||
(bType == BASE_ITEM_LONGSWORD) ||
(bType == BASE_ITEM_MORNINGSTAR) ||
(bType == BASE_ITEM_QUARTERSTAFF) ||
(bType == BASE_ITEM_RAPIER) ||
(bType == BASE_ITEM_SCIMITAR) ||
(bType == BASE_ITEM_SCYTHE) ||
(bType == BASE_ITEM_SHORTSPEAR) ||
(bType == BASE_ITEM_SHORTSWORD) ||
(bType == BASE_ITEM_SICKLE) ||
(bType == BASE_ITEM_TWOBLADEDSWORD) ||
(bType == BASE_ITEM_WARHAMMER) ||
(bType == BASE_ITEM_WHIP) ||
(bType == BASE_ITEM_SHURIKEN) ||
(bType == BASE_ITEM_WHIP))
{
iBonus=IPGetWeaponEnhancementBonus(oWeap);
iBonus++;
itemproperty ipAdd=ItemPropertyEnhancementBonus(iBonus);
IPSafeAddItemProperty(oWeap,ipAdd);
}
else
if ((bType == BASE_ITEM_SLING)||
(bType == BASE_ITEM_SHORTBOW)||
(bType == BASE_ITEM_LONGBOW)||
(bType == BASE_ITEM_LIGHTCROSSBOW)||
(bType == BASE_ITEM_HEAVYCROSSBOW))
{
itemproperty ipHasAttack=GetFirstItemProperty(oWeap);
GetItemPropertyType(ipHasAttack)==ITEM_PROPERTY_ATTACK_BONUS;
iBonus=GetItemPropertyCostTableValue(ipHasAttack);
if (iBonus<0) iBonus=0;
iBonus++;
itemproperty ipAddAttack=ItemPropertyAttackBonus(iBonus);
IPSafeAddItemProperty(oWeap,ipAddAttack);
}
}


************************************************************************************

КОНЕЦ ЦИКЛА "СКРИПТЫ RED DEVIL'A" СЕРИИ "СКРИПТЫ СТАРОЙ БАЗЫ"


КОНЕЦ СЕРИИ "СКРИПТЫ СТАРОЙ БАЗЫ"
Lex
СЕРИЯ "СКРИПТЫ ПРОКЛЯТИЯ ЛЕВОРА"
ЦИКЛ "СКРИПТЫ ДЯДЮШКИ BAAL'A"

Скриптовая система из "Проклятия Левора", предназначенная для переноса вещей хенчмана в следующий модуль. Работает только с одним хенчманом! Скрипт bm_inv_transit1 запускаеться перед переходом в новый модуль. Скрипт bm_inv_transit3 запускаеться в новом модуле, уже после того как присоединен хенчман(хенч должен быть с пустыми слотами и инвентарем).

На закрытой локе должны находиться 2 монстра с пустым инвентарем и с тагами SECOND_PC и SECOND_HENCH
в палитре должны быть 3 сумки с одинаковым тагом и ресрефом transit_cont1, transit_cont2 и transit_cont3

Neverwinter Script Source
//::///////////////////////////////////////////////
//:: FileName  bm_inv_transit1
//:: © 2005 WRG!
//:://////////////////////////////////////////////
/*
   Первый скрипт копирует все вещи из инвентарЯ РС и
      хенча в ивентари монстров на закрытой локе,
        уничтожаЯ оригиналы. "плотовые" вещи
         обрабатываютьсЯ в первую очередь
*/

//:://////////////////////////////////////////////
//:: Created By: BaaL
//:: Created On:
//:://////////////////////////////////////////////

int GetHasObject (object oCreature, object oItem)
{
object oItm = GetFirstItemInInventory(oCreature);
while(GetIsObjectValid(oItm))
  {
  if (oItm == oItem) return TRUE;
  oItm = GetNextItemInInventory(oCreature);
  }
return FALSE;
}

void main()
{
object oPC = GetFirstPC();
object oHench = GetHenchman(oPC);
object oSecPC = GetObjectByTag("SECOND_PC");
object oSecHench = GetObjectByTag("SECOND_HENCH");
object oCopy;
object oItem;
string sContainerTag;
object oContainer;
// Если нет хенча то скрипт не запускаетьсЯ.
if(!GetIsObjectValid(oHench)) return;
// plot PC
sContainerTag = "transit_cont1";
oContainer = CreateItemOnObject(sContainerTag, oSecPC);
oItem = GetFirstItemInInventory(oPC);
while(GetIsObjectValid(oItem))
  {
  if(GetPlotFlag(oItem))
    {
    if(GetBaseItemType(oItem) != BASE_ITEM_LARGEBOX)
      {
      oCopy = CopyItem(oItem, oContainer, TRUE);
      if(!GetHasObject(oContainer, oCopy))
        {
        DestroyObject(oCopy);
        oContainer = CreateItemOnObject(sContainerTag, oSecPC);
        oCopy = CopyItem(oItem, oContainer, TRUE);
        }
      DestroyObject(oItem);
      }
    }
  oItem = GetNextItemInInventory(oPC);
  }

// plot Hench
sContainerTag = "transit_cont2";
oContainer = CreateItemOnObject(sContainerTag, oSecHench);
oItem = GetFirstItemInInventory(oHench);
while(GetIsObjectValid(oItem))
  {
  if(GetPlotFlag(oItem))
    {
    if(GetBaseItemType(oItem) != BASE_ITEM_LARGEBOX)
      {
      oCopy = CopyItem(oItem, oContainer, TRUE);
      if(!GetHasObject(oContainer, oCopy))
        {
        DestroyObject(oCopy);
        oContainer = CreateItemOnObject(sContainerTag, oSecHench);
        oCopy = CopyItem(oItem, oContainer, TRUE);
        }
      DestroyObject(oItem);
      }
    }
  oItem = GetNextItemInInventory(oHench);
  }
// not plot PC
sContainerTag = "transit_cont1";
oContainer = CreateItemOnObject(sContainerTag, oSecPC);
oItem = GetFirstItemInInventory(oPC);
while(GetIsObjectValid(oItem))
  {
  if(!GetPlotFlag(oItem))
    {
    if(GetBaseItemType(oItem) != BASE_ITEM_LARGEBOX)
      {
      oCopy = CopyItem(oItem, oContainer, TRUE);
      if(!GetHasObject(oContainer, oCopy))
        {
        DestroyObject(oCopy);
        oContainer = CreateItemOnObject(sContainerTag, oSecPC);
        oCopy = CopyItem(oItem, oContainer, TRUE);
        }
      DestroyObject(oItem);
      }
    }
  oItem = GetNextItemInInventory(oPC);
  }
// not plot Hench
sContainerTag = "transit_cont2";
oContainer = CreateItemOnObject(sContainerTag, oSecHench);
oItem = GetFirstItemInInventory(oHench);
while(GetIsObjectValid(oItem))
  {
  if(!GetPlotFlag(oItem))
    {
    if(GetBaseItemType(oItem) != BASE_ITEM_LARGEBOX)
      {
      oCopy = CopyItem(oItem, oContainer, TRUE);
      if(!GetHasObject(oContainer, oCopy))
        {
        DestroyObject(oCopy);
        oContainer = CreateItemOnObject(sContainerTag, oSecHench);
        oCopy = CopyItem(oItem, oContainer, TRUE);
        }
      DestroyObject(oItem);
      }
    }
  oItem = GetNextItemInInventory(oHench);
  }
// Автоматически запускаем второй скрипт:
DelayCommand(0.5, ExecuteScript("bm_inv_transit2", OBJECT_SELF));
}

Neverwinter Script Source
//::///////////////////////////////////////////////
//:: FileName  bm_inv_transit2
//:: © 2005 WRG!
//:://////////////////////////////////////////////
/*
   Второй скрипт возвращает все вещи в инвентарь РС,
  раскладываЯ их по сумкам. По возможности заполнЯет
         уже имеющиесЯ у РС сумки (NEW!)
*/

//:://////////////////////////////////////////////
//:: Created By: BaaL
//:: Created On:
//:://////////////////////////////////////////////

void FindContainers(object oCreature)
{
int NN=0;
object oItm = GetFirstItemInInventory(oCreature);
while(GetIsObjectValid(oItm))
  {
  if(GetBaseItemType(oItm) == BASE_ITEM_LARGEBOX)
    {
    SetIdentified(oItm, TRUE);
    NN++;
    SetLocalInt(oCreature, "CONT_NUMBER", NN);
    SetLocalObject(oCreature, "CONTAINER"+IntToString(NN), oItm);
    }
  oItm = GetNextItemInInventory(oCreature);
  }
return;
}

int Ncont(object oCreature)
{
return GetLocalInt(oCreature, "CONT_NUMBER");
}

object GiveContainer(object oCreature, int NN)
{
return GetLocalObject(oCreature, "CONTAINER"+IntToString(NN));
}

void DeleteLocals(object oCreature)
{
int NN = Ncont(oCreature);
int NN1 = 1;
while (NN >= NN1)
  {
  DeleteLocalObject(oCreature, "CONTAINER"+IntToString(NN1));
  NN1++;
  }
DeleteLocalInt(oCreature, "CONT_NUMBER");
return;
}

int GetHasObject (object oCreature, object oItem)
{
object oItm = GetFirstItemInInventory(oCreature);
while(GetIsObjectValid(oItm))
  {
  if (oItm == oItem) return TRUE;
  oItm = GetNextItemInInventory(oCreature);
  }
return FALSE;
}

void main()
{
object oPC = GetFirstPC();
object oHench = GetHenchman(oPC);
object oSecPC = GetObjectByTag("SECOND_PC");
object oSecHench = GetObjectByTag("SECOND_HENCH");
object oCopy;
string sContainerTag;
int iContNumber = 1;
object oContainer;
object oItem = GetFirstItemInInventory(oHench);
while(GetIsObjectValid(oItem))
  {
  if(GetBaseItemType(oItem) == BASE_ITEM_LARGEBOX)
    {
    oCopy = CopyItem(oItem, oPC);
    DestroyObject(oItem);
    }
  oItem = GetNextItemInInventory(oHench);
  }
FindContainers(oPC);
///---///---
sContainerTag = "transit_cont1";
// oContainer = CreateItemOnObject(sContainerTag, oPC);
oContainer=(iContNumber>Ncont(oPC))?CreateItemOnObject(sContainerTag,oPC):GiveContainer(oPC,iContNumber);
oItem = GetFirstItemInInventory(oSecPC);
while(GetIsObjectValid(oItem))
  {
    if(GetBaseItemType(oItem) != BASE_ITEM_LARGEBOX && GetTag(oItem) != sContainerTag)
      {
      oCopy = CopyItem(oItem, oContainer, TRUE);
      // esli item v sumku ne vlez  - sozdaem novuyu
      if(!GetHasObject(oContainer, oCopy))
        {
        DestroyObject(oCopy);
        // oContainer = CreateItemOnObject(sContainerTag, oPC);
        iContNumber++;
        oContainer=(iContNumber>Ncont(oPC))?CreateItemOnObject(sContainerTag,oPC):GiveContainer(oPC,iContNumber);
        oCopy = CopyItem(oItem, oContainer, TRUE);
        }
      // uni4tojaem original
      DestroyObject(oItem);
      }
  oItem = GetNextItemInInventory(oSecPC);
  }

///---///---
sContainerTag = "transit_cont2";
// oContainer = CreateItemOnObject(sContainerTag, oPC);
iContNumber++;
oContainer=(iContNumber>Ncont(oPC))?CreateItemOnObject(sContainerTag,oPC):GiveContainer(oPC,iContNumber);
oItem = GetFirstItemInInventory(oSecHench);
while(GetIsObjectValid(oItem))
  {
    if(GetBaseItemType(oItem) != BASE_ITEM_LARGEBOX && GetTag(oItem) != sContainerTag)
      {
      oCopy = CopyItem(oItem, oContainer, TRUE);
      // esli item v sumku ne vlez  - sozdaem novuyu
      if(!GetHasObject(oContainer, oCopy))
        {
        DestroyObject(oCopy);
        // oContainer = CreateItemOnObject(sContainerTag, oPC);
        iContNumber++;
        oContainer=(iContNumber>Ncont(oPC))?CreateItemOnObject(sContainerTag,oPC):GiveContainer(oPC,iContNumber);
        oCopy = CopyItem(oItem, oContainer, TRUE);
        }
      // uni4tojaem original
      DestroyObject(oItem);
      }
  oItem = GetNextItemInInventory(oSecHench);
  }

///---///---
sContainerTag = "transit_cont3";
oContainer = CreateItemOnObject(sContainerTag, oPC);
int iSlot = 0;
oItem = GetItemInSlot(iSlot, oHench);
while (iSlot < 14)
  {
  if(GetIsObjectValid(oItem))
    {
    oCopy = CopyItem(oItem, oContainer, TRUE);
    // esli item v sumku ne vlez  - sozdaem novuyu
    if(!GetHasObject(oContainer, oCopy))
      {
      DestroyObject(oCopy);
      oContainer = CreateItemOnObject(sContainerTag, oPC);
      oCopy = CopyItem(oItem, oContainer, TRUE);
      }
    // uni4tojaem original
    DestroyObject(oItem);
    }
  iSlot ++;
  oItem = GetItemInSlot(iSlot, oHench);
  }
DeleteLocals(oPC);

oItem = GetFirstItemInInventory(oSecPC);
while(GetIsObjectValid(oItem))
  {
  DestroyObject(oItem);
  oItem = GetNextItemInInventory(oSecPC);
  }
oItem = GetFirstItemInInventory(oSecHench);
while(GetIsObjectValid(oItem))
  {
  DestroyObject(oItem);
  oItem = GetNextItemInInventory(oSecHench);
  }
}

Neverwinter Script Source
//::///////////////////////////////////////////////
//:: FileName  bm_inv_transit3
//:: © 2005 WRG!
//:://////////////////////////////////////////////
/*
   Третий скрипт запускаетьсЯ уже в новом модуле
      после того как присоеденен хенч. Скрипт
   раскладывает вещи в инвентаре хенча и копирует
     вещи РС монстру, попутно уничтожаЯ Ящики.
*/

//:://////////////////////////////////////////////
//:: Created By: BaaL
//:: Created On:
//:://////////////////////////////////////////////
int GetSuitableSlot(object oItem)
{
int iSlot;
switch  (GetBaseItemType(oItem))
  {
  case BASE_ITEM_AMULET:         iSlot = INVENTORY_SLOT_NECK;      break;
  case BASE_ITEM_ARMOR:          iSlot = INVENTORY_SLOT_CHEST;     break;
  case BASE_ITEM_ARROW:          iSlot = INVENTORY_SLOT_ARROWS;    break;
  case BASE_ITEM_BASTARDSWORD:   iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_BATTLEAXE:      iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_BELT:           iSlot = INVENTORY_SLOT_BELT;      break;
  case BASE_ITEM_BOLT:           iSlot = INVENTORY_SLOT_BOLTS;     break;
  case BASE_ITEM_BOOTS:          iSlot = INVENTORY_SLOT_BOOTS;     break;
  case BASE_ITEM_BRACER:         iSlot = INVENTORY_SLOT_ARMS;      break;
  case BASE_ITEM_BULLET:         iSlot = INVENTORY_SLOT_BULLETS;   break;
  case BASE_ITEM_CLOAK:          iSlot = INVENTORY_SLOT_CLOAK;     break;
  case BASE_ITEM_CLUB:           iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_DAGGER:         iSlot = INVENTORY_SLOT_LEFTHAND;  break;
  case BASE_ITEM_DART:           iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_DIREMACE:       iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_DOUBLEAXE:      iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_DWARVENWARAXE:  iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_GLOVES:         iSlot = INVENTORY_SLOT_ARMS;      break;
  case BASE_ITEM_HALBERD:        iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_HANDAXE:        iSlot = INVENTORY_SLOT_LEFTHAND;  break;
  case BASE_ITEM_HEAVYCROSSBOW:  iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_HEAVYFLAIL:     iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_HELMET:         iSlot = INVENTORY_SLOT_HEAD;      break;
  case BASE_ITEM_KAMA:           iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_KATANA:         iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_KUKRI:          iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_LARGESHIELD:    iSlot = INVENTORY_SLOT_LEFTHAND;  break;
  case BASE_ITEM_LIGHTCROSSBOW:  iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_LIGHTFLAIL:     iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_LIGHTHAMMER:    iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_LIGHTMACE:      iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_LONGBOW:        iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_LONGSWORD:      iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_MAGICSTAFF:     iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_MORNINGSTAR:    iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_QUARTERSTAFF:   iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_RAPIER:         iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_RING:           iSlot = INVENTORY_SLOT_RIGHTRING; break;
  case BASE_ITEM_SCIMITAR:       iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_SCYTHE:         iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_SHORTBOW:       iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_SHORTSPEAR:     iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_SHORTSWORD:     iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_SHURIKEN:       iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_SLING:          iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_SMALLSHIELD:    iSlot = INVENTORY_SLOT_LEFTHAND;  break;
  case BASE_ITEM_THROWINGAXE:    iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_TORCH:          iSlot = INVENTORY_SLOT_LEFTHAND;  break;
  case BASE_ITEM_TOWERSHIELD:    iSlot = INVENTORY_SLOT_LEFTHAND;  break;
  case BASE_ITEM_TWOBLADEDSWORD: iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  case BASE_ITEM_WARHAMMER:      iSlot = INVENTORY_SLOT_RIGHTHAND; break;
  }
return iSlot;
}

void main()
{
object oPC = GetFirstPC();
object oHench = GetHenchman(oPC);
object oSecPC = GetObjectByTag("SECOND_PC");
object oCopy;
object oContainer;
object oItem2;
object oItem = GetFirstItemInInventory(oPC);
// Если нет чемодана "transit_cont3" (это значит скрипты 1 и 2 не запускались,
// т.е. хенч в новый модуль не перешел), то удалЯем хенча в новом модуле
// и останавливаем скрипт
if(!GetIsObjectValid(GetItemPossessedBy(oPC, "transit_cont3")))
  {
  DestroyObject(oHench);
  return;
  }
AssignCommand(oHench, ClearAllActions());
while (GetIsObjectValid(oItem))
  {
  ///+++
  if(GetTag(oItem) == "transit_cont1")
    {
    oContainer = oItem;
    oItem2 = GetFirstItemInInventory(oContainer);
    while (GetIsObjectValid(oItem2))
      {
      oCopy = CopyItem(oItem2, oSecPC, TRUE);
      DestroyObject(oItem2);
      oItem2 = GetNextItemInInventory(oContainer);
      }
    DestroyObject(oContainer);
    }
  ///---
  ///+++
  if(GetTag(oItem) == "transit_cont2")
    {
    oContainer = oItem;
    oItem2 = GetFirstItemInInventory(oContainer);
    while (GetIsObjectValid(oItem2))
      {
      oCopy = CopyItem(oItem2, oHench, TRUE);
      DestroyObject(oItem2);
      oItem2 = GetNextItemInInventory(oContainer);
      }
    DestroyObject(oContainer);
    }
  ///---
  ///+++
  if(GetTag(oItem) == "transit_cont3")
    {
    oContainer = oItem;
    oItem2 = GetFirstItemInInventory(oContainer);
    while (GetIsObjectValid(oItem2))
      {
      oCopy = CopyItem(oItem2, oHench, TRUE);
      SetIdentified(oCopy, TRUE);
      AssignCommand(oHench, ActionEquipItem(oCopy, GetSuitableSlot(oCopy)));
      DestroyObject(oItem2);
      oItem2 = GetNextItemInInventory(oContainer);
      }
    DestroyObject(oContainer);
    }
  ///---
  oItem = GetNextItemInInventory(oPC);
  }
// Автоматически запускаем четвертый скрипт:
DelayCommand(0.5, ExecuteScript("bm_inv_transit4", OBJECT_SELF));
}

Neverwinter Script Source
//::///////////////////////////////////////////////
//:: FileName  bm_inv_transit4
//:: © 2005 WRG!
//:://////////////////////////////////////////////
/*
      Четвертый скрипт возвращает вещи РС
*/

//:://////////////////////////////////////////////
//:: Created By: BaaL
//:: Created On:
//:://////////////////////////////////////////////
void main()
{
object oPC = GetFirstPC();
object oSecPC = GetObjectByTag("SECOND_PC");
object oCopy;
object oItem = GetFirstItemInInventory(oSecPC);
while (GetIsObjectValid(oItem))
  {
  oCopy = CopyItem(oItem, oPC, TRUE);
  DestroyObject(oItem);
  oItem = GetNextItemInInventory(oSecPC);
  }
}
][umepa
скрипт чтобы NPC шел за игроком. Будет идти даже после окончания боя.
1создаёте диалог. на вкладке ACTION TAKEN пишите команду

Neverwinter Script Source
void main()
{
object oPC = GetPCSpeaker();
ActionForceFollowObject(oPC, 1.0);
SetLocalObject(OBJECT_SELF, "PC_TO_FOLLOW", oPC);
}


cтавьте на ветку диалога.
2теперь в скрипте OnSpawn надо раскомментировать строчку SetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT);
раскомментировать значит убрать вот такой знак // т.е просто стираете эти слэши.У меня в скрипте подобной комадны сразу не было я вставил сразу ту о которой говорил выше
3 теперь в скрипте OnUserDefined пишите
Neverwinter Script Source
void main()
{
int nEvent = GetUserDefinedEventNumber();
if (nEvent == EVENT_HEARTBEAT)
  {
  object oPC = GetLocalObject(OBJECT_SELF, "PC_TO_FOLLOW");
  // если ПС не определен ИЛИ идет бой -> прервать сценарий
  if(!GetIsObjectValid(oPC) || GetIsInCombat() ) return;
  ActionForceFollowObject(oPC, 1.0);
  }
}


не забудьте сохранить стандартный скрипт OnUserDefined,а новый скрипт под другим именем
вот вроде и всё.
RiPPeR

СЕРИЯ "СКРИПТЫ ДЛЯ ШАРДА"
ЦИКЛ "СКРИПТЫ RIPPER'a"


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

Что я сделал:
  • Индексацию игроков
  • Защита их аккаунтов от взлома
  • Сохранение локации и координат игрока после рестарта сервера
  • ДМ палка для управления игроками
Все скрипты взаимосвязанны.

pl_onlogon.nss (поставить в OnClientEnter модуля)
Neverwinter Script Source
//  ===========================================
//  pl_on_logon.nss             12.12.04                                            
//    © RiPPeR                                                                            
//                  glebkk@xaker.ru                                                     
//  ===========================================  

#include "main_spirit"

void main()
{
object oPlayer = GetEnteringObject();
object oSpirit = GetPlayerSpirit(oPlayer);
string ID = IntToString(GetLocalInt(oSpirit, "ID"));
string sAccount = GetPCPlayerName(oPlayer);

string sDB_CDKEY = GetCampaignString("db",sAccount+"_CDKEY");
string sPC_CDKEY = GetPCPublicCDKey(oPlayer);

if (GetStringLength(sDB_CDKEY) <= 1) //Нет записи в базе данных
  SetCampaignString("db",sAccount+"_CDKEY",sPC_CDKEY);
else
if (sDB_CDKEY != sPC_CDKEY)
  BootPC(oPlayer);

if (oSpirit == OBJECT_INVALID) //Новый персонаж
  {
  oSpirit = CreateItemOnObject("spirit", GetEnteringObject(), 1);

  int nCounter = GetCampaignInt("db","pl_Counter") + 1;

  SetLocalInt(oSpirit,"ID",nCounter);
  SetCampaignInt("db","pl_Counter",nCounter);

  ID = IntToString(nCounter);
  }
else //Старый
  {
  }

SetLocalInt(oSpirit,"bFlaged",1);
SetLocalInt(oSpirit,"bConnected",1);
}


pl_on_logoff.nss (поставить в OnClientLeave модуля)

Neverwinter Script Source
//  ===========================================
//  pl_on_logoff.nss             12.12.04                                            
//    © RiPPeR                                                                            
//                  glebkk@xaker.ru                                                     
//  ===========================================  

#include "main_spirit"

void main()
{
object oPlayer = GetExitingObject();
object oSpirit = GetPlayerSpirit(oPlayer);

string ID = IntToString(GetLocalInt(oSpirit,"ID"));

SetLocalInt(oSpirit,"bConnected",0);
}


default.nss
Neverwinter Script Source
//  ===========================================
//  default.nss             12.12.04                                            
//    © RiPPeR                                                                            
//                  glebkk@xaker.ru                                                     
//  ===========================================  

#include "main_spirit"

void main()
{
object oPlayer = OBJECT_SELF;
object oSpirit = GetPlayerSpirit(oPlayer);

vector vPos = GetPosition(oPlayer);

if (GetLocalInt(oSpirit,"bFlaged") == 0)
  {
  SetLocalFloat(oSpirit,"pos_x",vPos.x);
  SetLocalFloat(oSpirit,"pos_y",vPos.y);
  SetLocalFloat(oSpirit,"pos_z",vPos.z);
  SetLocalFloat(oSpirit,"pos_angle",VectorToAngle(vPos));
  }
else
  SetLocalInt(oSpirit,"bFlaged",0);
}

main_spirit.nss (просто инклуд)
Neverwinter Script Source
//  ===========================================
//  main_spirit.nss             12.12.04                                            
//    © RiPPeR                                                                            
//                  glebkk@xaker.ru                                                     
//  ===========================================  

object GetPlayerSpirit(object oPlayer);

object GetPlayerSpirit(object oPlayer)
{
object oItem = GetFirstItemInInventory(oPlayer);

if (GetResRef(oItem) == "spirit")
  return oItem;

while(oItem != OBJECT_INVALID)
  {
  oItem = GetNextItemInInventory(oPlayer);

  if (GetResRef(oItem) == "spirit")
    return oItem;
  }
return OBJECT_INVALID;
}


main_active_item.nss
Neverwinter Script Source
//  ===========================================
//  main_active_item.nss             12.12.04                                            
//    © RiPPeR                                                                            
//                  glebkk@xaker.ru                                                     
//  ===========================================  

#include "main_spirit"

void main()
{
object oPlayer = GetItemActivator();
object oItem = GetItemActivated();
object oTarget = GetItemActivatedTarget();

string sResRef = GetResRef(oItem);
string sTag = GetTag(oItem);

if (sResRef == "dm_wand")
//if (GetIsDM(oPlayer)) //Раскомментировать, если ДМ-палку может использовать только ДМ
  {
  AssignCommand(oPlayer,ActionStartConversation(oPlayer,"dm_wand_pl_list",TRUE,FALSE));
  ExecuteScript("dm_ban_info",oPlayer);
  SpeakString("DM_WAND ACT",TALKVOLUME_SHOUT);
  }
}


m_def_loc_enter.nss (ставить на OnEnter _всех_ локаций, _кроме_ стартовой)
Neverwinter Script Source
//  ===========================================
//  m_def_loc_enter.nss             12.12.04                                            
//    © RiPPeR                                                                            
//                  glebkk@xaker.ru                                                     
//  ===========================================  

#include "main_spirit"

void main()
{
object oArea = OBJECT_SELF;
object oPlayer = GetEnteringObject();
object oSpirit = GetPlayerSpirit(oPlayer);

string sTag = GetTag(oArea);
string sResRef = GetResRef(oArea);

SetLocalString(oSpirit, "pos_area", sTag);
ExecuteScript(sResRef,oArea); //Раскомментироваться для запуска OnEnter локи скрипта с именем - рес-реф'ом локи
}

m_loc_saver.nss
Сделать локацию 2х2.
Туда поставить таким образом триггеры:
CODE

====
=**=
=**=
====

= - Тригеры для перехода
* - Тригер с этим скриптом

В центре тригера со скриптом поставить стартовый вэйпоинт.

Neverwinter Script Source
//  ===========================================
//  m_loc_saver.nss             12.12.04                                            
//    © RiPPeR                                                                            
//                  glebkk@xaker.ru                                                     
//  ===========================================  

#include "main_spirit"

void main()
{
  object oPlayer = GetEnteringObject();
  object oSpirit = GetPlayerSpirit(oPlayer);

  vector vPlayer;
  location lPlayer;
  object oArea;

  float x = GetLocalFloat(oSpirit,"pos_x");
  float y = GetLocalFloat(oSpirit,"pos_y");
  float z = GetLocalFloat(oSpirit,"pos_z");
  float angle = GetLocalFloat(oSpirit,"pos_angle");

  string sArea = GetLocalString(oSpirit,"pos_area");

  vPlayer = Vector(x,y,z);
  oArea = GetObjectByTag(sArea);

  lPlayer = Location(oArea,vPlayer,angle);

  SetLocalInt(oSpirit,"bConnected",1);
  AssignCommand(oPlayer,ActionJumpToLocation(lPlayer));
}

dm_ban_boot.nss
Neverwinter Script Source
//  ===========================================
//  dm_ban_boot.nss             12.12.04                                            
//    © RiPPeR                                                                            
//                  glebkk@xaker.ru                                                     
//  ===========================================  

#include "main_spirit"

void main()
{
int nID = GetLocalInt(OBJECT_SELF,"DM_WAND_ID");

object oPlayer = GetFirstPC();
object oSpirit;

while (oPlayer != OBJECT_INVALID)
  {
  oSpirit = GetPlayerSpirit(oPlayer);

  if (GetLocalInt(oSpirit,"ID") == nID)
    {
    BootPC(oPlayer);
    break;
    }
  }
}


dm_ban_info.nss
Neverwinter Script Source
//  ===========================================
//  dm_ban_info.nss             12.12.04                                            
//    © RiPPeR                                                                            
//                  glebkk@xaker.ru                                                     
//  ===========================================  

#include "main_spirit"

string PlayerList(object oPC);
object GetPCByPlaceNum(int num);
int GetPCAmount();

string GetGoodEvil(object oPC);
string GetLawChaotic(object oPC);

void main()
{
int num = GetLocalInt(OBJECT_SELF,"DM_WAND_NUM");
int player_amount = GetPCAmount();

if (num == 0)
  num = player_amount;

if (num > player_amount)
  num = 1;

object oPC = GetPCByPlaceNum(num);
int ID = GetLocalInt(GetPlayerSpirit(oPC),"ID");

SetLocalInt(OBJECT_SELF,"DM_WAND_NUM",num);
SetLocalInt(OBJECT_SELF,"DM_WAND_ID",ID);

string sPlayerList = PlayerList(oPC);

SetCustomToken(1999, sPlayerList);
}

string PlayerList(object oPC)
{
//object oPC = GetFirstPC();
string Text = "  Информация о персонаже  \n";

string Account = GetPCPlayerName(oPC);
string Name = GetName(oPC);
string ID = IntToString(GetLocalInt(GetPlayerSpirit(oPC),"ID"));
string CD_KEY = GetPCPublicCDKey(oPC);
string IP = GetPCIPAddress(oPC);

string Level = IntToString(GetLevelByPosition(1, oPC) + GetLevelByPosition(2, oPC) + GetLevelByPosition(3, oPC));
string BadGood = GetGoodEvil(oPC);
string ChaoticLaw = GetLawChaotic(oPC);
string ThisHP = IntToString(GetCurrentHitPoints(oPC));
string MaxHP = IntToString(GetMaxHitPoints(oPC));
string AC = IntToString(GetAC(oPC));

string Area = GetName(GetArea(oPC));

Text += "<cццц>"+"-----------------------------\n";
Text += "<cццц>"+"Аккаунт: "+"<cк>"+Account+"\n";
Text += "<cццц>"+"Имя персонажа: "+"<cк>"+Name+"\n";
Text += "<cццц>"+"ID: "+"<cк>"+ID+"\n";
Text += "<cццц>"+"PUBLIC CD KEY: "+"<cк>"+CD_KEY+"\n";
Text += "<cццц>"+"IP: "+"<cк>"+IP+"\n";
Text += "<cццц>"+"\n";
Text += "<cццц>"+"Уровень: "+"<cк>"+Level+"\n";
Text += "<cццц>"+"Хороший/Злой: "+"<cк>"+BadGood+"\n";
Text += "<cццц>"+"Хаотичный/Порядочный: "+"<cк>"+ChaoticLaw+"\n";
Text += "<cццц>"+"HP: "+"<cк>"+ThisHP+"/"+"<cк>"+MaxHP+"\n";
Text += "<cццц>"+"AC: "+"<cк>"+AC+"\n";
Text += "<cццц>"+"Локация: "+"<cк>"+Area+"\n";

return Text;
}

object GetPCByPlaceNum(int num)
{
object oPC = GetFirstPC();
int num2 = 0;

for (num2 = 0; num2 < num - 1; num2++)
  oPC = GetNextPC();

return oPC;
}

int GetPCAmount()
{
object oPC = GetFirstPC();
int num = 0;

while (oPC != OBJECT_INVALID)
  {
  num++;
  oPC = GetNextPC();
  }

return num;
}

string GetGoodEvil(object oPC)
{
int ret = GetAlignmentGoodEvil(oPC);

if (ret == ALIGNMENT_GOOD)
  return "GOOD";

if (ret == ALIGNMENT_EVIL)
  return "EVIL";

if (ret == ALIGNMENT_NEUTRAL)
  return "NEUTRAL";

return "OBJECT_INVALID";
}

string GetLawChaotic(object oPC)
{
int ret = GetAlignmentLawChaos(oPC);

if (ret == ALIGNMENT_LAWFUL)
  return "LAWFUL";

if (ret == ALIGNMENT_CHAOTIC)
  return "CHAOTIC";

if (ret == ALIGNMENT_NEUTRAL)
  return "NEUTRAL";

return "OBJECT_INVALID";
}

dm_ban_minus.nss
Neverwinter Script Source
//  ===========================================
//  dm_ban_minus.nss             12.12.04                                            
//    © RiPPeR                                                                            
//                  glebkk@xaker.ru                                                     
//  ===========================================  

void main()
{
SetLocalInt(OBJECT_SELF,"DM_WAND_NUM",GetLocalInt(OBJECT_SELF,"DM_WAND_NUM") - 1);
ExecuteScript("dm_ban_info",OBJECT_SELF);
ExecuteScript("dm_w_return",OBJECT_SELF);
}

dm_ban_plus.nss
Neverwinter Script Source
//  ===========================================
//  dm_ban_plus.nss             12.12.04                                            
//    © RiPPeR                                                                            
//                  glebkk@xaker.ru                                                     
//  ===========================================  

void main()
{
SetLocalInt(OBJECT_SELF,"DM_WAND_NUM",GetLocalInt(OBJECT_SELF,"DM_WAND_NUM") + 1);
ExecuteScript("dm_ban_info",OBJECT_SELF);
ExecuteScript("dm_w_return",OBJECT_SELF);
}

dm_w_return.nss
Neverwinter Script Source
//  ===========================================
//  dm_w_return.nss             12.12.04                                            
//    © RiPPeR                                                                            
//                  glebkk@xaker.ru                                                     
//  ===========================================  

void main()
{
ExecuteScript("dm_ban_info",OBJECT_SELF);
AssignCommand(OBJECT_SELF,ActionStartConversation(OBJECT_SELF,"dm_wand_pl_list",TRUE,FALSE));
}


Для работы скриптов ДМ-посоха нужно:
Создать любой итем с рес-реф'ом "dm_wand" и Уник Повером.
Создать диалог dm_wand_pl_list

Структура диалога:
CODE

[OWNER] - <CUSTOM1999>
       |
Запутить (ActionTaken - dm_ban_boot)
Следующий игрок (ActionTaken - dm_ban_plus)
Предыдущий игрок (ActionTaken - dm_ban_minus)
Выход


Это чисто пример по созданию посоха, можно легко модернизировать во что-то оч. хорошее smile.gif. Дерзайте

Кроме того обязательно нужно создать в палитре новый итем с тагом "Spirit", ResRef'ом "spirit", Undropable

p.s. у кого проблемы с установкой пишите в приват.

МОДУЛЬ МОЖНО СКАЧАТЬ ТУТ
Aiwan
Тут мне понадобились факела включаемые. Помнится кто-то из молодежи спрашивал как сделать. Вот скрипт и демка в виде файла.
Neverwinter Script Source
//:://////////////////////////////////////////////
//:: OnEnter  am_ten_torch_on
//:: Copyright © 2005 WRG!
//:://////////////////////////////////////////////
/*
    ВКЛЮЧАЕМ ОГОНЬ ФАКЕЛОВ И ЗВУК К НИМ НОЧЬЮ.

Таг факела = "AM_PLS_TORCH_ON". Он должен быть с
активированной анимацией и отключена опция Static.
Звуковой объект ставим рядом с факелом, помните его таг
ДОЛЖЕН БЫТЬ УНИКАЛЬНЫМ ВО ВСЕМ МОДУЛЕ. Иначе не
сработает. К примеру таг моего звука, равен тагу
триггера плюс порядковый номер, начиная с еденицы:
AM_SOUND_TORTCH_(порядковый номер = i). Расставляйте
на локации факела и звуки рядом. Все готово!

*/

//:://////////////////////////////////////////////
//:: Created By: Aiwan
//:: Created On: 08.06.2005
//:://///////////////////////////////////////////
#include "am_inc_debug"
void main()
{
  int i=1; // Первый порядковый номер тага звука
  float f=0.5; // Задержка включения
  float r=f+0.2; // Задержка пересчета освещения
  object oPC = GetEnteringObject();
  string sSound = GetTag(OBJECT_SELF); // Приравнял таг триггера к звуовому
  object oTorch = GetFirstObjectInArea(OBJECT_SELF);
  object oSound = GetObjectByTag(sSound+IntToString(i)); // Звуковой объект
  if (!GetIsPC(oPC)) {return;}
//---------------------------------- ДЕНЬ --------------------------------------
  if (GetIsDay() && !GetLocalInt(OBJECT_SELF, "DEACTIVATED"))
     // Если день но факела горят
  {
  while (GetIsObjectValid(oTorch))
      {
       if (GetTag(oTorch) == "AM_PLS_TORCH_ON" && !GetLocalInt(oTorch, "LIGHT_OFF"))
         /* Проверяем все объекты на локации, берем с нужным тегом и без
             локальной переменной, что с объектом уже выключен. */

          {
          SetLocalInt(oTorch, "LIGHT_OFF", TRUE);
          AssignCommand(oTorch, PlayAnimation(ANIMATION_PLACEABLE_DEACTIVATE));
          DelayCommand(f, SetPlaceableIllumination(oTorch, FALSE));
          DelayCommand(r, RecomputeStaticLighting(GetArea(oTorch)));
          Debug(FloatToString(f));
          Debug(FloatToString®);
          f=f+0.4; // Сделай паузу!
          r=f+0.2; // Глотни-ка тоже, фанты.
        /* Каджый факел заставим съесть Твикс. И прересчитаем свет позже. Не
           должно быть рывков, но если они все же появились, увеличьте немного, на 0.2,
           к примеру. Если и потом не пропали, то выкиньте ваш компьютер в окно,
           Это надо было сделать года два назад.                                  */

          }
          if (GetIsObjectValid(oSound))
             {
             SoundObjectStop(oSound); // Выключаем звук
             i++;  // Присвоим объекту звука таг на единицу больше
             }
       oSound = GetObjectByTag("AM_SOUND_TORCH_"+IntToString(i));
       oTorch = GetNextObjectInArea(OBJECT_SELF);
      }
   SetLocalInt(OBJECT_SELF, "DEACTIVATED", TRUE);
   }
//----------------------------- НОЧЬ -------------------------------------------
  if (GetIsNight() && GetLocalInt(OBJECT_SELF, "DEACTIVATED"))
     // Если ночь но мы затушили факела
  {
  while (GetIsObjectValid(oTorch))
      {
       if (GetTag(oTorch) == "AM_PLS_TORCH_ON" && GetLocalInt(oTorch, "LIGHT_OFF"))
           {
          SetLocalInt(oTorch, "LIGHT_OFF", FALSE);
          AssignCommand(oTorch, PlayAnimation(ANIMATION_PLACEABLE_ACTIVATE));
          DelayCommand(f, SetPlaceableIllumination(oTorch, TRUE));
          DelayCommand(r, RecomputeStaticLighting(GetArea(oTorch)));
          Debug(FloatToString(f));
          Debug(FloatToString®);
          f=f+0.4;
          r=f+0.2;
          }
          if (GetIsObjectValid(oSound))
             {
             SoundObjectPlay(oSound); // Включаем звук
             i++; // Присвоим объекту звука таг на единицу больше
             }
       oSound = GetObjectByTag("AM_SOUND_TORCH_"+IntToString(i));
       oTorch = GetNextObjectInArea(OBJECT_SELF);
      }
   SetLocalInt(OBJECT_SELF, "DEACTIVATED", FALSE); // ЧТо бы один раз сработало
   return;
   }
}

Добавлено в [mergetime]1118299586[/mergetime]
CODE
Блин, парсется (r) на ®, заккоментрируйте строку в скрипте или исправьте Debug(FloatToString®);

Добавлено в [mergetime]1118299909[/mergetime]
Neverwinter Script Source
//::///////////////////////////////////////////////
//:: Name: am_inc_common
//:: Copyright © 2005 WRG!
//:://////////////////////////////////////////////
/*
          БИБЛИОТЕКА ДЛЯ ОТЛАДКИ СКРИПТОВ
*/

//:://////////////////////////////////////////////
//:: Created By: Aiwan      Aiwan@e-mail.ru
//:: Created On: 30.05.2005
//:://////////////////////////////////////////////

// СООБЩЕНИЯ ДЛЯ ПРОВЕРКИ (ИСПОЛЬЗУЮТСЯ В СЛУЖЕБНЫХ ЦЕЛЯХ ДЛЯ ОТЛАДКИ КОДА СКРИПТОВ)
// А ТАК ЖЕ ДЛЯ ДМ-ов
// LocalInt - "DEBAG_PC" на модуле, отключит дебаг игрокам
// LocalInt - "DEBAG_DM" на модуле, отключит дебаг DM-ам
void Debug(string message);
// Выводит в Debug: TAG, ResRef и Name объекта.
void DebugObject(object oObject);

//------------------------------------------------------------------------------
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);
          }
}
void DebugObject(object oObject)
{
    string sTag = GetTag(oObject);
    string sResRef = GetResRef(oObject);
    string sName = GetName(oObject);
    Debug ("TAG = "+sTag+", ResRef = "+sResRef+",  Name = "+sName+".");
}
/*
void main(){}
Buldog
Пришла мне в голову такая идея, а что если сделать такой тригер перехода, который бы перекидывал игрока не в какую то определенную точку, а ровно в то место, в которое игрок входит, с той разницей, что если выходит игрок из локации с востока, то войдет в локацию назначения с запада, ну или с севера на юг, так жн и наоборот.

И вылилась идейка вот в такой скрипт:
Neverwinter Script Source
//////////////////////////////////////
//////////////////////////////////////
//////For Area Transmition Trigers////
//////////////////////////////////////
//////////OnClick Script//////////////
//////////////////////////////////////
////////////Created By Buldog/////////
////////////////23.06.05//////////////
//////////////////////////////////////
//////////////////////////////////////

void main()
{
    object oPC = GetClickingObject();
    object oTarget = GetTransitionTarget(OBJECT_SELF);
    object oTArea = GetArea(oTarget);

    location lTarget;

    vector vPC = GetPosition(oPC);
    vector vTarget = GetPosition(oTarget);
    vector vTLoc = Vector();

    vTLoc.z = vPC.z;

    if(vPC.x < 10.0 || vPC.x > vTarget.x * 2 - 10) vTLoc.x = vTarget.x * 2 - vPC.x;
    else vTLoc.x = vPC.x;

    if(vPC.y < 10.0 || vPC.y > vTarget.y * 2 - 10) vTLoc.y = vTarget.y * 2 - vPC.y;
    else vTLoc.y = vPC.y;

    float fFace = GetFacing(oPC);

    lTarget = Location(oTArea, vTLoc, fFace);

    AssignCommand(oPC, ClearAllActions());
    AssignCommand(oPC, ActionJumpToLocation(lTarget));
}


Подготовка местности:

- В ЦЕНТР (и чем точнее тем лучше) нужной локации помещаем вейпоинт и задаем ему уникальный тэг.
- В локации из которой будем выходить помещаем тригер со скриптом, в поле для тэга точки назначения помещаем тэг размещенного в центре целевой локации вэйпоинта.

Ограничения:

- Тригер перехода должен размещаться по краю локации и не вылезать по ширине (или высоте, смотря с какой стороны находится) за пределы одной клетки.
- Не размещайте тригер в угловых клетках, будет глючить.
- Ширина (высота) тригера не должна превышать ширины (высоты) локации назначения.
Aiwan
Функция для библиотеки. Выдает любому уровню процент ХР заданный вами. К примеру у вас квестов 10. Зашел РС 30 левелом или 5 -м, всеравно выполнив 10 квестов он наберет 1 левел...
Neverwinter Script Source
//::///////////////////////////////////////////////
//:: Name: am_inc_dialog
//:: Copyright © 2005 WRG!
//:://////////////////////////////////////////////
/*
          БИБЛИОТЕКА ДЛЯ ДИАЛОГОВ
*/

//:://////////////////////////////////////////////
//:: Created By: Aiwan      Aiwan@e-mail.ru
//:: Created On: 22.06.2005
//:://////////////////////////////////////////////
#include "am_inc_debug"

// ФУНКЦИЯ РАЗДЕЛЕНИЯ ХР В ЗАВИСИМОСТИ ОТ УРОВНЯ
// iPercent - Проценты от уровня. По умолчанию 10%
void GiveXPScale(object oPC, int iPercent=10);

//------------------------------------------------------------------------------
void GiveXPScale(object oPC, int iPercent=10)
{
    object oCreature;
    int iHit = GetHitDice(oPC); // Берем уровень объекта
    int iXP; // Это искомое число ХР для квеста
    int i = iHit*1000; // Это ХР на один уровень больше чем у объекта
    iXP= i/iPercent;
    Debug("Уровень ХР на один больше нашего - "+IntToString(i));
    Debug("Процент добавляемого ХР от уровня - "+IntToString(iPercent));
    Debug("Искомая сумма ХР - "+IntToString(iXP));
    /*
    Нужное количество ХР равно ХР на уровень больше, деленное на число
    int iP, которое определяет процент от уровня. По умолчанию это 10%.
    */

    GiveXPToCreature(oPC,iXP);
}
/*
void main(){}
Friedrich
Вот маленький инклюд с функцией makeTrace изображает дымную трассу (типа как от ракеты) между двумя точками, с помощью виз. эффектов (н.п. VFX_FNF_SMOKE_PUFF).
Что-то похожее было в первом модуле СоУ в подземелье с плохой эльфой.
Neverwinter Script Source
// ********************************* //
// * fh_inc_trace                  * //
// * (с) Friedrich W. Heik, 2005.  * //
// * darkowl@inbox.ru              * //
// ********************************* //

//** Interface **

// Преобразует декартовы координаты в сферические
// Возвращаемый вектор имеет формат:
// x - ro:  расстояние от начала координат до точки
// y - fi:  угол поворота, вокруг вертикальной оси (от оси X против ч.с.)
// z - psi: угол наклона от горизонтальной плоскости
vector sph(vector vDsc);

// Преобразует сферические координаты в декартовы
// Формат вектора vSph:
// x - ro:  расстояние от начала координат до точки
// y - fi:  угол поворота, вокруг вертикальной оси (от оси X против ч.с.)
// z - psi: угол наклона от горизонтальной плоскости
vector dsc(vector vSph);

// Изменяет абс. величину вектора
// Возвр. вектор длиною fMagnitude, сонаправленный с vVector.
vector setMagnitude(vector vVector, float fMagnitude);

// Рисует дымную трассу между двумя точками
// lSource:  Начало трассы
// lTarget:  Цель
// fJump:    Дистанция шага между эффектами, м.
// fSpeed:    Скорость "снаряда", м/с
// nTraceVFX: эффект дыма, которым рисуется трасса
// nBurstVFX: эффект взрыва в конце трассы (исп. -1 (VFX_NONE), если взрыв не требуется) 
void makeTrace(location lSource, location lTarget, float fJump = 0.25f, float fSpeed = 10.0f, int nTraceVFX = VFX_FNF_SMOKE_PUFF, int nBurstVFX = VFX_FNF_FIREBALL);


//** Implementation **

// Преобразует декартовы координаты в сферические
// Возвращаемый вектор имеет формат:
// x - ro:  расстояние от начала координат до точки
// y - fi:  угол поворота, вокруг вертикальной оси (от оси X против ч.с.)
// z - psi: угол наклона от горизонтальной плоскости
vector sph(vector vDsc)
{
  float ro = VectorMagnitude(vDsc);
  float fi = atan(vDsc.y/vDsc.x); // I четверть
  float psi = asin(vDsc.z/ro);

  if (vDsc.x < 0.0) fi += 180.0;      // II, III: +Pi
  else if (vDsc.y < 0.0) fi += 360.0; // IV: +2Pi, чтобы угол был положительным smile.gif
  return Vector(ro, fi, psi);
}

// Преобразует сферические координаты в декартовы
vector dsc(vector vSph)
{
  float x = vSph.x*cos(vSph.z)*cos(vSph.y); // ro*cos(psi)*cos(fi)
  float y = vSph.x*cos(vSph.z)*sin(vSph.y); // ro*cos(psi)*sin(fi)
  float z = vSph.x*sin(vSph.z); // ro*sin(psi)
  return Vector(x, y, z);
}

vector setMagnitude(vector vVector, float fMagnitude)
{
  vector vSph = sph(vVector);
  vSph.x = fMagnitude;
  return dsc(vSph);
}

void makeTrace(
  location lSource,    // Начало трассы
  location lTarget,    // Цель
  float fJump = 0.25f// Дистанция шага между эффектами, м.
  float fSpeed = 10.0f, // Скорость "снаряда", м/с
  int nTraceVFX = VFX_FNF_SMOKE_PUFF,
  int nBurstVFX = VFX_FNF_FIREBALL) 
{
  float fInterval = fJump/fSpeed;
  effect eVis = EffectVisualEffect(nTraceVFX);

  vector vOA = GetPositionFromLocation(lSource); // вектор (OA)
  vector vOB = GetPositionFromLocation(lTarget); // вектор (OB)
  vector vAB = vOB - vOA; // вектор (AB) = (OB)-(OA)
 
  //vector vNorm = VectorNormalize(vAB); // единичный вектор, коллинеарный AB
  vector vJump = setMagnitude(vAB, fJump);
 
  vector vCurrent = vOA;
  object oArea = GetAreaFromLocation(lTarget);
  int n = FloatToInt( VectorMagnitude(vAB)/fJump );
  int i;
  float fDelay = 0.0;
  for (i=0; i < n; i++)
  {
    vCurrent += vJump;
    location lCurrent = Location(oArea, vCurrent, 0.0);
    fDelay += fInterval;
    DelayCommand(fDelay, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eVis, lCurrent));
  }
  // Fireball VFX on target:
  if (nBurstVFX != VFX_NONE)
  {
    fDelay += fInterval;
    effect eBurst = EffectVisualEffect(nBurstVFX);
    DelayCommand(fDelay, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eBurst, lTarget));
  }
}
//void main(){}


Функции, устанавливают заданное числовое значение аляймента:
Neverwinter Script Source
void setGoodEvilValue(object oCreature, int nValue)
{
  if(!GetIsObjectValid(oCreature)||
    (GetObjectType(oCreature) != OBJECT_TYPE_CREATURE))
    return;
 
  if (nValue < 0) nValue = 0;
  else if (nValue > 100) nValue = 100;
 
  int nCurGE = GetGoodEvilValue(oCreature);
  int nShift = abs(nCurGE - nValue);
  if (nShift == 0) return;
  int nDir = (nValue > nCurGE) ? ALIGNMENT_GOOD : ALIGNMENT_EVIL;
  AdjustAlignment(oCreature, nDir, nShift);
  if (GetGoodEvilValue(oCreature) != nValue)
    setGoodEvilValue(oCreature, nValue);
}

void setLawChaosValue(object oCreature, int nValue)
{
  if(!GetIsObjectValid(oCreature)||
    (GetObjectType(oCreature) != OBJECT_TYPE_CREATURE))
    return;
 
  if (nValue < 0) nValue = 0;
  else if (nValue > 100) nValue = 100;
 
  int nCurLC = GetLawChaosValue(oCreature);
  int nShift = abs(nCurLC - nValue);
  if (nShift == 0) return;
  int nDir = (nValue > nCurLC) ? ALIGNMENT_LAWFUL : ALIGNMENT_CHAOTIC;
  AdjustAlignment(oCreature, nDir, nShift);
  if (GetLawChaosValue(oCreature) != nValue)
    setLawChaosValue(oCreature, nValue);
}
//void main(){}

Вдруг кому-нибудь пригодится.
DraX
Нет проблем. Итак, вот он, скрипт:

Neverwinter Script Source
if(GetLocalInt(OBJECT_SELF, "DO_ONCE") != 1)
{
string sTag = "OBJECT"// Тэг нужного нам объекта
num nNum = 1// Начинаем считать объекты с номера 1 по нужный нам

for(nNum = 1; nNum <= 4; nNum++)  // Номер 4 - кол-во объектов
{
  int nNum2 = nNum++;

  if(nNum2 > 4)
    nNum2 = 1;

  object oStart = GetObjectByTag(sTag + "_" + nNum);
  object oEnd = GetObjectByTag(sTag + "_" + Num2);

  ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectBeam(VFX_BEAM_FIRE, oEnd, BODY_NODE_CHEST), oStart);
}

SetLocalInt(OBJECT_SELF, "DO_ONCE", 1);
}


Спасибо, Aiwan. Этот скрипт и вправду лучше - не загружает систему и более обширней в применении. Ставить на OnHeartbeat локации или триггера.

ЗЫ: Сорри за опечатки
2_advanced
альтернатива стандартному отдыху с возможностью ставить свою анимацию, выставлять время реста, проверки до/после/во время реста и т.п.

Neverwinter Script Source
void RestEnd()
{
    object oPC = OBJECT_SELF;

    int nRez = GetLocalInt(oPC, "LastEventRest"); // спим?

    DeleteLocalInt(oPC, "LastEventRest");
    DeleteLocalLocation(oPC, "RestLocation");

    if(!nRez) // не спим
        return;

    FadeFromBlack(oPC, FADE_SPEED_SLOWEST); //

    object oBedroll = GetLocalObject(oPC, "bedroll");
    if(GetIsObjectValid(oBedroll))
    {
        DestroyObject(oBedroll, 3.5f);
        CreateItemOnObject(BEDROLL_IT_RES, oPC);
        DeleteLocalObject(oPC, "bedroll");
    }
}

void RestFinish()
{
    object oPC = OBJECT_SELF;

    if(!GetLocalInt(oPC, "LastEventRest"))
        return;

    DeleteLocalInt(oPC, "NextRest");

    ActionMoveToLocation(GetLocation(oPC)); // stand up tongue.gif

//todo:сохр нужного - хп. и т.п.
    ForceRest(oPC);
//todo:восстановление

    SendMessageToPC(oPC, "<cооо>Отдых закончен..</c>");

    if(!GetLocalInt(oPC, "REST_DONT_SLEEP"))
        ActionPlayAnimation(ANIMATION_FIREFORGET_PAUSE_SCRATCH_HEAD);

    RestEnd();
}

void RestFailCheck() // check chance to rest // c:RestBegin: random(restduration)
{
    object oPC = OBJECT_SELF;
    object oArea = GetArea(oPC);

    ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_SLEEP), oPC);

    if(!GetLocalInt(oPC, "LastEventRest"))
        return;

    if(!GetIsObjectValid(oArea))
        return;

    object oPC2 = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC); // спокойный рест если рядом кто-то есть
    if(oPC2 != OBJECT_INVALID && !GetIsEnemy(oPC, oPC2) && GetDistanceBetween(oPC, oPC2) < 10.0)
        return;

    object oChance = GetNearestObjectByTag(REST_CHANCE_PL_TAG);
    if(oChance == OBJECT_INVALID)
        return;

    int nChance = GetLocalInt(oChance, "REST_CHANCE");

    if(!nChance || (nChance >= d100()))
        return;

    RestEnd();
}

void RestThread() // cancel rest checks tongue.gif // c:RestBegin
{
    object oPC = OBJECT_SELF;

    if(!GetLocalInt(oPC, "LastEventRest")) // уже не спим
        return;

// враждебная крича или перемещения игрока
    object oEnemy = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY);
    if( GetLocation(oPC) != GetLocalLocation(oPC, "RestLocation") ||
        (GetIsObjectValid(oEnemy) && GetDistanceBetween(oEnemy, oPC) < 15.0)   )
    {
        SendMessageToPC(oPC, "<cооо>Отдых сорван.</c>");
        RestEnd();
        return;
    }

    if(GetLocalInt(oPC, "REST_DONT_SLEEP"))
        ActionPlayAnimation(ANIMATION_LOOPING_MEDITATE, 1.0, 3.0);
    else
        ActionPlayAnimation(ANIMATION_LOOPING_DEAD_FRONT, 1.0, 3.0);

    AssignCommand(oPC, DelayCommand(3.0f, RestThread())); // повтор
}

void NextRestTimer() // proc. 4 min. for failed rest // c:RestBegin
{
    object oPC = OBJECT_SELF;

    int nCurr = GetLocalInt(oPC, "NextRest");

    if(nCurr)
    {
        if(!GetLocalInt(oPC, "LastEventRest"))
            SetLocalInt(oPC, "NextRest", nCurr - 1);

        AssignCommand(oPC, DelayCommand(30.0, NextRestTimer())); // временной промежуток между рестами(при неудаче): 8 * 30 сек = 4 мин
    }
}

void RestBegin(float fSeconds)
{
    object oPC = OBJECT_SELF;

    ClearAllActions();

    SetLocalInt(oPC, "NextRest", 8); // временной промежуток между рестами
    SetLocalInt(oPC, "LastEventRest", 1); // рест?!
    SetLocalLocation(oPC, "RestLocation", GetLocation(oPC));

    AssignCommand(oPC, DelayCommand(30.0f, NextRestTimer()));
    AssignCommand(oPC, DelayCommand(3.0f + fSeconds, RestFinish())); // финиш
    AssignCommand(oPC, DelayCommand(3.0f, RestThread())); // проверки

    DelayCommand(3.5f, FadeToBlack(oPC, FADE_SPEED_MEDIUM));
}

void main()
{
    object oPC = GetLastPCRested();

    if(GetIsDM(oPC) || GetIsDMPossessed(oPC))
    {
        ForceRest(oPC);
        return;
    }

    object oMod = GetModule();

    if(GetLocalInt(oPC, "LastEventRest")) // рест уже запущен. игрок пытается перезапустить
    {
        AssignCommand(oPC, ClearAllActions());
       
        if(GetLocalInt(oPC, "REST_DONT_SLEEP"))
            DelayCommand(0.1f, ActionPlayAnimation(ANIMATION_LOOPING_MEDITATE, 1.0, 3.0));
        else
            DelayCommand(0.1f, ActionPlayAnimation(ANIMATION_LOOPING_DEAD_FRONT, 1.0, 3.0));
       
        return;
    }


    int nNextRest = GetLocalInt(oPC, "NextRest");
    if(nNextRest)
    {
        AssignCommand(oPC, ClearAllActions());
        SendMessageToPC(oPC, "<cооо>Отдых возможен в течение " + IntToString(nNextRest/2) + " минут</c>");
        return;
    }


    object oChance = GetNearestObjectByTag(REST_CHANCE_PL_TAG); // неспокойность места smile.gif
    if(oChance != OBJECT_INVALID)
    {
        int nChance = GetLocalInt(oChance, "REST_CHANCE");
        if(!nChance)
        {
            AssignCommand(oPC, ClearAllActions());
            SendMessageToPC(oPC, "<cо0о>Вы не можете отдыхать тут.</c>");
            return;
        }
    }

    switch(GetLastRestEventType())
    {
        case REST_EVENTTYPE_REST_STARTED:
            int nDelay = REST_DELAY;
            int nLastRest = GetActionLastTime(oPC, "REST");

            if(nLastRest < nDelay)
            {
                FloatingTextStringOnCreature("<cооо>Вы не устали.</c>", oPC, 0);
                SendMessageToPC(oPC, "<cо0о>Отдых возможен через " + IntToString(nDelay - nLastRest - 1) + ":" + IntToString(59-GetTimeMinute()) + " час(а) .</c>");
                AssignCommand(oPC, ClearAllActions());
                return;
            }

// проверки на наличие необходимых для отдыха итемов
            oBedroll = GetItemPossessedBy(oPC, BEDROLL_IT_RES);
            if(GetClassByPosition(1, oPC) == CLASS_TYPE_MONK || GetRacialType(oPC) == RACIAL_TYPE_ELF)
            {
                SetLocalInt(oPC, "REST_DONT_SLEEP", 1);
            }
            else
            if(GetIsObjectValid(oBedroll))
            {
                DestroyObject(oBedroll);
                oBedroll = CreateObject(OBJECT_TYPE_PLACEABLE, BEDROLL_PL_RES, GetLocation(oPC));
                SetLocalObject(oPC, "bedroll", oBedroll);
            }
            else
            {
                SendMessageToPC(oPC, "<cооо>Вам не на чем спать.</c>");
                AssignCommand(oPC, ClearAllActions());
                return;
            }

// костёр smile.gif но тут не о нём
            object oCamp = GetNearestObjectByTag(CAMPFIRE_PL_RES, oPC);
            if(GetIsDay() || (GetIsObjectValid(oCamp) && GetDistanceBetween(oCamp, oPC) < 4.5))
                SetLocalInt(oPC, "REST_CAMPFIRE", 1);

// из 2да время отдыха
            int nRestDuration = StringToInt(Get2DAString("restduration", "DURATION", GetHitDice(oPC)));
            if(nRestDuration)
            {
                float fCheckDelay = IntToFloat(nRestDuration)/1000.0f;

                DelayCommand(0.1f, AssignCommand(oPC, ActionUnequipItem(GetItemInSlot(INVENTORY_SLOT_LEFTHAND)))); // убрать все из рук
                DelayCommand(0.2f, AssignCommand(oPC, ActionUnequipItem(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND))));
                DelayCommand(0.4f, AssignCommand(oPC, ActionPlayAnimation(ANIMATION_LOOPING_GET_LOW, 1.0, 2.7))); // анимация укладывания лежака
                DelayCommand(0.0f, AssignCommand(oPC, RestBegin(fCheckDelay))); // рест.начало

                DelayCommand(IntToFloat(Random(nRestDuration))/1000.0f, AssignCommand(oPC, RestFailCheck())); // ..проснуться в неспокойном месте tongue.gif
            }

            break;
    }
}

в модульный onEnter:
Neverwinter Script Source
DeleteLocalInt(oPC, "NextRest");
DeleteLocalInt(oPC, "LastEventRest");

Добавлено в 15:18
позволяет получать разницу во времени между действиями..

Neverwinter Script Source
void SetActionLastTime(object oPC, string sAction)
{
    string sPCName = GetPCPlayerName(oPC); // для уникальности.. вообще использую № персонажа

    int nHour = GetTimeHour();
    int nDay  = GetCalendarDay();
    int nMonth = GetCalendarMonth();
    int nYear = GetCalendarYear();

    string sData = IntToString(nHour) + ";" + IntToString(nDay) + ";" + IntToString(nMonth) + ";" + IntToString(nYear) + ";";

    SetLocalString(GetModule(), sAction + sPCName, sData);
}

int GetActionLastTime(object oPC, string sAction)
{
    string sPair;
    string sPCName = GetPCPlayerName(oPC);
    string sData = GetLocalString(GetModule(), sAction + sPCName);

    if(sData == "")
    {
        return 100;
    }

    int nLastMinute;
    int nLastHour;
    int nLastDay;
    int nLastMonth;
    int nLastYear;

    int i;
    for(i=0; i<5; i++)
    {
        int nPos = FindSubString(sData, ";"); // вычленение. почему в НВС нет phpшного explode? biggrin.gif
        if(nPos != -1)
        {
            sPair = GetStringLeft(sData, nPos);
            sData = GetStringRight(sData, GetStringLength(sData) - 1 - nPos);

            switch(i)
            {
                case 0: nLastHour   = StringToInt(sPair); break;
                case 1: nLastDay    = StringToInt(sPair); break;
                case 2: nLastMonth  = StringToInt(sPair); break;
                case 3: nLastYear   = StringToInt(sPair); break;
            }
        }
    }

    int nMinute = GetTimeMinute();
    int nHour = GetTimeHour();
    int nDay  = GetCalendarDay();
    int nYear = GetCalendarYear();
    int nMonth = GetCalendarMonth();

    if(nLastYear != nYear)
        nMonth = nMonth + 12;

    if(nLastMonth != nMonth)
        nDay = nDay + 28 * (nYear - nLastYear);

    if(nDay != nLastDay)
        nHour = nHour + 24 * (nDay - nLastDay);

    return (nHour - nLastHour);
}
Aiwan
Скрипт запрещает классы в модуле. Годится для сингла. Для шардов надо придумать как описать РС. Ставится это добро на OnPlayerLevelUp модуля.
Neverwinter Script Source
//:://////////////////////////////////////////////
//:: OnPlayerLevelUp  "am_mod_levelup"
//:: Copyright © 2005 WRG!
//:://////////////////////////////////////////////
/*
  Скрипт запрещающий использование выборочных
  классов в модуле. Спасибо Dumbo за упрощенную
  форумулу, моя была в пять раз больше pardon.gif.
*/

//:://////////////////////////////////////////////
//:: Created By: Aiwan
//:: Created On: 20.09.2005
//:://////////////////////////////////////////////
void main()
{
    object oPC = GetFirstPC();
    int iHit = GetHitDice(oPC); // Берем уровень игрока
    int iXP = GetXP(oPC); // Вся ХР игрока
    string sClass; // Для сообщения игроку что он сделал неправильно
    int iClass2 = GetClassByPosition(2, oPC); // Второй класс мультикласса
    int iClass3 = GetClassByPosition(3, oPC); // Третий  класс мультикласса
    int F = CLASS_TYPE_FIGHTER; // Воин
    int R = CLASS_TYPE_ROGUE;  // Вор
    int D = CLASS_TYPE_DRUID;  // Друид
    int P = CLASS_TYPE_PALADIN; // И так далее...

    // Для примера классs: Если Воин, Вор, Друид, Паладин
    if  ((iClass2==F || iClass3==F) || (iClass2==R || iClass3==R)
      || (iClass2==D || iClass3==D) || (iClass2==P || iClass3==P))
      {
          if(iClass2==F || iClass3==F) sClass = "Воин";
          if(iClass2==R ||  iClass3==R) sClass = "Вор";
          if(iClass2==D || iClass3==D) sClass = "Друид";
          if(iClass2==P || iClass3==P) sClass = "Паладин";

        // Присвоим РС в начале ХР на уровень меньше, значит заберем один
        // уровень, что мы запретили из использования. Дальше, мы возвращаем
        // назад всю нашу ХР, ведь ХР может быть намного больше чем мы
        // потратили на поднятие уровня.
        SetXP(oPC, (iHit*(iHit-1)*500)-((iHit-1)*1000));
        DelayCommand(0.5, SetXP(oPC, iXP));

        // Можно так сообщить, можно что-то другое.
        SendMessageToPC(oPC, "Вы использовали запрещенный класс: "+sClass);

        /*
          Тут можно вписать что-нибудь из эффектов, для острастки.
        */

      }
}
2_advanced
скрипт, усаживающий на стулья и т.п., не запарывает стул после выхода сидящего из игры
(хоть это и древняя недоработанная бетка, однако работает)

зы. необходим неразрушимый невидимый объект sittingsurface
Neverwinter Script Source
void main()
{
    object oPC = GetLastUsedBy();
    object oChair = OBJECT_SELF;

    if(GetIsObjectValid(oChair) && GetIsObjectValid(oPC))
    {
        object oSurf = GetLocalObject(oChair, "surf");

        if(GetIsObjectValid(oSurf))
        {
            object oSitter = GetSittingCreature(oSurf);

            if(!GetIsObjectValid(oSitter) || GetArea(oSitter) != GetArea(oChair))
                DestroyObject(oSurf);
            else
                return;
        }

        vector vSurf = GetPosition(oChair);
        vSurf.z = 0.0;

        location lSurf = Location(GetArea(oChair), vSurf, GetFacing(oChair));

        object oNewSurf = CreateObject(OBJECT_TYPE_PLACEABLE, "sittingsurface", lSurf, FALSE);

        SetLocalObject(oChair, "surf", oNewSurf);

        AssignCommand(oPC, ActionSit(oNewSurf));
    }
}
для доработки: выкидывать игрока с *объекта посадки* при уничтожении стула, профиксить баг с высотой посадки для разных расс (было такое на 1.29 о_О), сделать возможным усаживаться нескольким персонажам на 1 большой объект (диван pardon.gif) с автораспределением свободных сидячих мест.
<сделаю позже swoon.gif >
Aiwan
Скрипт вешается на строку диалога НПС. Если он загородил нам проход, просим отойти в сторону. Очень актуально для сингла. Когда НПС стоит поперек выхода и нет сил его обойти...
Neverwinter Script Source
//:://////////////////////////////////////////////
//:: ActionTaken  am_at_npc_step
//:: Copyright © 2005 WRG!
//:://////////////////////////////////////////////
/*
  NPC уходит на точку рандомную точку, освобождая
  игроку проход в локации. Использует функцию
  генерирования рандомной локации.
*/

//:://///////////////////////////////////////////
//:: Created By: Aiwan
//:: Created On: 01.10.2005
//:://///////////////////////////////////////////
//:: CreateRandomLocation Function by Baal
//:://///////////////////////////////////////////
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()
{
    object oPC = GetPCSpeaker(); // Игрок
    object oSelf = OBJECT_SELF; // НПС с которым идет диалог
    location lFree = CreateRandomLocation(oSelf, 5.0);
    // Генерим случайную точку в радиусе 5 метров
    int iRun = FALSE; // Параметр определяющий скорость НПС

    if(GetLocalInt(oSelf, "RUN"))
      {
        iRun = TRUE; // Если присвоить локалку "RUN" на НПС, то он побежит.
      }
    AssignCommand(oSelf, ClearAllActions()); // Почистим стек команд
    AssignCommand(oSelf, ActionMoveToLocation(lFree, iRun));
    // Использую ActionMove, что бы НПС не переместился в "мертвую" точку без прохода.
    AssignCommand(oSelf, ActionDoCommand(SetFacingPoint(GetPosition(oPC))));
}
Aiwan
Скрипт активирует на локации енкаучеры ночные и дневные. Соответсвенно одни выключает, другие включает. Все работает как часы и оптимизировано Лексом. За шо ему гранд респект. good.gif
Neverwinter Script Source
//:://////////////////////////////////////////////
//:: OnEnter  am_ahb_day_night
//:: Copyright © 2005 WRG!
//:://////////////////////////////////////////////
/*
  Скрипт локаций День/Ночь. Запускает OnUserDefined
*/

//:://////////////////////////////////////////////
//:: Created By: Aiwan
//:: Edit By: Lex
//:: Created On: 24.05.2005
//:://///////////////////////////////////////////
//#include "am_inc_common"
void main()
{
object oPC = GetFirstPC();
if (GetArea(oPC) != OBJECT_SELF) return;

if (GetIsDusk()||GetIsNight())
    {
    if (GetLocalInt(OBJECT_SELF, "Night") != 1)
        {
        SetLocalInt(OBJECT_SELF, "Day", 0);
        SetLocalInt(OBJECT_SELF, "Night", 1);
        SignalEvent(OBJECT_SELF, EventUserDefined(3000));
        return;
        }
    else return;
    }
if (GetIsDawn()||GetIsDay())
    {
    if (GetLocalInt(OBJECT_SELF, "Day") != 1)
        {
        SetLocalInt(OBJECT_SELF, "Night", 0);
        SetLocalInt(OBJECT_SELF, "Day", 1);
        SignalEvent(OBJECT_SELF, EventUserDefined(1000));
        return;
        }
    else return;
    }
}


Neverwinter Script Source
//:://////////////////////////////////////////////
//:: ActionTaken  lm_aud_enc_activ
//:: Copyright © 2005 WRG!
//:://////////////////////////////////////////////
/*
    Активирует енкаучеры. Дневные и ночные.
  LocalInt(oEnc, "ENCOUNTER_SPAWN_NIGHT") - ночные.
  LocalInt(oEnc, "ENCOUNTER_SPAWN_DAY") - дневные.
*/

//:://///////////////////////////////////////////
//:: Created By: Lex
//:: Created On: 08.11.2005
//:://///////////////////////////////////////////

void EncounterController(int ActivateStatus, object oArea = OBJECT_SELF)
{
int nEN = GetLocalInt(oArea,"ENCOUNTERS");
object oEncounter;
while (nEN > 0)
    {
    oEncounter = GetLocalObject(oArea,"ENCOUNTER_"+IntToString(nEN));
    if(GetLocalInt(oEncounter, "ENCOUNTER_SPAWN_NIGHT"))
        SetEncounterActive(!ActivateStatus, oEncounter);
    else  if(GetLocalInt(oEncounter, "ENCOUNTER_SPAWN_DAY"))
        SetEncounterActive(ActivateStatus, oEncounter);
    nEN--;
    }
}

void main()
{
  int nEvent = GetUserDefinedEventNumber();
  int ActivateStatus;
  int nEN = GetLocalInt(OBJECT_SELF,"ENCOUNTERS");
  if (nEN == 0)
      {
      object oEnc = GetFirstObjectInArea(OBJECT_SELF);
      while (GetIsObjectValid(oEnc))
          {
            if(GetObjectType(oEnc) == OBJECT_TYPE_ENCOUNTER)
                {
                nEN++;
                SetLocalObject(OBJECT_SELF,"ENCOUNTER_"+IntToString(nEN),oEnc);
                }
            oEnc = GetNextObjectInArea(OBJECT_SELF);
          }
      if (nEN == 0) nEN = -1;
      SetLocalInt(OBJECT_SELF,"ENCOUNTERS",nEN);
      }
if (nEvent == 1000) // День
  {
  if (nEN == -1) return;
  EncounterController(TRUE);
  return;
  }
if (nEvent == 3000) // Ночь
  {
  if (nEN == -1) return;
  EncounterController(FALSE);
  return;
  }
}

Добавлено в [mergetime]1131452068[/mergetime]
А, забыл! scratch_one-s_head.gif Первый на хертбит арены. Второй на юзерДеф ей же.
Aiwan
Выкладываю скрипт+заготовку ERF триггера, что бы вы не мучались с настройкой. Давно я использую на триггерах три своих темповых скрипта, для присвоения каких-нибудь локалок на игрока, для проверки того или иного диалога, строки, действия и прочее. Очень меня задолбало это. Писать каждый раз новый скрипт и я написал триггер для теста. Что он делает? Он присваивает до 5 уникальных локалок на игрока и НПС, может отправить НПС в точку которую вы укажите. Например, НПС в другой локе, вы наступили на триггер, он спавнился рядом и повесили на него три локалки, повесили на РС две локалки и можно быть в середине вашего сюжета. Еще он (скрипт) может запускать другие скрипты на НПС, РС и OBJECT_SEL, соответсвенно.

Как он настраивается:
DEACTIVATED == 1 отключает триггер после первого раза. Например, вы насупили раз, прошли одну ветку диалога. Подошли, наступили второй, прошли заново диалог и т.д. Надо? Ставьте 0 и будет бесконечно приваивать ваши локалки.
LOCAL_NPC_01 - Присваивает переменную на НПС. Пример: ПЕРЕМЕННАЯ_01
Neverwinter Script Source
SetLocalInt(oNPC, "ПЕРЕМЕННАЯ", 1);
SetLocalInt(oNPC, "ДРУГАЯ_ПЕРЕМЕННАЯ", 2);

LOCAL_PC_01 - Присваивает переменную на PС. Пример: ПЕРЕМЕННАЯ_01
Neverwinter Script Source
SetLocalInt(oPC, "ПЕРЕМЕННАЯ", 1);
SetLocalInt(oPC, "ДРУГАЯ_ПЕРЕМЕННАЯ", 5);

RUN_SCRIPT - ИМЯ_СКРИПТА - запускает на OBJECT_SELF
Neverwinter Script Source
ExecuteScript("ИМЯ_СКРИПТА", OBJECT_SELF);

RUN_SCRIPT_ON_NPC - ИМЯ_СКРИПТА - запускает на oNpc
Neverwinter Script Source
ExecuteScript("ИМЯ_СКРИПТА", oNpc);

На игрока понятное дело так же.
TAG_NPC - Таг нашего НПС.
TAG_WP_TO_JUMP - ТАГ нашего вейпоинта. НПС прыгнет на него, если только вы укажете ТАГ точки.
Ну вот и все. Все локалки работают до пяти штук на РС и НПС.

Neverwinter Script Source
//:://////////////////////////////////////////////
//:: OnEnter  am_ten_test
//:: Copyright © 2005 WRG!
//:://////////////////////////////////////////////
/*
    ТЕСТОВЫЙ СКРИПТ ДЛЯ ПРИСВОЕНИЯ ПЕРЕМЕННЫХ
*/

//:://////////////////////////////////////////////
//:: Created By: Aiwan
//:: Created On: 11.11.2005
//:://////////////////////////////////////////////
//#include "sz_inc_common"
#include "am_inc_debug"

void main()
{
object oPC = GetEnteringObject(); // PC
object oSelf = OBJECT_SELF;
string sNpc = GetLocalString(oSelf, "TAG_NPC");
string sWp = GetLocalString(oSelf, "TAG_WP_TO_JUMP");
object oNpc = GetObjectByTag(sNpc);
object oWp = GetWaypointByTag(sWp);

if(GetLocalInt(oSelf, "DEACTIVATED")==2)
  return;
/*
//------------------------------------------------------------------------------
  Заккоментированные строки работают с библиотекой SlavaZ-а, на которой
  построены многие квесты наших модулей.

//------------------------------ КВЕСТ #1 --------------------------------------
string sQ1 = GetLocalString(oSelf, "QUEST_01");
string sQuest1 = GetStringLeft(sQ1, GetStringLength(sQ1)-3);
int iQ1 = StringToInt(GetStringRight(sQ1, 2));
//------------------------------ КВЕСТ #2 --------------------------------------
string sQ2 = GetLocalString(oSelf, "QUEST_02");
string sQuest2 = GetStringLeft(sQ2, GetStringLength(sQ2)-3);
int iQ2 = StringToInt(GetStringRight(sQ2, 2));
//------------------------------ КВЕСТ #3 --------------------------------------
string sQ3 = GetLocalString(oSelf, "QUEST_03");
string sQuest3 = GetStringLeft(sQ3, GetStringLength(sQ3)-3);
int iQ3 = StringToInt(GetStringRight(sQ3, 2));
//------------------------------ КВЕСТ #4 --------------------------------------
string sQ4 = GetLocalString(oSelf, "QUEST_04");
string sQuest4 = GetStringLeft(sQ4, GetStringLength(sQ4)-3);
int iQ4 = StringToInt(GetStringRight(sQ4, 2));
//------------------------------ КВЕСТ #5 --------------------------------------
string sQ5 = GetLocalString(oSelf, "QUEST_05");
string sQuest5 = GetStringLeft(sQ5, GetStringLength(sQ5)-3);
int iQ5 = StringToInt(GetStringRight(sQ5, 2));

  if(sQ1!=""){
  SetQuestStatus(sQuest1, iQ1, TRUE);
  Debug("Установим переменную QUEST: "+sQuest1+" == "+IntToString(iQ1));}
  if(sQ2!=""){
  SetQuestStatus(sQuest2, iQ2, TRUE);
  Debug("Установим переменную QUEST: "+sQuest2+" == "+IntToString(iQ2));}
  if(sQ3!=""){
  SetQuestStatus(sQuest3, iQ3, TRUE);
  Debug("Установим переменную QUEST: "+sQuest3+" == "+IntToString(iQ3));}
  if(sQ4!=""){
  SetQuestStatus(sQuest4, iQ4, TRUE);
  Debug("Установим переменную QUEST: "+sQuest4+" == "+IntToString(iQ4));}
  if(sQ5!=""){
  SetQuestStatus(sQuest5, iQ5, TRUE);
  Debug("Установим переменную QUEST: "+sQuest5+" == "+IntToString(iQ5));}
*/

//------------------------------------------------------------------------------
//                  Эти переменные вешаются на игрока
//------------------------------------------------------------------------------

//--------------------------- ПЕРЕМЕННАЯ #1 ------------------------------------
string sL1 = GetLocalString(oSelf, "LOCAL_PC_01");
string sLocal1 = GetStringLeft(sL1, GetStringLength(sL1)-3);
int iL1 = StringToInt(GetStringRight(sL1, 2));
//--------------------------- ПЕРЕМЕННАЯ #2 ------------------------------------
string sL2 = GetLocalString(oSelf, "LOCAL_PC_02");
string sLocal2 = GetStringLeft(sL2, GetStringLength(sL2)-3);
int iL2 = StringToInt(GetStringRight(sL2, 2));
//--------------------------- ПЕРЕМЕННАЯ #3 ------------------------------------
string sL3 = GetLocalString(oSelf, "LOCAL_PC_03");
string sLocal3 = GetStringLeft(sL3, GetStringLength(sL3)-3);
int iL3 = StringToInt(GetStringRight(sL3, 2));
//--------------------------- ПЕРЕМЕННАЯ #4 ------------------------------------
string sL4 = GetLocalString(oSelf, "LOCAL_PC_04");
string sLocal4 = GetStringLeft(sL4, GetStringLength(sL4)-3);
int iL4 = StringToInt(GetStringRight(sL4, 2));
//--------------------------- ПЕРЕМЕННАЯ #5 ------------------------------------
string sL5 = GetLocalString(oSelf, "LOCAL_PC_05");
string sLocal5 = GetStringLeft(sL5, GetStringLength(sL5)-3);
int iL5 = StringToInt(GetStringRight(sL5, 2));

  if(sL1!=""){
  SetLocalInt(oPC, sLocal1, iL1);
  Debug("Установим переменную на РС LocalInt: "+sLocal1+" == "+IntToString(iL1));}
  if(sL2!=""){
  SetLocalInt(oPC, sLocal2, iL2);
  Debug("Установим переменную на РС LocalInt: "+sLocal2+" == "+IntToString(iL2));}
  if(sL3!=""){
  SetLocalInt(oPC, sLocal3, iL3);
  Debug("Установим переменную на РС LocalInt: "+sLocal3+" == "+IntToString(iL3));}
  if(sL4!=""){
  SetLocalInt(oPC, sLocal4, iL4);
  Debug("Установим переменную на РС LocalInt: "+sLocal4+" == "+IntToString(iL4));}
  if(sL5!=""){
  SetLocalInt(oPC, sLocal5, iL5);
  Debug("Установим переменную на РС LocalInt: "+sLocal5+" == "+IntToString(iL5));}

//------------------------------------------------------------------------------
//                  Эти переменные вешаются на НПС
//------------------------------------------------------------------------------

//--------------------------- ПЕРЕМЕННАЯ #1 ------------------------------------
string sLn1 = GetLocalString(oSelf, "LOCAL_NPC_01");
string sLocalN1 = GetStringLeft(sLn1, GetStringLength(sLn1)-3);
int iLn1 = StringToInt(GetStringRight(sLn1, 2));
//--------------------------- ПЕРЕМЕННАЯ #2 ------------------------------------
string sLn2 = GetLocalString(oSelf, "LOCAL_NPC_02");
string sLocalN2 = GetStringLeft(sLn2, GetStringLength(sLn2)-3);
int iLn2 = StringToInt(GetStringRight(sLn2, 2));
//--------------------------- ПЕРЕМЕННАЯ #3 ------------------------------------
string sLn3 = GetLocalString(oSelf, "LOCAL_NPC_03");
string sLocalN3 = GetStringLeft(sLn3, GetStringLength(sLn3)-3);
int iLn3 = StringToInt(GetStringRight(sLn3, 2));
//--------------------------- ПЕРЕМЕННАЯ #4 ------------------------------------
string sLn4 = GetLocalString(oSelf, "LOCAL_NPC_04");
string sLocalN4 = GetStringLeft(sLn4, GetStringLength(sLn4)-3);
int iLn4 = StringToInt(GetStringRight(sLn4, 2));
//--------------------------- ПЕРЕМЕННАЯ #5 ------------------------------------
string sLn5 = GetLocalString(oSelf, "LOCAL_NPC_05");
string sLocalN5 = GetStringLeft(sLn5, GetStringLength(sLn5)-3);
int iLn5 = StringToInt(GetStringRight(sLn5, 2));

  if(sLn1!=""){
  SetLocalInt(oNpc, sLocalN1, iLn1);
  Debug("Установим переменную на "+GetName(oNpc)+" LocalInt: "+sLocalN1+" == "+IntToString(iLn1));}
  if(sLn2!=""){
  SetLocalInt(oNpc, sLocalN2, iLn2);
  Debug("Установим переменную на "+GetName(oNpc)+" LocalInt: "+sLocalN2+" == "+IntToString(iLn2));}
  if(sLn3!=""){
  SetLocalInt(oNpc, sLocalN3, iLn3);
  Debug("Установим переменную на "+GetName(oNpc)+" LocalInt: "+sLocalN3+" == "+IntToString(iLn3));}
  if(sLn4!=""){
  SetLocalInt(oNpc, sLocalN4, iLn4);
  Debug("Установим переменную на "+GetName(oNpc)+" LocalInt: "+sLocalN4+" == "+IntToString(iLn4));}
  if(sLn5!=""){
  SetLocalInt(oNpc, sLocalN5, iLn5);
  Debug("Установим переменную на "+GetName(oNpc)+" LocalInt: "+sLocalN5+" == "+IntToString(iLn5));}
//------------------------------------------------------------------------------
// Тут мы определяем нашего НПС. Отправляем его на вейпоинт, енсли нужно.
//------------------------------------------------------------------------------
  if(sNpc!="" && !GetIsObjectValid(oNpc))
    {
      Debug("ОШИБКА! Вашего НПС не существует!");
    }
  if(sWp!="")
  {
      if(!GetIsObjectValid(oWp))
        {
          Debug("ОШИБКА! Неправильный ТАГ вейпоинта!");
          return;
        }
      AssignCommand(oNpc, ClearAllActions());
      AssignCommand(oNpc, JumpToObject(oWp));
  }
//------------------------------------------------------------------------------
//  Тут мы запускаем нужные скрипты на игрока, НПС или просто на сам триггер.
//------------------------------------------------------------------------------
string sScOnPC = GetLocalString(oSelf, "RUN_SCRIPT_ON_PC");
string sScOnNpc = GetLocalString(oSelf, "RUN_SCRIPT_ON_NPC");
string sScOnSelf = GetLocalString(oSelf, "RUN_SCRIPT");

if(sScOnPC!="")
{
  ExecuteScript(sScOnPC, oPC);
  Debug("Запущен скрипт "+sScOnPC+" на РС");
}
if(sScOnNpc!="")
{
  ExecuteScript(sScOnNpc, oNpc);
  Debug("Запущен скрипт "+sScOnNpc+" на "+GetName(oNpc));
}
if(sScOnSelf!="")
{
  ExecuteScript(sScOnSelf, oSelf);
  Debug("Запущен скрипт "+sScOnSelf+" на OBJECT_SELF");
}
//------------------------------------------------------------------------------
//                Параметры, определяют работу триггера.
//------------------------------------------------------------------------------
if(GetLocalInt(oSelf, "DEACTIVATED")==1)
  SetLocalInt(oSelf, "DEACTIVATED", 2);
}
-fenix-
Вот тут решил написать скрипты, которые может кому, пригодятся, но лично мне они пока не нужны. Зачем написал? Просто так. crazy.gif

Что эти скрипты делают?
Они дают процент экспы за убийство/разрушение объекта равное проценту нанесенного ущерба.
Пример:
Есть бочка, у нее 10 хитов.
За разрушение назначено 100 опыта.
Если вы снимите 100% хитов(10), то получите 100% опыта(100).
Если вы снимете 50% хитов(5), то получите 50% опыта(50). Остальной опыт либо пропадет (если кроме вас объект лупили только НПС), либо поделится между другими ПС лупившими объект, либо поделится между всеми ПС и часть пропадет, от лупивших НПС.
ХМ, надеюсь, идея ясна.
Приступим к скриптам.
Для реализации нам нужно два скрипта: один на OnDamaged объекта, другой на OnDeath объекта. Скрипты универсальные и ограничений по атакующим у них нет. Дома я проверил, как смог, но так как шарда у меня дома нет, то данный аспект проверить не смог. Но по идее все работает нормально, если заметите баг, обязательно сообщите. Еще, на шарде ни когда не играл, поэтому может это и не идеальный код для него, но думаю, что знающим людям поправить будет не сложно. smile.gif
И так, сами скрипты.


На OnDamaged объекта

Neverwinter Script Source
//:://////////////////////////////////////////////
//:: Created By: -fenix-
//:: Created On: 16.11.2005
//:://////////////////////////////////////////////

void main()
{
object oDamager = GetLastDamager();
int iMaxHit = GetMaxHitPoints();
int iCurHit = GetCurrentHitPoints();
string sNamePC = GetName(oDamager);
int i,Z, iDamage;

if(GetIsPC(oDamager))//если атакующий ПС
{
    //индекс, по каторому будут отличаться все переменные нужные
    for(i = 1; i <= GetLocalInt(OBJECT_SELF, "KOLICHESTVO"); i ++)
    {
        //если такое имя уже есть
        if(sNamePC == GetLocalString(OBJECT_SELF, "NAME_PC_" + IntToString(i)))
        {
            //сколько всего было нанесено ущерба(включая только что нанесенный удар)
            if(iCurHit < 0)
            {
                iDamage = iMaxHit;
            }
            else
            {
                iDamage = iMaxHit - iCurHit;
            }
            //запоминаем кол-во нанесенного ущерба данным ПС
            SetLocalInt(OBJECT_SELF, IntToString(i) + "_DamagePC", (iDamage - GetLocalInt(OBJECT_SELF, "DamageAll")) + GetLocalInt(OBJECT_SELF, IntToString(i) + "_DamagePC"));
            //запоминаем общий ущерб
            SetLocalInt(OBJECT_SELF, "DamageAll", GetLocalInt(OBJECT_SELF, "DamageAll") + (iDamage - GetLocalInt(OBJECT_SELF, "DamageAll")));
            //это для проверки. Можете удалить, можете оставить и потестить
            SendMessageToPC(oDamager, GetLocalString(OBJECT_SELF, "NAME_PC_" + IntToString(i)) + "_нанес1_" + IntToString(GetLocalInt(OBJECT_SELF, IntToString(i) + "_DamagePC")));
            //это для проверки. Можете удалить, можете оставить и потестить
            SendMessageToPC(oDamager, "DamageAll1="
            IntToString(GetLocalInt(OBJECT_SELF, "DamageAll")));
            Z = 1;// чтобы знать, был такой ПС или нет
        }
    }
    //новый ПС
    if(Z != 1)
    {
        //сколько всего было нанесено ущерба(включая только что нанесенный удар)
        if(iCurHit < 0)
        {
            iDamage = iMaxHit;
        }
        else
        {
            iDamage = iMaxHit - iCurHit;
        }
        //добавляем его к "старым" ПС
        SetLocalInt(OBJECT_SELF, "KOLICHESTVO", GetLocalInt(OBJECT_SELF, "KOLICHESTVO") + 1);
        //запоминаем его имя
        SetLocalString(OBJECT_SELF, "NAME_PC_" +
IntToString(GetLocalInt(OBJECT_SELF, "KOLICHESTVO")), sNamePC);
        //запоминаем кол-во нанесенного ущерба данным ПС
        SetLocalInt(OBJECT_SELF, IntToString(GetLocalInt(OBJECT_SELF
"KOLICHESTVO")) + "_DamagePC", (iDamage - GetLocalInt(OBJECT_SELF"DamageAll")));
        //запоминаем общий ущерб
        SetLocalInt(OBJECT_SELF, "DamageAll", GetLocalInt(OBJECT_SELF,
"DamageAll") + GetLocalInt(OBJECT_SELF,
      IntToString(GetLocalInt(OBJECT_SELF, "KOLICHESTVO")) + "_DamagePC"));

/*это для проверки. Можете удалить, можете оставить и потестить*/                     
SendMessageToPC(oDamager,GetLocalString(OBJECT_SELF,"NAME_PC_"+IntToString(GetLocalInt(OBJECT_SELF,"KOLICHESTVO")))
+"_нанес2_"+IntToString(GetLocalInt(OBJECT_SELF,IntToString(GetLocalInt(OBJECT_SELF,"KOLICHESTVO"))+"_DamagePC")));
        //это для проверки. Можете удалить, можете оставить и потестить
        SendMessageToPC(oDamager, "DamageAll2=" + IntToString(GetLocalInt(OBJECT_SELF, "DamageAll")));
    }
}
else//если атакующий не ПС
{
    //сколько всего было нанесено ущерба(включая только что нанесенный удар)
    if(iCurHit < 0)
    {
        iDamage = iMaxHit;
    }
    else
    {
        iDamage = iMaxHit - iCurHit;
    }
    //запоминаем общий ущерб
    SetLocalInt(OBJECT_SELF, "DamageAll", (iDamage - GetLocalInt(OBJECT_SELF,       
    "DamageAll")) + GetLocalInt(OBJECT_SELF, "DamageAll"));
    //это для проверки. Можете удалить, можете оставить и потестить
    SendMessageToPC(GetFirstPC(), "Общий ущерб_" +         
    IntToString(GetLocalInt(OBJECT_SELF, "DamageAll")));
}
}


Второй скрипт ставется на OnDeath объекта. Этот скрипт раздает опыт.
Neverwinter Script Source
//:://////////////////////////////////////////////
//:: Created By: -fenix-
//:: Created On: 16.11.2005
//:://////////////////////////////////////////////

void main()
{
int iMaxHit = GetMaxHitPoints();
int iMaxXP = 100;//тут указываем кол-во опыта за уничтожение объекта
int i, S, iXPPC;

//сколько всего ПС атаковало объект
for(i = 1; i <= GetLocalInt(OBJECT_SELF, "KOLICHESTVO"); i ++)
{
    object oPC = GetFirstPC();

    while(S != 100)
    {
        string sNamePC = GetName(oPC);
        //если мя совпадает
        if(sNamePC == GetLocalString(OBJECT_SELF, "NAME_PC_" + IntToString(i)))
        {
          //считаем кол-во опыта
          iXPPC=((100 * GetLocalInt(OBJECT_SELF, IntToString(i) + "_DamagePC") / iMaxHit) * iMaxXP) / 100;
            //если получается меньше одного, то округляем до 1
            if(iXPPC <1)
            {
                iXPPC = 1;
            }
            GiveXPToCreature(oPC, iXPPC);//даем опыт
            S = 100;
        }
        oPC = GetNextPC();
    }
    S = 0;
}
}

Ну и еще их маленький брат - скрипт считающий отдельно урон ПС и урон всех остальных. Иногда бывает очень нужно узнать урон нанесенный объекту ПС. Скрипт для сингла.
Neverwinter Script Source
//:://////////////////////////////////////////////
//:: Created By: -fenix-
//:: Created On: 20.10.2005
//:://////////////////////////////////////////////

void main()
{
object oPC = GetLastDamager();
int iMaxHit = GetMaxHitPoints();
int iCurHit = GetCurrentHitPoints();


if(GetIsPC(oPC))
{
    int i, j;

    for(i = 1; i = j; i ++)
    {
        if(GetName(oPC) == GetLocalString(OBJECT_SELF, IntToString(i)))
        {
            int iDamage = iMaxHit - iCurHit;

            SetLocalInt(OBJECT_SELF, "DamagePC", (iDamage - GetLocalInt(OBJECT_SELF, "DamageOther") - GetLocalInt(OBJECT_SELF, "DamagePC")) + GetLocalInt(OBJECT_SELF, "DamagePC"));
            SendMessageToPC(oPC, IntToString(GetLocalInt(OBJECT_SELF, "DamagePC")));
        }
        else
        {
            SetLocalString(OBJECT_SELF, IntToString(i + 1), GetName(oPC));
            j = j + 1;
        }
    }
}
else
{
    int iDamage = iMaxHit - iCurHit;

    SetLocalInt(OBJECT_SELF, "DamageOther", (iDamage - GetLocalInt(OBJECT_SELF, "DamagePC") - GetLocalInt(OBJECT_SELF, "DamageOther")) + GetLocalInt(OBJECT_SELF, "DamageOther"));
    SendMessageToPC(oPC, IntToString(GetLocalInt(OBJECT_SELF, "DamageOther")));
}
}


З.Ы Сорри, что порвал страницу blush.gif
Aiwan: вообще-то некоторые строки можно делить и переносить. this.gif
-fenix-: просто мне как-то неудобно так ориентироваться wacko.gif
Но впредь, на форуме, буду строки делить и переноситьyes.gif
Lex
Neverwinter Script Source
//::============================================================================
//::    L&A Script Systems - TEXT COLORS  (TS)
//::============================================================================
string sASCII = "#####################################$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ЂЃ‚ѓ„…†‡?‰Љ‹ЊЌЋЏђ‘’“”•--?™љ›њќћџ ЎўЈ¤Ґ¦§Ё©Є«¬­®Ї°±Ііґµ¶·ё№є»јЅѕїАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя";

//:: COLOR CONSTANTS
const string TC_DARK_GRAY = "<c°°°>";
const string TC_GRAY = "<c¦¦¦>";
const string TC_DARK_CYAN = "<c ¦¦>";
const string TC_DARK_MAGENTA = "<c¦ ¦>";
const string TC_DARK_YELLOW = "<c¦¦ >";
const string TC_DARK_RED = "<c¦  >";
const string TC_DARK_GREEN = "<c ¦ >";
const string TC_DARK_BLUE = "<c  ¦>";
const string TC_NONE = ""; // Default (no color)
const string TC_END = "</c>"; // (color end TAG)
const string TC_DEFAULT = TXT_COLOR_NONE;
const string TC_WHITE = "<cяяя>"; // White
const string TC_CYAN = "<c яя>"; // Light Cyan
const string TC_MAGENTA = "<cя я>"; // Magenta
const string TC_YELLOW = "<cяя >"; // Yellow
const string TC_RED = "<cя  >"; // Red
const string TC_GREEN = "<c я >"; // Green
const string TC_BLUE = "<c  я>"; // Blue


// Используйте числа более 35 (там системные знаки, они заменены на #)
string TC_GetASCIIChar(int nByte);
// меняет цвет текста на соответствующий 3 параметрам:
// Red   - красный
// Green - зеленый
// Blue  - синий
// цвет стандарта RGB
string TC_ColorTextRGB(string sText, int nRed, int nGreen, int nBlue);
// меняет цвет текста на соответствующий константе
string TC_ColorText(string sText, string sColor);

//::============================================================================
string TC_GetASCIIChar(int nByte)
{
return GetSubString(sASCII, nByte, 1);
}
//::============================================================================
string TC_ColorTextRGB(string sText, int nRed, int nGreen, int nBlue)
{
string sResult = "<c" + TC_GetASCIIChar(nRed) + TC_GetASCIIChar(nGreen) + TC_GetASCIIChar(nBlue) + ">" + sText + TC_END;
return sResult;
}
//::============================================================================
string TC_ColorText(string sText, string sColor)
{
string sResult = sColor + sText + TC_END;
return sResult;
}
justshurik
Скрипт мой, все совпадения с другими скриптами случайны.
Скрипт для управления группой NPC в реальном времени, без создания waypoint-ов. Позволяет группировать NPC в любые построения(к примеру в Каре, Свинью, Шеренгу,Полк и т д.и т п на Ваш вкус) и перемещать их в таком построении. Можно использовать при построении масштабных баталий с участием большого количества неписей(причем под управлением игрока)
CODE

location Preobr(vector a, object oArea);
vector Arifm(vector a,vector b,int flag=0);
float ABSVect(vector a);
vector Proizv(vector a, float n);
vector Ort(vector a);
vector Perpend(vector a);
location Loc(float a,float b, object oArea,object oPC,location CastSpell);
void Go(object NPC, location CastSpell,object oPC,object oArea,float a,float b );
////////////////////////////////////////////////////////////////////////////////
void main()
{
object oPC=GetItemActivator();
object oItem =GetItemActivated();
object oArea=GetObjectByTag("arena");
object oNPC1=GetObjectByTag("NPC1");
object oNPC2=GetObjectByTag("NPC2");
object oNPC3=GetObjectByTag("NPC3");
object oNPC4=GetObjectByTag("NPC4");
object oNPC5=GetObjectByTag("NPC5");
object oNPC6=GetObjectByTag("NPC6");
object oNPC7=GetObjectByTag("NPC7");

if("panel"==GetTag(oItem))
{
location lTarget=GetItemActivatedTargetLocation();
AssignCommand(oNPC1,ClearAllActions());
Go(oNPC1,lTarget,oPC,oArea,1.0,1.0);
//                         a     b
AssignCommand(oNPC2,ClearAllActions());
Go(oNPC2,lTarget,oPC,oArea,1.0,-1.0);
//                         a      b
AssignCommand(oNPC3,ClearAllActions());
Go(oNPC3,lTarget,oPC,oArea,5.0,5.0);
//                         a      b
AssignCommand(oNPC4,ClearAllActions());
Go(oNPC4,lTarget,oPC,oArea,5.0,-5.0);
//                         a     b
AssignCommand(oNPC5,ClearAllActions());
Go(oNPC5,lTarget,oPC,oArea,10.0,10.0);
//                         a     b
AssignCommand(oNPC6,ClearAllActions());
Go(oNPC6,lTarget,oPC,oArea,10.0,-10.0);
//                         a      b
AssignCommand(oNPC7,ClearAllActions());
Go(oNPC7,lTarget,oPC,oArea,5.0,0.0);
}; //                      a    b
}


/*******************************************************************************/
//preobrazovanie vector -> location

location Preobr(vector a, object oArea)
{
location Loc1=Location(oArea,a,GetFacing(oArea));
return Loc1;
}

//slogenie i vichitanie vectorov a i b

vector Arifm(vector a,vector b,int flag=0)
{
float ax,ay,az,bx,by,bz;
ax=a.x;
ay=a.y;
az=a.z;
bx=b.x;
by=b.y;
bz=b.z;
if(flag==0)
{
vector Res1=Vector(ax+bx,ay+by,az+bz);
return Res1;
}
else
{
vector Res2=Vector(bx-ax,by-ay,bz-az);
return Res2;
};
}

//ABS vectora
float ABSVect(vector a)
{
float Mod=sqrt((a.x*a.x)+(a.y*a.y)+(a.z*a.z));
return Mod;
}

//umnogenie vectora na skalyar

vector Proizv(vector a, float n)
{
vector Res=Vector(n*a.x,n*a.y,a.z);
return Res;
}

//Ortonormirovka vectora

vector Ort(vector a)
{
float Mod=ABSVect( a);
vector Res=Vector(a.x/Mod,a.y/Mod,a.z/Mod);
return Res;
}

//perpendikulyar k vectoru

vector Perpend(vector a)
{
vector Res=Vector((-1.0)*a.y,a.x,a.z);
return Res;
}

//osnovnaya funkciya

location Loc(float a,float b, object oArea,object oPC,location CastSpell)
{
vector vPC=GetPosition(oPC);

vector vCastSpell=GetPositionFromLocation(CastSpell);

vector vLocal1=Arifm(vPC,vCastSpell,2);

vector vLocal = Ort(vLocal1);

vector Dop=Proizv(vLocal,a);

vector vDop=Arifm(vLocal1,Dop);

vector vGlobalDop=Arifm(vDop,vPC);

vector vPerpendik=Perpend(vDop);

vector vOrt= Ort(vPerpendik);

vector vLocalRes= Proizv(vOrt,b );

vector vGlobalRes=Arifm(vLocalRes,vGlobalDop);

location Result2=Preobr(vGlobalRes,oArea);

return Result2;
}

void Go(object oNPC, location CastSpell,object oPC,object oArea,float a,float b )
{
CastSpell=GetItemActivatedTargetLocation();
location lTarget=Loc(a,b,oArea,oPC,CastSpell);
AssignCommand(oNPC,ActionMoveToLocation(lTarget,TRUE));
}

Построение можно регулировать с помощью двух параметров a и b. a отвечает за то как удален будет NPC от игрока, а b - за смещение NPC вправо или влево.

Для использования необходимо:
1) Создать предмет со свойством "активировать предмет:дальнее расстояние" и тагом "panel"
2)Поставить группу из семи NPC с тагоми:NPC1 , NPC2 , NPC3 , NPC4 , NPC5 , NPC6 , NPC7
При желании количество неписей и их построение можно поменять произвольным образом
azathoth
Библиотечка нескольких функций для работы со строками, фактически написана ради одной функции. Насколько оптимален алгоритм не знаю, но годится для обычных проверок на нужные тэги.
NSS
// name: i_string
// type: Библиотека
// desc: Строковые функции
// autor: Nightwalker Sorcerer
// date: 4.01.2006
// modified: 11.01.2006

////////////////////////////////////////////////////////////////////////////////
// INFO ////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

/*

Contains:

int FindFirstOf(string sString, string sPattern, int nFrom = 0, int bSymbols = TRUE);
int FindLastSubString(string sString, string sSubString);
int FindSubStringFrom(string sString, string sSubString, int nCount = 0);
int Match(string sString, string sPattern);

*/


////////////////////////////////////////////////////////////////////////////////
// CONSTANTS ///////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

const string ANY_SYMBOL = "?";
const string ANY_SEQUENCE = "*";
const string P_BEGIN = "["; // открывающая скобка (1 символ)
const string P_END = "]"; // закрывающая скобка (1 символ)
const string P_OR = "|"; // ИЛИ выражение внутри скобок (1 символ)
const string SYMBOL_NOT = "!";

////////////////////////////////////////////////////////////////////////////////
// FUNCTION DEFINITIONS ////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

// Нахождение первого вхождение в строку sString символов из набора sPattern.
// - sString: строка для поиска;
// - sPattern: набор символов;
// - nFrom: позиция символа, с которого начинается поиск;
// - bSymbols: Зарезервировано, используйте умолчание, чтобы в следующих
//             версиях библиотеки функция работала как предполагалось.
// * Возвращает позицию в строке или отрицательное значение, если
//   позиция не найдена.
// --> Например:
//   > FindFirstOf("a", "abc") - возвращает 0;
//   > FindFirstOf("word", "ro") - возвращает 1;
//   > FindFirstOf("word", " _[](),.-") - возвращает отрицательное значение;
//   > FindFirstOf("wоw", "w", 1) - возвращает 2;
//   > FindFirstOf("string", "some", 1) - возвращает отрицательное значение.
int FindFirstOf(string sString, string sPattern, int nFrom = 0, int bSymbols = TRUE);

// Нахождение последнего вхождения строки sSubString в строку sString.
// - sString: строка для поиска;
// - sSubString: искомая подстрока.
// * Возвращает позицию в строке или отрицательное значение, если позиция
//   не найдена.
int FindLastSubString(string sString, string sSubString);

// Нахождение позиции подстроки sSubstring внутри строки sString,
// начиная поиск с позиции nCount.
// - sString: строка, в которой ищем;
// - sSubString: что ищем;
// - nCount: ищем начиная с этой позиции.
// * Возвращает позицию подстроки или отрицательное значение, если подстрока
//   не найдена.
int FindSubStringFrom(string sString, string sSubString, int nCount = 0);

// Провека совпадения сторки sString с шаблоном sPattern:
// '?' считается любым символом;
// '*' cчитается любой последовательностью символов,
//     в том числе пустой (без символов);
// '!' совпадение считается, если остаток строки не подходит к шаблону,
//     испольйте только в начале шаблона или скобочного выражения,
//     иначе за результат не ручаюсь;
// [..|..|..] один из вариантов, допускается вложенность.
// - sString: строка для проверки;
// - sPattern: правильная палитра.
// * Возвращает TRUE, если строки совпадают, и FALSE, если нет.
// --> Например:
//   > "?*" - любая непустая последовательность;
//   > "itm_*" - все строки, начинающиеся с "itm_";
//   > "i_*_gold" - строки вида "i_25_gold", "i_pi_gold", а также "i__gold";
//   > "*a*" - строки, в которых есть хоть одна буква а;
//   > "[X|N]*" - тэги всех стандарнтых вещей NWN и дополнений;
//   > "[|?[|?]]" - пустая строка или 1-2 символа;
//   > "!wrong" - любая строка, кроме "wrong".
int Match(string sString, string sPattern);

////////////////////////////////////////////////////////////////////////////////
// IMPLEMENTATION //////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

int FindFirstOf(string sString, string sPattern, int nFrom = 0, int bSymbols = TRUE)
{
    int nResult = -1;
    int nCounter, nPosition, nLengthPattern = GetStringLength(sPattern);
    for (nCounter = 0; nCounter < nLengthPattern; nCounter++)
    {
        nPosition = FindSubStringFrom(sString, GetSubString(sPattern, nCounter, 1), nFrom);
             if (nResult < 0) nResult = nPosition;
        else if ((nPosition >= 0) && (nResult > nPosition)) nResult = nPosition;
    }

    return nResult;
}

int FindLastSubString(string sString, string sSubString)
{
    int nSubStrLength, nResult, nNext;

    if ((nSubStrLength = GetStringLength(sSubString)) == 0) return -1;
    if ((nNext = (nResult = FindSubString(sString, sSubString))) < 0) return nResult;

    while ((nNext = FindSubString((sString = GetStringRight(sString, GetStringLength(sString) - nNext - nSubStrLength)), sSubString)) >= 0)
    {
        nResult += (nNext + nSubStrLength);
    }

    return nResult;
}

int FindSubStringFrom(string sString, string sSubString, int nCount = 0)
{
    int nResult = FindSubString(GetStringRight(sString, GetStringLength(sString) - nCount) , sSubString);
    if (nResult < 0) return nResult;
    return (nResult + nCount);
}

int Match(string sString, string sPattern)
{
    // DEBUG
    //SendMessageToPC(GetFirstPC(), "Сравнение '"+sString+"' с '"+sPattern+"'.");

    int nS, nPhB, nPhE;
    int nLengthString = GetStringLength(sString);
    int nLengthPattern = GetStringLength(sPattern);

    if (GetStringLeft(sPattern, 1) == SYMBOL_NOT)
    {
        return (!Match(sString, GetStringRight(sPattern, nLengthPattern - 1)));
    }

    if ((nPhE = (nPhB = FindSubString(sPattern, P_BEGIN))) >= 0) // обработка ИЛИ выражений
    {
        int nNest = 1; // текущая вложенность
        while ((nPhE >= 0) && (nNest > 0))
        {
            nPhE = FindFirstOf(sPattern, P_BEGIN + P_END, nPhE + 1);
            if (GetSubString(sPattern, nPhE, 1) == P_BEGIN) nNest++;
            else nNest--;
        }
        if (nNest != 0) return FALSE; // неправильно расставлены скобки

        int nPhS, nPhF = nPhB; // начало и конец подстроки
        string sSymbol = "";
        while ((sSymbol != P_END) && (nPhF >= 0))
        {
            nPhS = nPhF + 1;
            sSymbol = "";
            while ((((sSymbol != P_OR) || (nNest > 0)) && ((sSymbol != P_END) || (nNest >= 0))) && (nPhF >= 0))
            {
                nPhF = FindFirstOf(sPattern, P_BEGIN + P_OR + P_END, nPhF + 1);
                sSymbol = GetSubString(sPattern, nPhF, 1);
                     if (sSymbol == P_BEGIN) nNest++;
                else if (sSymbol == P_END) nNest--;
            }
            if (Match(sString, GetStringLeft(sPattern, nPhB) + GetSubString(sPattern, nPhS, nPhF - nPhS) + GetStringRight(sPattern, nLengthPattern - nPhE - 1))) return TRUE;
        }
        return FALSE;
    }

    if ((nS = FindSubString(sPattern, ANY_SEQUENCE)) > 0) // строки, содержащие ANY_SEQUENCE, но не вначале
    {
        if (!Match(GetStringLeft(sString, nS), GetStringLeft(sPattern, nS))) return FALSE;

        // упрощаем в "*..."
        return Match(GetStringRight(sString, nLengthString - nS), GetStringRight(sPattern, nLengthPattern - nS));
    }

    if (nS == 0) // теперь ANY_SEQUENCE вначале
    {
        string sPattern2 = GetStringRight(sPattern, nLengthPattern - 1);
        if ((nS = (FindLastSubString(sPattern2, ANY_SEQUENCE) + 1)) > 0) // есть второй ANY_SEQUENCE
        {
            // конечные кусочки после последнего ANY_SEQUENCE должны "совпадать"
            string sPatternAfterSeq = GetStringRight(sPattern, GetStringLength(sPattern) - nS - 1);
            int nLengthAfterSeq = GetStringLength(sPatternAfterSeq);
            if (!Match(GetStringRight(sString, nLengthAfterSeq), sPatternAfterSeq)) return FALSE;

            // упрощаем в "*...*"
            nLengthString = GetStringLength(sString = GetStringLeft(sString, nLengthString - nLengthAfterSeq));
            nLengthPattern = GetStringLength(sPattern = GetStringLeft(sPattern, nS + 1));

            // DEBUG:
            //SendMessageToPC(GetFirstPC(), "тупой подбор '"+sString+"' к '"+sPattern+"'");
            int nCounter1, nCounter2;
            for (nCounter1 = 1; (nCounter1 < nLengthString); nCounter1++)
            {
                for (nCounter2 = 1; (nCounter2 < nLengthPattern); nCounter2++)
                {
                    if (Match(GetStringLeft(sString, nCounter1), GetStringLeft(sPattern, nCounter2)))
                    if (Match(GetStringRight(sString, nLengthString - nCounter1), GetStringRight(sPattern, nLengthPattern - nCounter2)))
                    return TRUE;
                }
            }
            return FALSE;
        }

        // только один ANY_SEQUENCE вначале; осталось сравнить конец строки с палитрой
        return Match(GetStringRight(sString, GetStringLength(sPattern2)), sPattern2);
    }

    // теперь строка и палитра должны быть одинакового размера
    if (nLengthString != nLengthPattern) return FALSE;

    if ((nS = FindSubString(sPattern, ANY_SYMBOL)) >= 0) // в палитре присутствует ANY_SYMBOL
    {
        return Match(GetStringLeft(sString, nS), GetStringLeft(sPattern, nS))
        &&     Match(GetStringRight(sString, nLengthString - nS - 1), GetStringRight(sPattern, nLengthPattern - nS - 1));
    }

    return (sString == sPattern);
}

//void main(){}

Библиотека функций для работы с инвентарем, используя предыдущий инклюд. Основные функции: CreateItemList HasItemList и RemoveItemList, остальные функции тоже полезны в тех или иных ситуациях.
NSS
// name: i_inv
// type: Библиотека
// desc: Функции для работы с инвентарем.
// autor: Nightwalker Sorcerer
// date: 11.01.2005
// modified: 13.01.2005

////////////////////////////////////////////////////////////////////////////////
// INFO ////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

/*

Contains:

void CreateItemList(string sList, object oTarget = OBJECT_SELF);
int GetNumItems(object oTarget = OBJECT_SELF, string sTag = "*", int bCreatureSlots = FALSE);
int GetNumItemsInInventory(object oInventory = OBJECT_SELF, string sTag = "*");
int GetNumItemsInSlot(object oTarget, int nSlot, string sTag = "*");
int HasItemList(object oTarget, string sList, int bCreatureSlots = FALSE);
void RemoveItemList(object oTarget, string sList, int bCreatureSlots = FALSE);
int RemoveItemsFromInventory(object oInventory = OBJECT_SELF, string sTag = "*", int nNum = -1);
int RemoveItemsFromSlot(object oTarget, int nSlot, string sTag = "*", int nNum = -1);
int RemoveItemsFromSlots(object oTarget = OBJECT_SELF, string sTag = "*", int nNum = -1, int bCreatureSlots = FALSE)

*/


////////////////////////////////////////////////////////////////////////////////
// INCLUDES ////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

#include "i_string"

////////////////////////////////////////////////////////////////////////////////
// CONSTANTS ///////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

const string SYMBOL_AND = "&";
const string SYMBOL_EQU = "=";

////////////////////////////////////////////////////////////////////////////////
// FUNCTION DEFINITIONS ////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

// Создание вещей из заданого списка в инвентаре oTarget
// - sList: список вещей в виде "вещь1=кол-во1&вещь2=кол-во2&вещь3=кол-во3",
//   при опускании "=колво", количество считается 1;
// - oTarget: в чьем инвентаре создаем?
// --> Например:
//   > CreateItemList("single_item");
//   > CreateItemList("first_item&second_item&one_arrow=99", oTreasure);
// ? Примечание: если символ '&' плохо видно в списке, можно использовать '&&'.
void CreateItemList(string sList, object oTarget = OBJECT_SELF);

// Нахождение количества вещей с тэгом sTag у персонажа oTarget (в инвентаре
// и слотах)
// - oInventory: персонаж, в имуществе которого ищем;
// - sTag: палитра для проверки тэга;
// - bCreatureSlots: искать ли в невидимых слотах?
// * Возвращает количество найденых вещей.
int GetNumItems(object oTarget = OBJECT_SELF, string sTag = "*", int bCreatureSlots = FALSE);

// Нахождение количества вещей с заданым тэгом sTag в инвентаре oInventory,
// предметы в слотах не учитываются.
// - oInventory: целевой инвентарь
// - sTag: палитра для проверки тэга
// * Возвращает количество найденых вещей, тэг которых подходит под палитру
// --> Например:
//   > GetNumItemsInInventory(oChest, "itm_sword*") - количество вещей с тэгом,
//     начинающимся с "itm_sword" у объекта oChest;
//   > GetNumItemsInInventory(oPC, "eda") - количество вещей с тэгом "eda" у oPC.
int GetNumItemsInInventory(object oInventory = OBJECT_SELF, string sTag = "*");

// Нахождение количества вещей с заданым тегом sTag в слоте инвентаря nSlot
// существа oTarget.
// - oTarget: существо, у которого ищем;
// - nSlot: слот инвентаря;
// - sTag: тэг.
// * Возвращает количество найденых вещей.
int GetNumItemsInSlot(object oTarget, int nSlot, string sTag = "*");

// Нахождение количества вещей с заданым тегом sTag в слотах инвентаря
// существа oTarget.
// - oTarget: существо, у которого ищем;
// - sTag: тэг;
// - bCreatureSlots: считать ли вещи в невидимых слотах?
// * Возвращает количество найденых вещей.
int GetNumItemsInSlots(object oTarget = OBJECT_SELF, string sTag = "*", int bCreatureSlots = FALSE);

// Проверка, имеет ли oTarget cписок вещей sList.
// - sList: список вещей в виде "вещь1=кол-во1&вещь2=кол-во2&вещь3=кол-во3",
//   при опускании "=колво", количество считается 1;
// - oTarget: у кого проверяем;
// - bCreatureSlots: проверять ли вещи в невидимых слотах?
// * Возвращеет TRUE, если объект имеет вещи из списка, иначе FALSE.
// --> Например:
//   > НasItemList(oPC, "quest&gem[1|2]=6") - проверка, есть ли у персонажа вещь
//     c тэгом "quest" и шесть вещей с тэгом gem1 или gem2
// ? Примечание: если символ '&' плохо видно, можно использовать '&&'.
int HasItemList(string sList, object oTarget = OBJECT_SELF, int bCreatureSlots = FALSE);

// Удаление у оTarget списка вещей sList.
// - sList: список вещей в виде "вещь1=кол-во1&вещь2=кол-во2&вещь3=кол-во3",
//   при опускании "=колво", количество считается 1;
// - oTarget: у кого удаляем;
// - bCreatureSlots: удалять ли вещи из невидимых ячеек?
// --> Например:
//   > RemoveItemList(oPC, "fragile=-1&extra") - удаление всех вещей с
//     тэгом "fragile" и одной вещи с тэгом "extra".
// ? Примечание: если символ '&' плохо видно, можно использовать '&&'.
void RemoveItemList(string sList, object oTarget = OBJECT_SELF, int bCreatureSlots = FALSE);

// Удаление заданого количества вещей с тэгом sTag у персонажа.
// - oTarget: персонаж;
// - sTag: палитра для проверки тэга;
// - nNum: количество вещей, коророе нужно удалить, при отрицательном
// значении будут удалены все вещи;
// - bCreatureSlots: удалять ли вещи из невидимых ячеек?
// * Возвращает количество вещей, коророе осталось удалить.
// --> Например:
//   > RemoveItems(oTarget) - удалить все вещи у цели;
//   > RemoveItems(oPC, "flower", 2) - удалить у oPC две вещи с тэгом "flower".
int RemoveItems(object oTarget, string sTag = "*", int nNum = -1, int bCreatureSlots = FALSE);

// Удаление вещей из инвентаря с заданым тэгом, вещи в слотах не удаляются
// - oInventory: целевой инвентарь
// - sTag: палитра для проверки тэга
// - nNum: количество удаляемых вещей, при -1 удалятся все вещи,
//   подходящие под палитру
// * Возвращает количество вещей, которые осталось удалить, т.е 0, если удалено
//   столько вещей, сколько указано или большее число, если найдено меньше вещей,
//   c подходящим тэгом. Возвращает -1, если указано удалять все вещи.
//   Количество удаленных вещей можно получить = nNum - RemoveItemsFromInventory(,, nNum)
// --> Например:
//   > int nNoFood = RemoveItemsFromInventory(oPC, "itm_food", 1) - удаляет 1 еду,
//     nNoFood = 1, если у oPC нет еды;
//   > RemoveItemsFromInventory(oPC, "x*") - удаляет из вещмешка oPC вещи из дополнений.
int RemoveItemsFromInventory(object oInventory = OBJECT_SELF, string sTag = "*", int nNum = -1);

// Удалить nNum вещей из слота nSlot существа oTarget,
// если тэг вещи подходит к sTag.
// - oTarget: существо, у которого удаляем вещи;
// - nSlot: ячейка, из которой удаляем;
// - sTag: палитра тэга;
// - nNum: количество вещей, которое нужно удалить, при отрицательном значении
//   удалять все вещи.
// * Возвращает количество вещей, которые осталось удалить, или отрицательное
//   значение, если указано удалять все вещи.
int RemoveItemsFromSlot(object oTarget, int nSlot, string sTag = "*", int nNum = -1);

// Удалить nNum вещей из ячеек инвентаря существа oTarget с заданным тэгом.
// - oTarget: цель;
// - sTag: палитра тэга;
// - nNum: количество вещей, которое нужно удалить, при отрицательном значении
//   удалять все вещи;
// - bCreatureSlots: удалять ли вещи из невидимых ячеек.
// * Возвращает количество вещей, которые осталось удалить, или отрицательное
//   значение, если указано удалять все вещи.
int RemoveItemsFromSlots(object oTarget = OBJECT_SELF, string sTag = "*", int nNum = -1, int bCreatureSlots = FALSE);

////////////////////////////////////////////////////////////////////////////////
// IMPLEMENTATION //////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

void CreateItemList(string sList, object oTarget = OBJECT_SELF)
{
    int nDiv, nNum;
    string sResRef;
    while (sList != "")
    {
        if ((nDiv = FindSubString(sList, SYMBOL_AND)) < 0)
        {
            nDiv = GetStringLength(sList);
        }
        sResRef = GetStringLeft(sList, nDiv);
        sList = GetStringRight(sList, GetStringLength(sList) - nDiv - 1);
        nNum = 1;
        if ((nDiv = FindSubString(sResRef, SYMBOL_EQU)) >= 0)
        {
            nNum = StringToInt(GetStringRight(sResRef, GetStringLength(sResRef) - nDiv - 1));
            sResRef = GetStringLeft(sResRef, nDiv);
        }

        for ( ; nNum > 0; nNum--) CreateItemOnObject(sResRef, oTarget); // лучше ничего не придумал
    }
}

int GetNumItems(object oTarget = OBJECT_SELF, string sTag = "*", int bCreatureSlots = FALSE)
{
    return GetNumItemsInInventory(oTarget, sTag) + GetNumItemsInSlots(oTarget, sTag, bCreatureSlots);
}

int GetNumItemsInInventory(object oInventory = OBJECT_SELF, string sTag = "*")
{
    int nNum = 0;
    object oItem = GetFirstItemInInventory(oInventory);
    while (GetIsObjectValid(oItem))
    {
        if (Match(GetTag(oItem), sTag))
        {
            nNum += GetItemStackSize(oItem);
        }

        oItem = GetNextItemInInventory(oInventory);
    }

    return nNum;
}

int GetNumItemsInSlot(object oTarget, int nSlot, string sTag = "*")
{
    object oItem = GetItemInSlot(nSlot, oTarget);
    if (Match(GetTag(oItem), sTag)) return GetItemStackSize(oItem);
    return 0;
}

int GetNumItemsInSlots(object oTarget = OBJECT_SELF, string sTag = "*", int bCreatureSlots = FALSE)
{
    int nNum = 0;
    nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_ARMS,      sTag);
    nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_ARROWS,    sTag);
    nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_BELT,      sTag);
    nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_BOLTS,     sTag);
    nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_BOOTS,     sTag);
    nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_BULLETS,   sTag);
    //nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_CARMOUR,   sTag);
    nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_CHEST,     sTag);
    nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_CLOAK,     sTag);
    //nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_CWEAPON_B, sTag);
    //nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_CWEAPON_L, sTag);
    //nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_CWEAPON_R, sTag);
    nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_HEAD,      sTag);
    nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_LEFTHAND,  sTag);
    nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_LEFTRING,  sTag);
    nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_NECK,      sTag);
    nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_RIGHTHAND, sTag);
    nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_RIGHTRING, sTag);
    if (bCreatureSlots)
    {
        nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_CARMOUR,   sTag);
        nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_CWEAPON_B, sTag);
        nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_CWEAPON_L, sTag);
        nNum += GetNumItemsInSlot(oTarget, INVENTORY_SLOT_CWEAPON_R, sTag);
    }

    return nNum;
}

int HasItemList(string sList, object oTarget = OBJECT_SELF, int bCreatureSlots = FALSE)
{
    int nDiv, nNum;
    string sTag;
    while (sList != "")
    {
        if ((nDiv = FindSubString(sList, SYMBOL_AND)) < 0)
        {
            nDiv = GetStringLength(sList);
        }
        sTag = GetStringLeft(sList, nDiv);
        sList = GetStringRight(sList, GetStringLength(sList) - nDiv - 1);
        if ((nDiv = FindSubString(sTag, SYMBOL_EQU)) >= 0)
        {
            nNum = StringToInt(GetStringRight(sTag, GetStringLength(sTag) - nDiv - 1));
            sTag = GetStringLeft(sTag, nDiv);
        }
        else
        {
            nNum = 1;
        }

        if (sTag != "")
        if (GetNumItems(oTarget, sTag, bCreatureSlots) < nNum) return FALSE;
    }
    return TRUE;
}

void RemoveItemList(string sList, object oTarget = OBJECT_SELF, int bCreatureSlots = FALSE)
{
    int nDiv, nNum;
    string sTag;
    while (sList != "")
    {
        if ((nDiv = FindSubString(sList, SYMBOL_AND)) < 0)
        {
            nDiv = GetStringLength(sList);
        }
        sTag = GetStringLeft(sList, nDiv);
        sList = GetStringRight(sList, GetStringLength(sList) - nDiv - 1);
        if ((nDiv = FindSubString(sTag, SYMBOL_EQU)) >= 0)
        {
            nNum = StringToInt(GetStringRight(sTag, GetStringLength(sTag) - nDiv - 1));
            sTag = GetStringLeft(sTag, nDiv);
        }
        else
        {
            nNum = 1;
        }

        RemoveItems(oTarget, sTag, nNum, bCreatureSlots);
    }
}

int RemoveItems(object oTarget, string sTag = "*", int nNum = -1, int bCreatureSlots = FALSE)
{
    nNum = RemoveItemsFromInventory(oTarget, sTag, nNum);
    return RemoveItemsFromSlots(oTarget, sTag, nNum, bCreatureSlots);
}

int RemoveItemsFromInventory(object oInventory = OBJECT_SELF, string sTag = "*", int nNum = -1)
{
    int nStack;
    object oItem = GetFirstItemInInventory(oInventory);
    while (GetIsObjectValid(oItem) && (nNum != 0))
    {
        if (Match(GetTag(oItem), sTag))
        {
                 if (nNum < 0) DestroyObject(oItem);
            else if ((nStack = GetItemStackSize(oItem)) > nNum)
            {
                SetItemStackSize(oItem, nStack - nNum);
                return 0;
            }
            else
            {
                DestroyObject(oItem);
                nNum -= nStack;
            }
        }

        oItem = GetNextItemInInventory(oInventory);
    }

    return nNum;
}

int RemoveItemsFromSlot(object oTarget, int nSlot, string sTag = "*", int nNum = -1)
{
    if (nNum == 0) return nNum;

    object oItem = GetItemInSlot(nSlot, oTarget);
    if (GetIsObjectValid(oItem))
    if (Match(GetTag(oItem), sTag))
    {
        int nStack;

             if (nNum < 0) DestroyObject(oItem);
        else if ((nStack = GetItemStackSize(oItem)) > nNum)
        {
            SetItemStackSize(oItem, nStack - nNum);
            return 0;
        }
        else
        {
            DestroyObject(oItem);
            nNum -= nStack;
        }

    }
    return nNum;
}

int RemoveItemsFromSlots(object oTarget = OBJECT_SELF, string sTag = "*", int nNum = -1, int bCreatureSlots = FALSE)
{
    nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_ARMS,      sTag, nNum);
    nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_ARROWS,    sTag, nNum);
    nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_BELT,      sTag, nNum);
    nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_BOLTS,     sTag, nNum);
    nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_BOOTS,     sTag, nNum);
    nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_BULLETS,   sTag, nNum);
    //nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_CARMOUR,   sTag, nNum);
    nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_CHEST,     sTag, nNum);
    nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_CLOAK,     sTag, nNum);
    //nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_CWEAPON_B, sTag, nNum);
    //nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_CWEAPON_L, sTag, nNum);
    //nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_CWEAPON_R, sTag, nNum);
    nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_HEAD,      sTag, nNum);
    nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_LEFTHAND,  sTag, nNum);
    nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_LEFTRING,  sTag, nNum);
    nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_NECK,      sTag, nNum);
    nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_RIGHTHAND, sTag, nNum);
    nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_RIGHTRING, sTag, nNum);
    if (bCreatureSlots)
    {
        nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_CARMOUR,   sTag, nNum);
        nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_CWEAPON_B, sTag, nNum);
        nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_CWEAPON_L, sTag, nNum);
        nNum = RemoveItemsFromSlot(oTarget, INVENTORY_SLOT_CWEAPON_R, sTag, nNum);
    }
    return nNum;
}

//void main(){}


Примеры использования (судя по всему маст би):
- Проверка в диалоге на наличие у персонажа игрока необходимого количества (пусть 3) предметов с заданым тэгом (пусть "quest_item")
NSS
#include "i_inv"

int StartingConditional()
{
    object oPC = GetPCSpeaker();
    int n = GetNumItems(oPC, "quest_item");
    return (n >= 3);
}

- Забрать необходимое кол-во предметов у игрока (пусть те же 3 "quest_item")
NSS
#include "i_inv"

void main()
{
    object oPC = GetPCSpeaker();
    RemoveItems(oPC, "quest_item", 3);
}
Aiwan
Эта функция копирует инвентарь объекта, если необходимо, то и все надетые вещи на существо.


NSS
//
// КОПИРУЕТ ВЕСЬ ИНВЕНТАРЬ oMaster=OBJECT_SELF В ИНВЕНТАРЬ oNewMaster
// iDel = TRUE - удаляет копируемый объект из инвентаря хозяина, FALSE - нет
// iUnequip = TRUE - раздевает объект, снимая с него все в инвентарь
void CopyInventory(object oNewMaster, object oMaster=OBJECT_SELF, int iDel=TRUE, int iUnequip=FALSE);

void CopyInventory(object oNewMaster, object oMaster=OBJECT_SELF, int iDel=TRUE, int iUnequip=FALSE)
{
      if(iUnequip==TRUE)
      {
        int i=0;
        while(i<14)
        {
          if(GetItemInSlot(i, oMaster)!= OBJECT_INVALID)
          CopyItem(GetItemInSlot(i, oMaster), oNewMaster, TRUE);
          if(iDel==TRUE) DestroyObject(GetItemInSlot(i, oMaster));
          i++;
        }
      }
      object oItem = GetFirstItemInInventory(oMaster);
      while(GetIsObjectValid(oItem))
      {
        if(GetBaseItemType(oItem) == BASE_ITEM_LARGEBOX)
        {
          CreateItemOnObject(GetResRef(oItem), oNewMaster, 1);
          if(iDel==TRUE) DestroyObject(oItem, 0.5);
        }
        else
            {
              CopyItem(oItem, oNewMaster, TRUE);
              if(iDel==TRUE) DestroyObject(oItem);
            }
          oItem = GetNextItemInInventory(oMaster);
      }
}


Тут все просто. Имеем 25 бутылочек, удаляем из них 3 или одну.
NSS
// ВОЗВРАЩАЕТ КОЛИЧЕСТВО ПРЕДМЕТОВ В СТЕКЕ В ИНВЕНТАРЕ ОБЪЕКТА
int GetItemStackNumber(string sTagItem, object oTarget=OBJECT_SELF);

// УДАЛЯЕТ iNum КОЛИЧЕСТВО ПРЕДМЕТОВ В СТЕКЕ В ИНВЕНТАРЕ ОБЪЕКТА
void RemoveItemStackNumber(string sTagItem, int iNum = 1, object oTarget=OBJECT_SELF);

//------------------------------------------------------------------------------
int GetItemStackNumber(string sTagItem, object oTarget=OBJECT_SELF)
{
  object oItem = GetFirstItemInInventory(oTarget);
  int iNum = 0;
  while (GetIsObjectValid(oItem))
  {
      if (GetTag(oItem) == sTagItem)
      {
        iNum = iNum+GetItemStackSize(oItem);
      }
        oItem = GetNextItemInInventory(oTarget);
    }
    return iNum;
}
//------------------------------------------------------------------------------
void RemoveItemStackNumber(string sTagItem, int iNum = 1, object oTarget=OBJECT_SELF)
{
  object oItem = GetFirstItemInInventory(oTarget);
  while (GetIsObjectValid(oItem) && (iNum != 0))
  {
      if (GetTag(oItem) == sTagItem)
        {
          int i = GetItemStackSize(oItem);
          if (i > iNum)
          {
            SetItemStackSize(oItem, GetItemStackSize(oItem)-iNum);
            iNum = 0;
          }
          else
              {
                DestroyObject(oItem);
                iNum = iNum-i;
              }
        }
        oItem = GetNextItemInInventory(oTarget);
    }
}


Определяем лучший класс мультикласса.
NSS
//
// ЛУЧШИЙ КЛАСС МУЛЬТИКЛАССОВОГО СОЗДАНИЯ
int GetCreatureBestClass(object oCr=OBJECT_SELF);

int GetCreatureBestClass(object oCr)
{
    int class1 = GetClassByPosition(1, oCr);
    int class2 = GetClassByPosition(2, oCr);
    int class3 = GetClassByPosition(3, oCr);
    int classlev1, classlev2, classlev3;
    classlev1 = GetLevelByClass(class1, oCr);
    if (class2 != CLASS_TYPE_INVALID)
        classlev2 = GetLevelByClass(class2, oCr);
    if (class3 != CLASS_TYPE_INVALID)
        classlev3 = GetLevelByClass(class3, oCr);
    int BestClass = class1;
    if (classlev1 < classlev2)
        BestClass = class2;
    if (classlev2 < classlev3)
        BestClass = class3;
    return BestClass;
}
kreon
Скрипт "резервирования" нескольких мест на сервере под DM'ов
Бывает, что сервер полностью забит и зайти DM'ом не получается.
Теперь несколько мест будут забиты для ДМов
P.S. Возможно где-то уже есть, если так то сорри
onClientEnter
NSS
int nMaxPlayers = 30; // Макс. число игроков в настройке сервера минус число зарезервированных мест
void main() {
object oPC = GetEnteringObject();
object oMod = GetModule();
int nCurrPC = GetLocalInt(oMod, "CurrPC");
if(nCurrPC >= nMaxPlayers && !GetIsDM(oPC)) {
  BootPC(oPC);
  return;
}
SetLocalInt(oMod, "CurrPC", nCurrPC+1);
// нормальный oncliententer
// ...

OnClientExit
NSS
void main() {
object oMod = GetModule();
SetLocalInt(oMod, "CurrPC", GetLocalInt(oMod, "CurrPC")-1);
// нормальный onclientexit
// ...
Zirrex
Скрипт резервирования мест для ДМ-ов.

Аналогичный скрипт. Только чуть эффективней и проще. В момент входа игрока, а не ДМ-а, пересчитывается количество игроков, и если их больше указанной цифры, то входящий игрок бутится.

В скрипте, что выше, есть недостатки. Если клиент "отвалится" от сервера, т.е. у него произойдет дисконнект, то скрипт изменения переменной не выполнится. Далее, ДМ-ы занимают места игроков. Это не очень хорошо. Учитывая то, что максимально клиентов может быть только 30. В настройках сервера надо сделать 35 мест, а игроков ограничить 30-ю местами, используя подобный скрипт. Т.е. изменение переменной необходимо включить в условие, которое игнорирует Дм. И соответственно на выходе с модуля тоже ограничить условие игроком.

NSS
void main()
{
    object oMod = GetModule();

//--------------------------------------------------//
// Данные записываются в отдельный скрипт, а потом  //
// считываются во время загрузки модуля через      //
// действие 'OnModuleLoad'.                        //
    int DMRESERVE = 30; // Для примера - 30 человек
    SetLocalInt(oMod, "DMRESERVE", DMRESERVE);
//--------------------------------------------------//

    object oClient = GetEnteringObject();

    if (GetIsDM(oClient) == FALSE)
    {
        int nReserve = GetLocalInt(oMod, "DMRESERVE");

        if (nReserve == TRUE)
        {
            int nPlayer;

            object oPlayer = GetFirstPC();

            while (GetIsObjectValid(oPlayer))
            {
                nPlayer++;
                oPlayer = GetNextPC();
            }

            if (nPlayer > nReserve)
            {
                BootPC(oClient);
                return;
            }
        }
    }
}


З.Ы. kreon, если не сложно, доработай скрипт.
Fluyka
Вообщем я хотела вот что,у меня была такая идея...нужно было разделить отдых и процесс подготовки заклинаний кастующем классом. Это все нужно было все, чтобы клерик мог молиться Богу о заклинаниях только в определенные часы времени суток....ну перепало и магу конечно.smile.gif)
NSS
////////////////////////////////////////////////////////////////////////////////
/////Эта функция каждые 3 секунды проверяет подготавливает ли персонаж магию.///
////////////////////////////////////////////////////////////////////////////////
void Examen(object oPC = OBJECT_SELF)
{
if(!GetLocalInt(oPC,"Rest"))
  {
  ForceRest(oPC);//востановление магии
  ActionMoveToLocation(GetLocation(oPC));//встаем
  FloatingTextStringOnCreature( "Вы успешно подготовили магию.",oPC);

  //удаление локалок
  if(GetIsObjectValid(GetLocalObject(oPC,"GodLay")))
    {
    DestroyObject(GetLocalObject(oPC,"GodLay"));
    DeleteLocalObject(oPC,"GodLay");
    }

  DeleteLocalLocation(oPC, "RestLocation");
  return;
  }
if(GetLocation(oPC) != GetLocalLocation(oPC, "RestLocation"))
  {
  ActionMoveToLocation(GetLocation(oPC));
  FloatingTextStringOnCreature("Вам неудалось подготовить магию.",oPC);

  //удаление локалок
  if(GetIsObjectValid(GetLocalObject(oPC,"GodLay")))
    {
    DestroyObject(GetLocalObject(oPC,"GodLay"));
    DeleteLocalObject(oPC,"GodLay");
    }

  DeleteLocalInt(oPC,"Rest");
  DeleteLocalLocation(oPC, "RestLocation");
  return;
  }
else
  {
  AssignCommand(oPC, DelayCommand(3.0f, Examen(oPC)));
  AssignCommand(oPC,ActionPlayAnimation(ANIMATION_LOOPING_MEDITATE,1.0,3.0));
  }
}

////////////////////////////////////////////////////////////////////////////////
///Это начало подготовки заклинаний для божественных заклинателей///////////////
////////////////////////////////////////////////////////////////////////////////
void BeginGodMagic(object oPC =OBJECT_SELF)
{
object oLay;//тут я сделала луч, с неба как бы, впрочем необязательно. Так что можно убратьsmile.gif

//проверка айламента
if(GetAlignmentGoodEvil(oPC)==ALIGNMENT_EVIL)
{oLay = CreateObject(OBJECT_TYPE_PLACEABLE,"plc_solred",GetLocation(oPC));}
else if (GetAlignmentGoodEvil(oPC)==ALIGNMENT_NEUTRAL)
{oLay = CreateObject(OBJECT_TYPE_PLACEABLE,"plc_solblue",GetLocation(oPC));}
else oLay = CreateObject(OBJECT_TYPE_PLACEABLE,"plc_solwhite",GetLocation(oPC));

//вешаем нужные локалки на Чара и плэйсебл
SetLocalLocation(oPC, "RestLocation", GetLocation(oPC));
SetLocalInt(oPC,"Rest",TRUE);
SetLocalObject(oPC,"GodLay",oLay);

AssignCommand(oPC,ActionPlayAnimation(ANIMATION_LOOPING_MEDITATE,1.0,3.0));
AssignCommand(oPC, DelayCommand(3.0, Examen()));

DelayCommand(1.0,FloatingTextStringOnCreature("Подготовка магии.",oPC));
DelayCommand(30.0,DeleteLocalInt(oPC,"Rest"));
}

////////////////////////////////////////////////////////////////////////////////
//Это проверка у божественных заклинателей наличия бога/////////////////////////
//если есть, то все нормально,нет-не подготовить заклинаний.////////////////////
//и времени, в которое можно помолиться этому богу./////////////////////////////
//Закоментировала.//////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

/*void ExsamenGod(object oPC = OBJECT_SELF)
{
object oGodLatander,oGodMysrta;
int nTime = GetTimeHour();

oGodLatander = GetItemPossessedBy(oPC,"i_latander_sign");
oGodMysrta = GetItemPossessedBy(oPC,"i_mystra_sign");

// Latander
if(GetIsObjectValid(oGodLatander))
{
if((nTime>=6)&&(nTime<13)){BeginGodMagic(oPC);return;}
else return;
}
//Mystra
else if(GetIsObjectValid(oGodMysrta))
{
if((nTime>=23)&&(nTime<4)){BeginGodMagic(oPC);return;}
else return;
}
else{FloatingTextStringOnCreature("Вам не кому молитьсЯ относительно заклинаний.",oPC);}
}*/


////////////////////////////////////////////////////////////////////////////////
/// Это начало подготовки заклинаний для арканных заклинателей /////////////////
////////////////////////////////////////////////////////////////////////////////
void BeginArcaneMagic(object oPC =OBJECT_SELF)
{
SetLocalLocation(oPC, "RestLocation", GetLocation(oPC));
SetLocalInt(oPC,"Rest",TRUE);

AssignCommand(oPC,ActionPlayAnimation(ANIMATION_LOOPING_MEDITATE,1.0,3.0));
DelayCommand(3.0,AssignCommand(oPC,ActionPlayAnimation(ANIMATION_FIREFORGET_READ,1.0,10.0)));
AssignCommand(oPC, DelayCommand(3.0, Examen()));
DelayCommand(1.0,FloatingTextStringOnCreature("Подготовка магии.",oPC));
DelayCommand(30.0,DeleteLocalInt(oPC,"Rest"));
}

////////////////////////////////////////////////////////////////////////////////
///// Проверка. Есть ли у персонажа кастующий класс?  //////////////////////////
////////////////////////////////////////////////////////////////////////////////
void ExamenCastClass(object oPC = OBJECT_SELF)
{

int iu = 1,iClass;
while(iu <=3)
  {
    iClass=GetClassByPosition(iu,oPC);
    if(iClass == CLASS_TYPE_CLERIC){BeginGodMagic(oPC);return;}
    else if(iClass == CLASS_TYPE_DRUID){BeginGodMagic(oPC);return;}
    else if(iClass == CLASS_TYPE_PALADIN){BeginGodMagic(oPC);return;}
    else if(iClass == CLASS_TYPE_RANGER){BeginGodMagic(oPC);return;}
    else if(iClass ==  CLASS_TYPE_WIZARD){BeginArcaneMagic(oPC);return;}
    else if(iClass == CLASS_TYPE_SORCERER){BeginArcaneMagic(oPC);return;}
    else if(iClass == CLASS_TYPE_BARD){BeginArcaneMagic(oPC);return;}
    iu++ ;
  }
}

////////////////////////////////////////////////////////////////////////////////
/// Удаление восстановленных при отдыхе заклинаний /////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void SpellDelete(object oPC = OBJECT_SELF)
{

int nSpell, nKSpell;
for (nSpell = 0; nSpell < 1000; nSpell++)
{
        nKSpell = GetHasSpell(nSpell, oPC);
        if (nKSpell)
        {
          while (nKSpell > 0)
          {
            DecrementRemainingSpellUses(oPC, nSpell);
            nKSpell--;
          }
        }
}
}

////////////////////////////////////////////////////////////////////////////////
//////////////////  Отдых  ///////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void main()
{
object oPC = GetLastPCRested();
object oItem,oItem1;
switch(GetLastRestEventType())
    {
      case REST_EVENTTYPE_REST_STARTED:
      {
      //Необходимые эффекты,проверки и тд..
      break;
      }
      case REST_EVENTTYPE_REST_CANCELLED:
      {
      break;
      }
      case REST_EVENTTYPE_REST_FINISHED:
      {

      SpellDelete(oPC);
      DelayCommand(1.5,ExamenCastClass(oPC));
      break;
      }
    }
}
kreon
Не знаю, было или нет... Раскидывание заходящих игроков по точкам (например для автоматического раскидывания игроков по камерам в тюрьме)
jail_include.nss
NSS
int WP_COUNT = 5; // кол-во вейпойнтов
int PC_PER_WP = 1; // скольо игроков в 1н вейпойнт
string WP_SUFFIX = "_jail_wp"; // суффикс для переменной

jail_on_enter.nss
NSS
#include "jail_include"
void main() {
object oPC = GetEnteringObject();
if(!GetIsPC(oPC) || GetIsDM(oPC)) return;
int i, count;
string sWTag;
object oWP;
for(i=0;i<WP_COUNT;i++) {
  oWP = GetObjectByTag("wp_"+IntToString(i)+WP_SUFFIX);
  count = GetLocalInt(oWP, "pc_count");
  if(count < PC_PER_WP) {
   SetLocalInt(oWP, "pc_count", count+1);
   SetLocalObject(oPC, "wp"+WP_SUFFIX, oWP);
   AssignCommand(oPC, ActionJumpToObject(oWP));
  return;
  }
}
oWP = GetObjectByTag("wp_all"+WP_SUFFIX);
AssignCommand(oPC, ActionJumpToObject(oWP));
}

jail_on_exit.nss
NSS
#include "jail_include"
void main() {
object oPC = GetExitingObject();
if(!GetIsPC(oPC) || GetIsDM(oPC)) return;
object oWP = GetLocalObject(oPC, "wp"+WP_SUFFIX);
int count = GetLocalInt(oWP, "pc_count");
SetLocalInt(oWP, "pc_count", count-1);
DeleteLocalObject(oPC, "wp"+WP_SUFFIX);
}

соотв. ставим вейпойнты с тегами "wp_"+id+WP_SUFFIX, и 1н с тегом "wp_all"+WP_SUFFIX
Думаю остальное все ясно smile.gif
azathoth
Функция, определяющая лучшее оружие ближнего боя для указаного персонажа. Учитываются не только фокусы, если они есть (им отдается преимущество), но и специализации. Упор на схему щит+меч. Впрочем нисколько не претендую на полноту, тем более нет учета фита "Weapon Finesse" для предпочтения легкого оружия и полной поддержки дистанционного (необходим фокус, чтобы оно появилось). Метательное вообще не стал включать (не лублу его), если нужно -- раскомментируйте первые три строки.
Опробовано и работает, в своем модуле я использовал эту функцию для создания рандомного оружия у спавнов монстров - если НВН беден на модели, то хотя бы разное оружие у противников смотрится куда лучше.
Функция возвращает константу типа BASE_ITEM_*, по которой нужно создавать необходимую экипировку.
NSS
int GetWeaponBestBaseType(object oFor)
{
    //if (GetHasFeat(FEAT_WEAPON_FOCUS_DART, oFor)) return BASE_ITEM_DART;
    //if (GetHasFeat(FEAT_WEAPON_FOCUS_SHURIKEN, oFor)) return = BASE_ITEM_SHURIKEN;
    //if (GetHasFeat(FEAT_WEAPON_FOCUS_THROWING_AXE, oFor)) return THROWINGAXE;

    if (GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oFor))
    {
        if (GetHasFeat(FEAT_WEAPON_FOCUS_BASTARD_SWORD, oFor)) return BASE_ITEM_BASTARDSWORD;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_KATANA, oFor)) return BASE_ITEM_KATANA;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_DWAXE, oFor)) return  BASE_ITEM_DWARVENWARAXE;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_KUKRI, oFor)) return BASE_ITEM_KUKRI;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_SCYTHE, oFor)) return BASE_ITEM_SCYTHE;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_TWO_BLADED_SWORD, oFor)) return BASE_ITEM_TWOBLADEDSWORD;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_DIRE_MACE, oFor)) return BASE_ITEM_DIREMACE;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_DOUBLE_AXE, oFor)) return BASE_ITEM_DOUBLEAXE;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_KAMA, oFor)) return BASE_ITEM_KAMA;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_WHIP, oFor)) return BASE_ITEM_WHIP;
    }
    if (GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oFor))
    {
        if (GetHasFeat(FEAT_WEAPON_FOCUS_BATTLE_AXE, oFor)) return BASE_ITEM_BATTLEAXE;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_GREAT_AXE, oFor)) return BASE_ITEM_GREATAXE;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_GREAT_SWORD, oFor)) return BASE_ITEM_GREATSWORD;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_HALBERD, oFor)) return BASE_ITEM_HALBERD;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_HAND_AXE, oFor)) return BASE_ITEM_HANDAXE;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_HEAVY_FLAIL, oFor)) return BASE_ITEM_HEAVYFLAIL;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_LIGHT_FLAIL, oFor)) return BASE_ITEM_LIGHTFLAIL;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_LIGHT_HAMMER, oFor)) return BASE_ITEM_LIGHTHAMMER;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_LONG_SWORD, oFor)) return BASE_ITEM_LONGSWORD;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_LONGBOW, oFor)) return BASE_ITEM_LONGBOW;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_RAPIER, oFor)) return BASE_ITEM_RAPIER;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_SCIMITAR, oFor)) return BASE_ITEM_SCIMITAR;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_SHORT_SWORD, oFor)) return BASE_ITEM_SHORTSWORD;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_SHORTBOW, oFor)) return BASE_ITEM_SHORTBOW;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_WAR_HAMMER, oFor)) return BASE_ITEM_WARHAMMER;
    }
    if (GetHasFeat(FEAT_WEAPON_PROFICIENCY_ELF, oFor))
    {
        if (GetHasFeat(FEAT_WEAPON_FOCUS_LONG_SWORD, oFor)) return BASE_ITEM_LONGSWORD;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_LONGBOW, oFor)) return BASE_ITEM_LONGBOW;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_RAPIER, oFor)) return BASE_ITEM_RAPIER;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_SHORTBOW, oFor)) return BASE_ITEM_SHORTBOW;
    }
    if (GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oFor))
    {
        if (GetHasFeat(FEAT_WEAPON_FOCUS_CLUB, oFor)) return BASE_ITEM_CLUB;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_DAGGER, oFor)) return BASE_ITEM_DAGGER;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_HAND_AXE, oFor)) return BASE_ITEM_HANDAXE;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_HEAVY_CROSSBOW, oFor)) return BASE_ITEM_HEAVYCROSSBOW;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_LIGHT_CROSSBOW, oFor)) return BASE_ITEM_LIGHTCROSSBOW;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_LIGHT_MACE, oFor)) return BASE_ITEM_LIGHTMACE;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_MORNING_STAR, oFor)) return BASE_ITEM_MORNINGSTAR;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_RAPIER, oFor)) return BASE_ITEM_RAPIER;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_SHORT_SWORD, oFor)) return BASE_ITEM_SHORTSWORD;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_SHORTBOW, oFor)) return BASE_ITEM_SHORTBOW;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_STAFF, oFor)) return BASE_ITEM_QUARTERSTAFF;
    }
    if (GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oFor))
    {
        if (GetHasFeat(FEAT_WEAPON_FOCUS_CLUB, oFor)) return BASE_ITEM_CLUB;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_DAGGER, oFor)) return BASE_ITEM_DAGGER;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_HEAVY_CROSSBOW, oFor)) return BASE_ITEM_HEAVYCROSSBOW;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_LIGHT_CROSSBOW, oFor)) return BASE_ITEM_LIGHTCROSSBOW;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_LIGHT_MACE, oFor)) return BASE_ITEM_LIGHTMACE;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_MORNING_STAR, oFor)) return BASE_ITEM_MORNINGSTAR;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_SICKLE, oFor)) return BASE_ITEM_SICKLE;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_SLING, oFor)) return BASE_ITEM_SLING;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_SPEAR, oFor)) return BASE_ITEM_SHORTSPEAR;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_STAFF, oFor)) return BASE_ITEM_QUARTERSTAFF;
    }
    if (GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oFor))
    {
        if (GetHasFeat(FEAT_WEAPON_FOCUS_CLUB, oFor)) return BASE_ITEM_CLUB;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_DAGGER, oFor)) return BASE_ITEM_DAGGER;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_SCIMITAR, oFor)) return BASE_ITEM_SCIMITAR;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_SICKLE, oFor)) return BASE_ITEM_SICKLE;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_SLING, oFor)) return BASE_ITEM_SLING;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_SPEAR, oFor)) return BASE_ITEM_SHORTSPEAR;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_STAFF, oFor)) return BASE_ITEM_QUARTERSTAFF;
    }
    if (GetHasFeat(FEAT_WEAPON_PROFICIENCY_MONK, oFor))
    {
        if (GetHasFeat(FEAT_WEAPON_FOCUS_KAMA, oFor)) return BASE_ITEM_KAMA;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_CLUB, oFor)) return BASE_ITEM_CLUB;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_DAGGER, oFor)) return BASE_ITEM_DAGGER;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_HAND_AXE, oFor)) return BASE_ITEM_HANDAXE;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_HEAVY_CROSSBOW, oFor)) return BASE_ITEM_HEAVYCROSSBOW;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_LIGHT_CROSSBOW, oFor)) return BASE_ITEM_LIGHTCROSSBOW;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_SLING, oFor)) return BASE_ITEM_SLING;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_STAFF, oFor)) return BASE_ITEM_QUARTERSTAFF;
    }
    if (GetHasFeat(FEAT_WEAPON_PROFICIENCY_WIZARD, oFor))
    {
        if (GetHasFeat(FEAT_WEAPON_FOCUS_CLUB, oFor)) return BASE_ITEM_CLUB;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_DAGGER, oFor)) return BASE_ITEM_DAGGER;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_HEAVY_CROSSBOW, oFor)) return BASE_ITEM_HEAVYCROSSBOW;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_LIGHT_CROSSBOW, oFor)) return BASE_ITEM_LIGHTCROSSBOW;
        if (GetHasFeat(FEAT_WEAPON_FOCUS_STAFF, oFor)) return BASE_ITEM_QUARTERSTAFF;
    }

    int nSize = GetCreatureSize(oFor);

    if (GetHasFeat(FEAT_POINT_BLANK_SHOT, oFor))
    {
        // TODO: range weapons
    }

    if (GetHasFeat(FEAT_WEAPON_FINESSE, oFor))
    {
        // TODO: fine weapons
    }

    if (GetHasFeat(FEAT_WEAPON_PROFICIENCY_MONK, oFor))
    {
        return BASE_ITEM_KAMA;
    }
    if (GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC, oFor))
    {
        // double weapons if has two-weapon fighting feats
        if (GetHasFeat(FEAT_AMBIDEXTERITY, oFor) && GetHasFeat(FEAT_IMPROVED_TWO_WEAPON_FIGHTING, oFor) && (nSize >= CREATURE_SIZE_MEDIUM))
        {
            switch (Random(3))
            {
                case 0: return BASE_ITEM_DIREMACE;
                case 1: return BASE_ITEM_DOUBLEAXE;
                case 2: return BASE_ITEM_TWOBLADEDSWORD;
            }
        }
        // two-handed weapon if can't use shield
        if (!GetHasFeat(FEAT_SHIELD_PROFICIENCY, oFor))
        {
            switch(nSize)
            {
            case CREATURE_SIZE_HUGE:
            case CREATURE_SIZE_LARGE:
            case CREATURE_SIZE_MEDIUM: return BASE_ITEM_SCYTHE;
            case CREATURE_SIZE_SMALL: switch (Random(3))
                {
                case 0: return BASE_ITEM_BASTARDSWORD;
                case 1: return BASE_ITEM_KATANA;
                case 2: return BASE_ITEM_DWARVENWARAXE;
                }
            case CREATURE_SIZE_TINY: switch (Random(3))
                {
                case 0: return BASE_ITEM_KAMA;
                case 1: return BASE_ITEM_WHIP;
                case 2: return BASE_ITEM_KUKRI;
                }
            }
        }
        // one-handed weapon
        switch (nSize)
        {
        case CREATURE_SIZE_HUGE:
        case CREATURE_SIZE_LARGE: return BASE_ITEM_SCYTHE;
        case CREATURE_SIZE_MEDIUM: switch (Random(3))
            {
            case 0: return BASE_ITEM_BASTARDSWORD;
            case 1: return BASE_ITEM_KATANA;
            case 2: return BASE_ITEM_DWARVENWARAXE;
            }
        case CREATURE_SIZE_SMALL: switch (Random(3))
            {
            case 0: return BASE_ITEM_KAMA;
            case 1: return BASE_ITEM_KUKRI;
            case 2: return BASE_ITEM_WHIP;
            }
        case CREATURE_SIZE_TINY:
        }
    }
    if (GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oFor))
    {
        if (!GetHasFeat(FEAT_SHIELD_PROFICIENCY, oFor))
        {
            // two-handed
            switch (nSize)
            {
            case CREATURE_SIZE_HUGE:
            case CREATURE_SIZE_LARGE:
            case CREATURE_SIZE_MEDIUM: switch (Random(4))
                {
                case 0: return BASE_ITEM_HALBERD;
                case 1: return BASE_ITEM_GREATSWORD;
                case 2: return BASE_ITEM_GREATAXE;
                case 3: return BASE_ITEM_HEAVYFLAIL;
                }
            case CREATURE_SIZE_SMALL: switch (Random(6))
                {
                case 0: return BASE_ITEM_LONGSWORD;
                case 1: return BASE_ITEM_RAPIER;
                case 2: return BASE_ITEM_SCIMITAR;
                case 3: return BASE_ITEM_BATTLEAXE;
                case 4: return BASE_ITEM_LIGHTFLAIL;
                case 5: return BASE_ITEM_WARHAMMER;
                }
            case CREATURE_SIZE_TINY: switch (Random(3))
                {
                case 0: return BASE_ITEM_SHORTSWORD;
                case 1: return BASE_ITEM_HANDAXE;
                case 2: return BASE_ITEM_LIGHTHAMMER;
                }
            }
        }
        // one-handed
        switch (nSize)
        {
        case CREATURE_SIZE_HUGE:
        case CREATURE_SIZE_LARGE: switch (Random(4))
            {
            case 0: return BASE_ITEM_HALBERD;
            case 1: return BASE_ITEM_GREATSWORD;
            case 2: return BASE_ITEM_GREATAXE;
            case 3: return BASE_ITEM_HEAVYFLAIL;
            }
        case CREATURE_SIZE_MEDIUM: switch (Random(6))
            {
            case 0: return BASE_ITEM_LONGSWORD;
            case 1: return BASE_ITEM_RAPIER;
            case 2: return BASE_ITEM_SCIMITAR;
            case 3: return BASE_ITEM_BATTLEAXE;
            case 4: return BASE_ITEM_LIGHTFLAIL;
            case 5: return BASE_ITEM_WARHAMMER;
            }
        case CREATURE_SIZE_SMALL: switch (Random(3))
            {
            case 0: return BASE_ITEM_SHORTSWORD;
            case 1: return BASE_ITEM_HANDAXE;
            case 2: return BASE_ITEM_LIGHTHAMMER;
            }
        case CREATURE_SIZE_TINY:
        }
    }
    if (GetHasFeat(FEAT_WEAPON_PROFICIENCY_ELF, oFor))
    {
        switch (Random(2))
        {
            case 0: return BASE_ITEM_LONGSWORD;
            case 1: return BASE_ITEM_RAPIER;
        }
    }
    if (GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oFor))
    {
        if (!GetHasFeat(FEAT_SHIELD_PROFICIENCY, oFor))
        {
            // two-handed
            switch (nSize)
            {
            case CREATURE_SIZE_HUGE:
            case CREATURE_SIZE_LARGE:
            case CREATURE_SIZE_MEDIUM: return BASE_ITEM_QUARTERSTAFF;
            case CREATURE_SIZE_SMALL: switch (Random(3))
                {
                case 0: return BASE_ITEM_CLUB;
                case 1: return BASE_ITEM_RAPIER;
                case 2: return BASE_ITEM_MORNINGSTAR;
                }
            case CREATURE_SIZE_TINY: switch (Random(3))
                {
                case 0: return BASE_ITEM_HANDAXE;
                case 1: return BASE_ITEM_LIGHTMACE;
                case 2: return BASE_ITEM_SHORTSWORD;
                }
            }
        }
        // one-handed
        switch (nSize)
        {
        case CREATURE_SIZE_HUGE:
        case CREATURE_SIZE_LARGE: return BASE_ITEM_QUARTERSTAFF;
        case CREATURE_SIZE_MEDIUM: switch (Random(3))
            {
            case 0: return BASE_ITEM_CLUB;
            case 1: return BASE_ITEM_RAPIER;
            case 2: return BASE_ITEM_MORNINGSTAR;
            }
        case CREATURE_SIZE_SMALL: switch (Random(2))
            {
            case 0: return BASE_ITEM_HANDAXE;
            case 1: return BASE_ITEM_LIGHTMACE;
            case 2: return BASE_ITEM_SHORTSWORD;
            }
        case CREATURE_SIZE_TINY: return BASE_ITEM_DAGGER;
        }
    }
    if (GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oFor))
    {
        if (!GetHasFeat(FEAT_SHIELD_PROFICIENCY, oFor))
        {
            // two-handed
            switch (nSize)
            {
            case CREATURE_SIZE_HUGE:
            case CREATURE_SIZE_LARGE:
            case CREATURE_SIZE_MEDIUM: switch (Random(2))
                {
                case 0: return BASE_ITEM_SHORTSPEAR;
                case 1: return BASE_ITEM_QUARTERSTAFF;
                }
            case CREATURE_SIZE_SMALL: switch (Random(2))
                {
                case 0: return BASE_ITEM_CLUB;
                case 1: return BASE_ITEM_MORNINGSTAR;
                }
            case CREATURE_SIZE_TINY: switch (Random(2))
                {
                case 0: return BASE_ITEM_LIGHTMACE;
                case 1: return BASE_ITEM_SICKLE;
                }
            }
        }
        // one-handed
        switch (nSize)
        {
        case CREATURE_SIZE_HUGE:
        case CREATURE_SIZE_LARGE: switch (Random(2))
            {
            case 0: return BASE_ITEM_SHORTSPEAR;
            case 1: return BASE_ITEM_QUARTERSTAFF;
            }
        case CREATURE_SIZE_MEDIUM: switch (Random(2))
            {
            case 0: return BASE_ITEM_CLUB;
            case 1: return BASE_ITEM_MORNINGSTAR;
            }
        case CREATURE_SIZE_SMALL: switch (Random(2))
            {
            case 0: return BASE_ITEM_LIGHTMACE;
            case 1: return BASE_ITEM_SICKLE;
            }
        case CREATURE_SIZE_TINY: return BASE_ITEM_DAGGER;
        }
    }
    if (GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oFor))
    {
        if (!GetHasFeat(FEAT_SHIELD_PROFICIENCY, oFor))
        {
            // two-handed
            switch (nSize)
            {
            case CREATURE_SIZE_HUGE:
            case CREATURE_SIZE_LARGE:
            case CREATURE_SIZE_MEDIUM: switch (Random(2))
                {
                case 0: return BASE_ITEM_SHORTSPEAR;
                case 1: return BASE_ITEM_QUARTERSTAFF;
                }
            case CREATURE_SIZE_SMALL: switch (Random(2))
                {
                case 0: return BASE_ITEM_CLUB;
                case 1: return BASE_ITEM_SCIMITAR;
                }
            case CREATURE_SIZE_TINY: return BASE_ITEM_SICKLE;
            }
        }
        // one-handed
        switch (nSize)
        {
        case CREATURE_SIZE_HUGE:
        case CREATURE_SIZE_LARGE: switch (Random(2))
            {
            case 0: return BASE_ITEM_SHORTSPEAR;
            case 1: return BASE_ITEM_QUARTERSTAFF;
            }
        case CREATURE_SIZE_MEDIUM: switch (Random(2))
            {
            case 0: return BASE_ITEM_CLUB;
            case 1: return BASE_ITEM_SCIMITAR;
            }
        case CREATURE_SIZE_SMALL: return BASE_ITEM_SICKLE;
        case CREATURE_SIZE_TINY: return BASE_ITEM_DAGGER;
        }
    }
    if (GetHasFeat(FEAT_WEAPON_PROFICIENCY_WIZARD, oFor))
    {
        if (!GetHasFeat(FEAT_SHIELD_PROFICIENCY, oFor))
        {
            // two-handed
            switch (nSize)
            {
            case CREATURE_SIZE_HUGE:
            case CREATURE_SIZE_LARGE:
            case CREATURE_SIZE_MEDIUM: return BASE_ITEM_QUARTERSTAFF;
            case CREATURE_SIZE_SMALL: return BASE_ITEM_CLUB;
            case CREATURE_SIZE_TINY:
            }
        }
        // one-handed
        switch (nSize)
        {
        case CREATURE_SIZE_HUGE:
        case CREATURE_SIZE_LARGE: return BASE_ITEM_QUARTERSTAFF;
        case CREATURE_SIZE_MEDIUM: return BASE_ITEM_CLUB;
        case CREATURE_SIZE_SMALL:
        case CREATURE_SIZE_TINY: return BASE_ITEM_DAGGER;
        }
    }

    return BASE_ITEM_INVALID;
}
Waromon
Не знаю было, нет что то подобное.
Скрипт, после смерти непися создает невидимый объект в который перекладываются все вещи моба, через минуту все уничтожается.

Синьки:
plc_сorpse - невидимый объект,
plc_blood - пятно крови, появляется если на мобе весит локалка - no_blood.

Переменные:
no_blood - отвечает за появление пятна крови, если переменная TRUE - крови не будет.

1. onDeath, NPC:

NSS
void ClearInventory(object oTarget)
{
object oFirstItem = GetFirstItemInInventory(oTarget);
while (GetIsObjectValid(oFirstItem))
    {
      DestroyObject(oFirstItem);
      oFirstItem = GetNextItemInInventory(oTarget);
    }
}

void main()
{
SetIsDestroyable(FALSE, FALSE);

object oCorpse = CreateObject(OBJECT_TYPE_PLACEABLE, "plc_сorpse",GetLocation(OBJECT_SELF));

if (!GetLocalInt(OBJECT_SELF, "no_blood"))
{
object oBlood = CreateObject(OBJECT_TYPE_PLACEABLE, "plc_blood",                                         GetLocation(OBJECT_SELF));
DestroyObject(oBlood, 120.0f);
}

DestroyObject(oCorpse, 60.0f);    
DestroyObject(OBJECT_SELF, 60.0f);
DelayCommand(59.0f, ClearInventory(oCorpse));
DelayCommand(60.0f, SetIsDestroyable(TRUE, FALSE));

object oItem = GetFirstItemInInventory();
while (GetIsObjectValid(oItem))
{
  if(GetBaseItemType(oItem) == BASE_ITEM_LARGEBOX)
  {
   CreateItemOnObject(GetResRef(oItem), oCorpse, 1);
   DestroyObject(oItem, 0.5);
  }
  else
  {
   CopyItem(oItem, oCorpse, TRUE);
   DestroyObject(oItem);
 }
oItem = GetNextItemInInventory();
}

int i;
for (i=0; i<14; i++)
{
CopyItem(GetItemInSlot(i), oCorpse, TRUE);
}
}


2. На оnClose, oCorpse:

NSS
void main()
{
if (!GetIsObjectValid(GetFirstItemInInventory()))
   {
   DestroyObject(OBJECT_SELF, 0.5);
   }
}
Angelelf
Это мой скрипт для разных таверн.Официантка ходит по таверне подходит к разнам клиентам ,спрашивает заказ

идет к стойке берерт заказ идет назад к тому же клиенту отдает ему заказ и берет плату.Время от времени

отдыхает и жалуется на жизнь.Реплики впишете сами не хотелось париться.
Что бы скрипты правильно работали следует создать следущие вай поинты:
Bar1-сюда приходят за напитками
Rest1-здесь отдыхает
wt_return1-ставиться возле бара
WP_TavernPatronXX_01-ставится возле клиентов у каждого клиент должен быть свой номер ХХ
Zone1-ставится где нибудь не подалеку от клиентов


Этот скрипт ставится на оnUserDef
NSS
////////////////////////////////////////////////////////////////////////////////
// Written by Angelelf 24.03.06
// Скрипт придаю щий реальную атмосферу таверне
// требуются следующие вай поинты
// WP_WTCommon_Bar      - место где берутся заказы.Бар
// WP_Rest1            - Здесь она будет отдыхать
// ZoneX                - этот вай поинт обозначает зону обслуживания
// X это номер зоны обслуживания начинается с 1
////////////////////////////////////////////////////////////////////////////////
void DrinkOrderKid(); // Заказ ребенка
void DrinkOrder();    // Заказ посетителей
string CountPatrons();  // Счетчик посетителей
void GetQueryString();  //
void TakeBreak();      // перерыв
void GetMyPay();        // получение пллаты

int StartingConditional()
{
    return TRUE;
}

void DrinkOrderKid() //  Заказ ребенка
{
    int nOrder= -1;
    string sOrder;  // реплика официанта
    string sAmount; // Реплика при передаче заказа
    string sBarkeepR;// Реплика бармена
    nOrder= d4();
    switch(nOrder)
    {
        case 1:
            sOrder = "Бармен,стакан молока для ребенка.";
            sAmount = "Вот твое молоко.";
            sBarkeepR = "Один стакан свежего молока готов.";
            break;
        case 2:
            sOrder = "Один стакан воды пожалуйста";
            sAmount = "Вот вода которую вы заказывали";
            sBarkeepR = "Держи.";
            break;
        case 3:
            sOrder = "Можешь себе представить ребенок попросил водки";
            sAmount = "Простите мы не продаем водку лицам моложе 18 лет";
            sBarkeepR = "Когда они поймут что водка это вредно.";
            break;
        case 4:
            sOrder = "________";
            sAmount = "________";
            sBarkeepR = "_______.";
            break;
    }
    SetLocalString(OBJECT_SELF, "WG_ORDER", sOrder);
    SetLocalString(OBJECT_SELF, "WG_AMOUNT", sAmount);
    SetLocalString(OBJECT_SELF, "WG_BARKEEP", sBarkeepR);
}

void DrinkOrder()  // заказы посетителей
{
    int nOrder= -1;
    string sOrder;
    string sAmount;
    string patronOrder;
    string sBarkeepR;
    nOrder= d8();
    switch(nOrder)
    {
        case 1:
            patronOrder = "Принеси мне эля."; // заказ
            sOrder = ""; //реплика официанта
            sAmount = "";    //реплика при передачи заказа
            sBarkeepR = ""//реплика бармена
            break;
        case 2:
            patronOrder = "";
            sOrder = "";
            sAmount = "";
            sBarkeepR = "";
            break;
        case 3:
            patronOrder = "";
            sOrder = "";
            sAmount = "";
            sBarkeepR = "";
            break;
        case 4:
            patronOrder = "";
            sOrder = "";
            sAmount = "";
            sBarkeepR = "";
            break;
        case 5:
            patronOrder = "";
            sOrder = "";
            sAmount = "";
            sBarkeepR = "";
            break;
        case 6:
            patronOrder = "";
            sOrder = "";
            sAmount = "";
            sBarkeepR = "";
            break;
        case 7:
            patronOrder = "";
            sOrder = "";
            sAmount = "";
            sBarkeepR = "";
            break;
        case 8:
            patronOrder = "";
            sOrder = "";
            sBarkeepR = "";
            sAmount = "";
            break;
    }
    SetLocalString(OBJECT_SELF, "PATRON_ORDER", patronOrder);
    SetLocalString(OBJECT_SELF, "WG_ORDER", sOrder);
    SetLocalString(OBJECT_SELF, "WG_AMOUNT", sAmount);
    SetLocalString(OBJECT_SELF, "WG_BARKEEP", sBarkeepR);
}

string CountPatrons()
{
    int i=-1;
    int j=-1;
    int myZone = GetLocalInt(OBJECT_SELF,"MyZone");
    float size;
    switch(myZone)
    {

    // Изменяйте величену size чтоб официант обслуживал разных клиентов за круг это увеличит реальность
        case 1:
            size=15.0;
            break;
        case 2:
            size=15.0;
            break;
        case 3:
            size=21.0;
            break;
        case 4:
            size=7.0;
            break;
    }
    string myTag = "Zone" + IntToString(myZone);
    string patronTag;
    object oJunk = GetFirstObjectInShape(SHAPE_CUBE, size, GetLocation(GetWaypointByTag(myTag)), TRUE,

CREATURE_TYPE_PLAYER_CHAR);
    if ((GetIsPC(oJunk) == TRUE) || (oJunk == OBJECT_SELF))
    {
        oJunk=GetNextObjectInShape(SHAPE_CUBE, size,GetLocation(GetWaypointByTag(myTag)), TRUE,

CREATURE_TYPE_PLAYER_CHAR);
    }
    while (oJunk != OBJECT_INVALID)
    {
        while ((GetIsPC(oJunk) == TRUE) || (oJunk == OBJECT_SELF))
        {
            oJunk=GetNextObjectInShape(SHAPE_CUBE, size,GetLocation(GetWaypointByTag(myTag)), TRUE,

CREATURE_TYPE_PLAYER_CHAR);
        }
        i++;
        oJunk=GetNextObjectInShape(SHAPE_CUBE, size,GetLocation(GetWaypointByTag(myTag)), TRUE,

CREATURE_TYPE_PLAYER_CHAR);
    }
    int bla=Random(i);

    oJunk = GetFirstObjectInShape(SHAPE_CUBE,  size, GetLocation(GetWaypointByTag(myTag)), TRUE,

CREATURE_TYPE_PLAYER_CHAR);
    if ((GetIsPC(oJunk) == TRUE) || (oJunk == OBJECT_SELF))
    {
        oJunk=GetNextObjectInShape(SHAPE_CUBE, size,GetLocation(GetWaypointByTag(myTag)),  TRUE,

CREATURE_TYPE_PLAYER_CHAR);
    }
    while (oJunk != OBJECT_INVALID)
    {
        while ((GetIsPC(oJunk) == TRUE) || (oJunk == OBJECT_SELF))
        {
            oJunk=GetNextObjectInShape(SHAPE_CUBE, size,GetLocation(GetWaypointByTag(myTag)), TRUE,

CREATURE_TYPE_PLAYER_CHAR);
        }
        j++;
        if (j == bla)
        {
            patronTag = GetTag(oJunk);
        }
        oJunk=GetNextObjectInShape(SHAPE_CUBE, size,GetLocation(GetWaypointByTag(myTag)), TRUE,

CREATURE_TYPE_PLAYER_CHAR);
    }
    return patronTag;
}

void GetQueryString() // Спрашивает заказ у PC
{
    switch(Random(4))
    {
        case 0:
            ActionSpeakString ("",TALKVOLUME_TALK);
            break;
        case 1:
            ActionSpeakString ("",TALKVOLUME_TALK);
            break;
        case 2:
            ActionSpeakString ("",TALKVOLUME_TALK);
            break;
        case 3:
            ActionSpeakString ("",TALKVOLUME_TALK);
            break;
    }
}

void TakeBreak()  // реплики во время перерыва
{
    switch(Random(4))
    {
        case 0:
            ActionSpeakString ("",TALKVOLUME_TALK);
            break;
        case 1:
            ActionSpeakString ("",TALKVOLUME_TALK);
            break;
        case 2:
            ActionSpeakString ("I",TALKVOLUME_TALK);
            break;
        case 3:
            ActionSpeakString ("",TALKVOLUME_TALK);
            break;
    }
}

void GetMyPay()    // gjctnbntkb jnlf.n gkfne
{
    string payAmount;

    switch(d4())
    {
        case 1:
            payAmount = "Вот твои деньги сдачи не надо";
            break;
        case 2:
            payAmount = "";
            break;
        case 3:
            payAmount = "";
            break;
        case 4:
            payAmount = "";
            break;
    }
    SetLocalString(OBJECT_SELF,"PAY_AMOUNT",payAmount);
}




void main() {

    int nUser = GetUserDefinedEventNumber();
    string sQuery;
    string sOrder;
    int myZone = GetLocalInt(OBJECT_SELF,"MyZone");
    string myPatron=CountPatrons();
    string sAmount;
    string payAmount;
    string patronOrder;
    string sBarkeepR;
    int isKid;
    object oCustomer = GetLocalObject(OBJECT_SELF, "CUSTOMER");
    object oBar;
    object oBar2;
    switch(myZone)
    {
        // Добавляйте или убирайте кол-во case в зависимости от того сколько зон вам надо обслуживать
        case 1:
          oBar = GetWaypointByTag("WP_WTCommon_Bar");    //Здесь официантка берет напитки
          oBar2 = GetWaypointByTag("Rest1");  //Сюда она возвращается когда разнесет напитки
          break;

    }
    if (nUser == 1001)
    {
        if (!GetIsObjectValid(oCustomer) && (GetLocalInt(OBJECT_SELF, "BARMAID_STATE") < 1))
        {
            // идет к своему клиенту не игроку
            oCustomer = GetObjectByTag(myPatron);
            if (oCustomer != GetObjectByTag("Barkeeper") &&
            oCustomer != OBJECT_SELF && GetIsObjectValid(oCustomer))
            {
                // подходит к клиенту и спрашивает чего он хочет
                SetLocalInt (OBJECT_SELF, "BARMAID_STATE", 1);
                SetLocalObject (OBJECT_SELF, "CUSTOMER", oCustomer);
                ActionForceMoveToObject(oCustomer, FALSE, 0.5, 60.0);
                GetQueryString();
                isKid = GetLocalInt(oCustomer,"IAmAKid");
                if (isKid == 1)
                {
                    DrinkOrderKid();
                }
                else
                {
                    DrinkOrder();
                }
                ActionWait(1.0);
                patronOrder = GetLocalString(OBJECT_SELF,"PATRON_ORDER");
                ActionDoCommand(AssignCommand(oCustomer,SpeakString(patronOrder,TALKVOLUME_TALK)));
                ActionWait(3.0); //ждет 3 сек

                // идет к бару за напитками
                ActionDoCommand (SetLocalInt(OBJECT_SELF, "BARMAID_STATE", 2));
                ActionForceMoveToObject(oBar, FALSE, 0.5, 60.0);

                sOrder = GetLocalString(OBJECT_SELF,"WG_ORDER");
                sBarkeepR = GetLocalString(OBJECT_SELF, "WG_BARKEEP");

                ActionSpeakString (sOrder);
                ActionWait(3.0);

                // проверяет к тому ли бару она идет
                if(myZone == 1)
                {
                    ActionDoCommand(AssignCommand(GetObjectByTag("wt_Barkeeper1"), ActionSpeakString

(sBarkeepR,TALKVOLUME_TALK)));
                }
                else
                {
                    ActionDoCommand(AssignCommand(GetObjectByTag("wt_Barkeeper2"), ActionSpeakString

(sBarkeepR,TALKVOLUME_TALK)));
                }
                ActionWait(3.0);
                // возвращается к клиенту и отдает напитки
                ActionDoCommand (SetLocalInt(OBJECT_SELF, "BARMAID_STATE", 3));
                ActionForceMoveToObject (oCustomer, FALSE, 0.5, 60.0);
                sAmount = GetLocalString(OBJECT_SELF,"WG_AMOUNT");
                GetMyPay();
                payAmount = GetLocalString(OBJECT_SELF,"PAY_AMOUNT");
                if (sAmount == "**") // реакция на выражения
                {
                    PlaySound("cb_ht_critical"); //звук
                    payAmount = ""; // фраза
                }
                ActionSpeakString (sAmount);
                ActionWait(2.0);
                ActionDoCommand(AssignCommand(oCustomer,SpeakString(payAmount,TALKVOLUME_TALK)));
                ActionDoCommand (SetLocalObject(OBJECT_SELF, "CUSTOMER", OBJECT_INVALID));

                // возвращается к бару и берет перерыв
                ActionForceMoveToObject(oBar2, FALSE, 0.5, 60.0);
                ActionWait(1.0);
                TakeBreak();
                ActionWait(2.0);
                ActionDoCommand (SetLocalInt(OBJECT_SELF, "BARMAID_STATE", 0));
            }
        }
    }
    if (nUser == 1004)
    {

        SetLocalObject (OBJECT_SELF, "CUSTOMER", OBJECT_INVALID);
        SetLocalInt (OBJECT_SELF, "BARMAID_STATE", 0);
    }
}

Этот на onSpawn официанта
NSS
//::///////////////////////////////////////////////
//:: Default: On Spawn In
//:: NW_C2_DEFAULT9
//:: Copyright © 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
    Determines the course of action to be taken
    after having just been spawned in
*/

//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Oct 25, 2001
//:://////////////////////////////////////////////
#include "NW_O2_CONINCLUDE"
#include "NW_I0_GENERIC"




void main()
{

SetLocalInt(OBJECT_SELF,"MyZone",1); // это значит что данный официант будет обслуживать зону 1.Создать вай

поинт Zone1

// OPTIONAL BEHAVIORS (Comment In or Out to Activate )

****************************************************************************
    //SetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION);
    //SetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVERSATION);
                // This causes the creature to say a special greeting in their conversation file
                // upon Perceiving the player. Attach the [NW_D2_GenCheck.nss] script to the desired
                // greeting in order to designate it. As the creature is actually saying this to
                // himself, don't attach any player responses to the greeting.

    //SetSpawnInCondition(NW_FLAG_SHOUT_ATTACK_MY_TARGET);
                // This will set the listening pattern on the NPC to attack when allies call
    //SetSpawnInCondition(NW_FLAG_STEALTH);
                // If the NPC has stealth and they are a rogue go into stealth mode
    //SetSpawnInCondition(NW_FLAG_SEARCH);
                // If the NPC has Search go into Search Mode
    //SetSpawnInCondition(NW_FLAG_SET_WARNINGS);
                // This will set the NPC to give a warning to non-enemies before attacking

    //SetSpawnInCondition(NW_FLAG_SLEEP);
                //Creatures that spawn in during the night will be asleep.
    //SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
    //SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
    //SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
    //SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
                //This will play Ambient Animations until the NPC sees an enemy or is cleared.
                //NOTE that these animations will play automatically for Encounter Creatures.

    // NOTE: ONLY ONE OF THE FOLOOWING ESCAPE COMMANDS SHOULD EVER BE ACTIVATED AT ANY ONE TIME.
    //SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN);    // OPTIONAL BEHAVIOR (Flee to a way point and return a

short time later.)
    //SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE);    // OPTIONAL BEHAVIOR (Flee to a way point and do not

return.)
    //SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE);  // OPTIONAL BEHAVIOR (Teleport to safety and do not

return.)
    //SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN);  // OPTIONAL BEHAVIOR (Teleport to safety and return a

short time later.)

// CUSTOM USER DEFINED EVENTS
/*
    The following settings will allow the user to fire one of the blank user defined events in the NW_D2_DefaultD.  Like the
    On Spawn In script this script is meant to be customized by the end user to allow for unique behaviors.  The user

defined
    events user 1000 - 1010
*/

    SetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT);        //OPTIONAL BEHAVIOR - Fire User Defined Event 1001
    //SetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT);        //OPTIONAL BEHAVIOR - Fire User Defined Event 1002
    //SetSpawnInCondition(NW_FLAG_ATTACK_EVENT);          //OPTIONAL BEHAVIOR - Fire User Defined Event 1005
    //SetSpawnInCondition(NW_FLAG_DAMAGED_EVENT);          //OPTIONAL BEHAVIOR - Fire User Defined Event 1006
    //SetSpawnInCondition(NW_FLAG_DISTURBED_EVENT);        //OPTIONAL BEHAVIOR - Fire User Defined Event 1008
    //SetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event

1003
    SetSpawnInCondition(NW_FLAG_ON_DIALOGUE_EVENT);      //OPTIONAL BEHAVIOR - Fire User Defined Event 1004
    //SetSpawnInCondition(NW_FLAG_DEATH_EVENT);            //OPTIONAL BEHAVIOR - Fire User Defined Event 1007

// DEFAULT GENERIC BEHAVIOR (DO NOT TOUCH)

*****************************************************************************************
    SetListeningPatterns();    // Goes through and sets up which shouts the NPC will listen to.
    WalkWayPoints();          // Optional Parameter: void WalkWayPoints(int nRun = FALSE, float fPause = 1.0)
                              // 1. Looks to see if any Way Points in the module have the tag "WP_" + NPC TAG + "_0X", if so walk

them
                              // 2. If the tag of the Way Point is "POST_" + NPC TAG the creature will return this way point after
                              //    combat.
//  GenerateNPCTreasure();    //* Use this to create a small amount of treasure on the creature
}

Этот на onConvercation
NSS
//::///////////////////////////////////////////////
//:: SetListeningPatterns
//:: NW_C2_DEFAULT4
//:: Copyright © 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
    Determines the course of action to be taken
    by the generic script after dialogue or a
    shout is initiated.
*/

//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Oct 24, 2001
//:://////////////////////////////////////////////

#include "NW_I0_GENERIC"

void main()
{
    int nMatch = GetListenPatternNumber();
    object oShouter = GetLastSpeaker();
    object oIntruder;

    if (nMatch == -1 && GetCommandable(OBJECT_SELF))
    {
        ClearAllActions();
        BeginConversation();
        ActionWait(8.0);
    }
    else
    if(nMatch != -1 && GetIsObjectValid(oShouter) && !GetIsPC(oShouter) && GetIsFriend(oShouter))
    {
        if(nMatch == 4)
        {
            oIntruder = GetLocalObject(oShouter, "NW_BLOCKER_INTRUDER");
        }
        else if (nMatch == 5)
        {
            oIntruder = GetLastHostileActor(oShouter);
            if(!GetIsObjectValid(oIntruder))
            {
                oIntruder = GetAttemptedAttackTarget();
                if(!GetIsObjectValid(oIntruder))
                {
                    oIntruder = GetAttemptedSpellTarget();
                    if(!GetIsObjectValid(oIntruder))
                    {
                        oIntruder = OBJECT_INVALID;
                    }
                }
            }
        }
        RespondToShout(oShouter, nMatch, oIntruder);
    }


    if(GetSpawnInCondition(NW_FLAG_ON_DIALOGUE_EVENT))
    {
        SignalEvent(OBJECT_SELF, EventUserDefined(1004));
    }
}

Этот на onDistr
NSS
//::///////////////////////////////////////////////
//:: Default: On Disturbed
//:: NW_C2_DEFAULT8
//:: Copyright © 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
    Calls the end of combat script every round
*/

//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Oct 16, 2001
//::///////////////////////////////////////////

// * Make me hostile the faction of my last attacker (TEMP)
//  AdjustReputation(OBJECT_SELF,GetFaction(GetLastAttacker()),-100);
// * Determined Combat Round

#include "NW_I0_GENERIC"

void main()
{
    object oTarget = GetLastDisturbed();

    if(!GetIsObjectValid(GetAttemptedAttackTarget()) && !GetIsObjectValid(GetAttemptedSpellTarget()))
    {
        if(GetIsObjectValid(oTarget))
        {
            DetermineCombatRound(oTarget);
        }
    }
    if(GetSpawnInCondition(NW_FLAG_DISTURBED_EVENT))
    {
        ActionWait(8.0);
    }
}

Этот сиавится на onSpawn клиента таверны
NSS
//::///////////////////////////////////////////////
//:: Default: On Spawn In
//:: NW_C2_DEFAULT9
//:: Copyright © 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
    Determines the course of action to be taken
    after having just been spawned in
*/

//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Oct 25, 2001
//:://////////////////////////////////////////////
#include "NW_O2_CONINCLUDE"
#include "NW_I0_GENERIC"

void main()
{
// OPTIONAL BEHAVIORS (Comment In or Out to Activate )

****************************************************************************
    //SetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION);
    //SetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVERSATION);
                // This causes the creature to say a special greeting in their conversation file
                // upon Perceiving the player. Attach the [NW_D2_GenCheck.nss] script to the desired
                // greeting in order to designate it. As the creature is actually saying this to
                // himself, don't attach any player responses to the greeting.

    //SetSpawnInCondition(NW_FLAG_SHOUT_ATTACK_MY_TARGET);
                // This will set the listening pattern on the NPC to attack when allies call
    //SetSpawnInCondition(NW_FLAG_STEALTH);
                // If the NPC has stealth and they are a rogue go into stealth mode
    //SetSpawnInCondition(NW_FLAG_SEARCH);
                // If the NPC has Search go into Search Mode
    //SetSpawnInCondition(NW_FLAG_SET_WARNINGS);
                // This will set the NPC to give a warning to non-enemies before attacking

    //SetSpawnInCondition(NW_FLAG_SLEEP);
                //Creatures that spawn in during the night will be asleep.
    //SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
    //SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
    //SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
    //SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
                //This will play Ambient Animations until the NPC sees an enemy or is cleared.
                //NOTE that these animations will play automatically for Encounter Creatures.

    // NOTE: ONLY ONE OF THE FOLOOWING ESCAPE COMMANDS SHOULD EVER BE ACTIVATED AT ANY ONE TIME.
    //SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN);    // OPTIONAL BEHAVIOR (Flee to a way point and return a

short time later.)
    //SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE);    // OPTIONAL BEHAVIOR (Flee to a way point and do not

return.)
    //SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE);  // OPTIONAL BEHAVIOR (Teleport to safety and do not

return.)
    //SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN);  // OPTIONAL BEHAVIOR (Teleport to safety and return a

short time later.)

// CUSTOM USER DEFINED EVENTS
/*


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

Lex
Название: Рубка железных деревьев.
Описание: Дерево, которое можно рубить только специальным топором и после некоторых мучений отрубить таки сук. Другое оружие тупится об это дерево.
скрипты:
NSS
// lx_pus_irontree
// ставится на слот onUsed дерева
void main()
{
object oPC = GetLastUsedBy();
object oTree = OBJECT_SELF;
// если мы сук уже срубили - выдаем сообщение
if (GetLocalInt(OBJECT_SELF,"CUTTED"))
    {
    FloatingTextStringOnCreature("**Нет ни одного подходящего сука, который можно было бы отрубить**",oPC);
    }
else // если еще не срубили, тоже сообщение
    {
    FloatingTextStringOnCreature("**У дерева есть сук, котороый вполне можно отрубить**",oPC);
// и начинаем рубить
    DelayCommand(0.8,AssignCommand(oPC,ClearAllActions()));
    DelayCommand(1.0,AssignCommand(oPC,ActionAttack(oTree)));
    }
}


NSS
// lx_pat_irontree
// скрипт на слот onAttacked дерева
void main()
{
object oPC = GetLastAttacker();
// если рубить нечего - сообщение и выход (можно добавить сброс рубки, по желанию)
if (GetLocalInt(OBJECT_SELF,"CUTTED"))
    {
    FloatingTextStringOnCreature("**Нет ни одного подходящего сука, который можно было бы отрубить**",oPC);
    return;
    }
// оружие, которым ведется рубка
object oW = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oPC);
// если это особый топор (он у меня двуручный, поэтому проверяю только правую руку)
if (GetTag(oW)=="ITM_GAXE_FORIRON")
    {
    // снимаем плот с дерева, теперь его можно дамажить (а до этого плот стоял по умочанию)
    SetPlotFlag(OBJECT_SELF,FALSE);
    }
else // если же мы пытаемся рубить не нужным топором
    {
    // ставим плот
    SetPlotFlag(OBJECT_SELF,TRUE);
    // если оружие есть, то одно сообщение
    if (GetIsObjectValid(oW))
          FloatingTextStringOnCreature("**Я только испорчу "+GetName(oW)+ " об это железное дерево**",oPC);
    // если нет - другое
    else  FloatingTextStringOnCreature("**Я только себе руки в кровь разобью об это железное дерево**",oPC);
    }
}


NSS
// lx_pdm_irontree
// скрипт на слот onDamage дерева
void main()
{
object oPC = GetLastDamager();
// если уже отрезано - чистим действия (сообщение было в *_pat_*)
if (GetLocalInt(OBJECT_SELF,"CUTTED"))
    {
    AssignCommand(oPC,ClearAllActions(TRUE));
    return;
    }
// оружие, которым рубим
object oW = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oPC);
// если нужное - все ок
if (GetTag(oW)=="ITM_GAXE_FORIRON")
    { // как только у дерева меньше 100 хп, значит сук мы срубили (у меня вначале стоит 150 хп)
    if (GetCurrentHitPoints()<100)
        {
        // отмечаем, что сук срублен
        SetLocalInt(OBJECT_SELF,"CUTTED",TRUE);
        // даем срубленный сук игроку
        CreateItemOnObject("ITM_IRONWOOD",oPC);
        // чистим действия и даем сообщение
        AssignCommand(oPC,ClearAllActions(TRUE));
        FloatingTextStringOnCreature("**Вы срубили сук железного дерева**",oPC);
        }
    }
else
    {
    // если рубим "левым" оружием
    SetPlotFlag(OBJECT_SELF,TRUE);
    if (GetIsObjectValid(oW))
        {
        // то на оружии накапливается повреждение
        int SPL = GetLocalInt(oW,"SPOILING");
        // и после 5 ударов по дереву
        if (SPL == 5)
            {
            // оружие тупится
            FloatingTextStringOnCreature("**Ваш "+GetName(oW)+ " затупился**",oPC);
            AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyAttackPenalty(2),oW);
            AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyDamagePenalty(2),oW);
            SetLocalInt(oW,"SPOILING",6);
            }
        else
            {
            SetLocalInt(oW,"SPOILING",SPL+1);
            }
        }
    }
}



установка:
- ставим в локации дерево, даем ему 150-200 хитов, ставим плот, настраиваем (я Hardness ставлю около 10)
- ставим с слоты вышеуказанные скрипты
- создаем в палитре предмет ITM_IRONWOOD

ps: тут есть пара моментов, которые я упустил (ну мне они не очень актуальны)
1. не учитывается магия.. а надо бы smile.gif Думаю простого плота на onSpellCast будет достаточно
2. не учитывается вариант атаки дерева дальнобойным оружием. В этом случае не должно оно тупиться. Но это так же легко проверить, немного дописав скрит lx_pdm_irontree

smile.gif
virusman
Пара скриптов посадки на стул:

NSS
void main()
{
    object oPC = GetLastUsedBy();
    object oChair = OBJECT_SELF;
    if (!GetIsObjectValid (GetSittingCreature(oChair))) {
        AssignCommand(oPC, ActionSit(oChair));
    }
}


NSS
void main()
{
  object oPlayer = GetLastUsedBy ();
  object oChair = OBJECT_SELF;
  object oSitter=GetSittingCreature(oChair);
  if (GetIsPC (oPlayer))
    {
        if (GetIsObjectValid(oChair) && !GetIsObjectValid
            (oSitter))
        {
            AssignCommand (oPlayer, ActionSit (oChair));
        }
    }
  else if(!GetIsObjectValid(oSitter))
  {
    AssignCommand(oPlayer, ActionSit(oChair));
  }
}
2_advanced
но не для шардов :-)
virusman
QUOTE(2_advanced @ Jan 29 2007, 13:44) [snapback]103439[/snapback]
но не для шардов :-)
Работало без проблем более 3 лет.
2_advanced
если сидячий персонаж выйдет из игры / перезайдет, уйдет в другую локу, то стульчик накроется:
GetSittingCreature на стуле останется до рестарта => проверять нужно GetSittingCreature не с запоротого стула, а с объекта, на который перс садится + место где он находится =) может уже в другой локе, а не рядом со стулом

древний извращенский метод:

NSS
void main()
{
    object oPC = GetLastUsedBy();
    object oChair = OBJECT_SELF;

    if(GetIsObjectValid(oChair) && GetIsObjectValid(oPC))
    {
        object oSurf = GetLocalObject(oChair, "surf"); // +очистка

        if(GetIsObjectValid(oSurf))
        {
            object oSitter = GetSittingCreature(oSurf);

            if(!GetIsObjectValid(oSitter) || GetArea(oSitter) != GetArea(oChair))
                DestroyObject(oSurf);
            else
                return;
        }

        vector vSurf = GetPosition(oChair);

        // сабж усаживал много персов на 1 скамейку smile.gif найду- выложу
        //vector vSurf = GenerateNewSurfPos(oChair, GetSubRace(oPC), GetGender(oPC));

        location lSurf = Location(GetArea(oChair), vSurf, GetFacing(oChair));

        object oNewSurf = CreateObject(OBJECT_TYPE_PLACEABLE, "sittingsurface", lSurf, FALSE);

        SetLocalObject(oChair, "surf", oNewSurf);

        AssignCommand(oPC, ActionSit(oNewSurf));
    }
}
virusman
О глюках при перезаходе ни разу не слышал.
Может, это уже давно пофиксили в 1.67?

Lex:
QUOTE(virusman @ Jan 30 2007, 08:57) [snapback]103489[/snapback]
О глюках при перезаходе ни разу не слышал.

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