Magic Missile question

Post » Wed Jun 20, 2012 2:23 pm

There are many spells in DnD, magic missile being the epitomization of these spells, that have multiple projectiles where the number of projectiles depends on your level. It would be relatively easy to replicate the damage stacking, but I was hoping someone knew a way to make the multiple projectiles actually visually show up.
Preferably they would take random 'arcs' towards the opponent. That would look awesome.
User avatar
:)Colleenn
 
Posts: 3461
Joined: Thu Aug 31, 2006 9:03 am

Post » Wed Jun 20, 2012 11:13 pm

Magic missile has been implemented a number of different ways in computer implementations...In the original game (pen and paper) the user could keep the missiles around until he needed them (no duration limit) and could send each one at a different target, while most computer versions send all of them at the same target, and any "extras" are wasted.
User avatar
George PUluse
 
Posts: 3486
Joined: Fri Sep 28, 2007 11:20 pm

Post » Wed Jun 20, 2012 11:23 am

Is it possible to create a projectile that looks like multiple projectiles?

If not, maybe it's possible to make it look like that through scripting. You could duplicate the fake Heal projectile and modify it so that it has ridiculous speed (say 100,000) so that it should hit instantly. The effect would be scripted so that it spawns a couple of disabled objects around the player, and then uses RemoteCast with them to cast some spells at the target.

But if you really want to make them arc, you'd have to do something different. I haven't looked at the scripts, but I checked the video in the second link of Redwood Elf's signature. That would be what you want to do, except using SplineTranslate instead of Translate.
User avatar
Mrs shelly Sugarplum
 
Posts: 3440
Joined: Thu Jun 15, 2006 2:16 am

Post » Wed Jun 20, 2012 10:05 am

Why not use multiple projectiles? Oh you need the arcing.... Can you simulate Bow Firing multiple "arrows" at the same time with a shader applied to the object? There's some left over script (that's not used) that's for bound arrows that might serve as a starting point. Check out BoundBowEffectScript.psc.
User avatar
Wayne Cole
 
Posts: 3369
Joined: Sat May 26, 2007 5:22 am

Post » Wed Jun 20, 2012 2:37 pm

Can you simulate Bow Firing multiple "arrows" at the same time with a shader applied to the object? There's some left over script (that's not used) that's for bound arrows that might serve as a starting point. Check out BoundBowEffectScript.psc.

I'm working on a solution to a very similar problem right now. The projectile itself can have a shader attached to it but the only way to fire a projectile is either from a Bow or from a Spell. You can't cast a spell with art from a script as Cast() doesn't animate (though I suppose if the spell has a projectile that still might fire, guess I have more testing to do), and the only way to fire a projectile from a script is using Fire() which can't be aimed - it just fires in whatever direction the object you are firing from is facing - the problem I am currently dealing with.

If anyone can find a way to get multiple projectiles to fire at a single target or single target area simultaneously, I'd like to see how it was done. If I get my script working, I'll share my findings too, but that probably won't be until later tonight (if at all this week). Headed off to the gym for the time being.
User avatar
Adam Kriner
 
Posts: 3448
Joined: Mon Aug 06, 2007 2:30 am

Post » Wed Jun 20, 2012 7:13 pm

I'm definitely going to look at Elf's tutorial on this sort of thing later.
In the meantime, I have 61 more spells to script, so I think I'll worry about quantity first.
EDIT: Just realized that I'm making 63 spells, and that is not the point of my mod.
User avatar
lolly13
 
Posts: 3349
Joined: Tue Jul 25, 2006 11:36 am

Post » Wed Jun 20, 2012 10:04 pm

If anyone can find a way to get multiple projectiles to fire at a single target or single target area simultaneously, I'd like to see how it was done. If I get my script working, I'll share my findings too, but that probably won't be until later tonight (if at all this week). Headed off to the gym for the time being.

Hmm... I created a test mod for you to check, but didn't realize that mediafire now requires an account... Well this is the script I made, according to the method I described above:

