Помощь - Поиск - Пользователи - Календарь
Полная версия: Нужно проверить несколько скриптов
Город Мастеров > РЕДАКТОРЫ > Neverwinter Nights 2 Obsidian Toolset
Chimeric
Всем привет. Я написал несколько скриптов, связанных с одним и тем же классом - некромантом. Хочется, чтобы мастера скриптового дела поглядели на них. В следующее мое появление здесь я их размещу и буду добавлять мало-помалу. Сам я не специализируюсь на скриптах, к тому же у меня нет возможности их протестировать, да и вообще поиграть в НВН2 - компьютер слишком слаб для него. То, что написано, ориентировано на первую часть НВН и Аврору, поэтому и понадобятся коррективы. Может показаться странным, что я что-то делаю для игры, которую сам не в состоянии запустить, но меня увлекает создание контента. Главное - ставить достижимые цели.

Еще (и здесь уже я полный профан) может понадобиться человек, хорошо знакомый с AI хенчменов. Есть идея сделать для некроманта хенчмена-гуля (я нашел интересное заклинание в Wizard Spell Compendium для AD&D). За мной в этом случае будет диалог или диалоги, но я не берусь перевести в код странные привычки, каких, вы понимаете, от гуля можно ждать. Заинтересовавшихся спецов прошу отметиться здесь.

Айван, Лекс, а не сделать ли это очередным конкурсом? Назовите его "Лучший AI для необычного хенчмена" или как-то так, и в качестве хенчмена, чтобы был фокус, назначить именно спутника-гуля. Тогда мы получили бы несколько работ и взяли бы лучшее из них. Этот замысел с гулем и скриптами для некроманта - не для моего личного пользования. Я не планирую ввести их в какой-нибудь свой модуль. Наоборот, я хочу сделать некий полезный набор, упругий пакет, достаточно соблазнительный и полный, чтобы приманить распорядителей шардов. Пусть они посмотрят на дополненного и исправленного некроманта и скажут себе "Эй, а ведь наш-то некромант - скучнее, просто hack-n-slash... Возьмем этого".
Aiwan
Chimeric, дружище. Круче гуру, чем ДБ на скрипты хеньчманов я не знаю. Но написать АИ хеньчману все равно что нарисовать мод равнозначный компании, если не круче. smile.gif Так что, конкурс получится из 0 участников smile.gif
Chimeric
Neverwinter Script
void LeafThroughCorpses(object oCorpse, int nHecatomb)



{



oCorpse = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_LARGE, GetLocation(OBJECT_SELF));

nHecatomb = GetLocalInt(oCorpse, "hecatomb") + nHecatomb;



while (GetIsObjectValid(oCorpse) & GetIsDead(oCorpse) == TRUE)



{



SetLocalInt(OBJECT_SELF, "hecatomb", nHecatomb);



}



oCorpse = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_LARGE, GetLocation(OBJECT_SELF));



}

}







void main()



{



location lSelf = GetLocation(OBJECT_SELF);



SetLocalInt(OBJECT_SELF, "hecatomb", GetHitDice(OBJECT_SELF));

LeafThroughCorpses;

DelayCommand(5.0, DeleteLocalInt(OBJECT_SELF, "hecatomb"));



if (nHecatomb =>50)



{



if (nHecatomb < 70)



{



CreateObject(OBJECT_TYPE_TRIGGER, "hecatomb_small", lSelf, FALSE);



}



else if (nHecatomb < 100)



{



CreateObject(OBJECT_TYPE_TRIGGER, "hecatomb_medium", lSelf, FALSE);



}



else



{



CreateObject(OBJECT_TYPE_TRIGGER, "hecatomb_great", lSelf, FALSE);





}



SetLocalInt(GetNearestObject(OBJECT_TYPE_TRIGGER, OBJECT_SELF), "hecatomb_worth", nHecatomb);

DeleteLocalInt(OBJECT_SELF, "hecatomb");



}



}




Это один скрипт, понятный. Вот скрипт заклинания - попытка.

