[WIP Brainstorming] Universal Follower Function Library

Post » Sat Dec 22, 2012 12:28 pm

Hey, all. Frostfall 2.0 is starting to get wrapped up, so I've been looking ahead at what comes next. Frostfall 2.1's major focus will be Followers and NPCs, and the way that they are affected by cold. However, some things I've already learned from experience from working on Wearable Lanterns:
  • Supporting followers, even in vanilla Skyrim, is a big bag of hurt. Bethesda can't make up their minds about how they would like to handle followers. There are at least 2 different conventions used in the base game ("normal" followers, like Jenassa, and Dark Brotherhood followers). Three if you count Dawnguard, which uses its own system of aliases.
  • There are several major multi-follower mods: Amazing Follower Tweaks, Ultimate Follower Overhaul, and Extensible Follower Framework. There might be more, but those are the ones that come to mind. They all have their own system of managing followers and their own ReferenceAliases.
Because of the above difficulties, it's hard to do things like:
  • Assign generic dialogue topics to followers.
  • Run scripts against some or all followers currently in service.
  • Know exactly how many followers you have.
  • Provide support for all types of multi-follower mods.
  • etc
Because of these problems and the fact that I'm tired of dealing with them, I would like to, after Christmas break, start putting together something called the Universal Follower Framework API that would try to bridge the gap between all of these. In my opinion, I should be able to support all multi-follower mods regardless of implementation, and support all followers from the base Bethesda game, while ensuring the integrity of my script information. This system would essentially be a set of Papyrus global functions call-able by any mod that wants to use them and support followers better.

In the words of charon711, who summarized the purpose of this quite succinctly,

So basically this mod will help "translate" functionality between followers (no matter how they are implemented) and mods that effect the followers. Making follower mods universally compatible with each other and with any mod that effects them.

My more technical summary would be,

"A Papyrus API that acts as a go-between (middleware) for script writers and followers by abstracting individual follower implementations and representing them in a generic way."

Some ideas for functions would be:

Spoiler

Actor function GetNthFollower(int iFollower)int function GetFollowerCount(bool bIncludeAnimals = false)bool function IsFollower()int function GetFollowerIndex()

...and so on. Just very generic functions that enable you to do powerful things regardless of the user environment.

WIth the above examples, I could do something like...

Spoiler

if Jenassa.IsFollower()	if Jenassa.GetFollowerIndex() == UFF.GetFollowerCount() - 1		notification("Jenassa, you are the last follower! Haha!")	endifendif

Or, imagine that you and all your followers are gearing up for a massive battle with the enemy, and you want to make sure that all of your companions are dressed appropriately.

Spoiler

int iFollowerCount = UFF.GetFollowerCount()int i = 0while i &--#60; iFollowerCount	Actor myFollower = UFF.GetNthFollower(i)	if myFollower.GetItemCount(BattleCape) == 0		myFollower.AddItem(BattleCape, 1)		myFollower.EquipItem(BattleCape)	endifendWhile

Silly, but you get the point. Imagine trying to do that when you don't know if your user is using EFF, or UFO, or AFT, or none of the above.

So, the purpose of this thread: what kinds of features would you want in a Follower API such as this? What would make your life easier when trying to support the multitude of followers and follower mods in existence?

Thanks!
User avatar
Facebook me
 
Posts: 3442
Joined: Wed Nov 08, 2006 8:05 am

Post » Sat Dec 22, 2012 5:50 pm

Do you plan to address followers outside of the vanilla system? If so, I'd like to suggest/request that you enable makers of follower mods to opt in or out of your framework's elements in a granular way. Otherwise--well, to use your example, followers like Vilja or my Aela already have systems to switch outfits when entering battle. I think some of the big follower frameworks do, too. If there's some other mod on top of that using the API to do the same thing, it just makes a mess. Likewise mods trying to add new dialogue topics to custom-voiced followers who have their own carefully crafted conversation trees...that sort of thing is as jarring and unaesthetic to me as a spotless tent in a Winterhold snowstorm probably is to you.

In other words, I can understand you might want to be able to do certain things like have all followers put on a warm cloak when it gets cold with Frostfall, regardless of how many followers the player has or which framework they're using. Fair enough. But I can equally see the maker of a follower, or a framework, wanting to have followers put on a warm cloak when it gets cold, regardless of whether or not the player is using Frostfall. And as a maker of a follower, the ideal thing for me would be to be able to say in some cases "Chesko's API has already allowed the creation of a mod that does X in a superior way, so if the player has it installed, I'll turn off my custom version of X and let the other mod do its thing" and in some other cases say "my method of offering that functionality suits the character and personality of my follower better than any generic system, so I'm going to opt-out of the API's awareness when it comes to that element and use my own functions." Does that make sense?

(Edit: or a third case, something like: "I'm going to combine elements of my mod and the other mod, so for example I'll use my own mod's follower outfit system to allow the player to define a cold-weather outfit for the follower, but I'll use Frostfall's region and weather definitions to determine when the follower should put that outfit on." That, I suppose, would mean a Frostfall API that follower mods could tap into, rather than/in addition to the reverse.)
User avatar
Horse gal smithe
 
Posts: 3302
Joined: Wed Jul 05, 2006 9:23 pm

Post » Sat Dec 22, 2012 2:22 pm

Interesting. Right when I was about to finish my custom made follower. I fiddled that last copple of days how to get multiple followers to work. Unfortunately my mod conflicts with UFO, so I had to drop it.

I'm trying to use a global (MaxFollowerCount) with 3 extra FollowerAliases on the DialogueFollower Quest, which are basically duplicated from the original alias. The global overrides the vanilla PlayerFollowerCount global inside the dialogue conditions. The aliases are basically the free 'follower slots'. I'm then trying to put this inside the DialogueFollower Script, but can't semm to get it working. I'm using:

Spoiler
int Slot1
int Slot2
int Slot3

...

Bool SlotFree1
Bool SlotFree2
Bool SlotFree3

...

ReferenceAlias Property FollowerAlias1 Auto
ReferenceAlias Property FollowerAlias2 Auto
ReferenceAlias Property FollowerAlias3 Auto

...

Global Property MaxFollowers Auto


But I can't seem to get it working inside the script. I've tried multiple different arrangements, to no avail. God, I just wish people would release their source files. I hate when they are so cryptic...:D
User avatar
Kara Payne
 
Posts: 3415
Joined: Thu Oct 26, 2006 12:47 am

Post » Sat Dec 22, 2012 7:47 am

I'm not currently using a companion and may not for this playthrough, but having used UFO and EFF I preferred EFF because you didn't have to initiate dialogue to give orders.

That right there was huge. The fact that to access the NPC inventory or give them a basic order required starting dialogue with them killed immersion and made companions cumbersome - even with UFO.
User avatar
James Smart
 
Posts: 3362
Joined: Sun Nov 04, 2007 7:49 pm

Post » Sat Dec 22, 2012 7:42 am

Ok, I think I'd share what I've got so far:

Spell to summon your follower when loosing him and to add the spell.

Scriptname AWC_AddArnulfSummonSpellScript extends QuestActor Property PlayerREF AutoSpell Property AWC_SummonArnulfSpell AutoQuest Property AWC_ArnulfRecruitQuest AutoEvent OnInit()	RegisterForUpdate(0.1)EndEventEvent OnUpdate()	Bool HasSpell = PlayerREF.HasSpell(AWC_SummonArnulfSpell)	If !HasSpell && AWC_ArnulfRecruitQuest.IsCompleted()		PlayerREF.AddSpell(AWC_SummonArnulfSpell, false)		UnregisterForUpdate()	EndIfEndEventScriptname AWC_SummonArnulfScript extends activemagiceffectVisualEffect Property MGTeleportOutEffect AutoVisualEffect Property MGTeleportInEffect AutoActor Property AWC_ArnulfWarzenSchleggerREF AutoActor Property PlayerREF AutoEvent OnEffectStart(actor Target, actor Caster)	AWC_ArnulfWarzenSchleggerREF.SetAlpha(0, false)	AWC_ArnulfWarzenSchleggerREF.MoveTo(PlayerREF)	MGTeleportInEffect.Play(AWC_ArnulfWarzenSchleggerREF, 2)	AWC_ArnulfWarzenSchleggerREF.SetAlpha(1, true)EndEvent

Trigger Effect for someone appearing out of nowwhere.