Spoiler
Scriptname TestMEScript extends ActiveMagicEffect  FormList Property AimedSpellsList AutoActivator Property DummyObject AutoInt Property ProjectilesMax AutoInt Property ProjectilesMin AutoFloat Property CastingDistance AutoObjectReference[] DummiesEvent OnEffectStart(Actor akTarget, Actor akCaster)	Dummies = New ObjectReference[128]	int Count = Utility.RandomInt(ProjectilesMin, ProjectilesMax)	int index = 0	while (index < Count)		Dummies[index] = PlaceInFrontOfMeRandom(akCaster, DummyObject, CastingDistance)		index += 1	endwhile	Spell TempSpell	index = 0	while (index < Count)		TempSpell = AimedSpellsList.GetAt(Utility.RandomInt(0, AimedSpellsList.GetSize() - 1)) as Spell		TempSpell.RemoteCast(Dummies[index], akCaster, akTarget)		Dummies[index].Delete()		index += 1	endwhileEndEventObjectReference Function PlaceInFrontOfMeRandom(ObjectReference Target, Form akObject, Float Distance)	ObjectReference PlacedObject = Target.PlaceAtMe(akObject, 1, false, true)	Float AngleZ = Target.GetAngleZ()	AngleZ = Utility.RandomFloat(AngleZ - 30.0, AngleZ + 30.0)	Float AngleX = Utility.RandomFloat(-30.0, 30.0)	Float OffsetZ = Distance * Math.Sin(AngleX)	Float DistanceXY = Distance * Math.Cos(AngleX)	Float OffsetX = DistanceXY * Math.Sin(AngleZ)	Float OffsetY = DistanceXY * Math.Cos(AngleZ)	PlacedObject.MoveTo(Target, OffsetX, OffsetY, OffsetZ)	Return PlacedObjectEndFunction

I tried it out and it worked... mostly. Did not realize that fireballs could hit each other and set themselves off right in front of the player. :lmao:
User avatar
Alycia Leann grace
 
Posts: 3539
Joined: Tue Jun 26, 2007 10:07 pm

Post » Wed Jun 20, 2012 1:19 pm

Magic missile has been implemented a number of different ways in computer implementations...In the original game (pen and paper) the user could keep the missiles around until he needed them (no duration limit) and could send each one at a different target, while most computer versions send all of them at the same target, and any "extras" are wasted.

Actually, I think I like this. I could just addItem the things to inventory and give a NPC a new spell called Fire Magic Missile. It checks if you have one, and if you do it removes and casts. The question is how to make it "unerring"...

Here's what I'm thinking. You have a script fire an imaginary line of points at basically the speed that the engine can make them in front of the player for a number of feet (let's say 80, since it's the range of the spell in DnD). Basically as each of these points pops into existence, "looks around" (I have no idea how to do this) in a radius of about five feet, finds any actors that match the ShouldAttack condition, and reports the distance from the point to the actor, and who the actor is. Then when it loops to be in a space about 2 feet in front of it, it finds the new distance to any unfriendlies, and compares it with the previous distance. If it is lesser, it re-reports the distance and actor. This decides who your target is, even if you didn't cast it accurately. Heck, even if you cast it in the wrong direction, it should find the nearest enemy to the path and hit them.
Then you make a missile I guess with a similar sort of thing. Basically it just constantly loops to find that actor's coordinates, and change its direction to be going in a straight line towards it. Even if the guy teleported it would probably just keep following them.

Well, that's my conceptual framework. No idea how to code that.

EDIT: Just looked it up, and there are NO functions or events associated with Projectiles. Back to the drawing board.
EDIT2: I think I've been going about this the wrong way. If the enemy nearest to the line was forced into an alias for a HomingQuest, you could then PlaceActorAtMe a little magelight guy. The magelight has a huge speed, and a follow procedure (or just an Approach procedure if there is such a thing) for the alias. It has a really small follow distance, and it has a condition that when it reaches a small distance from the alias.GetReference() it triggers an explosion, causes the alias's reference to lose health, and disables and deletes itself. Potentially there is no reason that several such actors couldn't be simultaneously generated...
EDIT3: Just found this: Function SplineTranslateToRefNode(ObjectReference arTarget, string arNodeName, float afTangentMagnitude, float afSpeed, float afMaxRotationSpeed)