Neverwinter Script
void SpellExpired()



{



DeleteLocalInt(oTarget, "seeking_hecatomb"));

DeleteLocalInt(oTarget, "health"));



if (GetIsDead(oTarget) != TRUE)



{

ClearAllActions(oTarget);



if ((GetObjectSeen(OBJECT_SELF), oTarget) == TRUE)



{

SetIsTemporaryEnemy(OBJECT_SELF, oTarget, TRUE, fHateLasts); /// нападает на мага, если видит его тут же

DetermineCombatRound();

}



else



{

AssignCommand, (oTarget, ActionMoveToLocation(lSelf, TRUE, 0.0f)); /// иначе бегом назад

}



}

}



void SeekHecatombHolocaust()



{



location lSelf = GetLocation(oTarget);

object oHecatomb = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_GARGANTUAN, lSelf, FALSE, OBJECT_TYPE_TRIGGER); /// ищем в огромном радиусе триггер. так как требуется лишь один, я обошелся без функции while и GetNextObjectInShape.

int nDuration = GetCasterLevel(OBJECT_SELF) * 5; /// длительность

int nMetaMagic = GetMetaMagicFeat(OBJECT_SELF); /// вдвое больше с метамагией

int nHealth = GetCurrentHitPoints(oTarget);

float fHateLasts = GetIntelligence(oTarget) * 20; ///умный ненавидит за это дольше



SetLocalVariable(oTarget, "health", nHealth);



if (nMetaMagic == METAMAGIC_EXTEND)

{

nDuration = nDuration * 2;

}





if (WillSave(oTarget, GetSpellSaveDC(), SAVING_THROW_TYPE_EVIL, OBJECT_SELF) == 0

&& ResistSpell(OBJECT_SELF, oTarget) != 1) /// типы спасброска имеют значение? можно ли указать два типа сразу для одного броска, например, TYPE_EVIL и TYPE_NEGATIVE?



{



if (oHecatomb != OBJECT_INVALID && (GetTag(oHecatomb) == "hecatomb_small" | GetTag(oHecatomb) == "hecatomb_medium" | GetTag(oHecatomb) == "hecatomb_great") && (GetRacialType(oTarget) != RACIAL_TYPE_UNDEAD) && (GetDistanceBetween(oHecatomb, oTarget) <= 100.0)) /// я не уверен, ставить ли && или &. смысл: "если объект с одним из трех тегов найден, И если oTarget - не нежить, И если oTarget в пределах ста метров от объекта с тегом"...



{

AssignCommand(oTarget, ActionMoveToObject(oHecatomb, 0.0f))); /// oTarget идет к триггеру так, чтобы зайти на него.

SetLocalInt(oTarget, "seeking_hecatomb", 1);

DelayCommand(IntToFloat(nDuration), SpellExpired()); /// когда срок вышел, то...



while (GetLocalInt(oTarget, "seeking_hecatomb") == 1)



{



if (nHealth < GetLocalVariable(oTarget, "health"))



{



ClearAllActions(oTarget);

SetLocalVariable(oTarget, "health", nHealth);

DelayCommand(IntToFloat(nDuration), DeleteLocalInt(oTarget, "seeking_hecatomb")); /// пока идет к триггеру, любая рана отменяет эффект



}

}

}

}



else if ((GetObjectSeen(OBJECT_SELF), oTarget) == TRUE)



{



SetIsTemporaryEnemy(OBJECT_SELF, oTarget, TRUE, fHateLasts); /// при неудачной попытке нападает на мага

DetermineCombatRound();



}

}





void main() /// как я понимаю, void main() выполняется раньше всех функций

