Scripted effect to fire a spell in random directions

Post » Thu Jun 21, 2012 10:36 am

I am trying to make a spell that fires an aimed spell in multiple directions all at once. Think "shrapnel" coming from an explosion. In this case, I am trying to basically create a frost rune type explosion on the target, and fling icy spears in random directions at the same time.

This is what I have so far. It doesn't work. I tried several variations of this.


Scriptname ESG_ShrapnelBlast extends activemagiceffect  Spell Property Shrapnel AutoSpell Property Blast AutoInt Property NumShards AutoActivator Property Marker AutoObjectReference[] MarkerArrayInt SetupCount = 0Int FragmentsFired = 0ObjectReference SourceInt MarkersDeletedEvent OnEffectFinish(Actor Target, Actor Caster)   MarkerArray = new ObjectReference[10]   While (SetupCount < NumShards)	  MarkerArray[SetupCount] = Target.PlaceAtMe(Marker)	  MarkerArray[SetupCount].MoveTo(Target, (100 * (0.5 - Utility.RandomFloat())), (100 * (0.5 - Utility.RandomFloat())), (50 * Utility.RandomFloat()))	  SetupCount += 1   EndWhile   Source = Target.PlaceAtMe(Marker)   Source.MoveTo(Target, 0, 0, 10)   Blast.RemoteCast(Source, Caster)   While (FragmentsFired < NumShards)	  Shrapnel.RemoteCast(Source, Caster, MarkerArray[FragmentsFired])	  FragmentsFired += 1   EndWhile   While MarkersDeleted < NumShards	  MarkerArray[MarkersDeleted].DisableNoWait()	  MarkerArray[MarkersDeleted].DisableNoWait()	  MarkersDeleted += 1   EndWhile   Source.DisableNoWait()   Source.Delete()EndEvent

One version, I tried using the target as the source of the projectiles. This didn't work, because most NPCs ignore the "target" parameter for remotecast and only fire in the direction they are facing, so most of the time they would just shoot all the projectiles straight up or straight down as this script is attached to a paralysis effect.

Another version, I didn't offset the "source" activator, and so the target ended up getting hit by every single ice shard (killing it most of the time) so none of them flew out and hit other targets.

There is also a problem where if the NPC dies due to this effect, their corpse doesn't go into ragdoll mode, instead they just stand there like they are about to attack but they are still a corpse.
User avatar
Jason King
 
Posts: 3382
Joined: Tue Jul 17, 2007 2:05 pm

Post » Thu Jun 21, 2012 12:24 pm

Nevermind. I got it working and it is pretty damn cool. This is a script that you attach to a magic effect. If the target is hit or the duration (which is set as a property) is reached, the target will create an explosion and send whatever spell you specify flying in all directions. The spells come from activators arranged in a ring just outside of the radius of the target, so the target wont be hit by its own "shrapnel." The shrapnel also tends to want to fly more horizontally than vertically to increase the liklihood that it will nail someone.

There may be a way to do this without using two activators for each spell, such that an angle is calculated for a single activator for each spell and then the spell is casted with none as the target parameter and thus the spell fires in the default direction, but I svck at math so I didn't attempt it. Such a method may be much faster.

Also, you can have this explosion effect with "shrapnel" only occur if the caster has a certain perk by removing the ";"s.


Scriptname ESG_ShrapnelBlast extends activemagiceffectSpell Property ShrapnelSpell AutoInt Property NumShards AutoActivator Property Marker AutoPerk Property ShrapnelPerk AutoSpell Property BaseSpell AutoExplosion Property ExplosionProperty AutoFloat Property Duration AutoObjectReference[] MarkerTargetArrayObjectReference[] MarkerSourceArrayInt SetupCount = 0Int FragmentsFired = 0ObjectReference SourceInt MarkersDeletedactor Targetactor Casterbool bWait = truebool Wa[censored] = falseFloat RandAngle = 0.0Event OnEffectStart(Actor akTarget, Actor akCaster)Target = akTargetCaster = akCasterRegisterForSingleUpdate(Duration)Utility.Wait(0.5)bWait = falseEndEventEvent OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)If !bWait  If !Wa[censored]   Wa[censored] = true;   If Caster.HasPerk(ShrapnelPerk)	FireShards();   EndIf   Dispel()  EndIfEndIfEndEventEvent OnUpdate(); If Caster.HasPerk(ShrapnelPerk)  FireShards(); EndIfDispel()EndEventFunction FireShards()MarkerTargetArray = new ObjectReference[15]MarkerSourceArray = new ObjectReference[15]While (SetupCount < NumShards)  RandAngle = Utility.RandomFloat(0, 360)  MarkerSourceArray[SetupCount] = Target.PlaceAtMe(Marker)  MarkerSourceArray[SetupCount].MoveTo(Target, (Target.GetHeight() * Math.Sin(RandAngle)),  (Target.GetHeight() * Math.Cos(RandAngle)), 10)  MarkerTargetArray[SetupCount] = Target.PlaceAtMe(Marker)  MarkerTargetArray[SetupCount].MoveTo(Target, (500 * Math.Sin(RandAngle)),  (500 * Math.Cos(RandAngle)), (Utility.RandomFloat(-0.2,1.0) * 400))  SetupCount += 1EndWhileTarget.PlaceAtMe(ExplosionProperty)While (FragmentsFired < NumShards)  ShrapnelSpell.RemoteCast(MarkerSourceArray[FragmentsFired], Caster, MarkerTargetArray[FragmentsFired])  FragmentsFired += 1EndWhileWhile MarkersDeleted < NumShards  MarkerTargetArray[MarkersDeleted].DisableNoWait()  MarkerTargetArray[MarkersDeleted].Delete()  MarkerSourceArray[MarkersDeleted].DisableNoWait()  MarkerSourceArray[MarkersDeleted].Delete()  MarkersDeleted += 1EndWhileEndFunction
User avatar
kasia
 