Scriptname AWC_ArnulfTriggerEffectScript extends ObjectReferenceActor Property AWC_ArnulfWarzenSchleggerREF AutoVisualEffect Property AbsorbBlueTargetVFX01 AutoVisualEffect Property DA10ReanimateTargetFX AutoVisualEffect Property DA07SummonTargetFX AutoSound Property MAGCloakShockLPSD AutoObjectReference Property AWC_ArnulfTriggerREF AutoEvent OnTriggerEnter(ObjectReference akActionRef)	Game.ForceFirstPerson()	Game.DisablePlayerControls(abMovement = true, abFighting = true, abCamSwitch = true, abLooking = false, abSneaking = true, abMenu = true, abJournalTabs = true)	Game.ShakeCamera(akSource = AWC_ArnulfTriggerREF, afStrength = 0.9, afDuration = 1.6)	AWC_ArnulfWarzenSchleggerREF.EnableNoWait(true)	Utility.Wait(0.1)	Debug.SendAnimationEvent(AWC_ArnulfWarzenSchleggerREF, "BleedOutStart")	AbsorbBlueTargetVFX01.Play(AWC_ArnulfWarzenSchleggerREF, 20)	DA10ReanimateTargetFX.Play(AWC_ArnulfWarzenSchleggerREF, 8)	DA07SummonTargetFX.Play(AWC_ArnulfWarzenSchleggerREF)	int instanceID = MAGCloakShockLPSD.play(AWC_ArnulfWarzenSchleggerREF)	Sound.SetInstanceVolume(instanceID, 1.2)	Utility.Wait(20)	Sound.StopInstance(instanceID)	Debug.SendAnimationEvent(AWC_ArnulfWarzenSchleggerREF, "BleedOutStop")	AWC_ArnulfTriggerREF.Disable()	Game.EnablePlayerControls()EndEvent

Script Fragments

Diverse Dialogue Script Fragments for follower customization.

akSpeaker.SetAV("CarryWeight", 999999) ;from 300AWC_ArnulfWarzenSchleggerREF.ShowGiftMenu(true)akSpeaker.IgnoreFriendlyHits(false)akTarget.SetEssential(); for single actors onlyAWC_ArnulfWarzenSchleggerREF.SetOutfit(AWC_ArnulfWarzenSchleggerOutfit); this is to make followers change outfits

Follower learns and unlearn spells from tomes that you gave him.

Spoiler
If akSpeaker.GetItemCount(SpellTomeBaneoftheUndead) &--#62; 0
akSpeaker.AddSpell(BaneoftheUndead)
akSpeaker.RemoveItem(SpellTomeBaneoftheUndead)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeBanishDaedra) &--#62; 0
akSpeaker.AddSpell(BanishDaedra)
akSpeaker.RemoveItem(SpellTomeBanishDaedra)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeBlizzard) &--#62; 0
akSpeaker.AddSpell(Blizzard)
akSpeaker.RemoveItem(SpellTomeBlizzard)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeBoundBattleaxe) &--#62; 0
akSpeaker.AddSpell(BoundBattleaxe)
akSpeaker.RemoveItem(SpellTomeBoundBattleaxe)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeBoundBow) &--#62; 0
akSpeaker.AddSpell(BoundBow)
akSpeaker.RemoveItem(SpellTomeBoundBow)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeBoundSword) &--#62; 0
akSpeaker.AddSpell(BoundSword)
akSpeaker.RemoveItem(SpellTomeBoundSword)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeCallToArms) &--#62; 0
akSpeaker.AddSpell(CallToArms)
akSpeaker.RemoveItem(SpellTomeCallToArms)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeCalm) &--#62; 0
akSpeaker.AddSpell(Calm)
akSpeaker.RemoveItem(SpellTomeCalm)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeCandleLight) &--#62; 0
akSpeaker.AddSpell(CandleLight)
akSpeaker.RemoveItem(SpellTomeCandleLight)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeChainLightning) &--#62; 0
akSpeaker.AddSpell(ChainLightning)
akSpeaker.RemoveItem(SpellTomeChainLightning)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeCircleOfProtection) &--#62; 0
akSpeaker.AddSpell(CircleOfProtection)
akSpeaker.RemoveItem(SpellTomeCircleOfProtection)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeClairvoyance) &--#62; 0
akSpeaker.AddSpell(Clairvoyance)
akSpeaker.RemoveItem(SpellTomeClairvoyance)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeCloseWounds) &--#62; 0
akSpeaker.AddSpell(CloseWounds)
akSpeaker.RemoveItem(SpellTomeCloseWounds)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeCommandDaedra) &--#62; 0
akSpeaker.AddSpell(CommandDaedra)
akSpeaker.RemoveItem(SpellTomeCommandDaedra)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeConjureDremoraLord) &--#62; 0
akSpeaker.AddSpell(ConjureDremoraLord)
akSpeaker.RemoveItem(SpellTomeConjureDremoraLord)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeConjureFamiliar) &--#62; 0
akSpeaker.AddSpell(ConjureFamiliar)
akSpeaker.RemoveItem(SpellTomeConjureFamiliar)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeConjureFlameAtronach) &--#62; 0
akSpeaker.AddSpell(ConjureFlameAtronach)
akSpeaker.RemoveItem(SpellTomeConjureFlameAtronach)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeConjureFrostAtronach) &--#62; 0
akSpeaker.AddSpell(ConjureFrostAtronach)
akSpeaker.RemoveItem(SpellTomeConjureFrostAtronach)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeConjureStormAtronach) &--#62; 0
akSpeaker.AddSpell(ConjureStormAtronach)
akSpeaker.RemoveItem(SpellTomeConjureStormAtronach)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeCourage) &--#62; 0
akSpeaker.AddSpell(Courage)
akSpeaker.RemoveItem(SpellTomeCourage)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeDeadThrall) &--#62; 0
akSpeaker.AddSpell(DeadThrall)
akSpeaker.RemoveItem(SpellTomeDeadThrall)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeDetectLife) &--#62; 0
akSpeaker.AddSpell(DetectLife)
akSpeaker.RemoveItem(SpellTomeDetectLife)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeDetectUndead) &--#62; 0
akSpeaker.AddSpell(DetectDead)
akSpeaker.RemoveItem(SpellTomeDetectUndead)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeDragonHide) &--#62; 0
akSpeaker.AddSpell(DragonHide)
akSpeaker.RemoveItem(SpellTomeDragonHide)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeDreadZombie) &--#62; 0
akSpeaker.AddSpell(DreadZombie)
akSpeaker.RemoveItem(SpellTomeDreadZombie)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeEbonyFlesh) &--#62; 0
akSpeaker.AddSpell(EbonyFlesh)
akSpeaker.RemoveItem(SpellTomeEbonyFlesh)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeExpelDaedra) &--#62; 0
akSpeaker.AddSpell(ExpelDaedra)
akSpeaker.RemoveItem(SpellTomeExpelDaedra)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeFastHealing) &--#62; 0
akSpeaker.AddSpell(FastHealing)
akSpeaker.RemoveItem(SpellTomeFastHealing)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeFear) &--#62; 0
akSpeaker.AddSpell(Fear)
akSpeaker.RemoveItem(SpellTomeFear)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeFireBall) &--#62; 0
akSpeaker.AddSpell(FireBall)
akSpeaker.RemoveItem(SpellTomeFireBall)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(pSpellTomeFireBolt) &--#62; 0
akSpeaker.AddSpell(FireBolt)
akSpeaker.RemoveItem(pSpellTomeFireBolt)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeFireRune) &--#62; 0
akSpeaker.AddSpell(FireRune)
akSpeaker.RemoveItem(SpellTomeFireRune)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeFireStorm) &--#62; 0
akSpeaker.AddSpell(FireStorm)
akSpeaker.RemoveItem(SpellTomeFireStorm)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeFlameCloak) &--#62; 0
akSpeaker.AddSpell(FlameCloak)
akSpeaker.RemoveItem(SpellTomeFlameCloak)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeFlames) &--#62; 0
akSpeaker.AddSpell(Flames)
akSpeaker.RemoveItem(SpellTomeFlames)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeFlameThrall) &--#62; 0
akSpeaker.AddSpell(FlameThrall)
akSpeaker.RemoveItem(SpellTomeFlameThrall)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeFrenzy) &--#62; 0
akSpeaker.AddSpell(Frenzy)
akSpeaker.RemoveItem(SpellTomeFrenzy)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeFrostBite) &--#62; 0
akSpeaker.AddSpell(FrostBite)
akSpeaker.RemoveItem(SpellTomeFrostBite)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeFrostCloak) &--#62; 0
akSpeaker.AddSpell(FrostCloak)
akSpeaker.RemoveItem(SpellTomeFrostCloak)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeFrostRune) &--#62; 0
akSpeaker.AddSpell(FrostRune)
akSpeaker.RemoveItem(SpellTomeFrostRune)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeFrostThrall) &--#62; 0
akSpeaker.AddSpell(FrostThrall)
akSpeaker.RemoveItem(SpellTomeFrostThrall)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeFury) &--#62; 0
akSpeaker.AddSpell(Fury)
akSpeaker.RemoveItem(SpellTomeFury)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeGrandHealing) &--#62; 0
akSpeaker.AddSpell(GrandHealing)
akSpeaker.RemoveItem(SpellTomeGrandHealing)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeGreaterWard) &--#62; 0
akSpeaker.AddSpell(WardGreater)
akSpeaker.RemoveItem(SpellTomeGreaterWard)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeGuardianCircle) &--#62; 0
akSpeaker.AddSpell(GuardianCircle)
akSpeaker.RemoveItem(SpellTomeGuardianCircle)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeHarmony) &--#62; 0
akSpeaker.AddSpell(Harmony)
akSpeaker.RemoveItem(SpellTomeHarmony)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeHealing) &--#62; 0
akSpeaker.AddSpell(Healing)
akSpeaker.RemoveItem(SpellTomeHealing)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeHealingHands) &--#62; 0
akSpeaker.AddSpell(HealingHands)
akSpeaker.RemoveItem(SpellTomeHealingHands)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeHealOther) &--#62; 0
akSpeaker.AddSpell(HealOther)
akSpeaker.RemoveItem(SpellTomeHealOther)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeHysteria) &--#62; 0
akSpeaker.AddSpell(Hysteria)
akSpeaker.RemoveItem(SpellTomeHysteria)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeIceSpike) &--#62; 0
akSpeaker.AddSpell(IceSpike)
akSpeaker.RemoveItem(SpellTomeIceSpike)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeIceStorm) &--#62; 0
akSpeaker.AddSpell(IceStorm)
akSpeaker.RemoveItem(SpellTomeIceStorm)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeIcySpear) &--#62; 0
akSpeaker.AddSpell(IcySpear)
akSpeaker.RemoveItem(SpellTomeIcySpear)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeIncinerate) &--#62; 0
akSpeaker.AddSpell(Incinerate)
akSpeaker.RemoveItem(SpellTomeIncinerate)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeInvisibility) &--#62; 0
akSpeaker.AddSpell(Invisibility)
akSpeaker.RemoveItem(SpellTomeInvisibility)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeIronFlesh) &--#62; 0
akSpeaker.AddSpell(IronFlesh)
akSpeaker.RemoveItem(SpellTomeIronFlesh)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeLesserWard) &--#62; 0
akSpeaker.AddSpell(WardLesser)
akSpeaker.RemoveItem(SpellTomeLesserWard)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeLightningBolt) &--#62; 0
akSpeaker.AddSpell(LightningBolt)
akSpeaker.RemoveItem(SpellTomeLightningBolt)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeLightningCloak) &--#62; 0
akSpeaker.AddSpell(LightningCloak)
akSpeaker.RemoveItem(SpellTomeLightningCloak)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeLightningStorm) &--#62; 0
akSpeaker.AddSpell(LightningStorm)
akSpeaker.RemoveItem(SpellTomeLightningStorm)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeMageLight) &--#62; 0
akSpeaker.AddSpell(MageLight)
akSpeaker.RemoveItem(SpellTomeMageLight)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeMassParalysis) &--#62; 0
akSpeaker.AddSpell(MassParalysis)
akSpeaker.RemoveItem(SpellTomeMassParalysis)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeMayhem) &--#62; 0
akSpeaker.AddSpell(Mayhem)
akSpeaker.RemoveItem(SpellTomeMayhem)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeMuffle) &--#62; 0
akSpeaker.AddSpell(Muffle)
akSpeaker.RemoveItem(SpellTomeMuffle)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeOakFlesh) &--#62; 0
akSpeaker.AddSpell(OakFlesh)
akSpeaker.RemoveItem(SpellTomeOakFlesh)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomePacify) &--#62; 0
akSpeaker.AddSpell(Pacify)
akSpeaker.RemoveItem(SpellTomePacify)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeParalyze) &--#62; 0
akSpeaker.AddSpell(Paralyze)
akSpeaker.RemoveItem(SpellTomeParalyze)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeRaiseZombie) &--#62; 0
akSpeaker.AddSpell(RaiseZombie)
akSpeaker.RemoveItem(SpellTomeRaiseZombie)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeRally) &--#62; 0
akSpeaker.AddSpell(Rally)
akSpeaker.RemoveItem(SpellTomeRally)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeReanimateCorpse) &--#62; 0
akSpeaker.AddSpell(ReanimateCorpse)
akSpeaker.RemoveItem(SpellTomeReanimateCorpse)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeRepelLesserUndead) &--#62; 0
akSpeaker.AddSpell(RepelLesserUndead)
akSpeaker.RemoveItem(SpellTomeRepelLesserUndead)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeRepelUndead) &--#62; 0
akSpeaker.AddSpell(RepelUndead)
akSpeaker.RemoveItem(SpellTomeRepelUndead)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeRevenant) &--#62; 0
akSpeaker.AddSpell(Revenant)
akSpeaker.RemoveItem(SpellTomeRevenant)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeRout) &--#62; 0
akSpeaker.AddSpell(Rout)
akSpeaker.RemoveItem(SpellTomeRout)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeShockRune) &--#62; 0
akSpeaker.AddSpell(ShockRune)
akSpeaker.RemoveItem(SpellTomeShockRune)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeSoulTrap) &--#62; 0
akSpeaker.AddSpell(SoulTrap)
akSpeaker.RemoveItem(SpellTomeSoulTrap)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeSparks) &--#62; 0
akSpeaker.AddSpell(Sparks)
akSpeaker.RemoveItem(SpellTomeSparks)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeSteadFastWard) &--#62; 0
akSpeaker.AddSpell(WardSteadFast)
akSpeaker.RemoveItem(SpellTomeSteadFastWard)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeStoneFlesh) &--#62; 0
akSpeaker.AddSpell(StoneFlesh)
akSpeaker.RemoveItem(SpellTomeStoneFlesh)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeStormThrall) &--#62; 0
akSpeaker.AddSpell(StormThrall)
akSpeaker.RemoveItem(SpellTomeStormThrall)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeTelekinesis) &--#62; 0
akSpeaker.AddSpell(Telekinesis)
akSpeaker.RemoveItem(SpellTomeTelekinesis)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeThunderbolt) &--#62; 0
akSpeaker.AddSpell(Thunderbolt)
akSpeaker.RemoveItem(SpellTomeThunderbolt)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeTransmuteOreMineral) &--#62; 0
akSpeaker.AddSpell(TransmuteOreMineral)
akSpeaker.RemoveItem(SpellTomeTransmuteOreMineral)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeTurnGreaterUndead) &--#62; 0
akSpeaker.AddSpell(TurnGreaterUndead)
akSpeaker.RemoveItem(SpellTomeTurnGreaterUndead)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeTurnLesserUndead) &--#62; 0
akSpeaker.AddSpell(TurnLesserUndead)
akSpeaker.RemoveItem(SpellTomeTurnLesserUndead)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeTurnUndead) &--#62; 0
akSpeaker.AddSpell(TurnUndead)
akSpeaker.RemoveItem(SpellTomeTurnUndead)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeWallOfFlames) &--#62; 0
akSpeaker.AddSpell(WallOfFlames)
akSpeaker.RemoveItem(SpellTomeWallOfFlames)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeWallOfFrost) &--#62; 0
akSpeaker.AddSpell(WallOfFrost)
akSpeaker.RemoveItem(SpellTomeWallOfFrost)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeWallOfStorms) &--#62; 0
akSpeaker.AddSpell(WallOfStorms)
akSpeaker.RemoveItem(SpellTomeWallOfStorms)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf
If akSpeaker.GetItemCount(SpellTomeWaterBreathing) &--#62; 0
akSpeaker.AddSpell(WaterBreathing)
akSpeaker.RemoveItem(SpellTomeWaterBreathing)
akSpeaker.PlayIdle(IdleBook_Reading)
EndIf