{

    int nSpell = GetSpellId();

    object oTarget = GetSpellTargetObject();

    effect eDark = EffectVisualEffect(VFX_DUR_BLINDVISION, FALSE);

    int nMetaMagic = GetMetaMagicFeat();

   

    if(nSpell == 5002) /// куда вписывать эти значения? в spells.2da?

   

    {

    SignalEvent(oTarget, EventSpellCastAt(oTarget, SPELL_RAVENS_FEAST, FALSE)); /// а константы?

    ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eDark, oTarget, 1.0); /// затемнение

    AdjustAlignment(OBJECT_SELF, 5, -5); /// правильно указал сдвиг ко злу?

    SeekHecatombHolocaust();



}

}


Теперь говорите, что не так.
Lex
Цитата(Chimeric @ Aug 18 2009, 16:49) *
Теперь говорите, что не так.

еще раз напишешь в кодбоксе - я тебе яйца оторву rolleyes.gif


мало выложить сюда тело скрипта (хорошо бы еще пустые строки убрать, читать неудобно).
надо проблему описать, указать где эти скрипты должны работать и как.
Chimeric
По-моему, ясно - то скрипт заклинания, вернее, двух. Одно создает "гекатомбу", очаг насыщенной смерти после одновременной гибели множества созданий. Эту силу может использовать некромант, но гекатомба невидима. Второе заклинание заставляет искать ее живое существо, которое идет в сторону гекатомбы, указывая некроманту путь, и там умирает, если добирается. Работают ли скрипты, вот вопрос?

Еще два заклинания:

Neverwinter Script
/// Заклинание Биополь. Некромантия. 8 уровень. Время наложения - 1. Длится три раунда. Выпускает жизненную силу мага, чтобы укрыть его и тех, кто рядом, от всякого прямого вреда и дает бонус к спасброскам Крепости. Жизненная сила, однако, быстро тает, а с ней и защита. До конца действия чар маг не в состоянии двигаться, даже когда заклинание его уже практически не оберегает. Поэтому возможно умереть, не рассчитав своих возможностей, или от мощной атаки на последнем раунде действия. Механика поощряет заблаговременное вытягивание чужой энергии, чтобы повысить эффективность и несколько обезопасить некроманта, но во время трех раундов действия он не подлежит лечению и регенерации никакими средствами. Заклинание для крайних случаев. 



void main()

{

location lSelf = GetLocation(oTarget);

float fDuration = 18.0; /// продолжительность - три раунда

int nAmount = (GetCurrentHitPoints(OBJECT_SELF) / 15) * GetHitDice(OBJECT_SELF); /// за каждый уровень после начального, 15-го, начинает собираться небольшой бонус

int nMetaMagic = GetMetaMagicFeat(OBJECT_SELF);

int nStartingHealth;

int nBackToWounded;

effect eShield = EffectDamageResistance(DAMAGE_TYPE_ACID | DAMAGE_TYPE_BASE_WEAPON DAMAGE_TYPE_BLUDGEONING | DAMAGE_TYPE_DIVINE | DAMAGE_TYPE_ELECTRICAL | DAMAGE_TYPE_FIRE | DAMAGE_TYPE_MAGICAL | DAMAGE_TYPE_NEGATIVE | DAMAGE_TYPE_PIERCING | DAMAGE_TYPE_POSITIVE | DAMAGE_TYPE_SLASHING | DAMAGE_TYPE_SONIC, nAmount, nAmount);

effect eSave = EffectSavingThrowIncrease(SAVING_THROW_FORTITUDE, nAmount / 8, SAVING_THROW_TYPE_ALL);

effect eCantMove = EffectParalyze(); /// если только при этом нет опасности coup de grace, иначе лучше Stun

effect eVisFreeze = EffectVisualEffect(VFX_DUR_FREEZE_ANIMATION); ///

effect eVisGlow = EffectVisualEffect(VFX_DUR_LIGHT_WHITE_15); ///

effect eVisAura = EffectVisualEffect(VFX_DUR_AURA_WHITE); /// /// или эквиваленты

effect eDamage = SupernaturalEffect(EffectDamage(1, DAMAGE_POWER_PLUS_SIX)); /// или эквивалент всепроникающего урона в NWN2

effect eLink1 = MagicalEffect(EffectLinkEffects(eShield, eSave));

effect eLink2 = MagicalEffect(EffectLinkEffects(eLink1, eCantMove));

effect eLink3 = MagicalEffect(EffectLinkEffects(eVisGlow, eVisAura));

effect eLink4 = MagicalEffect(EffectLinkEffects(eVisFreeze, eLink3));

effect eLink5 = MagicalEffect(EffectLinkEffects(eLink2, eLink4));

object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, 3.0f, lSelf, TRUE, OBJECT_TYPE_CREATURE); /// радиус в метрах?