EDIT4: Apparently there is no OnCollide event for some insane reason. There is however, and OnHit event for traps that knows what it hit. So, my idea is basically to spawn two invisible arrow traps with invisible damageless arrows as the ammo. A while loop basically causes them to fire and rotate by 3 degrees in the X dimension positively for 1 trap and negatively for the other. The loops goes until the iterator = 60, for two full 180 degree arcs.
The spell also has another OnUpdate event that just stops whatever its doing.

The trap itself actually looks like a magic missile, but has a null shader. It has an OnHit event that first updates the spell effect to stop it. It also disables whichever trap didn't hit. Then it remove its shader, and SplineTranslateToRefNode very quickly towards the hit actor. It has an OnTranslationComplete event that does the actual damage of the magic missile, and also disables and deletes itself.

I think that should do it...we'll see when my Skyrim gets done reinstalling.
User avatar
Dominic Vaughan
 
Posts: 3531
Joined: Mon May 14, 2007 1:47 pm

Post » Wed Jun 20, 2012 10:24 am

Yeah, if you want to do anything with projectiles, you need to make your own. (See link to Yngol Sprites in my sig for one possible implementation)
User avatar
Alisia Lisha
 
Posts: 3480
Joined: Tue Dec 05, 2006 8:52 pm

Post » Wed Jun 20, 2012 10:35 pm

Yeah, you need to create your own projectiles. I've been monkeying around with a magic missile spell too for my spell mod and it became pretty straightforward once I moved away from projectiles, if you want I can post a link to a video showing how it operates.
User avatar
CxvIII
 
Posts: 3329
Joined: Wed Sep 06, 2006 10:35 pm

Post » Wed Jun 20, 2012 10:09 am

If you want to make them unerring like the real Magic Missile spell, you'll have to use Redwood Elf's custom projectile method.

There are simpler ways of doing this using Fire() if you just want dumbfire missiles.
User avatar
El Goose
 
Posts: 3368
Joined: Sun Dec 02, 2007 12:02 am

Post » Thu Jun 21, 2012 12:23 am

If you want to make them unerring like the real Magic Missile spell, you'll have to use Redwood Elf's custom projectile method.

There are simpler ways of doing this using Fire() if you just want dumbfire missiles.

Nope, I want them to actually "decide" who the player meant to fire at, and then home in on them.
User avatar
Avril Churchill
 
Posts: 3455
Joined: Wed Aug 09, 2006 10:00 am

Post » Thu Jun 21, 2012 12:38 am

Well you could have the "go after him" part of the spell save the target in a global variable, then put a script like this on the actual missiles:

Spoiler
Scriptname DnDMagicMissileScript extends ObjectReference  Import UtilityFloat Property XOff AutoFloat Property YOff AutoFloat Property ZOff Auto ; The offset coordinates for the missile's "Standby" hover preference location.Float MySpeed = 1000.0 ; How fast do magic missiles move?Bool Property IsMoving = False Auto ; Am I currently in motion?Actor Property MyCaster Auto ; Whose magic missile am I?LinkedListControls Property MyNode AutoEvent OnInit()	RegisterForSingleUpdate(RandomFloat(1.0,5.0))EndEventEvent OnUpdate()	if !IsMoving		if Gvar.MissileTarget && GetDistance(Gvar.MissileTarget) < 500.0 && !(Gvar.MissileTarget as Actor).IsDead()			DealDamage()			TranslateToRef(Gvar.MissileTarget,MySpeed)			Disable(True)		    Delete()		elseif Gvar.MissileTarget && !(Gvar.MissileTarget as actor).IsDead()			IsMoving = True			TranslateToRef(Gvar.MissileTarget,MySpeed)		elseif GetDistance(MyCaster) > 600.0			TranslateTo(MyCaster.X+Xoff,MyCaster.Y+Yoff,MyCaster.Z+Zoff,0.0,0.0,0.0,MySpeed)		endif	endif	RegisterForSingleUpdate(RandomFloat(1.0,5.0)) ; Makes it unlikely that multiple missiles will reach the target at the same timeEndEventFunction DealDamage()	actor Target = Gvar.MissileTarget as Actor	int Damage = RandomInt(2,5)	if Target		Target.DamageAV("Health",Damage)		PushActorAway(Target,Damage)		if Target.IsDead()			Gvar.MissileTarget = None ; Prevent wastage of more missiles.		endif	else ; Target is not an actor.		Gvar.MissileTarget.ApplyHavokImpulse(0.0,0.0,-500,Damage*10)	endifEndFunctionEvent OnTranslationComplete()	IsMoving = False	if Gvar.MissileTarget && GetDistance(Gvar.MissileTarget) < 500.0 && !(Gvar.MissileTarget as Actor).IsDead()		IsMoving = True ; Don't wait for update.		DealDamage()		TranslateToRef(Gvar.MissileTarget,MySpeed)		Disable(True)		Delete()	elseif Gvar.MissileTarget && !(Gvar.MissileTarget as Actor).IsDead()		IsMoving = True		TranslateToRef(Gvar.MissileTarget,MySpeed)	endifEndEventDnDGlobalScript Property Gvar Auto