Idle Property IdleBook_Reading Auto
Spell Property BaneoftheUndead Auto
Spell Property BanishDaedra Auto
Spell Property Blizzard Auto
Spell Property BoundBattleAxe Auto
Spell Property BoundBow Auto
Spell Property BoundSword Auto
Spell Property CallToArms Auto
Spell Property Calm Auto
Spell Property CandleLight Auto
Spell Property ChainLightning Auto
Spell Property CircleOfProtection Auto
Spell Property Clairvoyance Auto
Spell Property CloseWounds Auto
Spell Property CommandDaedra Auto
Spell Property ConjureDremoraLord Auto
Spell Property ConjureFamiliar Auto
Spell Property ConjureFlameAtronach Auto
Spell Property ConjureFrostAtronach Auto
Spell Property ConjureStormAtronach Auto
Spell Property Courage Auto
Spell Property DeadThrall Auto
Spell Property DetectLife Auto
Spell Property DetectDead Auto
Spell Property DragonHide Auto
Spell Property DreadZombie Auto
Spell Property Ebonyflesh Auto
Spell Property ExpelDaedra Auto
Spell Property FastHealing Auto
Spell Property Fear Auto
Spell Property FireBall Auto
Spell Property FireBolt Auto
Spell Property FireRune Auto
Spell Property FireStorm Auto
Spell Property FlameCloak Auto
Spell Property Flames Auto
Spell Property FlameThrall Auto
Spell Property Frenzy Auto
Spell Property FrostBite Auto
Spell Property FrostCloak Auto
Spell Property FrostRune Auto
Spell Property FrostThrall Auto
Spell Property Fury Auto
Spell Property GrandHealing Auto
Spell Property GuardianCircle Auto
Spell Property Harmony Auto
Spell Property Healing Auto
Spell Property HealingHands Auto
Spell Property HealOther Auto
Spell Property Hysteria Auto
Spell Property IceSpike Auto
Spell Property IceStorm Auto
Spell Property IcySpear Auto
Spell Property Incinerate Auto
Spell Property Invisibility Auto
Spell Property IronFlesh Auto
Spell Property LightningBolt Auto
Spell Property LightningCloak Auto
Spell Property LightningStorm Auto
Spell Property MageLight Auto
Spell Property MassParalysis Auto
Spell Property Mayhem Auto
Spell Property Muffle Auto
Spell Property OakFlesh Auto
Spell Property Pacify Auto
Spell Property Paralyze Auto
Spell Property RaiseZombie Auto
Spell Property Rally Auto
Spell Property ReanimateCorpse Auto
Spell Property RepelLesserUndead Auto
Spell Property RepelUndead Auto
Spell Property Revenant Auto
Spell Property Rout Auto
Spell Property ShockRune Auto
Spell Property SoulTrap Auto
Spell Property Sparks Auto
Spell Property StoneFlesh Auto
Spell Property StormThrall Auto
Spell Property Telekinesis Auto
Spell Property ThunderBolt Auto
Spell Property TransmuteOreMineral Auto
Spell Property TurnGreaterUndead Auto
Spell Property TurnLesserUndead Auto
Spell Property TurnUndead Auto
Spell Property WallOfFlames Auto
Spell Property WallOfFrost Auto
Spell Property WallOfStorms Auto
Spell Property WardGreater Auto
Spell Property WardLesser Auto
Spell Property WardSteadFast Auto
Spell Property WaterBreathing Auto
Book Property SpellTomeBaneoftheUndead Auto
Book Property SpellTomeBanishDaedra Auto
Book Property SpellTomeBlizzard Auto
Book Property SpellTomeBoundBattleAxe Auto
Book Property SpellTomeBoundBow Auto
Book Property SpellTomeBoundSword Auto
Book Property SpellTomeCallToArms Auto
Book Property SpellTomeCalm Auto
Book Property SpellTomeCandleLight Auto
Book Property SpellTomeChainLightning Auto
Book Property SpellTomeCircleOfProtection Auto
Book Property SpellTomeClairvoyance Auto
Book Property SpellTomeCloseWounds Auto
Book Property SpellTomeCommandDaedra Auto
Book Property SpellTomeConjureDremoraLord Auto
Book Property SpellTomeConjureFamiliar Auto
Book Property SpellTomeConjureFlameAtronach Auto
Book Property SpellTomeConjureFrostAtronach Auto
Book Property SpellTomeConjureStormAtronach Auto
Book Property SpellTomeCourage Auto
Book Property SpellTomeDeadThrall Auto
Book Property SpellTomeDetectLife Auto
Book Property SpellTomeDetectUndead Auto
Book Property SpellTomeDragonHide Auto
Book Property SpellTomeDreadZombie Auto
Book Property SpellTomeEbonyflesh Auto
Book Property SpellTomeExpelDaedra Auto
Book Property SpellTomeFastHealing Auto
Book Property SpellTomeFear Auto
Book Property SpellTomeFireBall Auto
Book Property pSpellTomeFirebolt Auto
Book Property SpellTomeFireRune Auto
Book Property SpellTomeFireStorm Auto
Book Property SpellTomeFlameCloak Auto
Book Property SpellTomeFlames Auto
Book Property SpellTomeFlameThrall Auto
Book Property SpellTomeFrenzy Auto
Book Property SpellTomeFrostBite Auto
Book Property SpellTomeFrostCloak Auto
Book Property SpellTomeFrostRune Auto
Book Property SpellTomeFrostThrall Auto
Book Property SpellTomeFury Auto
Book Property SpellTomeGrandHealing Auto
Book Property SpellTomeGreaterWard Auto
Book Property SpellTomeGuardianCircle Auto
Book Property SpellTomeHarmony Auto
Book Property SpellTomeHealing Auto
Book Property SpellTomeHealingHands Auto
Book Property SpellTomeHealOther Auto
Book Property SpellTomeHysteria Auto
Book Property SpellTomeIceSpike Auto
Book Property SpellTomeIceStorm Auto
Book Property SpellTomeIcySpear Auto
Book Property SpellTomeIncinerate Auto
Book Property SpellTomeInvisibility Auto
Book Property SpellTomeIronFlesh Auto
Book Property SpellTomeLesserWard Auto
Book Property SpellTomeLightningBolt Auto
Book Property SpellTomeLightningCloak Auto
Book Property SpellTomeLightningStorm Auto
Book Property SpellTomeMageLight Auto
Book Property SpellTomeMassParalysis Auto
Book Property SpellTomeMayhem Auto
Book Property SpellTomeMuffle Auto
Book Property SpellTomeOakFlesh Auto
Book Property SpellTomePacify Auto
Book Property SpellTomeParalyze Auto
Book Property SpellTomeRaiseZombie Auto
Book Property SpellTomeRally Auto
Book Property SpellTomeReanimateCorpse Auto
Book Property SpellTomeRepelLesserUndead Auto
Book Property SpellTomeRepelUndead Auto
Book Property SpellTomeRevenant Auto
Book Property SpellTomeRout Auto
Book Property SpellTomeShockRune Auto
Book Property SpellTomeSoulTrap Auto
Book Property SpellTomeSparks Auto
Book Property SpellTomeSteadFastWard Auto
Book Property SpellTomeStoneFlesh Auto
Book Property SpellTomeStormThrall Auto
Book Property SpellTomeTelekinesis Auto
Book Property SpellTomeThunderBolt Auto
Book Property SpellTomeTransmuteOreMineral Auto
Book Property SpellTomeTurnGreaterUndead Auto
Book Property SpellTomeTurnLesserUndead Auto
Book Property SpellTomeTurnUndead Auto
Book Property SpellTomeWallOfFlames Auto
Book Property SpellTomeWallOfFrost Auto
Book Property SpellTomeWallOfStorms Auto
Book Property SpellTomeWaterBreathing Auto