SetLocalInt(OBJECT_SELF, "starting_health", nAmount);


if (nMetaMagic == METAMAGIC_EXTEND)

{

fDuration = 36.0; /// запомнив чары как 9-й уровень, можно получить шесть раундов защиты, но это опасно (смотри ниже)

}

while (GetIsDead(OBJECT_SELF) != TRUE & fDuration > 0)

{

ApplyEffectToObject(DURATION_TYPE_Temporary, eLink5, OBJECT_SELF, 0.5f);

ApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, OBJECT_SELF); /// постоянная потеря сил

DelayCommand(0.5, fDuration = fDuration - 0.5) /// это сработает? следующий виток всей функции - через полсекунды


if (nAmount > nAmount) /// попытки повысить hp, пока действуют чары, ни к чему не приводят

{

nStartingHealth = GetLocalInt(OBJECT_SELF, "starting_health");

nBacktoWounded = nStartingHealth - nAmount;

ApplyEffectToObject(DURATION_TYPE_INSTANT, SupernaturalEffect(EffectDamage(nBackToWounded, DAMAGE_POWER_PLUS_SIX), OBJECT_SELF));

nAmount = nAmount; /// здесь у меня сомнения

}


if (GetIsEffectValid(eLink5) = FALSE) /// если развеяли общий эффект, то остановка

break;

}

while (GetisEnemy(oTarget) != FALSE & GetRacialType(oTarget) != RACIAL_TYPE_UNDEAD)

{

ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink1, oTarget, 0.5f);

oTarget = GetNextObjectInShape(SHAPE_SPHERE, 3.0f, lSelf, TRUE, OBJECT_TYPE_CREATURE);

if (oTarget != OBJECT_INVALID & nDuration > 0)

{

oTarget = GetFirstObjectInShape(SHAPE_SPHERE, 3.0f, lSelf, TRUE, OBJECT_TYPE_CREATURE);  /// если перебрал всех существ в радиусе, начинай сначала

}

if (GetIsEffectValid(eLink5) = FALSE) /// если аура уже не излучается

break;

}

}




Другое заклинание - ESP (Чтение мыслей). Здесь несколько скриптов-добавлений к скриптам. Тоже прошу указать на ошибки или протестировать.

Neverwinter Script
/// Заклинание "Чтение мыслей" (Divination, Enchantment). 2 уровень. Время сотворения 5. Добавление к OnAreaTransitionClick модуля или шарда. Удаляет переменную ESP, стоит персонажу покинуть зону.


void CancelESP()


{

object oLeaving = GetClickingObject();


if (GetIsPC(oLeaving) = TRUE)

{

DeleteLocalString(oLeaving, "ESP"); /// отдельной функцией, чтобы несуществующий string не мешал выполнению остальной части скрипта ухода
}
}


Neverwinter Script
/// Заклинание "Чтение мыслей" (Divination, Enchantment). 2 уровень. Время сотворения 5. Добавление к OnConversation модуля или шарда (или, возможно, к OnUserDefined). Используя GetLastSpeaker, записывает и передает все, что говорит заколдованный персонаж, покуда он не покинет зону.


void main()