Posts: 3427
Joined: Sun Jun 18, 2006 10:46 pm

Post » Thu Jun 21, 2012 12:24 am

This is very cool, thanks for sharing. I think I'm going to adapt this to my Meteor Storm spell someday down the road.
User avatar
Chris Cross Cabaret Man
 
Posts: 3301
Joined: Tue Jun 19, 2007 11:33 pm

Post » Wed Jun 20, 2012 10:42 pm

NP. I do have a question about RemoteCast() though. Does the parameter for the actor to take the blame modify the casted spell with its own actor values and perks?
User avatar
[ becca ]
 
Posts: 3514
Joined: Wed Jun 21, 2006 12:59 pm

Post » Thu Jun 21, 2012 3:53 am

I would think it would use akSource for that information rather than BlameActor. Shouldn't be too hard to test and find out...
User avatar
Eddie Howe
 
Posts: 3448
Joined: Sat Jun 30, 2007 6:06 am

Post » Thu Jun 21, 2012 9:29 am

@Elseagoat
I have done a lot of testing with all the scripted cast functions and unfortunatly unless you use Cast() from the player no perk effects will activate. For my latest mod (which has so far taken me over a month to work on) I'm having to summon invisible wizards with set perks to get a remotecast() spell fired at a target USE perks effects too and even then there are limitations.
User avatar
JeSsy ArEllano
 
Posts: 3369
Joined: Fri Oct 20, 2006 10:51 am

Post » Wed Jun 20, 2012 10:16 pm

Testing reveals that attaching a script to a spell effect that says:

Event OnEffectStart(Actor Target, Actor Caster)
If Caster == Game.GetPlayer()
Debug.Notification("hurray")
Endif
EndEvent

and then remotecasting that spell with an NPC as the source and a different NPC as the target and the player as akBlameActor, I get the notification.

Still havent tested to see if it uses the perks and stats of the caster or the blameactor yet.



Still, this is useful for scaling mechanics. I have set up the projectiles launched by the explosion of this effect to get the level of the caster (even though the caster is FXEmptyActivator, it is blamed on the original caster of the spell that made the explosion) and thus I can scale the damage of the projectiles to the level of the caster by dealing damage through a script rather than setting the magnitude in the spell.

I found that 15 is really the largest number of projectiles you can launch before it gets rediculous and looks stupid. Any more, and the while loop that launches them drags on too long to make it look like a "burst"

So it is rare that the projectiles hit enemies, but not super rare. It still happens. So I decided to do damage through a script and scale it with the casters level and give it a high damage multiplier. The result is that it should do very large amounts of damage should you score a hit.




Now I just need a way to do area damage through a script. I could use an enchantment on the explosion, but I dont want to point at Game.GetPlayer() if possible I would like a way to point to the caster of the spell so that NPCs can use it and it scales with them instead.
User avatar
Izzy Coleman
 
Posts: 3336
Joined: Tue Jun 20, 2006 3:34 am

Post » Thu Jun 21, 2012 7:31 am

Now I just need a way to do area damage through a script. I could use an enchantment on the explosion, but I dont want to point at Game.GetPlayer() if possible I would like a way to point to the caster of the spell so that NPCs can use it and it scales with them instead.

Not sure if this will work or not, just throwing around ideas.

What if you made a primitive with a script that OnTriggerEnter an actor takes damage. The cube is 1 foot on a side. Wherever the explosion takes place, it does PlaceAtMe for the primitive. Here's the surprise though. The primitive has another script (or just another event) that says:
event OnLoad()float i = 1.0   while i<30.0	  i=i+0.1	  TriggerBox.SetScale(i)   endWhileTriggerBox.disable()Utility.Wait(0.1)TriggerBox.Delete()endEvent

What I think this would do is summon a growing trigger box that expands, hits everything inside causing them to lose life from the OnTriggerEnter effect, and then delete itself.

The only thing I'm concerned about is that the characters aren't really entering the trigger, it is entering them so to speak.

EDIT: I made a spell to check is SetScale works right. It does, and is humorous.

Scriptname EmbiggenScript extends activemagiceffect event OnEffectStart(Actor Target, Actor Caster)  float i=1.00   while i<=1.80	   i=i+0.01	   Target.SetScale(i)   endwhileendEvent
User avatar
Steven Nicholson
 
Posts: 3468
Joined: Mon Jun 18, 2007 1:24 pm


Return to V - Skyrim