senterpat Posted April 19, 2021 Share Posted April 19, 2021 (edited) So I'm using this script to try and basically recreate the frozen orb spell from Diablo II, but have reached a point where I am completely befuddled. I have an explosion that is placed as the orb moves, and that is triggering just fine, but the projectiles I tell to shoot from the same spot I placed the explosion at, for some reason are firing from the player, and not registering the rotation I'm trying to input. Hopefully someone can help me with this. So the script is as follows: scriptName patDestructFrozenOrbTriggerBoxScript extends ObjectReference ;this is the script to attach to the triggerbox i spawn Projectile Property MyProjectile Auto Activator Property XMarkerHeading Auto Spell Property IceBoltSpell Auto Float Property fTRotation = 20.0 Auto Explosion Property ExplosionRef Auto Float PosX Float PosY Float PosZ Float AngX Float AngY Float AngZ Int IceboltCount ObjectReference XMarkerHeadingRef ObjectReference FrozenOrb Actor Player Event OnTriggerEnter(ObjectReference akActionRef) Form Base = akActionRef.GetBaseObject() FrozenOrb = akActionRef If Base as Projectile If Base == MyProjectile Player = Game.GetPlayer() XMarkerHeadingRef = FrozenOrb.PlaceAtMe(XMarkerHeading) StartChain() Endif Endif EndEvent Function StartChain() RegisterForSingleUpdate(0.1) EndFunction Event OnUpdate() Bool bKeepUpdating = True if IceboltCount < 27 AngX = XMarkerHeadingRef.GetAngleX() AngY = XMarkerHeadingRef.GetAngleY() AngZ = XMarkerHeadingRef.GetAngleZ() AngZ = (AngZ + fTRotation) XMarkerHeadingRef.placeatme(ExplosionRef) XMarkerHeadingRef.Moveto(FrozenOrb, abMatchRotation = False) XMarkerHeadingRef.SetAngle(AngX, AngY, AngZ) IceBoltSpell.RemoteCast(XMarkerHeadingRef, Player) IceboltCount = (IceboltCount + 1) RegisterForSingleUpdate(0.1) else FrozenOrb.placeatme(ExplosionRef) FrozenOrb.Disable() IceboltCount = (IceboltCount + 0) endif EndEvent Originally I tried using remotecast on the projectile reference, but that ended up firing from the player as well, and had the added effect of the projectile altering course. But the explosions trigger at the location of the orb, so am I maybe using remotecast indirectly? edit: so I tried using cast instead of remote cast, which seems to be working a bit better, it is now firing the projectiles from around where the orb is. but the script is firing a bunch of projectiles in one direction, then a bunch in another direction, and doesnt seem to be able to keep up with the projectile (200 speed).Is there an issue with my Update Block that would cause it to rapid fire like that? I tried to set it up to fire one, wait a moment, and then rotate and fire another. Edited April 20, 2021 by senterpat Link to comment Share on other sites More sharing options...
dylbill Posted April 20, 2021 Share Posted April 20, 2021 Hmmm, it looks like it should be working. Try messing around with the update time. Reducing it or increasing it, and maybe reduce the script a bit: Projectile Property MyProjectile Auto Activator Property XMarkerHeading Auto Spell Property IceBoltSpell Auto Float Property fTRotation = 20.0 Auto Explosion Property ExplosionRef Auto Int IceboltCount ObjectReference XMarkerHeadingRef ObjectReference FrozenOrb Actor Player Event OnTriggerEnter(ObjectReference akActionRef) Form Base = akActionRef.GetBaseObject() If Base as Projectile If Base == MyProjectile FrozenOrb = akActionRef Player = Game.GetPlayer() XMarkerHeadingRef = FrozenOrb.PlaceAtMe(XMarkerHeading) IceboltCount = 0 RegisterForSingleUpdate(0.05) Endif Endif EndEvent Event OnUpdate() if IceboltCount < 27 XMarkerHeadingRef.placeatme(ExplosionRef) XMarkerHeadingRef.Moveto(FrozenOrb, abMatchRotation = False) XMarkerHeadingRef.SetAngle(XMarkerHeadingRef.GetAngleX(), XMarkerHeadingRef.GetAngleY(), (XMarkerHeadingRef.GetAngleZ() + fTRotation)) IceBoltSpell.Cast(XMarkerHeadingRef) IceboltCount += 1 ;add 1 to IceboltCount RegisterForSingleUpdate(0.05) else FrozenOrb.placeatme(ExplosionRef) FrozenOrb.Disable() endif EndEvent Link to comment Share on other sites More sharing options...
senterpat Posted April 20, 2021 Author Share Posted April 20, 2021 Much appreciated for cleaning up the script, I'm no professional scripter. But after adding it in and setting it back up its functioning much better, the ice spikes are firing with the orb now, not at an even pace, but that's likely script latency and I can live with.. But its still not registering the rotation. I can't for the life of me work this out. Is there possibly a setting on the XMarkerHeadingRef I'm missing? Its just a XMarkerHeading mesh, with default settings. I used it to create the trigger box that gets teleported to the player using an ability spell. Or something on the triggerbox? Link to comment Share on other sites More sharing options...
dylbill Posted April 20, 2021 Share Posted April 20, 2021 No problem. So I did some testing, and it turns out using .Cast or .RemoteCast on an object reference, it doesn't matter what angle it is, it always casts in the same direction. I tested with a Bee Activator, a Static, a Misc Object and a Movable Static. Using an Actor though, the spell fires from the correct direction. So, make a dummy invisible actor to use as the XMarkerHeading instead. Then modify the script slightly: Projectile Property MyProjectile Auto ActorBase Property ActorMarkerHeading Auto Spell Property IceBoltSpell Auto Float Property fTRotation = 20.0 Auto Explosion Property ExplosionRef Auto Int IceboltCount Actor ActorMarkerHeadingRef ObjectReference FrozenOrb Actor Player Event OnTriggerEnter(ObjectReference akActionRef) Form Base = akActionRef.GetBaseObject() If Base as Projectile If Base == MyProjectile FrozenOrb = akActionRef Player = Game.GetPlayer() ActorMarkerHeadingRef = FrozenOrb.PlaceActorAtme(ActorMarkerHeading) ActorMarkerHeadingRef.EnableAi(False) ;disable actor ActorMarkerHeadingRef.SetAlpha(0) ;make actor invisible IceboltCount = 0 RegisterForSingleUpdate(0.05) Endif Endif EndEvent Event OnUpdate() if IceboltCount < 27 ActorMarkerHeadingRef.placeatme(ExplosionRef) ActorMarkerHeadingRef.Moveto(FrozenOrb, abMatchRotation = False) ActorMarkerHeadingRef.SetAngle(ActorMarkerHeadingRef.GetAngleX(), ActorMarkerHeadingRef.GetAngleY(), (ActorMarkerHeadingRef.GetAngleZ() + fTRotation)) IceBoltSpell.Cast(ActorMarkerHeadingRef) IceboltCount += 1 ;add 1 to IceboltCount RegisterForSingleUpdate(0.05) else FrozenOrb.placeatme(ExplosionRef) FrozenOrb.Disable() ActorMarkerHeadingRef.Disable() ActorMarkerHeadingRef.Delete() endif EndEventIf the actor is invisible already the SetAlpha line isn't necessary. Hope that helps! Link to comment Share on other sites More sharing options...
senterpat Posted April 20, 2021 Author Share Posted April 20, 2021 (edited) Awesome. That helped out a lot. For some reason the script won't use moveto on the projectile with AI disabled (tho I can move it to the player via console while disabled). Easily circumvented by enabling AI before moving the NPC and then disabling again. I had to also add an Int to check for if the orb was active. Firing an additional spell would make the triggerbox ignore the original, causing the NPC activator to not be deleted. I tried using OnTriggerLeave, but the trigger box was proving to be a pain to get to the proper size to register the projectile without starting the effect too long after the spell was fired. So unless there is a way to tell the script to keep running on both projectiles I'll have to deal with it. Thank you so much for your help dylbill. The final script in case anyone wants to do anything similar: Projectile Property MyProjectile Auto ActorBase Property ActorMarkerHeading Auto Spell Property IceBoltSpell Auto Float Property fTRotation = 20.0 Auto Explosion Property ExplosionRef Auto Int OrbActive Int IceboltCount Actor ActorMarkerHeadingRef ObjectReference FrozenOrb Actor Player Event OnTriggerEnter(ObjectReference akActionRef) if OrbActive != 1 Form Base = akActionRef.GetBaseObject() If Base as Projectile If Base == MyProjectile FrozenOrb = akActionRef Player = Game.GetPlayer() ActorMarkerHeadingRef = FrozenOrb.PlaceActorAtme(ActorMarkerHeading) ActorMarkerHeadingRef.EnableAi(False) ;disable actor IceboltCount = 0 RegisterForSingleUpdate(0.05) OrbActive = 1 Endif Endif Endif EndEvent Event OnUpdate() if IceboltCount < 27 ActorMarkerHeadingRef.EnableAi(True) ActorMarkerHeadingRef.Moveto(FrozenOrb, abMatchRotation = False) ActorMarkerHeadingRef.EnableAi(False) ActorMarkerHeadingRef.SetAngle(ActorMarkerHeadingRef.GetAngleX(), ActorMarkerHeadingRef.GetAngleY(), (ActorMarkerHeadingRef.GetAngleZ() + fTRotation)) IceBoltSpell.RemoteCast(ActorMarkerHeadingRef, Player) IceboltCount += 1 ;add 1 to IceboltCount RegisterForSingleUpdate(0.05) else FrozenOrb.placeatme(ExplosionRef) FrozenOrb.Disable() ActorMarkerHeadingRef.Disable() ActorMarkerHeadingRef.Delete() OrbActive = 0 endif EndEvent I also had to set the casting NPC to .1 in order to get the spell to fire from the orb rather then above it. Friendly NPCs such as riverwood citizens also report the crime, but do not start combat with the player(not red on compass) but do try and attack the ActorMarkingHeadingRef. I may be able to get around this by making the ice spike magic effect painless while attaching a script that forces targets hit into combat with the player. Edited April 20, 2021 by senterpat Link to comment Share on other sites More sharing options...
dylbill Posted April 20, 2021 Share Posted April 20, 2021 No problem, glad you got it working mostly. Is the player the only one that will use the spell? If not, and you want NPC's to use, you can set up a caster actor property in the trigger box script, and set the property when casting the spell. Something like this: Projectile Property MyProjectile Auto ActorBase Property ActorMarkerHeading Auto Spell Property IceBoltSpell Auto Float Property fTRotation = 20.0 Auto Explosion Property ExplosionRef Auto Actor Property Caster Auto Int OrbActive Int IceboltCount Actor ActorMarkerHeadingRef ObjectReference FrozenOrb Actor Player Event OnTriggerEnter(ObjectReference akActionRef) if OrbActive != 1 Form Base = akActionRef.GetBaseObject() If Base as Projectile If Base == MyProjectile FrozenOrb = akActionRef Player = Game.GetPlayer() ActorMarkerHeadingRef = FrozenOrb.PlaceActorAtme(ActorMarkerHeading) ActorMarkerHeadingRef.EnableAi(False) ;disable actor IceboltCount = 0 RegisterForSingleUpdate(0.05) OrbActive = 1 Endif Endif Endif EndEvent Event OnUpdate() if IceboltCount < 27 ActorMarkerHeadingRef.EnableAi(True) ActorMarkerHeadingRef.Moveto(FrozenOrb, abMatchRotation = False) ActorMarkerHeadingRef.EnableAi(False) ActorMarkerHeadingRef.SetAngle(ActorMarkerHeadingRef.GetAngleX(), ActorMarkerHeadingRef.GetAngleY(), (ActorMarkerHeadingRef.GetAngleZ() + fTRotation)) IceBoltSpell.RemoteCast(ActorMarkerHeadingRef, Caster) IceboltCount += 1 ;add 1 to IceboltCount RegisterForSingleUpdate(0.05) else FrozenOrb.placeatme(ExplosionRef) FrozenOrb.Disable() ActorMarkerHeadingRef.Disable() ActorMarkerHeadingRef.Delete() OrbActive = 0 endif EndEvent Then when spawning the trigger box do something like this: Static Property IceTriggerBox Auto Event OnEffectStart(Actor akTarget, Actor akCaster) ObjectReference IceTriggerBoxRef = akCaster.PlaceAtMe(IceTriggerBox, 1) (IceTriggerBoxRef as patDestructFrozenOrbTriggerBoxScript).Caster = akCaster EndEventBut if the blame for the remoteCast function isn't working, then the point is moot anyway. Link to comment Share on other sites More sharing options...
Recommended Posts