{

object oSpyOn = GetLastSpeaker();

object oListener = GetFirstPC();

int nESPPattern = GetListenPatternNumber();

string sListener = GetLocalString(oSpyOn, "ESP");

string sspyOn = GetName(oSpyOn);



while (sListener != "" && oListener != OBJECT_INVALID && GetName(oListener) != sListener)



{

oListener = GetNextPC();

}


if (oListener != OBJECT_INVALID)


{


if (nESPPattern = 1)


{

string sAha = "~" + GetStringLowerCase(GetMatchedSubstring(0)) + "~"; /// записываем каждое слово

FloatingTextStringOnCreature(oListener, sAha, FALSE); /// и передаем его кому следует

}

}

}




Neverwinter Script
/// Заклинание "Чтение мыслей" (Divination, Enchantment). 2 уровень. Время сотворения 5. Основной скрипт.

void main()

{

object oSpyOn = GetSpellTargetObject();

string sPattern = "**";

int nListenPatternNum = 1; /// желательно сделать struct с индексами всех схем для ListenPattern

int nDuration = GetCasterLevel() * 60; /// длится минуту за уровень мага

effect eEffect = SupernaturalEffect(EffectParalyze());


SignalEvent(OBJECT_SELF, EventSpellCastAt(oSpyOn, SPELL_ESP, FALSE)); /// не вредное заклинание, может быть полезно и внутри компаний


if (GetMetaMagicFeat() = METAMAGIC_EXTEND)


{

nDuration * 2;

}



if (GetLocalString(oSpyOn, "ESP") != "" && sListener != GetName(OBJECT_SELF)) /// если кто-то уже слушает...


{


string sFormer = GetLocalString(oSpyOn, "ESP"); /// ...то устраиваем единоборство...

object oFormer = GetFirstPC();


while (oFormer != OBJECT_INVALID && GetName(oFormer) != sFormer)


{

oFormer = GetNextPC();

}


SetListening(oSpyOn, FALSE));

ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEffect, OBJECT_SELF, 11.0f);

ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEffect, oFormer, 11.0f);

FloatingTextStringOnCreature(OBJECT_SELF, "Вы обнаруживаете в разуме этого человека другого наблюдателя!", FALSE);

DelayCommand(1.0, FloatingTextStringOnCreature(OBJECT_SELF, "Напрягшись, пытаетесь вытеснить чужака...", FALSE));

DelayCommand(2.3, FloatingTextStringOnCreature(OBJECT_SELF, "...Ваши мышцы скрутились в узлы, пот сочится по лбу...", FALSE));

DelayCommand(6.0, FloatingTextStringOnCreature(OBJECT_SELF, "...Не в состоянии шевельнуть и пальцем, вы превратились в чистое ментальное усилие", FALSE));

string sWho = sSpyOn? + " ...Нет. Творится что-то неладное.";

FloatingTextStringOnCreature(oFormer, sWho, FALSE);

DelayCommand(1.0, FloatingTextStringOnCreature(oFormer, "Кто-то другой внедрился в это сознание и пытается выбросить вас!", FALSE));

DelayCommand(2.3, FloatingTextStringOnCreature(oFormer, "Сцепив зубы, вы вступаете на мысленную арену...", FALSE));

DelayCommand(6.0, FloatingTextStringOnCreature(oFormer, "Невидимая борьба умов высекает огромные, как звезды, искры у вас за переносицей...", FALSE));



float fOwnPower = GetHitDice(OBJECT_SELF);

float fTheirPower = GetHitDice(oListener);

float fSuperiority = fabs(fOwnPower - fTheirPower);

int nSuperiority = FloatToInt(fSuperiority);


if (fOwnPower => fTheirPower) /// ...в котором побеждает чаще всего сильнейший


