![]() |
Здравствуйте, гость ( Вход | Регистрация )
![]() ![]() |
![]() |
![]()
Сообщение
#1
|
|
Level 19 ![]() Класс: Воин Характер: Lawful Good Раса: Человек NWN: Скриптинг [PW] Gem of the North Край Лесов ![]() |
У нас очень обширно используются посты и маршруты, решил это дело проверить профайлером. Ужаснулся - в первые минуты скрипт срабатывает 70к раз (IMG:style_emoticons/kolobok_light/wacko.gif) Точнее сразу 1.6к и дальше растет. Начал копать скрипты - там скажем так писец:
Neverwinter Script X0_I0_WALKWAY: void WalkWayPoints(int nRun = FALSE, float fPause = 1.0) { ... // Лечение рекурсии что называется серпом по яйцам - сначала 55 раз запустимся, // сделаем проверки, а потом выйдем, ибо нафик не надо было запускаться if (bIsFighting == TRUE || bIsInConversation == TRUE || bMoving == TRUE || bWaiting == TRUE) return; ... object oWay = GetNextWalkWayPoint(OBJECT_SELF); if (GetIsObjectValid(oWay) == TRUE) { ... // Даже если непись стоит на точке, действие в стек добавится. // Не знаю, как влияет на производительность, но лучше проверить расстояние до точки. ActionMoveToObject(oWay, nRun); if(GetLocalInt(oWay,"X2_L_WAYPOINT_SETFACING") == 1) { // Аналогично ActionDoCommand(SetFacing(GetFacing(oWay))); } // А вот и корень зла (IMG:style_emoticons/kolobok_light/smile.gif) Рекурсия с шагом 1 сек на всех неписях с точками. Сама функция еще // запускается из хертбита. Получается ужасный хаос с кучей ненужных срабатываний, // которые хоть и отрезаются в начале, но ресурсы кушают неслабо ActionWait(fPause); ActionDoCommand(WalkWayPoints(nRun,fPause)); ... } ... } У всех по-разному конечно получится с цифрами, зависит от кол-во неписей с точками, но самыми банальными проверками (описанные тут + проверка в хб на присутствие игрока вблизи) и отключением рекурсии мне удалось снизить кол-во запусков раз в 100 кажется (IMG:style_emoticons/kolobok_light/smile.gif) Причем цифра перестала расти со временем в геометрической прогрессии. Минус - неписи чуть тормозят - после прерывания возобновляют ходьбу не сразу, а через 1-6 секунд (запуск только в хб остался). |
![]()
Сообщение
#2
|
|
Level 9 ![]() Класс: Обыватель Характер: Lawful Good Раса: Человек NWN: Модмейкер Рыцарская Сага ![]() |
У нас очень обширно используются посты и маршруты, решил это дело проверить профайлером. Ужаснулся - в первые минуты скрипт срабатывает 70к раз Точнее сразу 1.6к и дальше растет. Начал копать скрипты - там скажем так писец: У нас тоже стал тормозить модуль от ХБ с этой «левой» функцией WalkWayPoints. Это произошло от большого объема модуля и НПС с точками ходьбы. Отключение ХБ, когда нет в локе героя привело к потере ориентировки НПС и он стал бродить не по маршруту… К тому же базовая атака НПС глюченная и не пашет с ХБ… Пришлось полностью переписать функцию WalkWayPoints, и оставить ее так же только на ХБ скрипте. В инклюд вошло всего три функции: ходьба по точкам, посты (дневные и ночные), атака НПС. P.S. если кому интересно могу выложить скрипты… (IMG:style_emoticons/kolobok_light/wink3.gif) |
![]()
Сообщение
#3
|
|
Level 3 ![]() Класс: Монах Характер: Lawful Good Раса: Эльф ![]() |
Выложи если нетрудно,с пояснениями где на что заменять.
Сообщение отредактировал Sugo77 - May 10 2008, 12:11 |
![]()
Сообщение
#4
|
|
Level 9 ![]() Класс: Обыватель Характер: Lawful Good Раса: Человек NWN: Модмейкер Рыцарская Сага ![]() |
ОК!
Для полной замены базового WalkWayPoints, нужно сделать: 1. Меняем скрипт прерывания и окончания диалога nw_walk_wp 2. Переписываем скрипт спавна nw_c2_default9 3. Переписываем скрипт OnPerception монстров NW_C2_DEFAULT2 4. Пишем новый скрипт для ХБ монстров nw_c2_default1 5. Ну и сама новая функция ходьбы в инклюде gg_walkway Перенастройка модуля никакая не потребуется… НПС ходят по стандартным точкам ходьбы сделанным ранее редактором. Единственное отличие точки поста, я заменил на свои: Тег НПС+_POST Стоит т.ж. учитывать локалку на НПС "WPOIN_GO", если нужно для сценок и быстрого старта функции ходьбы, то ее нужно обнулять… Но это не критично, т.к. когда герой покинет область НПС, то автоматом обнулится и эта локалка. Вот и все (IMG:style_emoticons/kolobok_light/smile.gif) скрипт прерывания и окончания диалога nw_walk_wp Neverwinter Script //::////////////////////////////////////////////////// //:: Created By: Gennady nw_walk_wp //::////////////////////////////////////////////////// void main() { SetLocalInt(GetFirstPC(), "ConversationState", 0); SetLocalInt(OBJECT_SELF,"WPOIN_GO",0); SetCutsceneMode(GetFirstPC(), FALSE); SetImmortal(GetFirstPC(), FALSE); SetPlotFlag(GetFirstPC(), FALSE); } скрипт спавна nw_c2_default9 Тут пробита выдача золота и зелья. но это уж дело вкуса, сами пишите кому чего нужно… Neverwinter Script //::////////////////////////////////////////////////// //:: Created By: Gennady nw_c2_default9 //::////////////////////////////////////////////////// // Дать золото // object oTarget - Кому даем // int nMnGold - множитель *(случайность от 1 до 10) void CreateGold(object oTarget, int nMnGold); // Дать зелье // object oTarget - Кому даем void CreateZel(object oTarget); //////////////////////////////////////////////////////////////////////////////// //________________ Дать золото _________________________________________________ void CreateGold(object oTarget, int nMnGold) { int nGold = Random(10)+1; nGold = nMnGold*nGold; CreateItemOnObject("nw_it_gold001", oTarget, nGold); } //_________ Дать зелье __________ void CreateZel(object oTarget) { int nRandom = Random(32) + 1; string sItem; switch (nRandom) { case 1: sItem = "nw_it_mpotion022"; break; case 2: sItem = "nw_it_mpotion023"; break; case 3: sItem = "nw_it_mpotion021"; break; case 4: sItem = "nw_it_mpotion001"; break; case 5: sItem = "nw_it_mpotion020"; break; case 6: sItem = "nw_it_medkit001"; break; case 7: sItem = "nw_it_medkit002"; break; case 8: sItem = "nw_it_mpotion009"; break; case 9: sItem = "nw_it_mpotion010"; break; case 10: sItem = "nw_it_mpotion013"; break; case 11: sItem = "nw_it_mpotion014"; break; case 12: sItem = "nw_it_mpotion019"; break; case 13: sItem = "nw_it_mpotion005"; break; case 14: sItem = "nw_it_mpotion020"; break; case 15: sItem = "nw_it_mpotion022"; break; case 16: sItem = "nw_it_mpotion023"; break; case 17: sItem = "nw_it_mpotion021"; break; case 18: sItem = "nw_it_mpotion001"; break; case 19: sItem = "nw_it_mpotion020"; break; case 20: sItem = "nw_it_medkit001"; break; case 21: sItem = "nw_it_medkit002"; break; case 22: sItem = "nw_it_mpotion009"; break; case 23: sItem = "nw_it_mpotion003"; break; case 24: sItem = "nw_it_mpotion002"; break; case 25: sItem = "nw_it_mpotion011"; break; case 26: sItem = "nw_it_mpotion018"; break; case 27: sItem = "nw_it_mpotion016"; break; case 28: sItem = "nw_it_mpotion006"; break; case 29: sItem = "nw_it_mpotion015"; break; case 30: sItem = "nw_it_mpotion004"; break; case 31: sItem = "nw_it_mpotion017"; break; case 32: sItem = "nw_it_mpotion007"; break; } CreateItemOnObject(sItem, oTarget, 1); } //////////////////////////////////////////////////////////////////////////////// void main() { object oSelf = OBJECT_SELF ; int nRaType = GetRacialType(oSelf); if(nRaType == RACIAL_TYPE_UNDEAD || nRaType == RACIAL_TYPE_ANIMAL || nRaType == RACIAL_TYPE_VERMIN) return; // Нежить, животное, паразит. if(GetLevelByClass(CLASS_TYPE_COMMONER, oSelf) >= 1) // Простолюдин CreateGold(oSelf, 10); if (d10() > 5) return; if(d10() > 7) CreateZel(oSelf); if(d10() > 5) CreateGold(oSelf, 3); } скрипт OnPerception монстров NW_C2_DEFAULT2 Neverwinter Script //::////////////////////////////////////////////////// //:: NW_C2_DEFAULT2 /* Default OnPerception event handler for NPCs. Handles behavior when perceiving a creature for the first time. */ //::////////////////////////////////////////////////// //:: Created By: Gennady //:: Created On: 3.11.2006 #include "nw_i0_generic" void main() { // * if not runnning normal or better Ai then exit for performance reasons // * if not runnning normal or better Ai then exit for performance reasons if (GetAILevel() == AI_LEVEL_VERY_LOW) return; object oPercep = GetLastPerceived(); int bSeen = GetLastPerceptionSeen(); // This will cause the NPC to speak their one-liner // conversation on perception even if they are already // in combat. if(GetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVER SATION) && GetIsPC(oPercep) && bSeen) { SpeakOneLinerConversation(); } // March 5 2003 Brent // Had to add this section back in, since modifications were not taking this specific // example into account -- it made invisibility basically useless. //If the last perception event was hearing based or if someone vanished then go to search mode if ((GetLastPerceptionVanished()) && GetIsEnemy(GetLastPerceived())) { object oGone = GetLastPerceived(); if((GetAttemptedAttackTarget() == GetLastPerceived() || GetAttemptedSpellTarget() == GetLastPerceived() || GetAttackTarget() == GetLastPerceived()) && GetArea(GetLastPerceived()) != GetArea(OBJECT_SELF)) { //SpeakString("dude...like disappeared."); ClearAllActions(); DetermineCombatRound(); } } // This section has been heavily revised while keeping the // pre-existing behavior: // - If we're in combat, keep fighting. // - If not and we've perceived an enemy, start to fight. // Even if the perception event was a 'vanish', that's // still what we do anyway, since that will keep us // fighting any visible targets. // - If we're not in combat and haven't perceived an enemy, // see if the perception target is a PC and if we should // speak our attention-getting one-liner. if (GetIsFighting(OBJECT_SELF)) { // don't do anything else, we're busy MyPrintString("GetIsFighting: TRUE"); } // * BK FEB 2003 Only fight if you can see them. DO NOT RELY ON HEARING FOR ENEMY DETECTION else if (GetIsEnemy(oPercep) && bSeen) { MyPrintString("GetIsEnemy: TRUE"); // We spotted an enemy and we're not already fighting if(!GetHasEffect(EFFECT_TYPE_SLEEP)) { if(GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL)) { MyPrintString("DetermineSpecialBehavior"); DetermineSpecialBehavior(); } else { MyPrintString("DetermineCombatRound"); SetFacingPoint(GetPosition(oPercep)); SpeakString("NW_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK); DetermineCombatRound(); } } } else { if (bSeen) { MyPrintString("GetLastPerceptionSeen: TRUE"); if(GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL)) { DetermineSpecialBehavior(); } else if (GetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION) && GetIsPC(oPercep)) { // The NPC will speak their one-liner conversation // This should probably be: // SpeakOneLinerConversation(oPercep); // instead, but leaving it as is for now. ActionStartConversation(OBJECT_SELF); } } // activate ambient animations or walk waypoints if appropriate if (!IsInConversation(OBJECT_SELF)) { if (GetIsPC(oPercep) && (GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS) || GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS_AVI AN) || GetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMA TIONS) || GetIsEncounterCreature())) { SetAnimationCondition(NW_ANIM_FLAG_IS_ACTIVE); } } } // Send the user-defined event if appropriate if(GetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT) && GetLastPerceptionSeen()) { SignalEvent(OBJECT_SELF, EventUserDefined(EVENT_PERCEIVE)); } } скрипт ХБ монстров nw_c2_default1 Neverwinter Script //::////////////////////////////////////////////////// //:: Created By: Gennady nw_c2_default1 //::////////////////////////////////////////////////// #include "gg_walkway" void main() { object oSelf = OBJECT_SELF; if(GetArea(GetFirstPC()) != GetArea(oSelf)) // если ПС нет в локе { AssignCommand(oSelf, ClearAllActions(TRUE)); SetLocalInt(oSelf,"WPOIN_GO",0); return; } if (GetIsInCombat(oSelf)) {SetLocalInt(oSelf,"WPOIN_GO",0); return;} if (IsInConversation(oSelf)) {SetLocalInt(oSelf,"WPOIN_GO",0); return;} WayPOST(); //ДЛЯ ПОСТОВОГО WalkWayPoints(); // ДЛЯ ХОДЬБЫ ПО ТОЧКАМ ActAttackNPC(); // Атака врага if (GetLocalInt(oSelf, "FLAG_HEARTBEAT") == 1) SignalEvent(oSelf, EventUserDefined(EVENT_HEARTBEAT)); } инклюда ходьбы gg_walkway Neverwinter Script //::////////////////////////////////////////////////// //:: #include "gg_walkway" //:: Created By: Gennady //:: Created On: 3.11.2006 //::////////////////////////////////////////////////// // Атака врага, если герой в радиусе 15 метров void ActAttackNPC(object oSelf = OBJECT_SELF); //ДЛЯ ПОСТОВОГО // Вернет на точку поста, повернет в сторону вектора точки // Точка поста равна тэгу ПС +"_POST" // Должна быть более 2 метров от ближайшей точки ходьбы // Если интеллект выше 20, и есть точки ходьбы - ночью ходит, днем пост void WayPOST(object oSelf = OBJECT_SELF); // ДЛЯ ХОДЬБЫ ПО ТОЧКАМ расположенным в этой области void WalkWayPoints(object oSelf = OBJECT_SELF); ///////////////////////////////////////////////////////////////////////////// // Атака врага, если герой в радиусе 15 метров ///////////////////////////// void ActAttackNPC(object oSelf = OBJECT_SELF) { object oVrag = GetFirstObjectInShape(SHAPE_SPHERE, 15.0, GetLocation(oSelf), TRUE, OBJECT_TYPE_CREATURE); if (GetDistanceBetween(GetFirstPC(), oSelf) < 15.0) { while (GetIsObjectValid(oVrag))// Проверить враждебного ПС в радиусе 15 метров { if (GetObjectSeen(oVrag, oSelf) && GetIsEnemy(oVrag, oSelf)) { AssignCommand(oSelf, ClearAllActions(TRUE)); AssignCommand(oSelf, ActionAttack(oVrag)); return; } oVrag = GetNextObjectInShape(SHAPE_SPHERE, 15.0, GetLocation(oSelf), TRUE, OBJECT_TYPE_CREATURE); } } } /////////////// ДЛЯ ПОСТОВОГО ////////////////////////////////////////// void WayPOST(object oSelf = OBJECT_SELF) { object oWayPOST = GetNearestObjectByTag(GetTag(oSelf)+"_POST"); if (GetIsObjectValid(oWayPOST)) { if (GetAbilityScore(oSelf, ABILITY_INTELLIGENCE) > 20) { if (GetIsNight()) { if (GetDistanceBetween(oWayPOST, oSelf) < 1.0) SetLocalInt(oSelf,"WPOIN_GO",0); WalkWayPoints(oSelf); return; } else SetLocalInt(oSelf,"WPOIN_GO",1); } float fFacing = GetFacing(oWayPOST); ClearAllActions(); ActionForceMoveToObject(oWayPOST, FALSE, 0.0, 30.0); ActionDoCommand(DelayCommand(0.3, SetFacing(fFacing))); } } // ДЛЯ ХОДЬБЫ ПО ТОЧКАМ расположенным в этой области ////////////////////// void WalkWayPoints(object oSelf = OBJECT_SELF) { if (GetLocalInt(oSelf, "WPOIN_GO") == 1) return; object oWay = GetNearestObjectByTag("WP_"+GetTag(oSelf)+"_01"); int i =1; int iNPoint; string sPoint; if (GetIsObjectValid(oWay)) { ClearAllActions(); SetLocalInt(oSelf,"WPOIN_GO",1); } else return; oWay = GetNearestObject(OBJECT_TYPE_WAYPOINT, oSelf,i); while (GetIsObjectValid(oWay))// Цикл определить ближайшую точку { i++; string sTag = GetTag(oWay); // Тэг точки без 3 последних букв string sTreb = GetStringLeft(sTag, GetStringLength(sTag)-3); if("WP_"+GetTag(oSelf) == sTreb) { iNPoint = StringToInt(GetStringRight(sTag, 2)); if (iNPoint == 0) iNPoint = StringToInt(GetStringRight(sTag, 1)); break ; } oWay = GetNearestObject(OBJECT_TYPE_WAYPOINT, oSelf,i); } if (iNPoint < 10) sPoint = "0" + IntToString(iNPoint); else sPoint = IntToString(iNPoint); // Определили ближайшую точку oWay = GetNearestObjectByTag("WP_"+GetTag(oSelf)+"_"+sPoint); while (GetIsObjectValid(oWay)) // Цикл на возрастание точек { ActionForceMoveToObject(oWay, FALSE, 0.0, 30.0); iNPoint++; if (iNPoint < 10) sPoint = "0" + IntToString(iNPoint); else sPoint = IntToString(iNPoint); oWay = GetNearestObjectByTag("WP_"+GetTag(oSelf)+"_"+sPoint); } iNPoint = iNPoint-1; if (iNPoint < 10) sPoint = "0" + IntToString(iNPoint); else sPoint = IntToString(iNPoint); oWay = GetNearestObjectByTag("WP_"+GetTag(oSelf)+"_"+sPoint); while (GetIsObjectValid(oWay)) // Цикл на убывание точек { ActionForceMoveToObject(oWay, FALSE, 0.0, 30.0); iNPoint--; if (iNPoint < 10) sPoint = "0" + IntToString(iNPoint); else sPoint = IntToString(iNPoint); oWay = GetNearestObjectByTag("WP_"+GetTag(oSelf)+"_"+sPoint); } ActionDoCommand(SetLocalInt(oSelf,"WPOIN_GO",0)); } P.S. Скрипты все проверены и работают уже в моем моде 2 года, нареканий у меня к ним пока нет… (IMG:style_emoticons/kolobok_light/biggrin.gif) Сообщение отредактировал gennady - May 10 2008, 16:00 |
![]()
Сообщение
#5
|
|
Level 3 ![]() Класс: Монах Характер: Lawful Good Раса: Эльф ![]() |
О Боже лучше я повременю с такими глобальными переменами в модуле.
|
![]()
Сообщение
#6
|
|
Level 9 ![]() Класс: Обыватель Характер: Lawful Good Раса: Человек NWN: Модмейкер Рыцарская Сага ![]() |
Не боись! Вернуть все в исходное положение будет просто! Достаточно выкинуть эти 5 скриптов из модуля и это вернет модуль к базовым скриптам.
|
![]()
Сообщение
#7
|
|
Level 19 ![]() Класс: Воин Характер: Lawful Good Раса: Человек NWN: Скриптинг [PW] Gem of the North Край Лесов ![]() |
Ну думаю следует заметить 2 вещи:
1) это чисто сингловый набор, причем даже при прохождении мода по сетке скрипт будет работать не так, как ожидается 2) в стандартных скриптах на спавн происходит инициализация и дальше непись ходит по уже известным точкам в строгой последовательности. Этот же вариант каждый раз после сброса берет ближайшую точку, ведет к ней и потом номер увеличивает. В принципе это в глаза не бросается, но косяк есть, даже два. Во-первых, после диалога непись может делать пару шагов назад (если точки стоят далеко друг от друга, то может и не пару), а потом идти вперед. Во-вторых, происходит сброс направления. Т.е. непись прошел все точки по возрастанию, по убыванию половину, с ним поговорили, и он опять пойдет по возрастанию. |
![]()
Сообщение
#8
|
|
Level 9 ![]() Класс: Обыватель Характер: Lawful Good Раса: Человек NWN: Модмейкер Рыцарская Сага ![]() |
Цитата 1) это чисто сингловый набор И я этого не скрывал! (IMG:style_emoticons/kolobok_light/smile.gif) Хотя достаточно в скрипте ХБ пробить героя (т.е. заменить GetFirstPC()) на то что нужно для шарда… Остальное все пробито на OBJECT_SELF. Цитата 2) но косяк есть, даже два. Во-первых, после диалога непись может делать пару шагов назад (если точки стоят далеко друг от друга, то может и не пару), а потом идти вперед. Во-вторых, происходит сброс направления. Я бы сказал, что это не косяки, а БОЛЬШИЕ ПЛЮСЫ! НПС и базовой функции может вернуться назад, а потом двигать вперед, все зависит от фазы прерывания. А с направлением движения, после прерывания, в базовом варианте вообще большие косяки… НПС движется к точке, хоть и соответствующей его былому движению, но +1. И если маршрут ломанный, и к тому же блокируется объектами, НПС может просто на полминуты воткнуться в стену, или пойти по совсем ему не свойственной траектории… Это что лучше? Я же просто хочу еще отметить пару нюансов по своей функции. 1. Обязательно должна быть первая точка маршрута. 2. Желательно не ставить рядом начальную и конечную точку маршрута. Иначе НПС может пойти сперва по убывающим точкам... 3. НПС движется только по точкам своей области. |
![]()
Сообщение
#9
|
|
Level 5 ![]() ![]() Класс: Вор Характер: Neutral Good Раса: Человек ![]() |
ОК! Для полной замены базового WalkWayPoints, нужно сделать: 1. Меняем скрипт прерывания и окончания диалога nw_walk_wp 2. Переписываем скрипт спавна nw_c2_default9 3. Переписываем скрипт OnPerception монстров NW_C2_DEFAULT2 4. Пишем новый скрипт для ХБ монстров nw_c2_default1 5. Ну и сама новая функция ходьбы в инклюде gg_walkway Перенастройка модуля никакая не потребуется… НПС ходят по стандартным точкам ходьбы сделанным ранее редактором. Единственное отличие точки поста, я заменил на свои: Тег НПС+_POST Стоит т.ж. учитывать локалку на НПС "WPOIN_GO", если нужно для сценок и быстрого старта функции ходьбы, то ее нужно обнулять… Но это не критично, т.к. когда герой покинет область НПС, то автоматом обнулится и эта локалка. Вот и все (IMG:style_emoticons/kolobok_light/smile.gif) скрипт прерывания и окончания диалога nw_walk_wp Neverwinter Script //::////////////////////////////////////////////////// //:: Created By: Gennady nw_walk_wp //::////////////////////////////////////////////////// void main() { SetLocalInt(GetFirstPC(), "ConversationState", 0); SetLocalInt(OBJECT_SELF,"WPOIN_GO",0); SetCutsceneMode(GetFirstPC(), FALSE); SetImmortal(GetFirstPC(), FALSE); SetPlotFlag(GetFirstPC(), FALSE); } скрипт спавна nw_c2_default9 Тут пробита выдача золота и зелья. но это уж дело вкуса, сами пишите кому чего нужно… Neverwinter Script //::////////////////////////////////////////////////// //:: Created By: Gennady nw_c2_default9 //::////////////////////////////////////////////////// // Дать золото // object oTarget - Кому даем // int nMnGold - множитель *(случайность от 1 до 10) void CreateGold(object oTarget, int nMnGold); // Дать зелье // object oTarget - Кому даем void CreateZel(object oTarget); //////////////////////////////////////////////////////////////////////////////// //________________ Дать золото _________________________________________________ void CreateGold(object oTarget, int nMnGold) { int nGold = Random(10)+1; nGold = nMnGold*nGold; CreateItemOnObject("nw_it_gold001", oTarget, nGold); } //_________ Дать зелье __________ void CreateZel(object oTarget) { int nRandom = Random(32) + 1; string sItem; switch (nRandom) { case 1: sItem = "nw_it_mpotion022"; break; case 2: sItem = "nw_it_mpotion023"; break; case 3: sItem = "nw_it_mpotion021"; break; case 4: sItem = "nw_it_mpotion001"; break; case 5: sItem = "nw_it_mpotion020"; break; case 6: sItem = "nw_it_medkit001"; break; case 7: sItem = "nw_it_medkit002"; break; case 8: sItem = "nw_it_mpotion009"; break; case 9: sItem = "nw_it_mpotion010"; break; case 10: sItem = "nw_it_mpotion013"; break; case 11: sItem = "nw_it_mpotion014"; break; case 12: sItem = "nw_it_mpotion019"; break; case 13: sItem = "nw_it_mpotion005"; break; case 14: sItem = "nw_it_mpotion020"; break; case 15: sItem = "nw_it_mpotion022"; break; case 16: sItem = "nw_it_mpotion023"; break; case 17: sItem = "nw_it_mpotion021"; break; case 18: sItem = "nw_it_mpotion001"; break; case 19: sItem = "nw_it_mpotion020"; break; case 20: sItem = "nw_it_medkit001"; break; case 21: sItem = "nw_it_medkit002"; break; case 22: sItem = "nw_it_mpotion009"; break; case 23: sItem = "nw_it_mpotion003"; break; case 24: sItem = "nw_it_mpotion002"; break; case 25: sItem = "nw_it_mpotion011"; break; case 26: sItem = "nw_it_mpotion018"; break; case 27: sItem = "nw_it_mpotion016"; break; case 28: sItem = "nw_it_mpotion006"; break; case 29: sItem = "nw_it_mpotion015"; break; case 30: sItem = "nw_it_mpotion004"; break; case 31: sItem = "nw_it_mpotion017"; break; case 32: sItem = "nw_it_mpotion007"; break; } CreateItemOnObject(sItem, oTarget, 1); } //////////////////////////////////////////////////////////////////////////////// void main() { object oSelf = OBJECT_SELF ; int nRaType = GetRacialType(oSelf); if(nRaType == RACIAL_TYPE_UNDEAD || nRaType == RACIAL_TYPE_ANIMAL || nRaType == RACIAL_TYPE_VERMIN) return; // Нежить, животное, паразит. if(GetLevelByClass(CLASS_TYPE_COMMONER, oSelf) >= 1) // Простолюдин CreateGold(oSelf, 10); if (d10() > 5) return; if(d10() > 7) CreateZel(oSelf); if(d10() > 5) CreateGold(oSelf, 3); } скрипт OnPerception монстров NW_C2_DEFAULT2 Neverwinter Script //::////////////////////////////////////////////////// //:: NW_C2_DEFAULT2 /* Default OnPerception event handler for NPCs. Handles behavior when perceiving a creature for the first time. */ //::////////////////////////////////////////////////// //:: Created By: Gennady //:: Created On: 3.11.2006 #include "nw_i0_generic" void main() { // * if not runnning normal or better Ai then exit for performance reasons // * if not runnning normal or better Ai then exit for performance reasons if (GetAILevel() == AI_LEVEL_VERY_LOW) return; object oPercep = GetLastPerceived(); int bSeen = GetLastPerceptionSeen(); // This will cause the NPC to speak their one-liner // conversation on perception even if they are already // in combat. if(GetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVER SATION) && GetIsPC(oPercep) && bSeen) { SpeakOneLinerConversation(); } // March 5 2003 Brent // Had to add this section back in, since modifications were not taking this specific // example into account -- it made invisibility basically useless. //If the last perception event was hearing based or if someone vanished then go to search mode if ((GetLastPerceptionVanished()) && GetIsEnemy(GetLastPerceived())) { object oGone = GetLastPerceived(); if((GetAttemptedAttackTarget() == GetLastPerceived() || GetAttemptedSpellTarget() == GetLastPerceived() || GetAttackTarget() == GetLastPerceived()) && GetArea(GetLastPerceived()) != GetArea(OBJECT_SELF)) { //SpeakString("dude...like disappeared."); ClearAllActions(); DetermineCombatRound(); } } // This section has been heavily revised while keeping the // pre-existing behavior: // - If we're in combat, keep fighting. // - If not and we've perceived an enemy, start to fight. // Even if the perception event was a 'vanish', that's // still what we do anyway, since that will keep us // fighting any visible targets. // - If we're not in combat and haven't perceived an enemy, // see if the perception target is a PC and if we should // speak our attention-getting one-liner. if (GetIsFighting(OBJECT_SELF)) { // don't do anything else, we're busy MyPrintString("GetIsFighting: TRUE"); } // * BK FEB 2003 Only fight if you can see them. DO NOT RELY ON HEARING FOR ENEMY DETECTION else if (GetIsEnemy(oPercep) && bSeen) { MyPrintString("GetIsEnemy: TRUE"); // We spotted an enemy and we're not already fighting if(!GetHasEffect(EFFECT_TYPE_SLEEP)) { if(GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL)) { MyPrintString("DetermineSpecialBehavior"); DetermineSpecialBehavior(); } else { MyPrintString("DetermineCombatRound"); SetFacingPoint(GetPosition(oPercep)); SpeakString("NW_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK); DetermineCombatRound(); } } } else { if (bSeen) { MyPrintString("GetLastPerceptionSeen: TRUE"); if(GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL)) { DetermineSpecialBehavior(); } else if (GetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION) && GetIsPC(oPercep)) { // The NPC will speak their one-liner conversation // This should probably be: // SpeakOneLinerConversation(oPercep); // instead, but leaving it as is for now. ActionStartConversation(OBJECT_SELF); } } // activate ambient animations or walk waypoints if appropriate if (!IsInConversation(OBJECT_SELF)) { if (GetIsPC(oPercep) && (GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS) || GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS_AVI AN) || GetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMA TIONS) || GetIsEncounterCreature())) { SetAnimationCondition(NW_ANIM_FLAG_IS_ACTIVE); } } } // Send the user-defined event if appropriate if(GetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT) && GetLastPerceptionSeen()) { SignalEvent(OBJECT_SELF, EventUserDefined(EVENT_PERCEIVE)); } } скрипт ХБ монстров nw_c2_default1 Neverwinter Script //::////////////////////////////////////////////////// //:: Created By: Gennady nw_c2_default1 //::////////////////////////////////////////////////// #include "gg_walkway" void main() { object oSelf = OBJECT_SELF; if(GetArea(GetFirstPC()) != GetArea(oSelf)) // если ПС нет в локе { AssignCommand(oSelf, ClearAllActions(TRUE)); SetLocalInt(oSelf,"WPOIN_GO",0); return; } if (GetIsInCombat(oSelf)) {SetLocalInt(oSelf,"WPOIN_GO",0); return;} if (IsInConversation(oSelf)) {SetLocalInt(oSelf,"WPOIN_GO",0); return;} WayPOST(); //ДЛЯ ПОСТОВОГО WalkWayPoints(); // ДЛЯ ХОДЬБЫ ПО ТОЧКАМ ActAttackNPC(); // Атака врага if (GetLocalInt(oSelf, "FLAG_HEARTBEAT") == 1) SignalEvent(oSelf, EventUserDefined(EVENT_HEARTBEAT)); } инклюда ходьбы gg_walkway Neverwinter Script //::////////////////////////////////////////////////// //:: #include "gg_walkway" //:: Created By: Gennady //:: Created On: 3.11.2006 //::////////////////////////////////////////////////// // Атака врага, если герой в радиусе 15 метров void ActAttackNPC(object oSelf = OBJECT_SELF); //ДЛЯ ПОСТОВОГО // Вернет на точку поста, повернет в сторону вектора точки // Точка поста равна тэгу ПС +"_POST" // Должна быть более 2 метров от ближайшей точки ходьбы // Если интеллект выше 20, и есть точки ходьбы - ночью ходит, днем пост void WayPOST(object oSelf = OBJECT_SELF); // ДЛЯ ХОДЬБЫ ПО ТОЧКАМ расположенным в этой области void WalkWayPoints(object oSelf = OBJECT_SELF); ///////////////////////////////////////////////////////////////////////////// // Атака врага, если герой в радиусе 15 метров ///////////////////////////// void ActAttackNPC(object oSelf = OBJECT_SELF) { object oVrag = GetFirstObjectInShape(SHAPE_SPHERE, 15.0, GetLocation(oSelf), TRUE, OBJECT_TYPE_CREATURE); if (GetDistanceBetween(GetFirstPC(), oSelf) < 15.0) { while (GetIsObjectValid(oVrag))// Проверить враждебного ПС в радиусе 15 метров { if (GetObjectSeen(oVrag, oSelf) && GetIsEnemy(oVrag, oSelf)) { AssignCommand(oSelf, ClearAllActions(TRUE)); AssignCommand(oSelf, ActionAttack(oVrag)); return; } oVrag = GetNextObjectInShape(SHAPE_SPHERE, 15.0, GetLocation(oSelf), TRUE, OBJECT_TYPE_CREATURE); } } } /////////////// ДЛЯ ПОСТОВОГО ////////////////////////////////////////// void WayPOST(object oSelf = OBJECT_SELF) { object oWayPOST = GetNearestObjectByTag(GetTag(oSelf)+"_POST"); if (GetIsObjectValid(oWayPOST)) { if (GetAbilityScore(oSelf, ABILITY_INTELLIGENCE) > 20) { if (GetIsNight()) { if (GetDistanceBetween(oWayPOST, oSelf) < 1.0) SetLocalInt(oSelf,"WPOIN_GO",0); WalkWayPoints(oSelf); return; } else SetLocalInt(oSelf,"WPOIN_GO",1); } float fFacing = GetFacing(oWayPOST); ClearAllActions(); ActionForceMoveToObject(oWayPOST, FALSE, 0.0, 30.0); ActionDoCommand(DelayCommand(0.3, SetFacing(fFacing))); } } // ДЛЯ ХОДЬБЫ ПО ТОЧКАМ расположенным в этой области ////////////////////// void WalkWayPoints(object oSelf = OBJECT_SELF) { if (GetLocalInt(oSelf, "WPOIN_GO") == 1) return; object oWay = GetNearestObjectByTag("WP_"+GetTag(oSelf)+"_01"); int i =1; int iNPoint; string sPoint; if (GetIsObjectValid(oWay)) { ClearAllActions(); SetLocalInt(oSelf,"WPOIN_GO",1); } else return; oWay = GetNearestObject(OBJECT_TYPE_WAYPOINT, oSelf,i); while (GetIsObjectValid(oWay))// Цикл определить ближайшую точку { i++; string sTag = GetTag(oWay); // Тэг точки без 3 последних букв string sTreb = GetStringLeft(sTag, GetStringLength(sTag)-3); if("WP_"+GetTag(oSelf) == sTreb) { iNPoint = StringToInt(GetStringRight(sTag, 2)); if (iNPoint == 0) iNPoint = StringToInt(GetStringRight(sTag, 1)); break ; } oWay = GetNearestObject(OBJECT_TYPE_WAYPOINT, oSelf,i); } if (iNPoint < 10) sPoint = "0" + IntToString(iNPoint); else sPoint = IntToString(iNPoint); // Определили ближайшую точку oWay = GetNearestObjectByTag("WP_"+GetTag(oSelf)+"_"+sPoint); while (GetIsObjectValid(oWay)) // Цикл на возрастание точек { ActionForceMoveToObject(oWay, FALSE, 0.0, 30.0); iNPoint++; if (iNPoint < 10) sPoint = "0" + IntToString(iNPoint); else sPoint = IntToString(iNPoint); oWay = GetNearestObjectByTag("WP_"+GetTag(oSelf)+"_"+sPoint); } iNPoint = iNPoint-1; if (iNPoint < 10) sPoint = "0" + IntToString(iNPoint); else sPoint = IntToString(iNPoint); oWay = GetNearestObjectByTag("WP_"+GetTag(oSelf)+"_"+sPoint); while (GetIsObjectValid(oWay)) // Цикл на убывание точек { ActionForceMoveToObject(oWay, FALSE, 0.0, 30.0); iNPoint--; if (iNPoint < 10) sPoint = "0" + IntToString(iNPoint); else sPoint = IntToString(iNPoint); oWay = GetNearestObjectByTag("WP_"+GetTag(oSelf)+"_"+sPoint); } ActionDoCommand(SetLocalInt(oSelf,"WPOIN_GO",0)); } P.S. Скрипты все проверены и работают уже в моем моде 2 года, нареканий у меня к ним пока нет… (IMG:style_emoticons/kolobok_light/biggrin.gif) Он говорит "Нет главной функции" в инклюде gg_walkway |
![]()
Сообщение
#10
|
|
Level 11 ![]() Класс: Волшебник Характер: Lawful Evil Раса: Эльф NWN: Скриптинг [PW] Gem of the North ![]() |
Странно было бы, если бы она там была (IMG:style_emoticons/kolobok_light/rolleyes.gif)
|
![]()
Сообщение
#11
|
|
Level 6 ![]() ![]() Класс: Маг Характер: Lawful Evil Раса: Нежить ![]() |
Цитата Он говорит "Нет главной функции" в инклюде gg_walkway Скрипты в НВНе собираются либо как действия, либо как условия. В первом случае в них должна присутствовать ф-я main() (та самая "главная функция), во втором случаей StartingConditional(), иначе они не скомпилируются. Функционал инклюдов пишется в файлы скриптов, из которых эти инклюды вызываются. Сам файл инклюда не компилируется, поэтому на эту ошибку можно внимания не обращать. Некоторые скриптеры по заданной программистами Биоваров манере еще оставляют в конце файла закомментированный main() - это удобно, чтобы проверять работоспособность функций инклюда прямо на месте, надо просто раскомментировать ее во время работы над кодом, а на конечном этапе, когда все готово - закомментировать обратно. |
![]() ![]() |
Текстовая версия | Сейчас: 26th April 2025 - 18:18 |