akSpeaker.RemoveSpell(BaneoftheUndead)
akSpeaker.RemoveSpell(BanishDaedra)
akSpeaker.RemoveSpell(Blizzard)
akSpeaker.RemoveSpell(BoundBattleAxe)
akSpeaker.RemoveSpell(BoundBow)
akSpeaker.RemoveSpell(BoundSword)
akSpeaker.RemoveSpell(CallToArms)
akSpeaker.RemoveSpell(Calm)
akSpeaker.RemoveSpell(CandleLight)
akSpeaker.RemoveSpell(ChainLightning)
akSpeaker.RemoveSpell(CircleOfProtection)
akSpeaker.RemoveSpell(Clairvoyance)
akSpeaker.RemoveSpell(CloseWounds)
akSpeaker.RemoveSpell(CommandDaedra)
akSpeaker.RemoveSpell(ConjureDremoraLord)
akSpeaker.RemoveSpell(ConjureFamiliar)
akSpeaker.RemoveSpell(ConjureFlameAtronach)
akSpeaker.RemoveSpell(ConjureFrostAtronach)
akSpeaker.RemoveSpell(ConjureStormAtronach)
akSpeaker.RemoveSpell(Courage)
akSpeaker.RemoveSpell(DeadThrall)
akSpeaker.RemoveSpell(DetectLife)
akSpeaker.RemoveSpell(DetectDead)
akSpeaker.RemoveSpell(DragonHide)
akSpeaker.RemoveSpell(DreadZombie)
akSpeaker.RemoveSpell(Ebonyflesh)
akSpeaker.RemoveSpell(ExpelDaedra)
akSpeaker.RemoveSpell(FastHealing)
akSpeaker.RemoveSpell(Fear)
akSpeaker.RemoveSpell(FireBall)
akSpeaker.RemoveSpell(FireBolt)
akSpeaker.RemoveSpell(FireRune)
akSpeaker.RemoveSpell(FireStorm)
akSpeaker.RemoveSpell(FlameCloak)
akSpeaker.RemoveSpell(Flames)
akSpeaker.RemoveSpell(FlameThrall)
akSpeaker.RemoveSpell(Frenzy)
akSpeaker.RemoveSpell(FrostBite)
akSpeaker.RemoveSpell(FrostCloak)
akSpeaker.RemoveSpell(FrostRune)
akSpeaker.RemoveSpell(FrostThrall)
akSpeaker.RemoveSpell(Fury)
akSpeaker.RemoveSpell(GrandHealing)
akSpeaker.RemoveSpell(GuardianCircle)
akSpeaker.RemoveSpell(Harmony)
akSpeaker.RemoveSpell(Healing)
akSpeaker.RemoveSpell(HealingHands)
akSpeaker.RemoveSpell(HealOther)
akSpeaker.RemoveSpell(Hysteria)
akSpeaker.RemoveSpell(IceSpike)
akSpeaker.RemoveSpell(IceStorm)
akSpeaker.RemoveSpell(IcySpear)
akSpeaker.RemoveSpell(Incinerate)
akSpeaker.RemoveSpell(Invisibility)
akSpeaker.RemoveSpell(IronFlesh)
akSpeaker.RemoveSpell(LightningBolt)
akSpeaker.RemoveSpell(LightningCloak)
akSpeaker.RemoveSpell(LightningStorm)
akSpeaker.RemoveSpell(MageLight)
akSpeaker.RemoveSpell(MassParalysis)
akSpeaker.RemoveSpell(Mayhem)
akSpeaker.RemoveSpell(Muffle)
akSpeaker.RemoveSpell(OakFlesh)
akSpeaker.RemoveSpell(Pacify)
akSpeaker.RemoveSpell(Paralyze)
akSpeaker.RemoveSpell(RaiseZombie)
akSpeaker.RemoveSpell(Rally)
akSpeaker.RemoveSpell(ReanimateCorpse)
akSpeaker.RemoveSpell(RepelLesserUndead)
akSpeaker.RemoveSpell(RepelUndead)
akSpeaker.RemoveSpell(Revenant)
akSpeaker.RemoveSpell(Rout)
akSpeaker.RemoveSpell(ShockRune)
akSpeaker.RemoveSpell(SoulTrap)
akSpeaker.RemoveSpell(Sparks)
akSpeaker.RemoveSpell(StoneFlesh)
akSpeaker.RemoveSpell(StormThrall)
akSpeaker.RemoveSpell(Telekinesis)
akSpeaker.RemoveSpell(ThunderBolt)
akSpeaker.RemoveSpell(TransmuteOreMineral)
akSpeaker.RemoveSpell(TurnGreaterUndead)
akSpeaker.RemoveSpell(TurnLesserUndead)
akSpeaker.RemoveSpell(TurnUndead)
akSpeaker.RemoveSpell(WallOfFlames)
akSpeaker.RemoveSpell(WallOfFrost)
akSpeaker.RemoveSpell(WallOfStorms)
akSpeaker.RemoveSpell(WardGreater)
akSpeaker.RemoveSpell(WardLesser)
akSpeaker.RemoveSpell(WardSteadFast)
akSpeaker.RemoveSpell(WaterBreathing)