{


if (d100() > nSuperiority * 10)

{


DelayCommand(10.0, FloatingTextStringOnCreature(oFormer, "Трах! Телепатическую связь уводят у вас из-под носа!", TRUE)); /// переключаем канал на себя и даем знать ему и всей его шатии - ради интриги

DelayCommand(10.0, FloatingTextStringOnCreature(OBJECT_SELF, "Прикрыв глаза, вы вплываете в чужой разум", FALSE));

DelayCommand(10.0, GiveXP(OBJECT_SELF, (10 - nSuperiority) * 20)); /// небольшая награда активно нападающему, но не защищавшемуся

SetListenPattern(oSpyOn, sPattern, 1);

DelayCommand(11.0, SetListening(oSpyOn, TRUE));

DelayCommand(11.0, SetLocalString(oSpyOn, "ESP", GetName(OBJECT_SELF)));

DelayCommand(nDuration, DeleteLocalString(oSpyOn, "ESP"));

DelayCommand(nDuration, SetListening(oSpyOn, FALSE));


}


else


{

sWho = "Есть! Усилием воли вы изгоняете нахала. Это был кто-то по имени " + GetName(OBJECT_SELF) + ".";

DelayCommand(11.0, FloatingTextStringOnCreature(oFormer, sWho, FALSE));

DelayCommand(10.0, FloatingTextStringOnCreature(OBJECT_SELF, "...Но тот, другой, слишком силен.", FALSE));

sWho = "Вы отступаете, узнав имя соперника -" + sFormer + ".";

DelayCommand(11.0, FloatingTextStringOnCreature(OBJECT_SELF, sWho, FALSE));

DelayCommand(10.0, FloatingTextStringOnCreature(oSpyOn, "У вас путаются мысли.", FALSE);

DelayCommand(12.0, SetListening(oSpyOn, TRUE));

DelayCommand(nDuration, DeleteLocalString(oSpyOn, "ESP"));

DelayCommand(nDuration, SetListening(oSpyOn, FALSE));


}

}


else if (d100() > nSuperiority * 10)



{

sWho = "Есть! Усилием воли вы изгоняете нахала. Это был кто-то по имени " + GetName(OBJECT_SELF) + ".";

DelayCommand(11.0, FloatingTextStringOnCreature(oFormer, sWho, FALSE));

DelayCommand(10.0, FloatingTextStringOnCreature(OBJECT_SELF, "...Но тот, другой, слишком силен.", FALSE));

sWho = "Вы отступаете, узнав имя соперника -" + sFormer + ".";

DelayCommand(11.0, FloatingTextStringOnCreature(OBJECT_SELF, sWho, FALSE));

DelayCommand(10.0, FloatingTextStringOnCreature(oSpyOn, "У вас путаются мысли.", FALSE);

DelayCommand(12.0, SetListening(oSpyOn, TRUE));

DelayCommand(nDuration, DeleteLocalString(oSpyOn, "ESP"));

DelayCommand(nDuration, SetListening(oSpyOn, FALSE));

}


else


{

DelayCommand(10.0, FloatingTextStringOnCreature(oFormer, "Трах! Телепатическую связь уводят у вас из-под носа!", TRUE)); /// переключаем канал на себя и даем знать ему и всей его шатии - ради интриги

DelayCommand(10.0, FloatingTextStringOnCreature(OBJECT_SELF, "Прикрыв глаза, вы вплываете в чужой разум", FALSE));

DelayCommand(10.0, GiveXP(OBJECT_SELF, (10 - nSuperiority) * 20)); /// небольшая награда активно нападающему, но не защищавшемуся

SetListenPattern(oSpyOn, sPattern, 1);

DelayCommand(11.0, SetListening(oSpyOn, TRUE));

DelayCommand(11.0, SetLocalString(oSpyOn, "ESP", GetName(OBJECT_SELF)));

DelayCommand(nDuration, DeleteLocalString(oSpyOn, "ESP"));

DelayCommand(nDuration, SetListening(oSpyOn, FALSE));


}

}


else


{

DelayCommand(10.0, FloatingTextStringOnCreature(OBJECT_SELF, "Прикрыв глаза, вы вплываете в чужой разум", FALSE));

SetListenPattern(oSpyOn, sPattern, 1);

SetListening(oSpyOn, TRUE);

SetLocalString(oSpyOn, "ESP", GetName(OBJECT_SELF));

DelayCommand(nDuration, DeleteLocalString(oSpyOn, "ESP"));

DelayCommand(nDuration, SetListening(oSpyOn, FALSE));

}

}


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