Изложен простой метод исправления проблемы с помощью TES5Edit.
В принципе, это голимый откат навмешей на дефолт, такое можно и в СК сделать (само же переписывание FormID... вот лично я, как-то противник такого). И это не исправление как таковое, а если вы нажмёте "финализацию", то опять получите рефинализацию ячейки. Баг разрабов никуда не денется с таким методом, как были кривые навмеши, так они такими и останутся. Увы.
*********************************************** Если выйти из этого помещения с лифтом, то сам лифт опустится на исходную позицию (вниз). Если лифт изначально стоит на верху, то поменяй местами "+" и "-" в команде перемещения. При неудачном движении лифта есть "авариный сброс" и лифт со скриптом придут в исходное положение. Пока лифт движется активировать его невозможно, надо подождать до полной остановки. Все рычаги работают однотипно, нет рычагов "вниз" и "наверх". Если лифт внизу, то при нажатии на любой рычаг он поедет вверх, а если на верху, то поедет вниз.
Добавлено (16 Декабря 2013, 21:51) ---------------------------------------------
Цитата LordVadim
Scriptname LiftUp extends ObjectReference Event OnActivate(ObjectReference akActionRef) if GetLinkedRef().Z == координата ; лифт внизу (координату по оси Z взять из СК) GetLinkedRef().TranslateTo(GetLinkedRef().X, GetLinkedRef().Y, GetLinkedRef().Z + fZZ, 0.0, 0.0, 0.0, 200.0) ; отправка лифта вверх endif endEvent
Так делать нельзя. Если в скрипте присутствует "добавляющее число" (fZZ) и нет жёсткой привязки (координата, параметр и прочее), то при повторной активации команды это "добавленное число" добавится и получится уже двойное значение. Чтобы этого избежать необходимо блокировать повторный/внеочередной вызов команды. Можно доп. переменными или статусами.
Это касается любых скриптов с подобными переменными типа fZZ.
подскажите наиболее правильный способ подсчитать кол-во видов предметов в инвентаре определенной категории.
int iFormIndex = akActor.GetNumItems() - количество категорий/типов/базовых предметов
Определить конкретный тип объекта, типа "мясо", стандартыми методами нельзя, т.к. мясо лося и мясо крысы ничем не отличается вообще, только ID. (разрабы не простовляли кейворды на типы предметов)
Можно проверить по основному типу объекта: яд, пища, зелье (по кейвордам). Но выделить "это == мясо" не получится.
int iPotion int iPoison int Food
Function ChengInventory() int iFormIndex = akActor.GetNumItems() iPotion = 0 iPoison = 0 Food = 0 While iFormIndex > 0 iFormIndex -= 1 Form kForm = akActor.GetNthForm(iFormIndex) if kForm.GetType() == 46 ; Potion if kForm.HasKeywordString("vendoritempotion") ; зелье iPotion += 1 elseif kForm.HasKeywordString("vendoritempoison") ; яд iPoison += 1 elseif kForm.HasKeywordString("vendoritemfood") ; пища/вино Food += 1 endif endif endWhile endFunction
Можно конкретизировать поиск, тогда надо сделать форм-лист со своими проверяемыми предметами. Например, в лист сперва вносите всё вино, потом добавляете всё мясо, потом всё ... и т.д. Получится список, в котором отсортированы предметы Potion. Можно сделать отдельными списками на каждый тип продукта, это как будет удобнее автору. Далее проверка очень простая:
FormList Property ListItemPotion Auto
Function ChengInventory() int iFormIndex = akActor.GetNumItems() While iFormIndex > 0 iFormIndex -= 1 Form kForm = akActor.GetNthForm(iFormIndex) int iIndex = ListItemPotion.Find(kForm) if iIndex != -1 if iIndex <= 12 ; это вино, т.к. в листе первые 12 объектов == вино ; считаем кол-во вина elseif iIndex > 12 && iIndex <= 25 ; это мясо, т.к. в листе с 13 по 25 объект == мясо ; считаем кол-во мяса elseif iIndex > 25 ; это продукты питания типа сыра и лука, т.к. ... ; считаем кол-во endif endif endWhile endFunction
*********************************************
На этом принципе построения можно создать много разных вариантов скрипта. (необходимые переменные добавь сам, и не забудь назначить/обозначить akActor)
AleksTirex, не знаеш случайно, а можна ли во время движения лифта сделать так, чтобы ГГ или напарник стояли жёстко на платформе. А то лифт едет вверх - ноги встряют в модель, едет вниз - персонаж зависает в воздухе, а потом падает вдогонку на лифт. Всё бы ничего, но кроме двухэтажного дома планирую ещё и небоскрёб, а там уже падение критично (шутка ли, 100 этажей, вровень с Высоким Хротгаром)
Скинь ниф лифта и заодно положи в архив все исходники скриптов, связанные с этим лифтом. Есть разные варианты решения, я посмотрю, какой лучше подойдёт.
Пока Криста не начнет создавать НПС, будем с этим иметь геморрой с кулак... я давно спрашивал Кристу об этом... она не отказала, но и воз по ныне там.
А причём здесь Криста? Подобные вопросы надо задавать создателям этих моделей, а не ей.
При создании любой модели автор обязательно проверяет её в игре, и не увидеть такого положения модели в СК просто невозможно. А раз автор видел и ничего не исправил, значит, это или невозможно, или слишком трудно.
На сколько я знаю, на этом и большинстве других форумов нет ни единого модмейкера, способного создать/переделать модель головы, а уж сделать её без багов... и речи не идёт. Увы, но привыкайте к такому виду в СК этой головы, по другому никогда не будет.
******************** Я тоже попробовал использовать эту модель головы для своего НПС, но в последствии отказался. Уж больно забагована она, особенно в плане лицевой анимации, да и "морфинг" плохой - лицо получается гораздо хуже/некрасивее, нежели на дефолтной модели.
при активации рычага или же попадание в определённое место на карте, скажем ходьба через коридор где игрок наступает на триггер и появляется нужный объект. Например чтобы пройдя коридор за спиной появился, предположим, скелет.
Скрипт вешается на активатор(рычаг) или на триггер. Там пошагово расписано, поэтому там всё понятно.
AleksTirex, разве с xMarkerHeading нужно использовать не PlaceAtMe()? И зачем удалять созданного актера через 5 секунд после создания? Он же для чего то создавался... И попутно вопрос: вот таким образом созданный, а потом удаленный актер оставляет какие либо следы в сейвах или нет?
Да, всё верно, это я со слепу и по запарке ошибся надо PlaceAtMe().
Удалять же актёра... так он сам писал: "...появлялся скелет, а потом исчезал." (но сейчас уже не нахожу этой строки, или он откорректировал сообщение, или я уже совсем суперстар, типа совсем старый, слепой и чуть-чуть в маразме ). Если актёра удалять не надо, тогда просто удалить строки ожидания и удаления актёра: Utility.Wait(5.0) ; ждём 5 сек. потом удаляем актёра и временный маркер akNewActor.Disable() akNewActor.Delete()
Следов в сейвах, в принципе, остаться не должно, для этого и пишется команда Delete(), т.е. не выключить, а именно удалить.
******************************************
Иероним, свойствам назначил нужные ID? (маркер и актёра)
И замени akPlayer.PlaceActorAtMe(xMarkerHeading) на akPlayer.PlaceAtMe(xMarkerHeading)
Это код из модификации Lightning Just in Time. Он очень хитрий и я решил не трогать его а добавить свой скрипт.
Если правильно понял, то надо не включать объект при каких-то условиях. И этот объект один из light_1...light_3 и т.д? Если это так, и очень не хочется вмешиваться/изменять тот скрипт, то можно просто в том скрипте удалять (стирать) ссылку на свой объект если включать нельзя, и потом опять её добавлять, когда включать/управлять можно.
Например, твой объект light_3, тогда на него повесь скрипт:
ObjectReference Property akObject Auto
Function OnOff() if ; условие запрета включения объекта light_3 (akObject as LightingBall).light_3 = none else (akObject as LightingBall).light_3 = self as ObjectReference endif endFunction
akObject - это объект, на котором висит основной скрипт, LightingBall - название того скрипта.
В любой функции или событии запускается команда на эту функцию OnOff(), или при загрузки локации, или по какому-то триггеру (но до срабатывания основного триггера того скрипта), или ещё как. Там в зависимости от условий, можно включаться или нет, стирается или восстанавливается ссылка на свой объект.
Если нет ссылки на объект, то его и выключить нельзя, просто нечего выключать.
*************
Можно и на другой объект повесить такой скрипт, тогда вместо self передавать назначенное свойство на свой объект. Это сам принцип, дальше уже придумаете что и как.
Собственно говоря, задача в том, чтобы вправлять мозги редактору и заставить его считать валидным тот меш, который считаю валидным я сам и не позволить ему диктовать мне, когда мне этот меш экспортировать, а когда нет.
Myprism, вот я прочитав это, подумал, а зачем это надо, для какой цели? Не проще ли нажимать кнопки и генерить снимки после редактирования внешности головы?
Если это надо для "динамических голов", т.е. когда прямо в игре меняется голова, например при смене расы, то тогда понятно, но при редактировании в СК, не понятно (честно, не могу придумать ни одного примера).
Например я, для манекенов вообще не использую эти снимки, и мои манекены могут менять и расу и пол. При этом их головы всегда нормальные, ничего серого и неправильного, и это без всяких снимков. Дело в том, что у движка есть баг с генерацией/чтением снимков головы НПС во время игры, и это дело можно использовать во благо. Так вот, при загрузки НПС генерится голова на основе снимка (который FormID.nif) и сравнивается с записями в ESP/ESM, и если есть различия, то и происходит баг "серой головы", т.е. движок начинает игнорировать снимок. Но и это не всё, при повторной генерации головы движок как бы "понимает", что накосячил и генерит правильную голову, но только от предыдущего варианта, т.е. запаздывает.
Так если принудительно быстро заставить перегенерить голову 2-3 раза со сменой расы так, чтобы предпоследний вариант головы совпал с нужной/желаемой нам головой, то голова сгенерится правильная, на основе записей из ESP, а не из снимка. Геометрия и текстуры будут правильные, серого бага не будет. Хотя, для идеала желательно, чтобы "тон кожи" у НПС отсутствовал вообще, или как минимум, был совсем белым, тогда цвет головы и тела будут идентичны.
********* Это информация для самых любопытных искателей. Пробуйте, это работает точно.
Так вот мой вопрос в том и заключался - как обходиться без этих шаманских бубнов?
А никак. В нынешнем СК даже довольно безобидные операции, причём даже дефолтные, практически и есть тот самый бубен. А сам принцип "безснимковых голов" довольно прост, и в игре этого даже не видно, в смысле бубна и остального.
Для твоих целей, конечно, этот метод не нужен, но вот ты в игре попробуй командой любому НПС сменить расу, и сразу увидишь, что от "серого эффекта" ничем не спастись, Скайрим просто на такое не рассчитывался. Корректная смена расы только у ГГ. А этот метод позволяет менять расы НПС с сохранением внешности.
Не могли бы вы помочь со скриптом? Мне нужен скрипт, при котором между игроком и нпс начинается поединок, при этом - или нпс не наносить никакого урона (и магией тоже, или магия блокируется). - или стоит со щитом и просто блокирует удары. Мне этот скрипт нужен для создания тренера, который учит не только с помощью окно, но и проводит настоящие тренировочные поединки.
akFaction - любая фракция с Ally сама на себя. Перк - EntryPoint - Mod Attac Damage - *0.0, т.е. наносимый урон неписем никакой.
Старт "дружбы":
akActor.IgnoreFriendlyHits() akActor.AddPerk(akPerk) akActor.AddToFaction(akFaction) Game.GetPlayer().AddToFaction(akFaction) akActor.GetActorBase().SetInvulnerable() ; актёр теперь неуязвимый, ему не нанести урон
Теперь непися можно лупить как угодно, он не ответит.
Далее пакет или сцена-пакет: НПС атакует UseWeapon (желательно правильно поставить все галочки), или НПС стоит лицом к ГГ и оборняется (пакет Travel, галочки Weapon Draw + Ignore Combat). Запуск сцены akScena.Start().
Однако эффекта не вижу. Похоже, спеллы просто не назначаются. Лог папируса выдает следующее:
Если компилятор выдаёт ошибки, то это значит, что скрипт не скомпилирован и работать не будет. Поэтому и эффекта не видно.
Возможно, компилятору не нравится сам массив. Тогда просто введи временную переменную Actor и назначай на неё актёра из массива, потом работай с этой переменной, а не с массивом. Тогда компилятор будет видеть "чистого актёра", и возможно, он перестанет кочевряжиться. Попробуй такой вариант:
Scriptname aaAlliriaRCRNPCQuestScript extends Quest Spell Property aaARCRWeapArmMatSpecBase auto Spell Property aaARCRabilityWeapArmMatSpecDrag auto Spell Property aaARCRabilityUndead auto Spell Property aaARCRabilityUndeadMod auto Faction Property _00SICUndeadFaction auto Actor[] ClosestActors Event OnInit() Actor TempActor ClosestActors = new Actor[120] ; назначаем массив на 120 ячеек While IsRunning() ; работает, пока квест активный int iIndex = 40 ; количество попыток поиска актёров While(iIndex > 0) ; поиск актёров около ГГ iIndex -= 1 Actor randomActor = Game.FindRandomActorFromRef(Game.GetPlayer(), 30000.0) ; радиус поиска ~4096*7 If !randomActor.HasSpell(aaARCRWeapArmMatSpecBase) ; если у НПС нет спелла randomActor.AddSpell(aaARCRWeapArmMatSpecBase) ; добавляем спелл endIf If !randomActor.HasSpell(aaARCRabilityWeapArmMatSpecDrag) randomActor.AddSpell(aaARCRabilityWeapArmMatSpecDrag) endIf If !randomActor.HasSpell(aaARCRabilityUndead) randomActor.AddSpell(aaARCRabilityUndead) endIf If !randomActor.HasSpell(aaARCRabilityUndeadMod) && randomActor.IsInFaction(_00SICUndeadFaction) randomActor.AddSpell(aaARCRabilityUndeadMod) endIf int iEmpty = ClosestActors.Find(none) ; поиск свободного слота в массиве if iEmpty > -1 ClosestActors [iEmpty]= randomActor ; записываем актёра в массив endif int iIndexActor = 120 While iIndexActor > 0 ; проверка массива iIndexActor -= 1 TempActor = ClosestActors [iIndexActor]if TempActor ; если есть актёр под этим номером if (TempActor.GetDistance(Game.GetPlayer()) > 30000) || TempActor.IsDead() ; если актёр далеко или актёр мёртв TempActor.RemoveSpell(aaARCRWeapArmMatSpecBase) TempActor.RemoveSpell(aaARCRabilityWeapArmMatSpecDrag) TempActor.RemoveSpell(aaARCRabilityUndead) TempActor.RemoveSpell(aaARCRabilityUndeadMod) ;TempActor.DispelAllSpells() ClosestActors [iIndexActor]= none ; очищаем слот в массиве endif endif endWhile endWhile Utility.Wait(3.0) ; через 3 сек. новый поиск актёров endWhile int iIndexClear = 120 While iIndexClear > 0 ; очистка массива iIndexClear -= 1 TempActor = ClosestActors [iIndexClear]if TempActor ; если есть актёр под этим номером TempActor.RemoveSpell(aaARCRWeapArmMatSpecBase) TempActor.RemoveSpell(aaARCRabilityWeapArmMatSpecDrag) TempActor.RemoveSpell(aaARCRabilityUndead) TempActor.RemoveSpell(aaARCRabilityUndeadMod) ; TempActor.DispelAllSpells() ClosestActors [iIndexClear]= none ; очищаем слот в массиве endif endWhile Debug.Notification("Alliria NPC quest and script had finished") ; сообщение для теста endEvent
Радиус поиска 30000 - это слишком много, т.к. загружаются в игру максимум 3 ячейки от ГГ (1 ячейка == 4098), в интерьерах так вообще будут видны и обрабатываться все имеющиеся там НПС, хоть и находятся они "в трёх днях пути". А так же в скрипте нет проверки на "что это за актёр", т.е. скрипт без этого будет вешать абилки и на крабов, и на драугов и на всё движущееся и шевелящееся, а оно надо? (достаточно проверки наличия кейворда ActorTypeNPC).
Для гарантированного получения события смерти через маг.эффект достаточно в событиии OnEffectFinish() обозначить условие IsDead() (галочку No Dispel Death обязательно снять), и уже там прописать нужное действие.
Event OnEffectFinish(Actor akTarget, Actor akCaster) if akTarget.IsDead() ; делаем endIf endEvent
Для получения референса кастующего и цели в маг.эффекте не обязательно использовать перенос переменной из OnEffectStart наружу и запоминать его. Можно их получать непосредственно в теле любой функции скрипта:
Function AAA() Actor akActorCaster = GetCasterActor() Actor akActorTarget = GetTargetActor() ; endFunction
Alliria, если у тебя цель скрипта "повесить абилку на НПС и потом её удалить при отдалении или смрти НПС", то не надо никаких массивов и форм-листов, и не надо вообще запрминать каких-либо НПС. Есть решение проще: делаешь цикл только на поиск НПС и раздачу абилок тем, у кого нет такой абилки. Это работает на порядок быстрее и надёжнее. На самой абилке условие: расстояние self-player < №№ и GetDead == 0. Тогда абилка сама выключится. Для полного удаления абилки на её эффекте вешается простой скрипт:
Spell Property akSpell Auto Event OnEffectFinish(Actor akTarget, Actor akCaster) akTarget.RemoveSpell(akSpell) endEvent
В результате в рабочем скрипте останется только цикл на поиск и раздачу. Несовместимостей и лаж будет минимум.
Так делать нельзя, точнее бесполезно. Пересчёта запусков не будет. Статус тоже бесполезен, второго OnEffectStart в данном эффекте по определению возниктуть не может. Считать количество OnEffectStart, естественно, тоже не получится.
Scriptname newscript extends activemagiceffect
При оконяании эффекта заканчивается работа данного скрипта, и всё, что было в нём - переменные, свойства и т.д. безвозвратно теряются. При следующем возникновении этого эффекта будет работать уже другой скрипт, копия этого, но другой, и все данные в нём будут девственно чисты.
Если необходим просчёт количества стартов этого эффекта, то надо запоминать вне этого эффекта, например в квесте или устойчивом референсе. Наапрмер:
Event OnEffectStart(Actor akTarget, Actor akCaster) (muQuest as muQuestScript).ivCounter += 1 endEvent
*****
Для справки: таким же эффектом обладают массивы (!), при перезапуске скрипта они обнуляюся и их надо назначать по новой. Напимер, если создать массив в квестовом скрипте, то при выключении квеста массив стирается, что не происходит с другими переменными и свойствами в этом скрипте.
Скрипты начинают работать сразу при их создании и инициализации в игре. Если скрипт не запустился, то ищите причину не в порядке загрузки и прочем подобном, а в самом написании скрипта. Скрипт может не запустится, если его команда "зависает" и/или не может выполнится, из-за некорректных команд и т.д. Так же следует проверить "возможно, уже запущен твой маг.эффект", вот скрипт и как бы не срабатывает, т.е. стартеффект не запускается, что вполне естественно. Событие-функция OnInit() отрабатывает только один раз при инициализации скрипта движком. В квестах оно срабатывает ещё и при каждом запуске этого квеста (квестовый скрипт и алиас). Так же не надо забывать о свойствах - они не изменятся, если скрипт уже начал свою работу и вы сохранились. Как не меняй значение этого своёства в СК, оно так и останется тем старым, что было при запуске скрипта, эти данные остаются в сохранке.
Добавлено (02 Апреля 2014, 23:38) --------------------------------------------- Форматирование стёрло содержание спойлера, тот оно:
Scriptname newscript extends activemagiceffect Spell property Fireball auto Int ivCounter = 0 Event OnEffectStart(Actor akTarget, Actor akCaster) Fireball.cast(selfRef) ivCounter += 1 if ivCounter > 2 ;- Скрипт сработает 3 раза потом выключится и перезагрузится ivCounter = 0 GoToState("DoNotWork") ;- Переводим скрипт в состояние ничего не делать Utility.Wait(2) ;- Задержка 2 сек. GoToState("") ;- Возвращаем скрипт в нормальное состояние EndIf EndEvent State DoNotWork ;- Скрипт в состоянии: "Ничего не делать" Event OnEffectStart(Actor akTarget, Actor akCaster) EndEvent EndState
AleksTirex, а что происходит в игре если скрипт попал в сохранение, а после он был полностью заменен, то есть название тоже, а содержание (процедуры, события, свойства) другое. Можно новый скрипт как то заставить работать или это не реально?
Новые события и новые функции работать должны при любом изменении скрипта. Но желательно, чтобы на момент сохранения ВСЕ команды отработали полностью. Особо это касается циклов и OnUpdate(), они продолжат свою работу и в изменённом виде. Хотя, OnUpdate уже станет отрабатывать новые вложенные в него команды, если старые полностью отработали. Сохранка запоминает своёства и работающие фрагменты скрипта. Если блок (событие/функция) отработали полностью, то их можно смело изменять, они начнут свою работу по новому сценарию. А вот свойства так и останутся теми, что попали в сохранку, и менять их бесполезно, разве что создавать новые с новыми именами. Ну или грузится с чистой сохранки, что лучше.
Изменение репутации для пользователя AleksTirex
AleksTirexOffline
Сообщение №289
| Тема: Вопросы по скриптам Papyrus
написано: 2 апреля 2014, 21:34
| Отредактировано: AleksTirex - 2 апреля 2014, 21:29
Так нельзя, ГГ будет бросать спелл себе под ноги. Ведь спелл целевой, а не на себя, поэтому цель надо обозначить. Проблема именно в определении этой цели, в её референсе. С НПС проще, можно взять Target и использовать как цель. С ГГ сложнее, Target толком не работает на нём, т.е. движок не может определить цель игрока.
Но можно схитрить и обмануть движок: 1. Делается свой визуально невидимый Projecticle с большой скоростью. 2. В основной спелл назначается этот Projecticle, и именно этим спеллом будет лупить ГГ. 3. На этот эффект вешается простой скрипт, который отдаёт референс жертвы, она и есть наша цель. Далее отдаёт его в ... это уже дело хозяйское куда именно, но туда, где будет команда для визуальных кастов, хоть дюжины. Это можно сделать и в этом эффекте и никуда не передавать:
4. Делается спелл или берётся уже готовый, который будет визуально кастоваться на уже известную нам цель/референс.
Можно дать небольшую задержку между кастами, для большей визуальности.
Добавлено (03 Апреля 2014, 01:34) --------------------------------------------- Забыл добавить: спеллы надо делать одного типа, чтобы визуально было подобие родного каста, ведь командой кастуется спелл без анимации.
nepewka, а почему именно onSpellCast? Чем плохо событие OnEffectStart?
Тогда внимательно читаем мой пост: Проблема именно в определении этой цели, в её референсе. Так вот при любом событии, хоть onSpellCast, хоть при OnHit и т.д. нужно знать референс цели, куда направить заклинание. А где его взять то? Вот OnEffectStart и выдаст нам этот референс.
Если сделать быстрый Projecticle, то практически срезу при касте будет известен референс цели. И видимый спелл полетит в цель почти сразу же, так будет видимость, что именно этот спелл и кастовал ГГ.
Если Тебе надо один видимый Projecticle и несколько взрывов от него, то это совсем другой вариант, нежели ты описывал ранее. Вот здесь и нужен именно вариант с OnEffectStart в основном эффекте. Тогда при его срабатывании жертва сама на себя кастанёт нужные заклинания и в любом количестве. И не будет лишних визуальных Projecticle, а будет эффект, как будто твой спелл имеет несколько эффектов.
№ 3) - OnHit работать не будет. Какие либо другие события тоже не будут. Ведь любое событие должно на чём-то висеть. И оно отслеживает "что именно произошло с этим объектом". Так OnHit - это событие возникает, когда объект получает удар. И именно тот объект, на котором висит этот скрипт с этим событием. Чтобы его использовать, надо на всех возможных в игре жертвах повесить скрипт с этим событием, а это... сам понимаешь. Точно так же и с любым другим событием.
№ 4) вообще не понял.
"Смысл в том, чтобы не кастуя основной спелл, лишь запуская на долю секунды его анимацию, у нас вылетал уже готовый спелл по скрипту.. " Вот это я и предлагал с быстрым Projecticle. (смотри начало этого поста)
Ты определись, сколько видимых Projecticle ты хочешь, и сколько и как видимых "взрывов". В разных пунктах своего поста у тебя разные мнения/пожелания.
Добавлено (03 Апреля 2014, 02:43) ---------------------------------------------
Цитата nepewka
Animation events в CK wiki. Там есть анимации, BeginCastLeft, BeginCastRight, StopCast Смысл в том, чтобы не кастуя основной спелл, лишь запуская на долю секунды его анимацию, у нас вылетал уже готовый спелл по скрипту..
Но опять же, нужен референс цели akTarget. (а где его взять?..) BeginCastLeft - должно быть событие, а не ID анимации (в настройках анимации оно написано) Писать эти команды можно где угодно и в любом скрипте, событии, функции.
Alliria, так нет проблем. Делаешь одну абику, и в ней сколько надо разных маг.эффектов. В каждом эффекте свои условия на своего актёра. Так при получении общей абики у каждого актёра сработает свой эффект, условия которого совпадут.
Все манипуляции можно проводить в том же эффекте, а можно и сделать отдельный эффект для всех актёров, а в нём играться с одеждой и прочим. Если возникнут проблемы нежелательного отключения эффекта и потере данных, то можно все функции и переменные вынести в не выключаемый квестовый скрипт, и уже командой из эффекта запускать нужные функции в том скрипте, при этом передавая все нужные данные в тот скрипт.
Проще, чем простое сканирование и простая раздача - уже никак, меньше просто некуда. Все остальные проверки пусть сам движок делает в своём дефолтном режиме.
Но если ты повесишь этот скрипт на основной спелл и назначишь akSpell этот же самый спелл, то получишь цикл, почти бесконечный цикл.
Ты на одно из свойств akSpell назначил этот же спелл, на котором висит этот скрипт, т.е. самого себя. Вот ты и получил цикл. В итоге этот спелл плодит сам себя. А надо назначать любой другой спелл, хоть самодельный, хоть дефолтный. Тогда при одном касте полетят только те спеллы, что прописаны в свойствах и в количестве равном количеству команд каста. И не будет ГГ строчить как из пулемёта. (я же всё это писал, надо только внимательно читать)
OnEffectEtart работает только один раз, и команды в нём срабатывают тоже только один раз.
Если хочешь сделать "очередь" как из пулемёта, но не бесконечную очередь, а 1-2-3 секунды, то можно так:
Event OnEffectStart(Actor akTarget, Actor akCaster) int index = 5 While index > 0 index -= 1 akSpellXX.Cast(akCaster, akTarget) Utility.Wait(0.2) endWhile endEvent
akSpellXX - другой спелл, не этот, на котором висит скрипт (!) В течении одной секунды вылетит 5 файерболов. Количество кастов и задержку меняй сам по своему желанию.
************************
Твой пример скрипта не совсем корректный. Там при начале анимации ГГ кастует сам на себя заклинание. Тебе это не подходит, у тебя целевые заклинания (!). А где ты возьмёшь референс цели, на которую должны полететь заряды? Всё упирается именно в это. Пока ты не решишь вопрос с получением референса цели, что-либо дальше делать бесполезно. А вот когда в своём скрипте будет известен этот референс, то можно хоть сотню разных вариантов напридумывать.
Вот для этого и нужен скоростной невидимый спелл, который и определит этот референс. Этот спелл/эффект может просто отдать/передать значение референса в любой твой скрипт, и уже в нём можешь как угодно развлекаться с кастами по цели, она ведь будет уже определена.
************* Внимательно прочитай самую первую строчку этого поста и хорошо запомни её.
Изменение репутации для пользователя AleksTirex
AleksTirexOffline
Сообщение №293
| Тема: Вопросы по скриптам Papyrus
написано: 3 апреля 2014, 13:17
| Отредактировано: AleksTirex - 3 апреля 2014, 14:35
Создали мы этот спелл, что дальше. Как сделать из него референс?
Короче говоря, я не могу понять: а) как конкретно спелл может стать референсом? б) Чем спелл может помочь в определении референса цели? (в упор просто не пойму)
Из спелла никак не сделать, как и из любого объекта. Референс - это типа как имя, номер изделия, и т.д. У тебя есть имя? Есть, но ведь из тебя не получится сделать твоё имя, его можно только узнать, но не сделать (!). Так же и с референсом, его можно узнать, какой именно референс у данного объекта, типа "какое имя у объекта". Каждому объекту в игре назначается свой референс, типа имени или номера, а иначе как бы движок различал объекты в игре. И если надо что-то сделать с объектом, например с Алдуином, надо знать какой у него референс в игре.
Так вот при попадании на НПС заклинания на нём/НПС возникает магический эффект, это ты знаешь, так этот эффект непосредственно висит на этом НПС и он/эффект "знает", на ком именно он висит, что логично. Так можно узнать у этого эффекта, на ком именно он висит, как бы спросить у него.
При возникновении на НПС-жертве маг.эффекта возникает событие - "старт-эффект" Event OnEffectStart(Actor akTarget, Actor akCaster) , которое знает, кто послал это заклинание и в кого оно попало.
Так вот: akCaster - это кто послал этот спелл/заклинание, т.е. кто кастовал его. akTarget - это цель спелла/зклинания, т.е. в кого оно попало и на ком возник данный маг.эффект. Т.е. есть референсы кастующего и жертвы.
Вот этот референс akTarget и надо использовать как цель ГГ для каста новых заклинаний.
****** Сперва пойми и вникни в это. И пойми/разберись, что такое референс и что такое заклинание и маг.эффект. Тогда сможешь дальше сам писать скрипты и делать заклинания.
Как отследить момент, когда ГГ дает указание спутнику, чтоб тот взаимодействовал с миром, например обыскал сундук или колол дрова или крафтил ченить?
Твой созданный спутник или вообще любой?
В Скайриме всё построено на событиях, так вот их и надо отслеживать. Т.е. события, возникающие на НПС-спутнике. Для этого надо записать НПС в свой алиас и в нём отслеживать события, происходящие с НПС. Отслеживать можно изменение пакетов, активацию неписем каких-то объектов (это проще через перк на НПС) и т.д.
Если спутник твой, то просто в каждом топике/команде результирующий скрипт, который отдаст "описание" команды, которую даёт ему ГГ.
Если НПС может и без приказа что-то начать делать (колоть дрова, крафтить и т.д.), то только первый вариант.
А именно, при указании спутнику на алтарь Боэтии сделать агр персонажа с неизбежной смертью ГГ.
Не ругайтесь и не смейтесь - опять заклинание-абилка.
Делаешь абилку и даёшь алиасу НПС (дак угодно даёшь). В условиях заклинания (не на эффекте !) ставишь: Target - референс_Боэтии - ==1. И другие нужные условия (если надо). На эффекте скрипт с нужными тебе командами.
Т.е. когда у НПС целью станет статуя Боэтии, тогда запустится эффект и отработает скрипт с твоими командами. Произвольно целью статуя стать не сможет, т.к. цель-Target возникает у НПС в момент, когда НПС "решил" активировать объект и пошёл к нему (вплоть до окончания взаимодействия с этим объектом). Сам по себе НПС ну очень вряд ли пойдёт активировать статую, пока ГГ не даст на это команду.
nepewka, "выход"... какой выход? Получение референса цели? Так я же всё подробно расписал.
Вот этот референс akTarget и надо использовать как цель ГГ для каста новых заклинаний.
Референс - это не существо, это идентификационный номер объекта, любого объекта: НПС, грязекраб, статуя, камень на дороге, валяющаяся палка или монетка и т.д. Референс есть у каждого объекта в игровом мире.
LordVadim, RegisterForUpdate(3)так нельзя. (читай свой собственный пост немного раньше)
Циклы и постоянное обновление вместе делать нельзя. В данном случае это не критично, но всё же не стоит (народ привыкнет так делать и... результат предсказуем )
Изменение репутации для пользователя AleksTirex
AleksTirexOffline
Сообщение №297
| Тема: Вопросы по скриптам Papyrus
написано: 3 апреля 2014, 20:33
| Отредактировано: AleksTirex - 3 апреля 2014, 20:41
Например если я надену шапку, то когда подпрыгну - буду висеть в воздухе в позе "лотоса"; а без шапки прыжок оставался бы обычным.
Анимация в Скайриме работает довольно глючно. Отследить событие своей анимации вряд ли получится, разрабы об этом позаботились. Отслеживать событие прыжка тоже... не факт, что сможешь зарегистрировать и получить его событие, ведь довольно мало событий анимации можно так получить. Если же ты не против SKSE, то всё гораздо проще - следишь за нажатием кнопки "пробел", а это работает стабильно.
Добавлять свою анимацию прыжка и подменять ей дефолтную, скорее всего можно (я именно прыжки не пробовал подменять). Открываешь в СК анимацию, нужный бехавиор, ActionJamp. Дублируешь JumpRoot и вставляешь его выше родного. Там добавляешь новое условие: "subject - если надета шапка == 1". Возможно, в родной JumpRoot придётся добавить обратное условие: "если не надета шапка". (чаще всего порядок расположения анимаций движком игнорируется) Далее внутри своего JumpRoot прописываешь свои события анимации. Естественно, что СК надо запускать только после создания своего бехавиора и после обновления мастер-бехавиора FNIS-сом, иначе СК не увидит этих событий. Названия файлов анимации и события должны быть исключительно уникальными, иначе однозначно возникнут лажи (IdleJamp - так писать нельзя).
Далее уже сам крути как хочешь, но зарегистрировать и получить событие этой анимации не получится, просто не сработает, увы.
Кстати, если ты хочешь сделать последовательную анимацию прыжок+висит, то забудь, FNIS это очень глючно прописывает, и как правило, стартовая анимация (s -a) пропускается и сразу начинает работать бесконечная (+). Это происходит с шансом ~20%, а при первом запуске этой анимации за сеанс ~95%. Т.е. такую цепочку из анимаций лучше запускать отдельно, каждую анимацию отдельно, а не запускать стартовую в цепочке связанных анимаций.
********************************************
сергей007788, в играх, и Скайрим не исключение, весь мир крутится вокруг игрока, так что... не ищи ответа на этот вопрос. Разве что, телепортировать туда ГГ.
LordVadim, безумный вариант: делаешь тестовый мод, копируешь в него свой ЗЭ, остальные удаляешь (!), сохраняешься и проверяешь. Поскольку твой там один (и оставь экран майн-меню), то и срабатывать он будет постоянно. Потом ESP удалишь.
Изменение репутации для пользователя AleksTirex
AleksTirexOffline
Сообщение №299
| Тема: Вопросы по скриптам Papyrus
написано: 4 апреля 2014, 12:14
| Отредактировано: AleksTirex - 4 апреля 2014, 12:31
Есть ли какие команды или способы сделать чтобы объект к которому применена команда Translate не проходил сквозь стены.
Заранее благодарен.
Чтобы объект перемещался с сохранением коллизии, надо делать MovableStatik с изменённым нифом, т.е. немного поправить нужный ниф:
bhkRigidBody Layer: Заменить OL_STATIC на OL_ANIM_STATIC. Layer Copy: Заменить OL_STATIC на OL_ANIM_STATIC. Motion System: Заменить MO_SYS_BOX_STABILIZED на MO_SYS_BOX.
В этом случае можно стоять на таком движущемся объекте и не проваливаясь двигаться вместе с ним, т.е. на нём. При команде TranslateTo() коллизия статиков игнорируется, и объект проходит сквозь них. К сожалению, пока неизвестен вариант это изменить без багов.
anton, у меня на озере, недалеко от Ривервуда в Полулунной лесопилке, есть лодка, на которой можно покататься по озеру. Можно с собой и подружек взять и покатать их. Лодка плавает, управляется, по ней можно ходить во время плавания и т.д. (но не ГГ, т.к. управление лодкой повторяет управление ГГ, а НПС могут по ней ходить) Т.е. всё работает. Вот только проблему столкновения с препятствиями и берегом я не стал решать, так и оставил - лодка их не видит.
Эвента на столкновение с коллизией нет, в бехавиоре другой принцип - он использует эвенты для запуска анимации, а не генерит само событие. Это событие/эвент с привязкой к объекту генерит движок, а бехавиор реагирует на него и запускает нужную анимацию на нужном объекте (точнее это движок запускает анимацию, ведь бехавиор - это в принципе как список анимаций, а не исполнительное устройство). Если движок сгенерил событие Weapequip_Out, то бехавиор запускает анимацию вынимания оружия из ножен. А вот почему движок сгенерил это событие - он сам знает (нажата кнопка №№, если событие на НПС, то при начале атаки или режима Alert и т.д.). Так же и с приземлением - движок определяет это дело, и выдаёт нужную команду/событие и т.д. И не факт, что можно найти и "выцепить" само событие приземления, в лучшем случае, можно засечь реакцию движка на это дело (например, запуск анимации приземления).
Высота прыжка действительно не зависит от анимации, это длительность воспроизведения/работы самой анимации зависит от высоты. Сама анимация прыжка длится около 10 сек. (точно не помню), и этого хватает для любой высоты. SpeedMult - это скорость перемещения НПС. В параметрах/скиллах есть JumpingBonus, но вот работает ли он... не знаю. akActor.SetAV("JumpingBonus", 100) - ??? я что-то разницы не замечал.
Добавлено (04 Апреля 2014, 21:09) ---------------------------------------------
Цитата anton
1. Коллизия у "статика" сама всё таки не перемещается. (перемещаю триггером со скриптом, командой Stone.TranslateToRef(Place, StoneSpeed))
Не Static, а MovableStatic. На статике и не будет работать, этот объект надо в моваблестатике прописать.