Spell Property BaneoftheUndead Auto
Spell Property BanishDaedra Auto
Spell Property Blizzard Auto
Spell Property BoundBattleAxe Auto
Spell Property BoundBow Auto
Spell Property BoundSword Auto
Spell Property CallToArms Auto
Spell Property Calm Auto
Spell Property CandleLight Auto
Spell Property ChainLightning Auto
Spell Property CircleOfProtection Auto
Spell Property Clairvoyance Auto
Spell Property CloseWounds Auto
Spell Property CommandDaedra Auto
Spell Property ConjureDremoraLord Auto
Spell Property ConjureFamiliar Auto
Spell Property ConjureFlameAtronach Auto
Spell Property ConjureFrostAtronach Auto
Spell Property ConjureStormAtronach Auto
Spell Property Courage Auto
Spell Property DeadThrall Auto
Spell Property DetectLife Auto
Spell Property DetectDead Auto
Spell Property DragonHide Auto
Spell Property DreadZombie Auto
Spell Property Ebonyflesh Auto
Spell Property ExpelDaedra Auto
Spell Property FastHealing Auto
Spell Property Fear Auto
Spell Property FireBall Auto
Spell Property FireBolt Auto
Spell Property FireRune Auto
Spell Property FireStorm Auto
Spell Property FlameCloak Auto
Spell Property Flames Auto
Spell Property FlameThrall Auto
Spell Property Frenzy Auto
Spell Property FrostBite Auto
Spell Property FrostCloak Auto
Spell Property FrostRune Auto
Spell Property FrostThrall Auto
Spell Property Fury Auto
Spell Property GrandHealing Auto
Spell Property GuardianCircle Auto
Spell Property Harmony Auto
Spell Property Healing Auto
Spell Property HealingHands Auto
Spell Property HealOther Auto
Spell Property Hysteria Auto
Spell Property IceSpike Auto
Spell Property IceStorm Auto
Spell Property IcySpear Auto
Spell Property Incinerate Auto
Spell Property Invisibility Auto
Spell Property IronFlesh Auto
Spell Property LightningBolt Auto
Spell Property LightningCloak Auto
Spell Property LightningStorm Auto
Spell Property MageLight Auto
Spell Property MassParalysis Auto
Spell Property Mayhem Auto
Spell Property Muffle Auto
Spell Property OakFlesh Auto
Spell Property Pacify Auto
Spell Property Paralyze Auto
Spell Property RaiseZombie Auto
Spell Property Rally Auto
Spell Property ReanimateCorpse Auto
Spell Property RepelLesserUndead Auto
Spell Property RepelUndead Auto
Spell Property Revenant Auto
Spell Property Rout Auto
Spell Property ShockRune Auto
Spell Property SoulTrap Auto
Spell Property Sparks Auto
Spell Property StoneFlesh Auto
Spell Property StormThrall Auto
Spell Property Telekinesis Auto
Spell Property ThunderBolt Auto
Spell Property TransmuteOreMineral Auto
Spell Property TurnGreaterUndead Auto
Spell Property TurnLesserUndead Auto
Spell Property TurnUndead Auto
Spell Property WallOfFlames Auto
Spell Property WallOfFrost Auto
Spell Property WallOfStorms Auto
Spell Property WardGreater Auto
Spell Property WardLesser Auto
Spell Property WardSteadFast Auto
Spell Property WaterBreathing Auto


This is to either level up or redress followers

MQ101BlackOutImod.ApplyCrossFade()Utility.Wait(2)akSpeaker.RemoveAllItems(Chest)akSpeaker.SetPlayerTeamMate(false, true)akSpeaker.Disable()akSpeaker.MoveTo(Chest, 0.0, 0.0, 0.0, true)akSpeaker.Enable(true)Chest.RemoveAllItems(akSpeaker)akSpeaker.SetPlayerTeamMate(true, true)akSpeaker.MoveTo(PlayerREF, 0.0, 0.0, 0.0, false)Utility.Wait(1)ImageSpaceModifier.RemoveCrossFade()Actor Property Chest AutoImageSpaceModifier Property MQ101BlackOutImod AutoActor Property PlayerREF Auto

To get their skills showen in messagebox.

int Level = akSpeaker.GetLevel() as intint Health = akSpeaker.GetAV("Health") as intint Stamina = akSpeaker.GetAV("Stamina") as intint Magicka = akSpeaker.GetAV("Magicka") as intint OneHanded = akSpeaker.GetAV("OneHanded") as intint TwoHanded = akSpeaker.GetAV("TwoHanded") as intint Marksman = akSpeaker.GetAV("Marksman") as int ;Archeryint Block = akSpeaker.GetAV("Block") as intint HeavyArmor = akSpeaker.GetAV("HeavyArmor") as intint LightArmor = akSpeaker.GetAV("LightArmor") as intint Pickpocket = akSpeaker.GetAV("Pickpocket") as intint Lockpicking = akSpeaker.GetAV("Lockpicking") as intint Sneak = akSpeaker.GetAV("Sneak") as intint Alchemy = akSpeaker.GetAV("Alchemy") as intint Speechcraft = akSpeaker.GetAV("Speechcraft") as int ;Speechint Alteration = akSpeaker.GetAV("Alteration") as intint Conjuration = akSpeaker.GetAV("Conjuration") as intint Destruction = akSpeaker.GetAV("Destruction") as intint Illusion = akSpeaker.GetAV("Illusion") as intint Restoration = akSpeaker.GetAV("Restoration") as intint Enchanting = akSpeaker.GetAV("Enchanting") as intint InventoryWeight = akSpeaker.GetAV("InventoryWeight") as intint CarryWeight = akSpeaker.GetAV("CarryWeight") as intint DamageResist = akSpeaker.GetAV("DamageResist") as intint PoisonResist = akSpeaker.GetAV("PoisonResist") as intint FireResist = akSpeaker.GetAV("FireResist") as intint ElectricResist = akSpeaker.GetAV("ElectricResist") as intint FrostResist = akSpeaker.GetAV("FrostResist") as intint MagicResist = akSpeaker.GetAV("MagicResist") as intstring AttributesText = "Character Attributes: "string LevelText = "\nLevel: " + Levelstring HealthText = "\nHealth: " + Healthstring StaminaText = "\tStamina: " + Staminastring MagickaText = "\t Magicka: " + Magickastring InventoryWeightText = "\tCarry Weight: " + InventoryWeightstring CarryWeightText = "\tMax. Weight: " + CarryWeightstring DamageResistText = "\nDamage Resistance: " + DamageResiststring PoisonResistText = "\tPoison Resistance: " + PoisonResiststring FireResistText = "\nFire Resistance: " + FireResiststring ElectricResistText = "\tElectric Resistance: " + ElectricResiststring FrostResistText = "\nFrost Resistance: " + FrostResiststring MagicResistText = "\tMagic Resistance: " + MagicResiststring WarriorText = "Warrior Skills: "string OneHandedText = "\nOne Handed: " + OneHandedstring TwoHandedText = "\tTwo Handed: " + TwoHandedstring MarksmanText = "\tArchery: " + Marksmanstring BlockText = "\nBlock: " + Blockstring HeavyArmorText = "\tHeavy Armor: " + HeavyArmorstring LightArmorText = "\tLight Armor: " + LightArmorstring ThiefText = "Thievery Skills: "string PickpocketText = "\nPickpocket: " + Pickpocketstring LockpickingText = "\tLockpicking: " + Lockpickingstring SneakText = "\nSneak: " + Sneakstring AlchemyText = "\nAlchemy: " + Alchemystring SpeechcraftText = "\t Speech: " + Speechcraftstring MageText = "Magic Skills: "string AlterationText = "\nAlteration: " + Alterationstring ConjurationText = "\nConjuration: " + Conjurationstring DestructionText = "\tDestruction: " + Destructionstring IllusionText = "\tIllusion: " + Illusionstring RestorationText = "\nRestoration: " + Restorationstring EnchantingText = "\tEnchanting: " + EnchantingDebug.Messagebox(AttributesText + LevelText + HealthText + StaminaText + MagickaText + InventoryWeightText + CarryWeightText + DamageResistText + PoisonResistText + FireResistText + ElectricResistText +  FrostResistText + MagicResistText)Debug.Messagebox(WarriorText + OneHandedText + TwoHandedText + MarksmanText + BlockText + HeavyArmorText)Debug.Messagebox(ThiefText + PickpocketText + LockpickingText + SneakText + AlchemyText + SpeechcraftText + LightArmorText)Debug.Messagebox(MageText + AlterationText + ConjurationText + DestructionText + IllusionText + RestorationText + EnchantingText)