Then have the initial "Spawn Missiles" code work like this:
Spoiler
Scriptname DnDMissileControllerScript extends ObjectReference  import UtilityFunction NewMissiles(int N, actor Caster)Debug.Notification("Creating " + N + " Missiles.")	int Count = 0	DnDMagicMissileScript Missile	While Count < N		Missile = (Caster.PlaceAtme(Gvar.MagicMissileType,1) as DnDMagicMissileScript)		Missile.XOff = RandomFloat(-250.0,250.0)		Missile.YOff = RandomFloat(-250.0,250.0)		Missile.ZOff = RandomFloat(-250.0,250.0) + 300 ; Store the missile's holding position.		Missile.MyCaster = Caster		Missile.MoveTo(Caster ,Missile.XOff,Missile.YOff,Missile.ZOff)		Count += 1	EndWhileEndFunctionEvent OnInit()	if Gvar.MissileController		Disable()		Delete()	else		Gvar.MissileController = Self	endifEndEventDnDGlobalScript Property Gvar Auto
User avatar
^_^
 
Posts: 3394
Joined: Thu May 31, 2007 12:01 am

Post » Wed Jun 20, 2012 6:48 pm

Okay, I think I&#39;ve got this pretty much licked. One last thing though, what is a node exactly? Basically the way my thing works is there is a first spell that basically adds some little light items to the players inventory. They are the magelight balls basically. Then it UnEquips itself, and equips another spell Fire MAgic Missile. This spell forces akTarget into an Alias for a Quest for this purpose. Then it makes you drop all of the magic missiles in your inventory, and makes you forget it as a spell if akTarget!=None. This ensures that if the player misses his cast, he can continue clicking until he picks a legitimate target.
Finally the light balls themselves have a script that has an OnContainerChanged that if akNewContainer==None, it does a SplineTranslateToRefNode() which basically allows an object to continuously move towards an object, and finally it has an OnTranslationComplete event that actually damages the opponent, and then disables itself, waits a few seconds (to make sure all the missiles have time to hit) and clears the referencealias.



Problem is, OnTranslationComplete has a node requirement, and I don&#39;t know how to fill it.



Nvm, found this SplineTranslateToRef(ObjectReference arTarget, float afTangentMagnitude, float afSpeed, float afMaxRotationSpeed = 0.0)
User avatar
Kit Marsden
 
Posts: 3467
Joined: Thu Jul 19, 2007 2:19 pm

Post » Wed Jun 20, 2012 3:12 pm

Okay I have this working...sort of.
Here's what I've got. First spell just gives you some Magic Missiles in the old inventory and adds the firing spell. Here is the firing spell.
Scriptname DnDMMIssileFireScript extends activemagiceffectReferenceAlias Property DnDMMissileTarget autoMiscObject Property DnDMMissileLight autoSpell Property DnDMMissileFireSPell autoevent OnEffectStart(Actor akTarget, Actor akCaster)   DnDMMissileTarget.ForceRefTo(akTarget as ObjectReference)   int MMissileCount = akCaster.GetItemCount(DnDMMissileLight)   int MissileDropper = 0   while MissileDropper<= MMissileCount	  akCaster.DropObject(DnDMMissileLight)	  MissileDropper = MissileDropper+1	  Utility.Wait(0.30)   endWhile   akCaster.RemoveSpell(DnDMMissileFireSpell)endEvent

The objects that his drops have this script:

