Problem: You can't get a reference to a projectile that you can use to do...well...anything with it. You can't even find it's location.
Solution: Make your own projectile.
Procedure:
First, you will need to create an object to represent your projectile. I used an Activator because I could easily attach a script directly to it, and not have to attach an effect to it to do so like you would with lots of other objects.
Next, you want the projectile to be visible. Use a BSM unpacker to unpack the Nif files so you can pick a model, or you can learn how to use a program like Blender (I haven't used a modelling program since version 2 of 3D Studio Max, I'd need to take a class or something to learn how again...) and make your own model. Click on "Edit" on the model slot of your activator and pick the model you want.
Now you'll need global variables. Create a dummy quest and put a script in it containing properties you can access in other scripts. Such a script would look like this:
Scriptname NodeVariableScript extends Quest {Variables used by the Node Based spells}NodeGlow property NodeMote AutoObjectReference property Missile auto ; Tvar.Missile = The Pseudo-Projectile. For more than one you can use an Array.ObjectReference property Target auto ; Tvar.Target = Storing the destination target of the Node, which it will follow.float property Speed=2000.0 Auto; Tvar.Speed = How fast the Projectile moves.bool property UsingTargetType Auto; Tvar.UsingTargetType = Is the current target a Target object? If not there is none or it's an actor.; To access these variables and functions in a script, place the following line in the script:; NodeVariableScript Property TVar Auto
Next, go back to your Projectile, and add a script like this:
Scriptname FollowObjectTracker extends ObjectReference {Object will follow an object.}import gameimport utilityfloat Distance ; sure, we could pass the variable isntead.bool Moving = TrueObjectReference Following = Nonefloat Velocity = 0.0Float Function DistanceBetween(Objectreference A,ObjectReference B) global ; Returns the distance between 2 objectreferences return A.GetDistance(B)endfunctionFunction Move() ObjectReference Target = Following float Speed = Velocity Distance = DistanceBetween(Self,Target) if Distance > 200.0 Self.TranslateTo(Target.X,Target.Y,Target.Z,0.0,0.0,0.0,Tvar.NodeSpeed,0.0) else ; If it's close enough, don't bother to move.; Insert "On reaching your target" code here...explosions, apply effects to nearby enemies, etc.; But only if it's a seeker type missile.; Be sure to include any Self-Destruction code so you don't have missiles running around forever. Moving = False endifEndFunctionFunction Follow(ObjectReference inTarget=None, float inSpeed=0.0) ; Function call is.Follow(FollowObject,Speed) ObjectReference Target = Tvar.Target ; The "Destination" node set in the global variable. float Speed = Tvar.Speed ; The "Speed" assigned in the global variable. If inTarget != None ; If passed an object, use that object instead. Target = inTarget endif If inSpeed != 0.0 ; If passed a speed, use that instead. Speed = inSpeed endif Velocity = Speed Following = Target ; Store values so the Events can tell what we're following. While Target if !Moving ; If we have stopped moving; If missile is NOT seeker type, put "on reaching your target" Code here and comment the Move out. Move(Target,Speed) ; Get a wiggle on...or try to. (Seeking Missile option) endif ;Move(Target,Speed) Non-Seeking weapon option. endwhileendFunctionEvent OnTranslationComplete() Moving = FalseEndEventEvent OnTranslationFailed() ; couldn't move Debug.Notification("Unable to move: " + self)endeventEvent OnUpdate() Self.Disable() Self.Delete()EndEventEvent OnInit() Follow(Tvar.Target) ; This is initialized before any Missiles are created.EndEventNodeVariableScript Property TVar Auto
Be sure to assign the property Tvar to the global variables script.
OK, that's the projectile itself. Now we need to make a navigation system for it. I copied the Magelight spell, ramped the projectile speed up to around 10000, and the duration down to 1 second, made a custom explosion to occur when it strikes something (no damage, but drops a second type of activator, with the following script on it):
Scriptname NodeTargetScript extends ObjectReference {An object whose purpose in life is to be followed by another object.}import gameimport utilityFunction FireMissile() Tvar.Missile = Game.GetPlayer().PlaceAtMe(Node,1,false,false); Make a Missile Tvar.Missile.Moveto(Game.GetPlayer(),0.0,0.0,60.0); Put it above the ground.EndFunctionEvent OnInit() if Tvar.Target && Tvar.UsingTargetType; No killing NPCs just because they were being followed by a missile! Let the missiles' damage handle that part. Tvar.Target.Delete() ; Gets rid of the last target if it was an invisible node. endif Tvar.Target = self Tvar.UsingTargetType = True int Count = 0 while Count < NumberOfMissiles FireMissile() Count += 1 EndWhileEndEventint property NumberOfMissiles AutoActivator property Node AutoNodeVariableScript Property TVar Auto
OK, so once the Target is in place, IT launches the missiles essentially at itself.
One more script to add, to the Light-spell-launching Effect copy:
Scriptname LaunchMissileScript extends activemagiceffect import gameimport utilityObjectReference TeleportHereEvent OnEffectStart(Actor Target, Actor Caster) ; Only fires when the Targetting projectile strikes an actor and "sticks" If Tvar.UsingTargetType ; If the previous node was an invisible Target Wait(2.0) ; Wait til the explosion dropped Target has spawned it's follow node and missiles. Tvar.Target.Delete() ; Bye Bye, You mean old invisible Target! endif TVar.UsingTargetType = False ; Protects the NPC from deletion later. TVar.Target = (Target as ObjectReference); The missiles check this, and if they are seeker type, they will try to find the NPC after reaching initial point.EndEventNodeVariableScript Property TVar Auto
That's basically the guts of the solution. The global variable will keep track of the last missile you created, and you can search for the others, or make an array to store references to multiple missiles. Once the missiles are launched, they will pretty much do whatever you told them to with any code modifications you added.
http://www.youtube.com/watch?v=b_Tvl55fCoE(Sorry for the lousy resolution...wanted upload to be shorter than 3 hours or more...)