Make followers essential...very tricky one. Notice you'll need to change the original ActorBaser akSpeaker = akSpeakerREF as Actor Base to ActorBase akSpeaker only.

ActorBase akSpeaker;BEGIN CODEakSpeaker = akSpeakerREF.GetBaseObject() as ActorBaseakSpeaker.SetEssential()

I have tons of more features. It's probably better just to wait for Arnulf Warzenschlegger see its release, because I'm also releasing all of the source files...:D
User avatar
brandon frier
 
Posts: 3422
Joined: Wed Oct 17, 2007 8:47 pm

Post » Sat Dec 22, 2012 11:57 am

Do you plan to address followers outside of the vanilla system?

Yes, that's a large part of the point of this exercise. The job of UFF will be to handle follower inside and outside of the vanilla system, across disparate multi-follower frameworks.

If so, I'd like to suggest/request that you enable makers of follower mods to opt in or out of your framework's elements in a granular way. Otherwise--well, to use your example, followers like Vilja or my Aela already have systems to switch outfits when entering battle. I think some of the big follower frameworks do, too. If there's some other mod on top of that using the API to do the same thing, it just makes a mess. Likewise mods trying to add new dialogue topics to custom-voiced followers who have their own carefully crafted conversation trees...that sort of thing is as jarring and unaesthetic to me as a spotless tent in a Winterhold snowstorm probably is to you.

I think you're confusing a framework with an implementation. There will be no "opt in" or "opt out" because no follower mods will be directly dependent on UFF. The only things that will be directly dependent on UFF are mods that affectfollowers, not follower mods themselves. I'm coming at it from the other side.

To address the concern you bring up about switching outfits, that's exactly the kind of thing I'm wanting to solicit feedback on. Say, for instance, we don't want to do what I just did up above because just straight up changing their gear like that might be a bad thing. So, what if I wrote a function called FollowerEquipItem() that looks at the follower, determines what follower framework you're using, and uses the framework's implementation of gear switching?

To give a specific Frostfall example of a real problem, say I have a tent with 3 spare bedrolls, and I decide that when the player goes to bed, my followers should too. Any extra followers should just hang out outside. I need to know the following:
  • How many followers does the player have?
  • Who are they?
  • Where are they?
I currently have no way of answering those questions easily. If you just look at DialogueFollowers aliases, that will lie to you. If you just look at a particular framework's aliases, that will "lie" as well. You have to be good enough to look at (and specifically support) all of these different frameworks just to answer these simple questions.

Using this framework, I'd want you to be able to do something like...
Spoiler

function PlayerWentToSleep()	if UFF.GetFollowerCount() &--#62; 0		myFirstFollower = UFF.GetNthFollower(0)		if myFirstFollower	 	   myFirstFollower.Activate(SpareBedroll1)		endif		mySecondFollower = UFF.GetNthFollower(1)		if mySecondFollower			mySecondFollower.Activate(SpareBedroll2)		endif		myThirdFollower = UFF.GetNthFollower(2)		if myThirdFollower			myThirdFollower.Activate(SpareBedroll3)		endif	endifendFunction

...without caring about the multi-follower framework, without caring whether or not it's a Dawnguard follower or a Dark Brotherhood follower, and so on.

In other words, I can understand you might want to be able to do certain things like have all followers put on a warm cloak when it gets cold with Frostfall, regardless of how many followers the player has or which framework they're using. Fair enough. But I can equally see the maker of a follower, or a framework, wanting to have followers put on a warm cloak when it gets cold, regardless of whether or not the player is using Frostfall. And as a maker of a follower, the ideal thing for me would be to be able to say in some cases "Chesko's API has already allowed the creation of a mod that does X in a superior way, so if the player has it installed, I'll turn off my custom version of X and let the other mod do its thing" and in some other cases say "my method of offering that functionality suits the character and personality of my follower better than any generic system, so I'm going to opt-out of the API's awareness when it comes to that element and use my own functions." Does that make sense?

Again, framework vs. implementation. I'm just trying to build a set of tools; how I decide to implement how exactly or under what circumstances a follower equips a warm cloak is outside the scope of what I'm trying to build here. I'm trying to build a set of tools that make it easy to manage followers from a script perspective, regardless of the multi-follower framework. I don't want you, the mod author, to have to care about that any more. I want you to be able to execute generic functions, and then have UFF go and do it in the best way possible, using the multi-follower framework's own functions if possible. It will, of course, be up to the mod author to not abuse the framework or not do silly things with it.

The biggest point I guess I'm trying to make is that this goes way beyond Frostfall. I'm trying to think as generically as possible.

Mofakin - This thread isn't intended to provide you with support for your follower mod issues, or to provide me with scripting help. Instead, what I'd like to know is, what sorts of problems would you like to be able to solve with a generic follower framework? What specific challenges have you run into? And, please, put your code in spoiler tags.
User avatar
Andrew Tarango
 
Posts: 3454
Joined: Wed Oct 17, 2007 10:07 am

Post » Sat Dec 22, 2012 2:47 pm

Oh, I also figured how to make followers collect ingrdients and stuff, but that rendered the mod not working. I still got the source files here. Basically you're just making a package 'acquire' put a single idle on it, use the package inside a scene and then fire the scene with a script.
User avatar
Alyce Argabright
 
Posts: 3403
Joined: Mon Aug 20, 2007 8:11 pm

Post » Sat Dec 22, 2012 4:05 pm

I think you're confusing a framework with an implementation. There will be no "opt in" or "opt out" because no follower mods will be directly dependent on UFF. The only things that will be directly dependent on UFF are mods that affectfollowers, not follower mods themselves. I'm coming at it from the other side.

I do understand that (mostly, I think... ;))--but in your terms, what I was suggesting was the ability to opt an individual follower out of certain broad types or categories of affects.

I should also clarify, by "followers outside the vanilla system" I didn't mean those managed by UFO/EFF/AFT, which extend the vanilla system, but rather followers like Vilja, Atvir Dres, Aela, etc. who are never part of the CurrentFollowerFaction and so are not affected by those overhauls or other mods which use that faction as their condition.

One of the tricky aspects in that regard is that a player can have Vilja, Aela, Atvir, and UFO-controlled Jenassa all following, and essentially have four different follower frameworks in operation simultaneously.
User avatar
Laura Shipley
 
Posts: 3564
Joined: Thu Oct 26, 2006 4:47 am

Post » Sat Dec 22, 2012 10:26 am

I do understand that (mostly, I think... :wink:)--but in your terms, what I was suggesting was the ability to opt an individual follower out of certain broad types or categories of affects.

Not to be pedantic, but why? What problem would that solve? Edit: Because I can't read, I see (just now) that you're the author of ESF: Aela, so I assume you have a horse in the race here. What about having a framework like this "frightens" you? What issues are you foreseeing that something like this might cause? Since you're an author of one of these kinds of mods, you're exactly the kind of person I really want to talk to about this.

One of the tricky aspects in that regard is that a player can have Vilja, Aela, Atvir, and UFO-controlled Jenassa all following, and essentially have four different follower frameworks in operation simultaneously.

That is precisely the problem that UFF will try to solve. I don't want you to have to care about that. A follower is a follower is a follower. :tongue: That exact nightmare scenario is what's staring me in the face right now, which is what spawned the idea for something like UFF. I want to abstract away those details.

Edit: and to be clearer myself, the main goal of UFF is not to really affect anything. It's more to answer questions, like the ones I posed above. But if we here think that certain actions would be handy, by all means, suggest them and we can talk about it.
User avatar
Eric Hayes
 
Posts: 3392
Joined: Mon Oct 29, 2007 1:57 am

Post » Sat Dec 22, 2012 11:14 pm

Since you're an author of one of these kinds of mods, you're exactly the kind of person I really want to talk to about this.

Well, not really--the current situation doesn't cause me many problems. But I can understand how it does for you, and other modders who want to make systems that handle followers generically.

What about having a framework like this "frightens" you?

This:

I don't want you to have to care about that. A follower is a follower is a follower.