Scriptname DnDMMissileLightScript extends ObjectReferenceReferenceAlias Property DnDMMissileTarget autoEvent OnContainerChanged(ObjectReference akNewContainer, ObjectReference akOldContainer)   if akNewContainer==None	  (self as ObjectReference).SplineTranslateToRef(DnDMMissileTarget.GetReference(), 2.0, 1000.00,  0.0)endIfendEventevent OnTranslationComplete()   Actor HitActor = DnDMMissileTarget.GetReference() as actor   int MMissileDam = Utility.RandomInt(2,5)   HitActor.DamageAV("Health", MMissileDam)   Utility.Wait(2)   DnDMMissileTarget.Clear()   self.disable()endEvent

Two problems thus far, the objects do home in, but don't seem to do any damage, not even the first one. Second problem is, it homes in on the feet of the actor. Is there any way to make it home in on their torso? I know there is a SplineTranslatetoRefNode function, but I don't know how to make it specify the torso, or if that sort of thing is what is meant by Node.
Suggestions?
User avatar
e.Double
 
Posts: 3318
Joined: Tue Jul 24, 2007 11:17 pm

Post » Wed Jun 20, 2012 5:36 pm

I think I read a topic where someone said they had a problem with the health bars not updating, even though the NPC was taking damage. Are you sure that your missiles aren't doing any damage?

Also, just took a quick look at the skeleton.nif in NifSkope, and it looks like 'NPC Spine1 [Spn1]' is the node closest to the center of the body. I looked at the skeleton in 'actors\character\character assets' so I'm not sure that bears, wolves, etc have the node (probably not).
User avatar
!beef
 
Posts: 3497
Joined: Wed Aug 16, 2006 4:41 pm

Post » Wed Jun 20, 2012 12:44 pm

Okay I have this working...sort of.
Here's what I've got. First spell just gives you some Magic Missiles in the old inventory and adds the firing spell. Here is the firing spell.
Scriptname DnDMMIssileFireScript extends activemagiceffectReferenceAlias Property DnDMMissileTarget autoMiscObject Property DnDMMissileLight autoSpell Property DnDMMissileFireSPell autoevent OnEffectStart(Actor akTarget, Actor akCaster)   DnDMMissileTarget.ForceRefTo(akTarget as ObjectReference)   int MMissileCount = akCaster.GetItemCount(DnDMMissileLight)   int MissileDropper = 0   while MissileDropper<= MMissileCount	  akCaster.DropObject(DnDMMissileLight)	  MissileDropper = MissileDropper+1	  Utility.Wait(0.30)   endWhile   akCaster.RemoveSpell(DnDMMissileFireSpell)endEvent

The objects that his drops have this script:

Scriptname DnDMMissileLightScript extends ObjectReferenceReferenceAlias Property DnDMMissileTarget autoEvent OnContainerChanged(ObjectReference akNewContainer, ObjectReference akOldContainer)   if akNewContainer==None	  (self as ObjectReference).SplineTranslateToRef(DnDMMissileTarget.GetReference(), 2.0, 1000.00,  0.0)endIfendEventevent OnTranslationComplete()   Actor HitActor = DnDMMissileTarget.GetReference() as actor   int MMissileDam = Utility.RandomInt(2,5)   HitActor.DamageAV("Health", MMissileDam)   Utility.Wait(2)   DnDMMissileTarget.Clear()   self.disable()endEvent

Two problems thus far, the objects do home in, but don't seem to do any damage, not even the first one. Second problem is, it homes in on the feet of the actor. Is there any way to make it home in on their torso? I know there is a SplineTranslatetoRefNode function, but I don't know how to make it specify the torso, or if that sort of thing is what is meant by Node.
Suggestions?

Instead of doing a TranslateToRef, do TranslateTo and load the target's X, Y, and Z+100 as the parameters. 100 higher on the Z axis should at least get it off their shoes.
User avatar
Chloe :)
 
Posts: 3386
Joined: Tue Jun 13, 2006 10:00 am

Post » Wed Jun 20, 2012 11:13 pm

Instead of doing a TranslateToRef, do TranslateTo and load the target's X, Y, and Z+100 as the parameters. 100 higher on the Z axis should at least get it off their shoes.

Smart.
User avatar
Strawberry
 
Posts: 3446
Joined: Thu Jul 05, 2007 11:08 am


Return to V - Skyrim