http://skyrim.nexusmods.com/mods/23135
that works pretty well.
The trick is this: Make first a custom MiscItem (I use the soul gem fragment mesh as it is small). Apply the NullTextureSet shader to it to make it invisible. Now, put a script on this object that OnLoad() it does whatever you want. Probably you'll want to have the first line be something like this:
TargetObject = Game.FindClosestReferenceOfAnyTypeInListFromRef(DamnNearEverything, self, 45.0)
The list you will have to make yourself, and should consist of every object you would ever want to be able to cast your spell at. My list for the gravity gun spell includes every single object in the game that isn't an activator, actor, or static.
Don't worry about the size of the list much. Mine is about 7000 entries long, and it doesn't slow down the spell's performance one bit. I think FindClosestReferenceOfAnyTypeInList has a built in non-iterative search function based upon FormID, but this is pure conjecture.
Another thing you will want to do in all likelihood is put this objectreference in an alias, so make yourself an alias placeholder quest, and do that.
Also, make sure to disable/delete the MiscItem once it has accomplished its function, or you'll have a lot of invisible tiny objects around.
Now, make an explosion. It needn't have any special things about it, and should probably have a force of 0 unless you want to piss off everyone around you. The explosion should however place the MiscItem you made.
Now, make a custom projectile for your spell that includes this explosion. I've found this to be more consistent than using a vanilla projectile with your explosion declared in the Magic Effect for whatever reason.
Now make your spell's effect with the projectile you made.
Done.
In the spoiler below I will give a thorough examination of my gravgunspell as an example.
Spoiler
The first event that occurs is that my projectile's explosion's miscitem is spawned. It has this script.
As you can see, all this does is find the nearest object, put it in an alias, set it's motion type to KeyFramed (meaning I can manipulate it with translation functions (Thanks Verteiron!)) translate it once, and then disable deletes the miscitem itself.
Now, in the alias for the item I have this script.
Now, once the translation from my MiscItem's script is accomplished, it will trigger the first OnTranslationComplete event. Now, since the globalvariable shouldthrow==1 (meaning that it shoudln't be thrown) it will translate to a spot in front of the player. Once this is done, the event will be thrown again, and if shouldthrow still ==1, it will track to the spot in front of the player again. Now, this is where the script on the MagicEffect comes in. It is as follows:
So, whenever my projectile hits an actor (this is a concentration spell btw) it will register that actor as the target, filling an alias with him. Whenever I let go of the spell, ShouldThrow is set to 0. Now we revisit the alias script on Thrown.
Now I get to the second if statement of Thrown, where it has not yet translated to the hitactor, but there is a hitactor to go to. It translates to him and sets a boolean to true. Now, when the OntranslationComplete event is thrown again, as this boolean is true, it will deal him damage according to the mass of the object being thrown, and then sets its motion back to simulated.
That's about it, thanks for reading!
The first event that occurs is that my projectile's explosion's miscitem is spawned. It has this script.
Scriptname Portal_OnLoadFillAlias extends ObjectReference FormList Property DamnNearEverything autoReferenceAlias Property Thrown autoGlobalVariable Property ShouldThrow autoObjectReference Pulledevent OnLoad()if !Thrown.GetReference() Pulled = Game.FindClosestReferenceOfAnyTypeInListFromRef(DamnNearEverything, self, 45.0) if (Pulled) Pulled.SetMotionType(Pulled.Motion_Keyframed) ShouldThrow.SetValue(1) Thrown.ForceRefIfEmpty(Pulled) Thrown.GetReference().SplineTranslateTo(Thrown.GetReference().GetPositionX(), Thrown.GetReference().GetPositionY(), (Thrown.GetReference().GetPOsitionZ() + 48.0), 0.0, 0.0, 0.0, 1.0, 300.0, 0.0) endIFendIfdisable()delete()endEvent
As you can see, all this does is find the nearest object, put it in an alias, set it's motion type to KeyFramed (meaning I can manipulate it with translation functions (Thanks Verteiron!)) translate it once, and then disable deletes the miscitem itself.
Now, in the alias for the item I have this script.
Scriptname PCKP_Script_GravThrownAlias extends ReferenceAlias GlobalVariable Property ShouldThrow autoReferenceAlias Property HitActor autoActor Property PlayerREF autoint DealDamage=0bool transfailed=falseevent OnTranslationComplete()if ShouldThrow.GetValue() as int==1 GetReference().TranslateTo(PlayerRef.GetPositionX() + (50*Math.sin(PlayerREF.GetAngleZ())), PlayerRef.GetPositionY() + (50*(Math.cos(PlayerREF.GetAngleZ()))), PlayerRef.GetPositionZ() +90, 0, 0, 0, 256, 1) elseIf HitActor.GetReference() && DealDamage==0 GetReference().SplineTranslateToRefNode(HitActor.GetReference(), "NPC Head [Head]", 1, 5000) DealDamage=1 elseIf DealDamage==1 GetReference().SetMotionType(GetReference().Motion_Dynamic) float DamageDealt = (GetReference().GetMass() * 5.0) if (GetReference().GetBaseObject() as Weapon) || (GetReference().GetBaseObject() as Ammo) DamageDealt = DamageDealt * 2.0 endIf if DamageDealt >=10.0 (HitActor.GetReference() as Actor).SendAssaultAlarm() endIf Debug.Notification(DamageDealt) (HitActor.GetReference() as Actor).DamageActorValue("Health", DamageDealt) HitActor.Clear() dealdamage=0 Clear()else GetReference().SetMotionType(GetReference().Motion_Dynamic) HitActor.Clear() Clear()endIfendEvent
Now, once the translation from my MiscItem's script is accomplished, it will trigger the first OnTranslationComplete event. Now, since the globalvariable shouldthrow==1 (meaning that it shoudln't be thrown) it will translate to a spot in front of the player. Once this is done, the event will be thrown again, and if shouldthrow still ==1, it will track to the spot in front of the player again. Now, this is where the script on the MagicEffect comes in. It is as follows:
Scriptname Portal_MEffScript_FillHitActorAlias extends activemagiceffect ReferenceAlias Property HitActor autoGlobalVariable Property ShouldThrow autoevent OnEffectSTart(Actor T, Actor C)if !HitActor.Getreference()HitActor.ForceRefTo(T)endIfendEventevent OnEffectFinish(Actor T, Actor C)if (HitActor.GetReference()) ShouldThrow.SetValue(0)endIFendEvent
So, whenever my projectile hits an actor (this is a concentration spell btw) it will register that actor as the target, filling an alias with him. Whenever I let go of the spell, ShouldThrow is set to 0. Now we revisit the alias script on Thrown.
Now I get to the second if statement of Thrown, where it has not yet translated to the hitactor, but there is a hitactor to go to. It translates to him and sets a boolean to true. Now, when the OntranslationComplete event is thrown again, as this boolean is true, it will deal him damage according to the mass of the object being thrown, and then sets its motion back to simulated.
That's about it, thanks for reading!