From your perspective, based on the kinds of mods you're interested in, perhaps. From my perspective, not so much. Part of the fun of creating a custom follower is imagining (and then developing) unique reactions, gameplay elements and systems, etc., in a way that conveys character and generates a sense of progress--a story. And part of the fun of playing the game with different custom followers is to experience their unique reactions to various stimuli, and see how those contribute to a character and their story. So I want to care; or at least, I want to be able to choose when I care. As a result I'm inclined to be wary of efforts to treat all followers as equal, "a follower is a follower is a follower." Not unmovably opposed, but wary. At worst, it allows for adding all sorts of out-of-character behaviors, or redundant and confusing functionality--some of the very reasons I didn't build using the CurrentFollowerFaction. At best, if UFF is a sort of universal translator between common functions of the various frameworks, it still likely means a fair amount of work to enable that, to package up any necessary personality logic into functions that UFF can call.

That said, I feel like I'm talking too much here--I should step back and listen to what other people have to say.
User avatar
quinnnn
 
Posts: 3503
Joined: Sat Mar 03, 2007 1:11 pm

Post » Sat Dec 22, 2012 11:22 am

I'm not quite sure why you're going on about multiple follower systems, since there are only four followers who don't use the DialogueFollower quest: Cicero, the Dark Brotherhood initiates, and Serana.

Quest DarkBrotherhood contains vars for DB followers; Serana goes in the CurrentFollowerFaction.

As long as mod makers remain cognizant of the different systems, by which I mean the fact that Cicero and the initiates don't go in the CurrentFollowerFaction, they're fine.


This took me all of two minutes to work around doing Lively Followers; I'm not sure why this has to be a big deal.
User avatar
alyssa ALYSSA
 
Posts: 3382
Joined: Mon Sep 25, 2006 8:36 pm

Post » Sat Dec 22, 2012 7:09 pm

I'm not quite sure why you're going on about multiple follower systems, since there are only four followers who don't use the DialogueFollower quest: Cicero, the Dark Brotherhood initiates, and Serana.

Quest DarkBrotherhood contains vars for DB followers; Serana goes in the CurrentFollowerFaction.

As long as mod makers remain cognizant of the different systems, by which I mean the fact that Cicero and the initiates don't go in the CurrentFollowerFaction, they're fine.


This took me all of two minutes to work around doing Lively Followers; I'm not sure why this has to be a big deal.
Let's say I wanted to make a spell mod that detects followers and gives them some sort of buff, or adds an effect that makes it so that they can't take friendly fire, or something like that. I don't want this spell to affect just any NPC who's fighting alongside the player, for whatever reason; I just want it to affect only his follower(s).

As it is now, I check to see if nearby NPCs are in the CurrentFollowerFaction or are one of the DB followers. Then I check to see if it's one of the other modder-made companions like Vilja, who use entirely custom scripting. Okay, so say that I've somehow accounted for every modded companion out there, finish my mod, pat myself on the back, and then retire from modding. A job well done, no?

But what I didn't realize was that, 6 months down the line, a bright-eyed and bushy-tailed new modder created the greatest companion ever made, Madeline the duck-princess. Madeline's follower functions are all custom, of course, and don't work with my mod. But I retired! I don't even know Madeline exists! Do I have to rely on other modders to update my mod or make a patch for me?

But what if instead, I rely on the UFF? Assuming that someone is keeping the UFF up-to-date and the API stays consistent, then my mod will always be compatible with new mod-added companions, duck-princesses and others.


...Long story short, I think this is a fantastic idea. However, I haven't made any follower mods and I'm not working on any major for-release projects, so I don't have any suggestions for what you could add. =/ Sorry.
User avatar
neen
 
Posts: 3517
Joined: Sun Nov 26, 2006 1:19 pm

Post » Sat Dec 22, 2012 7:44 am

From your perspective, based on the kinds of mods you're interested in, perhaps. From my perspective, not so much. Part of the fun of creating a custom follower is imagining (and then developing) unique reactions, gameplay elements and systems, etc., in a way that conveys character and generates a sense of progress--a story. And part of the fun of playing the game with different custom followers is to experience their unique reactions to various stimuli, and see how those contribute to a character and their story. So I want to care; or at least, I want to be able to choose when I care. As a result I'm inclined to be wary of efforts to treat all followers as equal, "a follower is a follower is a follower." Not unmovably opposed, but wary. At worst, it allows for adding all sorts of out-of-character behaviors, or redundant and confusing functionality--some of the very reasons I didn't build using the CurrentFollowerFaction. At best, if UFF is a sort of universal translator between common functions of the various frameworks, it still likely means a fair amount of work to enable that, to package up any necessary personality logic into functions that UFF can call.

You are... misunderstanding the purpose of this. I don't want to change your follower or modify its behavior. Period. I don't want to "override" it or damage the presentation of your work. I am coming at this from a programmatical standpoint. When I say "a follower is a follower is a follower", I'm talking about in Papyrus code. In Papyrus, your follower should not be a unique snowflake that I have to personally account for. It should be just another object in an index of current followers that I can retrieve. As in the above examples, I can use that information to cause followers to perform other actions, but... that's something I could do anyway right now, it's just harder. You are making it sound like I want to strip your follower of all unique personality, and it's nothing like that.

I'm not quite sure why you're going on about multiple follower systems, since there are only four followers who don't use the DialogueFollower quest: Cicero, the Dark Brotherhood initiates, and Serana.


Ok, so let's rack them up. We've got:
  • Cicero
  • Dark Brotherhood Initiates
  • Serana
  • The DialogueFollower quest, which by default has an alias for one follower and one dog.
  • The dialoguefollower quest, which is modified by UFO to support up to 20 (?) followers.
  • Extensible Follower Framework, which uses its own quest with its own aliases to support up to 100 followers.
  • Amazing Follower Tweaks. I don't know how it implements followers just yet.
That's a lot of points of failure. And every single modder that wants to support followers is supposed to write their own logic to support all of that? That's insane. Given all of the above, would you rather call 7 different sets of logic to count up the total number of followers you have, or would you rather just make a single call to UFF.GetFollowerCount() and know that it will give you the right answer?

What will happen (and does happen) is that modders will support a subset of the above, and some of it might work better than other parts because to get this right, you need a well-written framework.

Opaj hit the nail on the head. Being able to access followers from Papyrus doesn't need to be this hard.

Anyway, the main purpose of this thread is to solicit feedback from papyrus script writers who would like easier access to followers across all systems, and what kinds of functions would be useful. Not to argue the merits for doing so. I don't mean to be crass, but if you're not a script writer, this is probably not the thread for you. I seem to have done a very poor job communicating what I want to accomplish here.

I could just develop this thing in a vacuum in order to solve the specific problems I'm trying to overcome, but my intention was to make this a community-wide tool that takes into account script author feedback. Perhaps this should be moved to the Creation Kit forum instead.

Edit: Someone on my Nexus thread just posted the following:

When I think epic journey, I think Lord of the Rings, so my thing has always been making the Journey from point A to point B just as much, if not more fun, than reaching the actual destination. What I mean to say is, do you have anything planned along the lines of Follower interactions around a campfire?

It's these kinds of things that I'd like to take the pain out of implementing, no matter if it's Serana or Vilja or Aela or 20 UFO followers, without relying on Follower authors to implement specific behavior, and without me having to check in 10 different places for a current set of followers such that the whole thing operates as a cohesive whole. If someone asks me, "Does Wearable Lanterns support Followers?", I don't want the answer to be "Well, yes, I support UFO, and EFF, but not AFT, and Vilja might not work correctly all of the time." I want the answer to be, "Yes."
User avatar
Euan
 
Posts: 3376
Joined: Mon May 14, 2007 3:34 pm

Post » Sat Dec 22, 2012 10:42 pm

It's these kinds of things that I'd like to take the pain out of implementing, no matter if it's Serana or Vilja or Aela or 20 UFO followers, without relying on Follower authors to implement specific behavior, and without me having to check in 10 different places for a current set of followers such that the whole thing operates as a cohesive whole. If someone asks me, "Does Wearable Lanterns support Followers?", I don't want the answer to be "Well, yes, I support UFO, and EFF, but not AFT, and Vilja might not work correctly all of the time." I want the answer to be, "Yes."

This problem wouldn't be solved by a UFF. You'd need to incooperate features such as wearable lanterns into your UFF to make it easily accesible for all users that are trying to make custom followers. I remember Toasters and CM based companions actually had a framework that everyone else used, though I'd always prefered Toasters.

Given that Skyrims follower system is so much more complex it's not an easy task to create a complete set of new follower framework. I think you will end up with just as much complexity. Have a look at the Viljas files. So far this is the only follower mod I'm aware of that doesn't use DialogueFollower. My mod does the same, but unfortunately only partial.

Edit: Ha, you'll be happy to hear that I completely pulled my follower out of the DialogueFollower Quest and it's attached scripts. Basically you'd just need to copy all instances related to followers (quests, scripts, packages, globals, factions etc.) and set them up wit unique names. Funny thing is, there's a lot of unnecessary code you don't even need when making a custom follower framework... :biggrin:

Edit2: You'll probably want to have a look at http://www.gamesas.com/topic/1432218-tut-how-to-completely-set-up-a-custom-follower-framework-without-using-the-vanilla-follower-framework/...:D
User avatar
El Goose
 
