![]() |
Здравствуйте, гость ( Вход | Регистрация )
![]() ![]() |
![]() |
![]()
Сообщение
#91
|
|
Level 8 ![]() Класс: Некромант Характер: Chaotic Evil Раса: Дракон NWN: Скриптинг [PW] ![]() |
Не знаю, было или нет... Раскидывание заходящих игроков по точкам (например для автоматического раскидывания игроков по камерам в тюрьме)
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 Думаю остальное все ясно (IMG:style_emoticons/kolobok_light/smile.gif) Сообщение отредактировал kreon - May 10 2006, 22:18 |
![]()
Сообщение
#92
|
|
Level 12 ![]() Класс: Оборотень Характер: Chaotic Neutral Раса: Нежить NWN: Скриптинг [Sn] ![]() |
Функция, определяющая лучшее оружие ближнего боя для указаного персонажа. Учитываются не только фокусы, если они есть (им отдается преимущество), но и специализации. Упор на схему щит+меч. Впрочем нисколько не претендую на полноту, тем более нет учета фита "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; } |
![]()
Сообщение
#93
|
|
Level 4 ![]() ![]() Класс: Некромант Характер: Chaotic Evil Раса: Нежить ![]() |
Не знаю было, нет что то подобное.
Скрипт, после смерти непися создает невидимый объект в который перекладываются все вещи моба, через минуту все уничтожается. Синьки: 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); } } Сообщение отредактировал Waromon - Aug 10 2006, 19:30 |
![]() ![]()
Сообщение
#94
|
|
Level 1 Класс: Тайный Лучник Характер: True Neutral Раса: Полуэльф ![]() |
Это мой скрипт для разных таверн.Официантка ходит по таверне подходит к разнам клиентам ,спрашивает заказ
идет к стойке берерт заказ идет назад к тому же клиенту отдает ему заказ и берет плату.Время от времени отдыхает и жалуется на жизнь.Реплики впишете сами не хотелось париться. Что бы скрипты правильно работали следует создать следущие вай поинты: 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 /* Вот и все вроде бы скрипт работает без багов но если такие найдутся попытаесь разобраться в чем дело. |
![]()
Сообщение
#95
|
|
Level 5 ![]() Класс: Обыватель Характер: Lawful Neutral Раса: Человек NWN: Модмейкер Проклятие Левора Порядок Времени ![]() |
Название: Рубка железных деревьев.
Описание: Дерево, которое можно рубить только специальным топором и после некоторых мучений отрубить таки сук. Другое оружие тупится об это дерево. скрипты: 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. не учитывается магия.. а надо бы (IMG:style_emoticons/kolobok_light/smile.gif) Думаю простого плота на onSpellCast будет достаточно 2. не учитывается вариант атаки дерева дальнобойным оружием. В этом случае не должно оно тупиться. Но это так же легко проверить, немного дописав скрит lx_pdm_irontree (IMG:style_emoticons/kolobok_light/smile.gif) |
![]()
Сообщение
#96
|
|
Level 17 ![]() Класс: Волшебник Характер: Neutral Good Раса: Человек NWN: Скриптинг [PW] Axistown SR 1.9 NWNX ![]() |
Пара скриптов посадки на стул:
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)); } } |
![]()
Сообщение
#97
|
|
Level 9 ![]() Класс: Вор Характер: True Neutral Раса: Эльф NWN: Скриптинг [PW] ![]() |
но не для шардов :-)
|
![]()
Сообщение
#98
|
|
Level 17 ![]() Класс: Волшебник Характер: Neutral Good Раса: Человек NWN: Скриптинг [PW] Axistown SR 1.9 NWNX ![]() |
QUOTE(2_advanced @ Jan 29 2007, 13:44) [snapback]103439[/snapback] но не для шардов :-) Работало без проблем более 3 лет.
|
![]()
Сообщение
#99
|
|
Level 9 ![]() Класс: Вор Характер: True Neutral Раса: Эльф NWN: Скриптинг [PW] ![]() |
если сидячий персонаж выйдет из игры / перезайдет, уйдет в другую локу, то стульчик накроется:
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 скамейку (IMG:style_emoticons/kolobok_light/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)); } } Сообщение отредактировал 2_advanced - Jan 30 2007, 08:44 |
![]()
Сообщение
#100
|
|
Level 17 ![]() Класс: Волшебник Характер: Neutral Good Раса: Человек NWN: Скриптинг [PW] Axistown SR 1.9 NWNX ![]() |
О глюках при перезаходе ни разу не слышал.
Может, это уже давно пофиксили в 1.67? Lex: QUOTE(virusman @ Jan 30 2007, 08:57) [snapback]103489[/snapback] О глюках при перезаходе ни разу не слышал. на Аксисе такие "запоротые" стулья были сто пудов, сам видел. А вот фиксено это на 1.67 или нет - мне не ведомо. Сообщение отредактировал Lex - Jan 31 2007, 19:40 |
![]()
Сообщение
#101
|
|
Level 2 ![]() Класс: Обыватель Характер: Lawful Good Раса: Человек ![]() |
Один из простых вариантов создания случайно генерируемой комнаты.
Нужно сделать комнату, в ней расставить все нужные предметы, делаем триггер, потом в переменных триггера ставим int "roomclean" = число (здесь ставим, сколько раз будет очищаться комната). Скрипт ставим на ОнЕнтер триггера. Сам триггер ставим возле двери (там, где должен появиться игрок). Если нужно несколько таких комнат - просто копируем комнаты(локации) в меню слева. Действие : удаляет случайно, с шансом 1 к 2, предметы (в т.ч. создания). Если нужно, могу переделать так, чтобы удаляло только итемы и плейсеблы. Neverwinter Script void main() { object oArea = GetArea(GetEnteringObject()); // локациЯ игрока int nClean = GetLocalInt(OBJECT_SELF, "roomclean"); // считываем переменную while(nClean>0) // пока переменнаЯ больше 0 - исполнЯем скрипт { nClean == nClean - 1; // изменЯем переменную object oClean = GetFirstObjectInArea(oArea); // задаем обьект while(GetIsObjectValid(oClean)) // пока обьект ЯвлЯетсЯ валидным (существующим) - исполнЯем код { if(GetIsPC(oClean) == FALSE) // здесь вставлЯем ограничениЯ длЯ типа объекта { switch(d2()) // разбор объектов { case 1: DestroyObject(oClean); break; // удалЯем case 2: // ничего не делаем } } oClean = GetNextObjectInArea(oArea); // берем следующий объект } } DeleteLocalInt(OBJECT_SELF, "roomclean"); // удалЯем локалку } Этот скрипт хорош тем, что не нужно постоянно просчитывать размещение предметов (вейпов для предметов), а также постоянно смотреть на резрефы обьектов - достаточно просто расставить нужные предметы, а скрипт сам все "разберёт". Универсальный скрипт для рычагов, открывающий ближайшую дверь. Скрипт ставим на OnUsed рычага. Рычаг ставим возле нужной двери. Neverwinter Script void main() { object oSelf = OBJECT_SELF;// Рычаг int nUsed = GetLocalInt(oSelf, "used");//ПеременнаЯ использованиЯ object oDoor = GetNearestObject(OBJECT_TYPE_DOOR);//БлижайшаЯ дверь SetLocalInt(oSelf, "used", 1-nUsed);//ПроставлЯем переменную if(nUsed == 0)//Проверка переменной { //Отпираем и открываем запертую дверь PlayAnimation(ANIMATION_PLACEABLE_ACTIVATE); AssignCommand(oDoor, ActionOpenDoor(oDoor)); } else//иначе { //Закрываем и запираем открытую дверь PlayAnimation(ANIMATION_PLACEABLE_DEACTIVATE); AssignCommand(oDoor, ActionCloseDoor(oDoor)); } } Исцеление сидящих обьектов (скрипт хорошо подойдет для таверн). Скрипт ставим на OnHeartbeat стула (дивана, кровати). Neverwinter Script void main()
{ object oPC = GetSittingCreature(OBJECT_SELF); // Берем сидЯщий обьект ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(1), oPC); // ИсцелЯем его } Сообщение отредактировал ReyBrujo - Jun 21 2010, 15:40 |
![]()
Сообщение
#102
|
|
Level 6 ![]() ![]() Класс: Маг Характер: Lawful Evil Раса: Нежить ![]() |
Универсальный скрипт триггеров для начала разговора с NPC. Успешно работает и в случае, если в разговоре участвуют члены партии. Вешается на OnEnter триггера; в локальных переменных триггера указываем string'и "NPC" и "DIALOG" - тэг парня, с которым будем разговаривать и название диалога соответственно. MAX_PARTY_SIZE меняем по своим надобностям, я обычно выношу это в инклюд. Легко разбавляется любыми необходимыми проверками.
Neverwinter Script const int MAX_PARTY_SIZE = 4; // Максимальный размер партии void Talk(string sDIALOG, object oPC) { BeginConversation(sDIALOG, oPC); } void main() { // Срабатывает 1 раз... if(GetLocalInt(OBJECT_SELF, "DONE") == 1) return; SetLocalInt(OBJECT_SELF, "DONE",1); // ...и только для PC object oPC = GetEnteringObject(); if(GetIsPC(oPC) == FALSE) return; int i; string sDIALOG = GetLocalString(OBJECT_SELF,"DIALOG"); object oNPC = GetNearestObjectByTag(GetLocalString(OBJECT_SELF,"NPC")); AssignCommand(oPC, ClearAllActions()); // Если член партии участвует в диалоге и находится слишком далеко от PC, то диалог может не сработать или оборваться. Поэтому перемещаем партийцев к PC. for(i=0;i<MAX_PARTY_SIZE;i++) AssignCommand(GetHenchman(oPC,i),JumpToObject(oPC) ); DelayCommand(1.0,AssignCommand(oNPC, Talk(sDIALOG,oPC))); } Рекомендуется также установить у всех участвующих в разговоре NPC "длинное" расстояние чувствительности. Сообщение отредактировал Talarasha - Aug 28 2010, 21:40 |
![]()
Сообщение
#103
|
|
Level 6 ![]() ![]() Класс: Маг Характер: Lawful Evil Раса: Нежить ![]() |
Вот простой скриптик, ставится на строку НПС и во время длинного расказа, происходит, как бы временной интервал с потухшим экраном. Что то навроде, как в кино: "Прошло два года..." :?) Neverwinter Script //::////////////////////////////////////////////// //:: Created By: WRG! Aiwan aiwan@e-mail.ru //:: Created On: 21.12.2003 //::////////////////////////////////////////////// /* ПАУЗА В РАЗГОВОРЕ С НПС */ //::////////////////////////////////////////////// void main() { object oPC = GetPCSpeaker(); AssignCommand(OBJECT_SELF, ActionPauseConversation()); AssignCommand(OBJECT_SELF, FadeToBlack(oPC, FADE_SPEED_SLOW)); AssignCommand(OBJECT_SELF, ActionWait(4.0)); AssignCommand(OBJECT_SELF, FadeFromBlack(oPC, FADE_SPEED_SLOW)); SetTime(GetTimeHour()+(Random(4)), GetTimeMinute()+(Random(60)), 0, 0); AssignCommand(OBJECT_SELF, ActionResumeConversation()); } Скрипт работает некорректно. ActionWait никоим образом не разделяет FadeToBlack и FadeFromBlack, независимо от указанной задержки затухание-появление всегда будет дергано-моментальным. AssignCommand тоже лишние. Нормальное затухание будет так: Neverwinter Script void main() { object oPC = GetPCSpeaker(); AssignCommand(OBJECT_SELF, ActionPauseConversation()); FadeToBlack(oPC, FADE_SPEED_SLOW); DelayCommand(4.0,FadeFromBlack(oPC, FADE_SPEED_SLOW)); DelayCommand(4.0,AssignCommand(OBJECT_SELF, ActionResumeConversation())); //SetTime(GetTimeHour()+(Random(4)), GetTimeMinute()+(Random(60)), 0, 0); } P.S. Кроме того, скрипт выложен в теме дважды: Первая страница Вторая страница Видать полезный. Сообщение отредактировал Talarasha - Sep 2 2010, 22:54 |
![]()
Сообщение
#104
|
|
Миловидный Бегрюссунг ![]() Класс: Воин Характер: Chaotic Good Раса: Человек NWN: Модмейкер Проклятие Левора Порядок Времени ![]() |
Talarasha, а кто тебе сказал, что пауза ДЛЯ РАЗДЕЛЕНИЯ FadeToBlack и FadeFromBlack? (IMG:style_emoticons/kolobok_light/smile.gif) Зачем игроку ЧЕТЫРЕ(!) секунды черноты, которая плавно и так наступает. Пауза нужна НПС, что бы не появлялось веток диалога 4 секунды. Посмотри внимательно код, который кстати написан мной семь лет назад (IMG:style_emoticons/kolobok_light/lol.gif) А вот в твоем коде может быть сбой (теоретически), так как несколько команд на одном тайминге задержки могут не сработать. Во втором делей лучше поставить 4.1. И этот скрипт работает как и задумано, причем не единожды вставлен и нигде сбоя нет. Одна особенность кода, все команды отдаются OBJECT_SELF-ом, так как я часто писал скрипты катсцен, то это просто кусок оттуда.
п.с. К тому же Биовар частенько поправляет функции и то что семь лет назад затухало плавно, сейчас может просто моргать. А насчет дубля. Удалить свое сообщение я не могу (попробовал только что), там ошибка какая-то базы два сообщения склеились и не объединились. Видишь в сообщении две надписис об редактировании. В 2005 году модератор пытался стереть и не смог. Лучше пусть будет два сообщения чем крах БД (IMG:style_emoticons/kolobok_light/smile.gif) |
![]()
Сообщение
#105
|
|
Level 6 ![]() ![]() Класс: Маг Характер: Lawful Evil Раса: Нежить ![]() |
Цитата Зачем игроку ЧЕТЫРЕ(!) секунды черноты, которая плавно и так наступает. Если бы она наступала, то конечно незачем (IMG:style_emoticons/kolobok_light/rolleyes.gif) Мне бы тогда и скрипт не было нужды переписывать. Цитата Пауза нужна НПС, что бы не появлялось веток диалога 4 секунды. Ветки диалога действительно не появляются 4 секунды. Четыре секунды после того, как экран просветлеет. Цитата А вот в твоем коде может быть сбой (теоретически) С удовольствием приму и рассмотрю любые жалобы на сбои, проявившиеся из-за использования моих скриптов (IMG:style_emoticons/kolobok_light/thank_you.gif) Цитата К тому же Биовар частенько поправляет функции и то что семь лет назад затухало плавно, сейчас может просто моргать. Можно рассматривать это как 1.69-апдейт. Пока я не проверю работу на более старых версиях (IMG:style_emoticons/kolobok_light/rolleyes.gif) А вообще за комментарий спасибо, теперь хотя бы понятно, почему скрипт написан "так" =) |
![]()
Сообщение
#106
|
|
Level 5 ![]() Класс: Обыватель Характер: Lawful Neutral Раса: Человек NWN: Модмейкер Проклятие Левора Порядок Времени ![]() |
Система крафта от PaiNt'a
Набор скриптов позволяет реализовать «производственный/собирательный» крафт практически любой сложности. Система включает 70 скриптов, 1 общий управляющий диалог, 10 чертежей палитры (инструмент-существо, инструмент-предмет, инструмент-плейсабл, инструмент-триггер, шаблоны различных предметов класса «сырье», специальные инструменты), все чертежи палитры находятся во вкладках «Специальная->Настройка1-2». Особенность системы - ее наращивание не путем создания инструментов в палитре и строчек в скрипте – а создание конечных продуктов переработки в тулсете и присваивание им переменных определяющих, что требуется для производства. Подробные инструкции и описание системы приложены в Word документе с картинками в архиве. |
![]()
Сообщение
#107
|
|
Level 2 ![]() Класс: Обыватель Характер: Lawful Good Раса: Человек ![]() |
для скрипта дежурящих ночью гвардов
if ( !GetIsInCombat() || GetCurrentAction() != ACTION_DIALOGOBJECT) Сдается мне, что скрипт не будет срабатывать только тогда, когда нпс будет в бою и в диалоге одновременно О_о Недоглядели, благородный дон То был скрипт со второй страницы Вот еще один, с первой страницы. Цитата Код while ((pos = FindSubString(sProperties, "@")) != -1) { sProperties = GetStringRight(sProperties, GetStringLength(sProperties) - pos - 1); pos = FindSubString(sProperties, "@"); if (pos == -1) pos = GetStringLength(sProperties); sTemp = GetStringLeft(sProperties, pos); //SendMessageToPC(GetFirstPC(), "sTemp["+ IntToString(i) +"] == "+ sTemp); SetProperty(oItem, sTemp); i++; } Тут есть счетчик i, который используется только при дебагге. Так то ничего страшного, но он стоит в цикле while, и мы будем делать десятки ненужных вычислений. //SendMessageToPC(GetFirstPC(), "sTemp["+ IntToString(i) +"] == "+ sTemp);i++; А нужно всего то ее закомментить |
![]()
Сообщение
#108
|
|
Level 2 ![]() Класс: Обыватель Характер: Lawful Good Раса: Человек ![]() |
Здесь описанная часть системы поджигания, я ее использую чтобы с помощью факела можно было поджечь деревья, дома, и т.д.
Я выложил три скрипта, с подробным описанием. SetFire - ставит огонь по указанным координатам DestroyFire - уничтожает все огни. локальные переменные Fire - хранит индикатор, насколько разгорелся объект FireObject - Содержит количество созданных огней Я постарался сделать как можно более детальное описание каждой строчки кода, надеюсь, моя работа кому-нибудь, да пригодится) "Спасибо" приветствуется :rolleyes: Код ///////////////////////////////////////////////////////////////////////////////
// * Функциz удалzет все пробелы из строки * // /////////////////////////////////////////////////////////////////////////////// string RemoveSpace(string str) { string str2; // Результат while(str!="")// Пока в строке есть хоть один символ { // Если символ первой строки - не пробел, то // добавлzем его к переменной результата if(GetStringLeft(str , 1)!=" ") str2 += GetStringLeft(str , 1); // Берем строку с конца до второго символа // (то есть избавлzемсz от первого символа) str = GetStringRight(str , GetStringLength(str)-1); } // Возвращаем результат строки без пробелов return str2; } /////////////////////////////////////////////////////////////////////////////// // * Функциz устанавливает огни по заданным точкам * // К примеру, "1*0.2,0.1,0.0;", где // 1 - номер устанавливаемого огнz (они должны // всегда идти по порzдку), // * - тип огнz (* - огонек, ! - искры), должны // создаватьсz отдельно, резрефы заменить ниже, blueprint003 и blueprint033 // соответственно. Используйте длz огонька костер, а длz искр - // магическую вспышку, в котором бы неплохо было вырезать с помощью 3dmax'a // верхний zркий огонек в виде шарика). // 0.2 - изменение координаты относительно oObject по оси x (ширине) x \ // 0.1 - изменение координаты относительно oObject по оси y (длине) y |> координаты огонька // 0.1 - изменение координаты относительно oObject по оси z (высоте) z / // "," разделzет оси координат (их должно быть обzзательно 3) // ";" разделzет огни друг от друга // // Все пробелы из функции удалzютсz. Оформлzйте данные так, как вам удобнее // читаетсz. // // >> P.S.Сейчас z работаю над системой дебагга вводных данных, но z надеюсь, вы // люди не глупые, перечитаете верхние правила ввода данных, не // будете злоупотреблzть количеством огоньков, и... удачи :) /////////////////////////////////////////////////////////////////////////////// void SetFire(object oObject = OBJECT_SELF, string str = "1* 0.0,0.0,0.0; 2! 0.0,0.0,1.0;" ) { // str = RemoveSpace(str); int iFire = GetLocalInt(oObject,"Fire"); int iFireObject = GetLocalInt(oObject,"FireObject"); iFire++; // Сохранzем переменную SetLocalInt(oObject,"Fire", iFire); // * Если что то пойдет не так по причине некорректного // * ввода данных при вызове функции, то, поскольку мы уже сохранили локальную // * переменную, мы сможем в дальнейшем использовать ее, чтобы наносить // * повреждение объекту // Длz нанесениz повреждений можно использовать такие строчки // iFire = GetLocalInt("имz объекта, которому наносим повреждение","Fire") // ApplyEffectToObject(1,EffectDamage(iFire, DAMAGE_TYPE_FIRE),"имz объекта, которому наносим повреждение"); // Берем координаты длz созданиz будущего огонька object oArea = GetArea(oObject); vector vVector = GetPosition(oObject); while(str!="")//Пока строчка не станет пустой { // Переменнаz отвечает за визуальный вид огонька // FALSE если искры int bCheck = FALSE; // С помощью этой переменной проверzем номер введенного объекта, // это длz того, чтобы уменьшить объем повреждений от неверно введенных данных int iCheckFireObject; //* Ниже код разбирает по косточкам введенный текст в переменную str. //* Каждый раз то символа ";". //vvvvvvvvvvvvvvvvvvvvvvvvvvv->S T R<-vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv// // Определzем тип огнz, котороый мы ставим ("-1" возвращаетсz, если символ не найден) if((FindSubString(str, "*")<FindSubString(str, "!") && FindSubString(str, "*")!=-1)||FindSubString(str, "!")==-1) { // Визуальный вид огонька. TRUE если огонек bCheck = TRUE; // Соответственно берем номер объекта устанавленного огнz iCheckFireObject = StringToInt (GetStringLeft (str, FindSubString(str, "*"))); } else { iCheckFireObject = StringToInt (GetStringLeft (str, FindSubString(str, "!"))); } // Выделzем из строчки str координаты x, y и z в другую строку string xyz = GetStringLeft (GetStringRight(str, GetStringLength(str) - 2),FindSubString(str, ";")-2); // Убираем обработанную строчку из кода str = GetStringRight (str, GetStringLength(str)-GetStringLength(xyz)-3); // Проверzем, если выделенный номер объекта следует за уже существующим номером // то каждые три индикатора огнz ставим огонек if(iCheckFireObject == iFireObject + 1 && iFire>iFireObject*3) { // Разбиваем строку с координатами xyz на отдельные координаты float x = StringToFloat(GetStringLeft (xyz, FindSubString(xyz, ","))); xyz = GetStringRight (xyz, GetStringLength(xyz)-FindSubString(xyz,",")-1); float y = StringToFloat(GetStringLeft (xyz, FindSubString(xyz, ","))); float z = StringToFloat(GetStringRight (xyz, GetStringLength(xyz)-FindSubString(xyz,",")-1)); //^^^^^^^^^^^^^^^^^^^^^^^^^^^->S T R<-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// // Устанавливаем точку, на которую поставим огонек location lLoc = Location(oArea,Vector(vVector.x+x, vVector.y+y, vVector.z+z) , IntToFloat(Random(360))); // Регистрируем установку огонька iFireObject++; // Ставим модель огонька соответственно установленной ранее переменной. TRUE - огонь, FALSE - искры if(bCheck == TRUE) CreateObject(OBJECT_TYPE_PLACEABLE, "blueprint003", lLoc, FALSE, "fplace" + IntToString(iFireObject) ); else CreateObject(OBJECT_TYPE_PLACEABLE, "blueprint033", lLoc, FALSE, "fplace" + IntToString(iFireObject) ); // Сохранzем переменную, так как огонь мы уже поставили SetLocalInt(oObject,"FireObject", iFireObject); } } } /////////////////////////////////////////////////////////////////////////////// // * Функциz удалzет все установленные огоньки * // /////////////////////////////////////////////////////////////////////////////// void DestroyFire(object oObject) { // Объzвлzем счетчик и переменную, в которую заносим количество установленных огней в объекте int i, iFireObject = GetLocalInt(oObject, "FireObject"); // Удалzем огни for(i=iFireObject;i>0;i--) DestroyObject(GetObjectByTag("fplace" + IntToString(i))); // Очищаем объект от локальных переменных, хранzщих огонь DeleteLocalInt(oObject, "FireObject"); DeleteLocalInt(oObject, "Fire"); } |
![]()
Сообщение
#109
|
|
Level 5 ![]() Класс: Обыватель Характер: Lawful Neutral Раса: Человек NWN: Модмейкер Проклятие Левора Порядок Времени ![]() |
поставь патч dumbo на русскую букву "я" в скриптах. ( http://wrg.ru/download.php?view.109 )
|
![]()
Сообщение
#110
|
|
Level 2 ![]() Класс: Обыватель Характер: Lawful Good Раса: Человек ![]() |
У меня стоит.
Просто жаль тех людей, кому лень этот патч ставить) Им тем более будет лень исправлять все "я" на не "я" (IMG:style_emoticons/kolobok_light/rolleyes.gif) |
![]()
Сообщение
#111
|
|
Level 11 ![]() Класс: Волшебник Характер: Neutral Good Раса: Фея NWN: Скриптинг [PW] Край Лесов ![]() |
Как-то давно мне пришла в голову интересная мысль и захотелось ее реализовать - деньги в нвн не просто золотые, а монеты с весом. На ваулте лежало несколько реализаций, но меня они не устраивали, в виду некоторых причин их реализации.
Для работы системы нужен NWNX и 2 плагина nwnx_events и nwnx_fixes Суть: 2 типа магазина: скупщик и продающий Зацепляем событие на Еxamine item в nwnx_events Берем голд-стоимость итема, вычисляем. В мое случае это 1 электрум = 100 золото = 10000 серебро 3 вида вычислений стоимости: 1). Когда еxamine item производиться просто в инвентаре, без открытого магазина. -выдается стоимость без всяких надбавок + экономическое изменение (можно регулировать общее подорожание или удешевление) 2). С открытым магазине типа продающий -производиться оценка, обоюдный бросок – в зависимости от этого скидки или наценка + экономическое изменение 3). в инвентаре при открытом магазине типа скупщик -производиться оценка, обоюдный бросок – в зависимости от этого скидки или наценка + экономическое изменение Надо добавить, что при реализации идеи использовались наработки КЛ, в частности - по поломке предметов, так что его (предмета) состояние непосредственно влияло на стоимость продажи/покупки Результат выводиться виде сообщения игроку, когда он смотрит свойства предмета. Продажа/Покупка осуществляется через REMOVE_DISTURBED_ITEM, простым перетаскиванием, без всяких диалогов. На магазин вешается переменная с ДЦ ОЦЕНКИ и типом магазина. Всего два действия по сути: первое вы смотрите стоимость во время просмотра свойств, второе – покупка/продажа =) Значит, обычный плэйс, с инвентарем. На нем 2 локалки типа int TD_MERCANT_DC - ДЦ для ОЦЕНКИ и TD_MERCANT - тип магазина 1 и 2 Название валют можно придумать свои, для простоты ориентации в скрипте: MonE - это сама дорогая (Электрумовая) = 100 золотым = 10000 серебра MonG - средняя (Золотая) = 100 серебрянным MonS - нифиля (Сребрянная) Т.е. грубо говоря если в разных городах разные валюты (города в разных странах), то стоимость итема будет выдана в той валюте, которая в городе с учетом той экономической ситуации, которая в стране. Была идея сделать разные наценки в городах, в зависимости от типов предмета. Например, на мечи - такая, на бронь - такая. Что-то типо предложения спроса в городе. Идея не воплотилась) Скрипты: nwnx_events Neverwinter Script const int TD_SECS_IN_HOUR = 120.0f; // Melisse: Берет goldvalue предмета и переводит его в валюту и выдает ввиде сообщения игроку void td_SendMessageItemMoneyCost (object oPC, object oInvent, object oTarget); // Main void main( ){ object oPC = OBJECT_SELF; object oTarget = GetNWNXEventTarget( ); int nEvent = GetNWNXEventType( ); switch( nEvent ){ case EVENT_EXAMINE: { if(GetObjectType(oTarget) == OBJECT_TYPE_ITEM) { object oInvent = GetItemPossessor(oTarget); if(GetPlotFlag(oTarget) == FALSE) td_SendMessageItemMoneyCost (oPC, oInvent, oTarget); } else SendMessageToPC( oPC, "NWNX Knows you just examined "+GetName( oTarget )+"!" ); break; } } } void td_SendMessageItemMoneyCost (object oPC, object oInvent, object oTarget) { int nInvent = (GetObjectType(oInvent) == OBJECT_TYPE_PLACEABLE); int nCost = GetGoldPieceValue(oTarget); SendMessageToPC (oPC, "============================================= ===="); //SendMessageToPC (oPC, "Value = "+IntToString(nCost)); SendMessageToPC (oPC, td_ColorText(GetName(oTarget),TD_TXT_COLOR_GRAY)); /* Закоментровано. Это относитсья к системе поломки, которую тут не выкладываю. // Вычислим стоимость, если итем сломан struct strItemDur strMyItemDur = td_GetItemDur(oTarget); int nDurCur = strMyItemDur.nDurCur; int nDurMax = strMyItemDur.nDurMax; int nDurResult = nDurMax - nDurCur; if(nDurResult > 0) { float fBroken = IntToFloat(nCost)/100.0*IntToFloat(nDurResult); nCost -= FloatToInt(fBroken); SendMessageToPC (oPC, "Сломан! = -"+IntToString(nDurResult)+ "% от полной цены"); }*/ // Если просмотр производиться в чьем-то инвентаре if(GetIsObjectValid(oInvent)) { // Магазин // При просмотре описания с открытым магазином // стоимость товара учитывает со скидкой/наценкой if(GetLocalInt(oInvent, "TD_MERCANT")) { int nSell = FALSE; object oStore; if (oPC == oInvent) { // Игрок продает oStore = GetLocalObject(oPC, "TD_MERCANT_OBJ"); nSell = TRUE; } else if(nInvent) { // Игрок покупает oStore = oInvent; } else return; string sCharID = IntToString(GetLocalInt (oPC, "nCharID")); int nDiscount = GetLocalInt (oStore, "TD_DISCOUNT"+sCharID); int nTime = GetLocalInt (oStore, "TD_DISCOUNT_TIME"+sCharID); int nEcoKingdom = GetLocalInt (GetModule(), "TD_MOD_ECO" +GetSubString(GetTag(GetArea(oPC)), 2, 1)); SendMessageToPC (oPC, "Экономическая ситуация = "+IntToString(nEcoKingdom)+"%"); // Рачитаем на сколько поднимиться цена в этой стране на этот предмет nEcoKingdom = FloatToInt(IntToFloat(nCost)/100.0*IntToFloat(nEcoKingdom)); // Скидки нет или время пришло (1 раз в сутки) if(!nDiscount || nTime < td_Uptime()) { int nDC = GetLocalInt(oStore, "TD_MERCANT_DC"); int nSkill = GetSkillRank(SKILL_APPRAISE, oPC); nDiscount = nDC - nSkill; if(nDiscount < 0) nDiscount *= -1; if(nDiscount == 0) nDiscount = 1; if(GetIsSkillSuccessful(oPC, SKILL_APPRAISE, nDC)) { if(!nSell) { nDiscount += 100; } SetLocalInt (oStore, "TD_DISCOUNT"+sCharID, nDiscount); } else { if(nSell) { nDiscount += 100; } SetLocalInt (oStore, "TD_DISCOUNT"+sCharID, nDiscount); } SetLocalInt (oStore, "TD_DISCOUNT_TIME"+sCharID, td_Uptime ()+24*TD_SECS_IN_HOUR ); } // Скидка есть - расчитаем if(nDiscount >= 100) { nDiscount -= 100; float fDiscount = IntToFloat(nCost)/100.0*IntToFloat(nDiscount); if(nSell) { SendMessageToPC (oPC, "Продажа: цена = +"+IntToString(nDiscount)+"%"); nCost += FloatToInt(fDiscount)-nEcoKingdom; // С учетом общего экономического состояния в стране } else { nCost -= FloatToInt(fDiscount)+nEcoKingdom; // С учетом общего экономического состояния в стране SendMessageToPC (oPC, "Покупка: скидка = -"+IntToString(nDiscount)+"%"); } } else { float fDiscount = IntToFloat(nCost)/100.0*IntToFloat(nDiscount); if(nSell) { SendMessageToPC (oPC, "Продажа: цена = -"+IntToString(nDiscount)+"%"); nCost -= FloatToInt(fDiscount)-nEcoKingdom; // С учетом общего экономического состояния в стране } else { nCost += FloatToInt(fDiscount)+nEcoKingdom; // С учетом общего экономического состояния в стране SendMessageToPC (oPC, "Покупка: цена = +"+IntToString(nDiscount)+ "%"); } } //SendMessageToPC (oPC, "Игрок = "+GetName(oPC)); //SendMessageToPC (oPC, "Магазин = "+GetName(oStore)); } } // Переведем в денежынй эквивалент int nMonE = nCost/10000; // Электрумовые int nMonG = (nCost - nMonE*10000)/100; // Золотые int nMonS = nCost - (nMonG*100+nMonE*10000); // Серебряные // Покажем игроку результаты SendMessageToPC (oPC, td_ColorText("*СТОИМОСТЬ:",TD_TXT_COLOR_GRAY)); SendMessageToPC (oPC, td_MoneyName(GetArea(oPC),nMonS,nMonG,nMonE)); } на OnOpen на плэйсе Neverwinter Script void main() { object oPC = GetLastOpenedBy(); // Магазин, который скупает if(GetIsPC(oPC) && GetLocalInt(OBJECT_SELF, "WS_MERCANT") == 2) { SetLocalInt(oPC, "WS_MERCANT", TRUE); SetLocalObject(oPC, "WS_MERCANT_OBJ", OBJECT_SELF); } // Запускается проверка на "Опознание" предметов в инвентаре магазина // 1 раз за рестарт, при 1-вом открытии if(!GetLocalInt(OBJECT_SELF, "nActiveted")) { object oItem = GetFirstItemInInventory(OBJECT_SELF); while (GetIsObjectValid(oItem)) { if(!GetIdentified(oItem)) SetIdentified(oItem, TRUE); int nBaseType = GetBaseItemType(oItem); // Выставляем на итемы со стэком > 1 // Это необходимо для того, чтобы они не стыкались с теми что в инвентаре // nwnx_fixed убирает баг, при котором стэкались итемы, когда у них локалки if(nBaseType == BASE_ITEM_ARROW || nBaseType == BASE_ITEM_BOLT || nBaseType == BASE_ITEM_BULLET || nBaseType == BASE_ITEM_DART || nBaseType == BASE_ITEM_POTIONS || nBaseType == BASE_ITEM_THROWINGAXE) { SetLocalInt(oItem, "WS_MERCANT_ITEM", TRUE); } oItem = GetNextItemInInventory(OBJECT_SELF); } SetLocalInt(OBJECT_SELF, "nActiveted", TRUE); } } на OnDisturbed на плэйсе Neverwinter Script /**************************************\ td_pds_shop -------------------------- Author : Melisse E-mail : ICQ : Started : -------------------------- Скрипт магазина \**************************************/ //#include "td_inc_craft" void td_ReturnItem (object oSubject, object oItem); void main() { object oMerchant = OBJECT_SELF; object oPC = GetLastDisturbed(); object oItem = GetInventoryDisturbItem(); object oArea = GetArea(oPC); string sMonE = td_GetTagMoney(GetTag(oArea), "sMonE"); string sMonG = td_GetTagMoney(GetTag(oArea), "sMonG"); string sMonS = td_GetTagMoney(GetTag(oArea), "sMonS"); string sTradeType = GetLocalString(oMerchant, "sTradeType"); int nDistType = GetInventoryDisturbType(); int nMoneyPC = td_GetCountAllMoney (oPC, sMonE, sMonG, sMonS); int nCost = GetGoldPieceValue(oItem); /* Закоментровано. Это относитсья к системе поломки, которую тут не выкладываю. // Вычислим стоимость, если итем сломан struct strItemDur strMyItemDur = td_GetItemDur(oItem); int nDurCur = strMyItemDur.nDurCur; int nDurMax = strMyItemDur.nDurMax; if((nDurMax - nDurCur) > 0) { float fCost = IntToFloat(nCost)/100.0*IntToFloat(nDurCur); nCost -= FloatToInt(fCost); } */ // стоимость товара учитывает со скидкой/наценкой string sCharID = IntToString(GetLocalInt (oPC, "nCharID")); int nDiscount = GetLocalInt (oMerchant, "TD_DISCOUNT"+sCharID); int nTime = GetLocalInt (oMerchant, "TD_DISCOUNT_TIME"+sCharID); int nSell = FALSE; int nEcoKingdom = GetLocalInt (GetModule(), "TD_MOD_ECO_" +GetSubString(GetTag(GetArea(oPC)), 2, 1)); if(GetLocalInt(oMerchant, "TD_MERCANT") == 2) nSell = TRUE; // Рачитаем на сколько поднимиться цена в этой стране на этот предмет nEcoKingdom = FloatToInt(IntToFloat(nCost)/100.0*IntToFloat(nEcoKingdom)); // ---- // Вычисление скидки/наценки // ---- if(!nDiscount || nTime < td_Uptime()) { int nDC = GetLocalInt(oMerchant, "TD_MERCANT_DC"); int nSkill = GetSkillRank(SKILL_APPRAISE, oPC); nDiscount = nDC - nSkill; if(nDiscount < 0) nDiscount *= -1; if(nDiscount == 0) nDiscount = 1; if(GetIsSkillSuccessful(oPC, SKILL_APPRAISE, nDC)) { if(!nSell) { nDiscount += 100; } SetLocalInt (oMerchant, "TD_DISCOUNT"+sCharID, nDiscount); } else { if(nSell) { nDiscount += 100; } SetLocalInt (oMerchant, "TD_DISCOUNT"+sCharID, nDiscount); } SetLocalInt (oMerchant, "TD_DISCOUNT_TIME"+sCharID,td_Uptime()+24*TD_SECS_IN_HOUR ); } // Скидка есть - расчитаем if(nDiscount >= 100) { nDiscount -= 100; float fDiscount = IntToFloat(nCost)/100.0*IntToFloat(nDiscount); if(nSell) { //SendMessageToPC (oPC, "Повышение цены = "+IntToString(nDiscount)+ "%"); nCost += FloatToInt(fDiscount)-nEcoKingdom; // С учетом общего экономического состояния в стране } else { nCost -= FloatToInt(fDiscount)+nEcoKingdom; // С учетом общего экономического состояния в стране //SendMessageToPC (oPC, "Скидка = "+IntToString(nDiscount)+ "%"); } } else { float fDiscount = IntToFloat(nCost)/100.0*IntToFloat(nDiscount); if(nSell) { //SendMessageToPC (oPC, "Снижение цены = "+IntToString(nDiscount)+ "%"); nCost -= FloatToInt(fDiscount)-nEcoKingdom; // С учетом общего экономического состояния в стране } else { nCost += FloatToInt(fDiscount)+nEcoKingdom; // С учетом общего экономического состояния в стране //SendMessageToPC (oPC, "Наценка = "+IntToString(nDiscount)+ "%"); } } // ---- // Процесс Покупка/Продажа // ---- if(nDistType == INVENTORY_DISTURB_TYPE_REMOVED) { if(GetPlotFlag(oItem) || GetLocalInt(oMerchant, "TD_MERCANT") != 1) { td_ReturnItem (oMerchant, oItem); FloatingTextStringOnCreature ("Этот предмет не продается.", oPC, FALSE); } else if(nMoneyPC < nCost) { td_ReturnItem (oMerchant, oItem); FloatingTextStringOnCreature ("Не хватает денег для покупки этой вещи.", oPC, FALSE); } else { // ------- // Транзакция денег и выдача предмета // ------- td_MoneyTransaction (oPC, TRUE, nMoneyPC, nCost, sMonE, sMonG, sMonS); CopyItem (oItem, oMerchant, TRUE); DeleteLocalInt(oItem, "TD_MERCANT_ITEM"); } AssignCommand(oPC, ActionInteractObject(oMerchant)); DelayCommand(0.5f, AssignCommand(oPC, ActionInteractObject(oMerchant))); } else if (nDistType == INVENTORY_DISTURB_TYPE_ADDED) { if(GetPlotFlag(oItem) || GetLocalInt(oMerchant, "TD_MERCANT") != 2) { td_ReturnItem (oPC, oItem); FloatingTextStringOnCreature ("*Вы не можете продать этот предмет здесь.", oPC, FALSE); } // Нельзя продать не идентифицированый итем или продать предмет который не покупает магазин else if (!GetIdentified (oItem) || FindSubString(sTradeType, IntToString(GetBaseItemType (oItem))) == -1) { td_ReturnItem (oPC, oItem); FloatingTextStringOnCreature ("*Вы не можете продать этот предмет здесь.", oPC, FALSE); } else { // ------- // Транзакция денег и удаление проданого предмета // ------- td_MoneyTransaction (oPC, FALSE, nMoneyPC, nCost, sMonE, sMonG, sMonS); SetLocalInt(oItem, "TD_DESTROY",TRUE); DestroyObject(oItem,0.5f); } AssignCommand(oPC, ActionInteractObject(oMerchant)); DelayCommand(0.5f, AssignCommand(oPC, ActionInteractObject(oMerchant))); } } void td_ReturnItem (object oSubject, object oItem) { CopyItem (oItem, oSubject, TRUE); DestroyObject (oItem); } Далее выкладываю просто функции и их прототипы: Neverwinter Script // Возвращает текстовую строку со стоимость и названиями валют // Можно устанавливать разные валюты для разных городов и тут высталять названия string ws_MoneyName(int nMoneyS, int nMoneyG = 0, int nMoneyE = 0); string ws_MoneyName(int nMoneyS, int nMoneyG = 0, int nMoneyE = 0) { sText = ws_ColorText(IntToString(nMoneyE)+" Хан ",WS_TXT_COLOR_WHITE) + ws_ColorText(IntToString(nMoneyG)+" Мон ",WS_TXT_COLOR_YELLOW) + ws_ColorText(IntToString(nMoneyS)+ " Шо",WS_TXT_COLOR_CYAN); return sText; } // Возвращает полное количество денег в GoldValue int ws_GetCountAllMoney (object oSubject, string sMonE, string sMonG, string sMonS); int ws_GetCountAllMoney (object oSubject, string sMonE, string sMonG, string sMonS) { object oMoney = GetFirstItemInInventory(oSubject); int i; while (GetIsObjectValid(oMoney)) { string sMoney = GetTag(oMoney); if(sMoney == sMonE) i += GetNumStackedItems(oMoney)*10000; else if (sMoney == sMonG) i += GetNumStackedItems(oMoney)*100; else if (sMoney == sMonS) i += GetNumStackedItems(oMoney); oMoney = GetNextItemInInventory(oSubject); } return i; } // Производит пересоздание денег у игрока void ws_MoneyTransaction (object oPC, int nType, int nMoneyPC, int nCost, string sMonE, string sMonG, string sMonS); void ws_MoneyTransaction (object oPC, int nType, int nMoneyPC, int nCost, string sMonE, string sMonG, string sMonS) { int nResult; if(nType) // Покупка предмета nResult = nMoneyPC - nCost; else // Продажа предмета nResult = nMoneyPC + nCost; SendMessageToPC (oPC, "Было денег = "+IntToString(nMoneyPC)+" Стоимость итема = "+IntToString(nCost)+" Стало денег = "+IntToString(nResult) ); int nMonE = nResult/10000; // Электрумовые int nMonG = (nResult - nMonE*10000)/100; // Золотые int nMonS = nResult - (nMonG*100+nMonE*10000); // Серебряные /* SendMessageToPC (oPC, "Эле = "+IntToString(nMonE)+" Золо = "+IntToString(nMonG)+" Сере = "+IntToString(nMonS) );*/ object oItem = GetFirstItemInInventory(oPC); while (GetIsObjectValid(oItem)) { string sTag = GetTag(oItem); if (sTag == sMonE || sTag == sMonG || sTag == sMonS) { SetLocalInt(oItem, "WS_DESTROY",TRUE); DestroyObject(oItem); } oItem = GetNextItemInInventory(oPC); } object oNew; if(nMonS) { oNew = CreateItemOnObject(sMonS, oPC); SetItemStackSize (oNew, nMonS); } if(nMonG) { oNew = CreateItemOnObject(sMonG, oPC); SetItemStackSize (oNew, nMonG); } if(nMonE) { oNew = CreateItemOnObject(sMonE, oPC); SetItemStackSize (oNew, nMonE); } } // Возвращает тэг валюты sMoneyType используемой в этом городе string ws_GetTagMoney (string sAreaTag, string sMoneyType); string ws_GetTagMoney (string sAreaTag, string sMoneyType) { string sTown = sAreaTag; string sMoneyTag; if(sTown == "Area001") { if(sMoneyType == "sMonE") sMoneyTag = "IT_MON_FE"; else if (sMoneyType == "sMonG") sMoneyTag = "IT_MON_FG"; else if (sMoneyType == "sMonS") sMoneyTag = "IT_MON_FS"; } return sMoneyTag; } Скрипты и функции выдернуты из целого комплекса систем, поэтому могут быть какие-то не компиляции, но суть мысли должна быть понятна. Сообщение отредактировал Melisse - Oct 21 2011, 17:29 |
![]()
Сообщение
#112
|
|
Тролль ![]() ![]() ![]() ![]() Класс: Пьяный Мастер Характер: Chaotic Neutral Раса: Тварь ![]() |
Люди только осваивающие скрипты в тулсете довольно часто спрашивают как сделать, чтоб объект появлялся в локации только в определенное время (эдакие лунные руны по Толкиену (IMG:style_emoticons/kolobok_light/smile.gif) ). Продвинутые модульмэйкеры знают сотню способов как это реализовать, однако недавно копался в очередной раз над наиболее лаконичным ответом на этот вопрос в тулсете (пользуясь случаем передаю привет Аконит (IMG:style_emoticons/kolobok_light/biggrin.gif) ) – и обнаружил довольно универсальную формулу скрипта:..
Neverwinter Script void main() ...Комментарии на английском из-за возможных боков с "я" вот их перевод для не знающих:{ object oTarget = OBJECT_SELF; effect eEffect = EffectDisappearAppear(GetLocation(OBJECT_SELF), 1); int DoOnce = GetLocalInt(OBJECT_SELF, GetTag(OBJECT_SELF)); float fHour = 60.0; //<- hour longitude in module (in seconds) int iHour = 0; //<- hour of appear (from 0 to 23) int iTimeout = 1; //<- longitude of appear (in hours, from 1 to 23) int iDifferent; iDifferent = iHour+iTimeout; if (iDifferent > 23) { iDifferent = iDifferent-24; } if ((GetTimeHour()==iDifferent)&&(DoOnce==FALSE)) { ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEffect, oTarget, fHour*(24-iTimeout)); SetLocalInt(OBJECT_SELF, GetTag(OBJECT_SELF), TRUE); DelayCommand(fHour*(24-iTimeout), SetLocalInt(OBJECT_SELF, GetTag(OBJECT_SELF), FALSE)); } } <- hour longitude in module (in seconds)/длительность игрового часа в модуле (в секундах) <- hour of appear (from 0 to 23)/игровой час появления объекта (от 0 до 23) <- longitude of appear (in hours, from 1 to 23)/длительность появления объекта (в игровых часах, от 1 до 23) Эти значения вы должны подставить в скрипт сами в соответствии с особенностями модуля и собственно эвента с объектом. Скрипт нужно ставить на OnHeartbeat существа/объекта, при этом если это объект - он не должен иметь в своих свойствах галочку в окошке "статик", иначе скрипт не сработает (однако при этом объект не обязательно должен быть "активным"). У скрипта есть единственный недостаток - при старте модуля объект будет видимым, пока и если в модуле не наступит час его исчезновения. Далее скрипт будет работать исправно. |
![]() ![]() |
Текстовая версия | Сейчас: 18th September 2025 - 08:01 |