Posts: 3368
Joined: Sun Dec 02, 2007 12:02 am

Post » Sat Dec 22, 2012 8:40 pm

This problem wouldn't be solved by a UFF. You'd need to incooperate features such as wearable lanterns into your UFF to make it easily accesible for all users that are trying to make custom followers. I remember Toasters and CM based companions actually had a framework that everyone else used, though I'd always prefered Toasters.

You still don't understand what the purpose of this is.

There are two important questions that there are currently no easy way to answer via Papyrus:
  • How many followers do I have?
  • Who are they?
There is no single function to retrieve any of that data across every multi-follower framework, the default Bethesda framework (and its variances). There may be more than those two questions that might be relevant to answer in a generic Follower API. That is the (sole) purpose of this framework.

Maybe "framework" sends the wrong message. If I had to write a one-sentence "sales pitch" for the UFF, it would be:

"A Papyrus API that acts as a go-between (middleware) for script writers and followers by abstracting individual follower implementations and representing them in a generic way."

Here's another function that could be created from the examples I gave in the OP:

Actor function FindClosestFollowerFromPlayer()

The question being, "which of my followers is closest to me?" You have no way to easily answer that.

Edit: Ha, you'll be happy to hear that I completely pulled my follower out of the DialogueFollower Quest and it's attached scripts. Basically you'd just need to copy all instances related to followers (quests, scripts, packages, globals, factions etc.) and set them up wit unique names. Funny thing is, there's a lot of unnecessary code you don't even need when making a custom follower framework...

And now you've just made it a little bit harder for anyone who wants to support followers generically. Now I have to account for your unique follower implementation since you don't use the DialogueFollower quest. If everyone, absolutely everyone, used the DialogueFollower quest, and if the DialogueFollower quest had enough aliases in it by default to support as many followers as people wanted, this problem would not exist and the UFF would be unnecessary. There are tons of these "one-off" implementations that need to be accounted for, which is a large part of what UFF would seek to do.

From my personal perspective, you have broken my ability in Wearable Lanterns to assign generic dialogue to your follower so that I can control the lantern position. UFF would help solve this problem. No part of Wearable Lanterns would need to be integrated into the UFF because the intention of the UFF isn't to do anything.

You have to look at it from a user's perspective. To a user, followers are just followers. They expect things to "just work" if a mod claims to "support followers". But we currently don't have a way to do that. That's the point of UFF.
User avatar
Gen Daley
 
Posts: 3315
Joined: Sat Jul 08, 2006 3:36 pm

Post » Sat Dec 22, 2012 7:47 pm

did you make any Chesko mod's thread? I am starting to loose track of what you are doing , completed , wip and planned ...
User avatar
gemma
 
Posts: 3441
Joined: Tue Jul 25, 2006 7:10 am

Post » Sat Dec 22, 2012 7:28 pm

An idea: what about trying to make a system that learns who the followers are....something like checking who's following you between cells maybe.
Also, I didn't look into mechanics of the followers but would they use a common package to follow you? and maybe check http://www.creationkit.com/GetIsCurrentPackage
User avatar
Nicole Elocin
 
Posts: 3390
Joined: Sun Apr 15, 2007 9:12 am

Post » Sat Dec 22, 2012 8:04 am

So basically this mod will help "translate" functionality between followers (no matter how they are implemented) and mods that effect the followers. Making follower mods universally compatible with each other and with any mod that effects them.

Sounds like a god send if this can get up and working. Would SkyProc be of any use in this? (honestly I have no idea how SkyProc works I just think it's the closest thing to magic I have ever seen in the real world)
User avatar
helliehexx
 
Posts: 3477
Joined: Fri Jun 30, 2006 7:45 pm

Post » Sat Dec 22, 2012 10:54 pm

did you make any Chesko mod's thread? I am starting to loose track of what you are doing , completed , wip and planned ...

Thanks for reminding me.

An idea: what about trying to make a system that learns who the followers are....something like checking who's following you between cells maybe.
Also, I didn't look into mechanics of the followers but would they use a common package to follow you? and maybe check http://www.creationkit.com/GetIsCurrentPackage

Learning that kind of information would be a big part of it, yes. It might not actually "learn" (store) it, but it would probably have functions that can go query that on demand instead (assuming that the operation isn't too expensive; if it is, storing it might be better if it makes sense to do so).

So basically this mod will help "translate" functionality between followers (no matter how they are implemented) and mods that effect the followers. Making follower mods universally compatible with each other and with any mod that effects them.

Yes. This. Thank you.

Would SkyProc be of any use in this? (honestly I have no idea how SkyProc works I just think it's the closest thing to magic I have ever seen in the real world)

I don't think so, I think SkyProc tries to solve a different set of problems. I'll have to look into it.
User avatar
lucile
 
Posts: 3371
Joined: Thu Mar 22, 2007 4:37 pm

Post » Sat Dec 22, 2012 2:55 pm

This sounds like a much needed endeavour.

Every once in a while the same question pops up in the CK forum: "How can I restrict my dungeon to only be accessible by the player?" (Or similar)

UFF will make this a piece of cake

- Hypno
User avatar
Gemma Archer
 
Posts: 3492
Joined: Sun Jul 16, 2006 12:02 am

Post » Sat Dec 22, 2012 7:19 pm

Yes. This. Thank you.

You can quote me If you like in the OP, maybe it will help get some people on board for what this does.
User avatar
RUby DIaz
 
Posts: 3383
Joined: Wed Nov 29, 2006 8:18 am

Post » Sat Dec 22, 2012 8:47 am

Every once in a while the same question pops up in the CK forum: "How can I restrict my dungeon to only be accessible by the player?" (Or similar)

Yep. That's another one. Or to take it a step further, you could say, "This dungeon is designed with a group of 3 or less, so you can only take the first two followers in with you." You would be able to query the first two followers you have (no matter if it's Vilja or Aela or UFO or whatever) and treat them equally.

So, is that really the only four or so functions that this framework would really need? GetFollowerCount, GetFollowerAtIndex, FindClosestFollower, IsFollower? Any other suggestions?

You can quote me If you like in the OP, maybe it will help get some people on board for what this does.
Done.
User avatar
CYCO JO-NATE
 
Posts: 3431
Joined: Fri Sep 21, 2007 12:41 pm

Post » Sat Dec 22, 2012 7:16 pm

The question being, "which of my followers is closest to me?" You have no way to easily answer that.

Funny you're saying that, as I achieved something similar when trying to make the 'Follower Hotkey' Mod. What it did was checking which follower was closest to open inventory etc....wait, I'll look on the wiki...tada...

http://www.creationkit.com/IsNearPlayer_-_ObjectReference

...can't right remember how I've used it, but I think it was a script that got the ActorBases Object Reference when pressing a key, and whoever was closest, opened their inventory.

This sounds like a much needed endeavour.

Every once in a while the same question pops up in the CK forum: "How can I restrict my dungeon to only be accessible by the player?" (Or similar)

UFF will make this a piece of cake

- Hypno

As I said, somehing like that existed for Oblivion and Fallout games, with the difference they were not interpolating between each other. People were quite satisfied with just using base framerwork to build up their followers.

As it is now with Skyrim, things get out of ahnds, because there are so many custom followers. I think the easiest way, or at least the first one to try, are interpolating compatibility patches.

And now you've just made it a little bit harder for anyone who wants to support followers generically. Now I have to account for your unique follower implementation since you don't use the DialogueFollower quest. If everyone, absolutely everyone, used the DialogueFollower quest, and if the DialogueFollower quest had enough aliases in it by default to support as many followers as people wanted, this problem would not exist and the UFF would be unnecessary. There are tons of these "one-off" implementations that need to be accounted for, which is a large part of what UFF would seek to do.

Your opinion granted, but you're wrong. Give me some barebones and if it's good, I'm creating followers only on thoose. Why interpolation if anyone uses one base?
User avatar
Thomas LEON
 
Posts: 3420
Joined: Mon Nov 26, 2007 8:01 am

Post » Sat Dec 22, 2012 6:10 pm

Your opinion granted, but you're wrong. Give me some barebones and if it's good, I'm creating followers only on thoose. Why interpolation if anyone uses one base?

It's not an opinion. If you are using your own quest, to manage your own follower, you have created a new special case that has to be handled. That makes things, by every definition, more difficult (for those that want to interface with followers via Papyrus). You have introduced complexity. I'm not saying that you're wrong for doing it; I'm saying that it is a problem that needs to be handled.

The UFF is not something you would "plug into", or "use". As a Follower author, this is not anything you need to worry about. My objective is to allow other authors to interface with your follower, and every other follower in existence.

This is not intended for Follower authors. This is intended for modders who want to interface with followers. It's not to help you implement your follower, it's for everyone else that wants to manage your follower in some way.
User avatar
SHAWNNA-KAY
 
Posts: 3444
Joined: Mon Dec 18, 2006 1:22 pm

Post » Sat Dec 22, 2012 7:57 pm

Universal Follower Framework sounds like a COBL for followers. If so, this is really exciting. :thumbsup:
User avatar
Cameron Wood
 
Posts: 3384
Joined: Wed Oct 31, 2007 3:01 pm

Next

Return to V - Skyrim