Jump to content

[LE] Scripting summoned creature to cast at hostiles then stop script upon death


Noober1

Recommended Posts

Hello! I've been working diligently on a mod that circling around 2 1h crossbows (the oldrim mod everyone by now has seen) and its coming along really well. I planning a D3 Demon Hunter style class and currently am working on a summon spell that summons a turret. When cast, the summon appears just find and turns to attack enemies but does not shoot any arrows or cast any spells. It has both arrows in inventory and spells added in spell list with plenty of magicka and skill offset to cast them. I looked into adding a script to force it to attack and it works, somewhat.

 

What I have causes it to fire a firebolt at ANYONE (including the player) that is in range. I could live with that, though would optimally prefer it just attack hostiles, however the script stays in effect after the summon has disappeared/died. It just keeps firing off firebolts endlessly from the location the summon entered at. I used a 'Completed Script Example' from creation kit website and plugged in some of my Properties.

 

Here's what I have so far....

 

Scriptname WHA_SentryCombatScript extends ObjectReference
import Utility
Actor Property PlayerREF Auto
Float Property xOffset Auto
Float Property yOffset Auto
Float Property zOffset Auto
Float Property RandomOffsetX Auto
Float Property RandomOffsetY Auto
Float Property RandomOffsetZ Auto
Float Property PulseRate = 1.0 Auto
Float Property RandomRate Auto
Activator Property TargetType Auto
ObjectReference Property CurrentTarget Auto
Bool Property SpawnNode Auto
Spell Property WHA_SentryFirebolt Auto
FormList Property TargetTypeList Auto
Float Property SeekRange = 500.0 Auto
Event OnUpdate()
if !SpawnNode && !TargetTypeList && GetDistance(PlayerREF) < SeekRange
CurrentTarget = PlayerREF
elseif TargetTypeList
CurrentTarget = Game.FindClosestReferenceOfAnyTypeInListfromRef(TargetTypeList, Self, SeekRange)
endif
if CurrentTarget
WHA_SentryFirebolt.Cast(Self,CurrentTarget)
endif
RegisterForSingleUpdate(PulseRate + RandomFloat(0.0, RandomRate))
EndEvent
I recently got into scripting and am fairly new at it and would appreciate any help anyone could throw my way. Thanks

 

Link to comment
Share on other sites

Actually this is my script...not the above reference which was missing an Event.

 

Scriptname WHA_SentryCombatScript extends ObjectReference
import Utility
Actor Property PlayerREF Auto
Float Property xOffset Auto
Float Property yOffset Auto
Float Property zOffset Auto
Float Property RandomOffsetX Auto
Float Property RandomOffsetY Auto
Float Property RandomOffsetZ Auto
Float Property PulseRate = 1.0 Auto
Float Property RandomRate Auto
Activator Property TargetType Auto
ObjectReference Property CurrentTarget Auto
Bool Property SpawnNode Auto
Spell Property WHA_SentryFirebolt Auto
FormList Property TargetTypeList Auto
Float Property SeekRange = 500.0 Auto
Event OnInit()
if CurrentTarget
elseIf SpawnNode
float newXOffset = XOffSet + RandomFloat(-RandomOffsetX, RandomOffsetX)
float newYOffset = YOffSet + RandomFloat(-RandomOffsetY, RandomOffsetY)
float newZOffset = ZOffSet + RandomFloat(-RandomOffsetZ, RandomOffsetZ)
CurrentTarget = PlaceAtme(TargetType)
CurrentTarget.MoveTo(Self, newXOffSet, newYOffSet, 500)
endif
RegisterForSingleUpdate(PulseRate)
EndEvent
Event OnUpdate()
if !SpawnNode && !TargetTypeList && GetDistance(PlayerREF) < SeekRange
CurrentTarget = PlayerREF
elseif TargetTypeList
CurrentTarget = Game.FindClosestReferenceOfAnyTypeInListfromRef(TargetTypeList, Self, SeekRange)
endif
if CurrentTarget
WHA_SentryFirebolt.Cast(Self,CurrentTarget)
endif
RegisterForSingleUpdate(PulseRate + RandomFloat(0.0, RandomRate))
EndEvent
Link to comment
Share on other sites

Okay, if you're not already, instead of using a spawn magic effect archetype, I would spawn your sentry with a script, use script archetype for your magic effect. That way you can set an owner in the sentry script and check if your target is hostile before casting. So the sentry script would look like this:

 

 

 

Scriptname WHA_SentryCombatScript extends Actor 

import Utility
Actor Property PlayerREF Auto
Float Property xOffset Auto 
Float Property yOffset Auto 
Float Property zOffset Auto
Float Property RandomOffsetX Auto
Float Property RandomOffsetY Auto 
Float Property RandomOffsetZ Auto 
Float Property PulseRate = 1.0 Auto 
Float Property RandomRate Auto 
Activator Property TargetType Auto 
ObjectReference Property CurrentTarget Auto
Bool Property SpawnNode Auto 
Spell Property WHA_SentryFirebolt Auto 
FormList Property TargetTypeList Auto
Float Property SeekRange = 500.0 Auto 
Actor Property Owner Auto Hidden ;the actor that spawned this sentry

Event OnInit()
    RegisterForSingleUpdate(PulseRate)
EndEvent

Event OnUpdate()
   
    Actor Target = Game.FindRandomActorFromRef(Self, SeekRange)
        
    if Target 
        If Target.IsHostileToActor(Owner) ;only cast spell if hostile to owner.
            WHA_SentryFirebolt.Cast(Self,Target) 
        Endif 
    endif
    
    If Self.IsDead() == False
        RegisterForSingleUpdate(PulseRate + RandomFloat(0.0, RandomRate))
    Endif
EndEvent

Then the script for you spawn magic effect would look something like this.

Scriptname WHA_SentrySpawnScript extends ActiveMagicEffect 

ActorBase Property WHA_Sentry Auto
Float Property Distance = 100.0 Auto 

Event OnEffectStart(Actor akTarget, Actor akCaster)
    Actor WHA_SentryRef = akCaster.PlaceActorAtMe(WHA_Sentry) ;place one sentry at caster
    (WHA_SentryRef as TWHA_SentryCombatScript).Owner = akCaster ;Set owner of sentry to the caster.
EndEvent

 

Hope that helps.

Edited by dylbill
Link to comment
Share on other sites

For that, you can add in a time check, like so:

 

 

 

Scriptname WHA_SentryCombatScript extends Actor 

import Utility
Actor Property PlayerREF Auto
Float Property xOffset Auto 
Float Property yOffset Auto 
Float Property zOffset Auto
Float Property RandomOffsetX Auto
Float Property RandomOffsetY Auto 
Float Property RandomOffsetZ Auto 
Float Property PulseRate = 1.0 Auto 
Float Property RandomRate Auto 
Activator Property TargetType Auto 
ObjectReference Property CurrentTarget Auto
Bool Property SpawnNode Auto 
Spell Property WHA_SentryFirebolt Auto 
FormList Property TargetTypeList Auto
Float Property SeekRange = 500.0 Auto 
Actor Property Owner Auto Hidden ;the actor that spawned this sentry
Float InitTime

Event OnInit()
    InitTime = Game.GetRealHoursPassed()
    RegisterForSingleUpdate(PulseRate)
EndEvent


Event OnUpdate()
   
    Actor Target = Game.FindRandomActorFromRef(Self, SeekRange)
        
    if Target 
        If Target.IsHostileToActor(Owner) ;only cast spell if hostile to owner.
            WHA_SentryFirebolt.Cast(Self,Target) 
        Endif 
    endif
    
    If ((Game.GetRealHoursPassed() - InitTime) > 0.016) || Self.IsDead() 
        Self.Disable()
        Self.Delete()
    Else 
        RegisterForSingleUpdate(PulseRate + RandomFloat(0.0, RandomRate))
    Endif
        
EndEvent

Link to comment
Share on other sites

That seemed to have worked but I have another odd issue. The object (or actor) I am summoning/placingatme is actually is a Dwemer Trap bow, the ones that fire giant bolts at you.

 

I used its nif as the model for the actor. Its animations do not play but I am completely fine with that since I am having a firebolt fling from it. However, the firebolt originates from the very bottom of the model/nif which pokes just below the ground and 9/10 times the firebolt is fired below ground and just hits the floor mesh and not the actor.

 

Is there anyway to place the actor higher off the ground when it is summoned or have to firebolt shoot higher? I imagine the latter is far less likely as that most likely has to do with the nodes in the nif file itself.

 

I tried to mess with the randomoffset z property but I didn't see any effect no matter how high or low I set the number.

Link to comment
Share on other sites

In the magic effect script you can try to use moveto:

 

ActorBase Property WHA_Sentry Auto
Float Property Distance = 100.0 Auto 

Event OnEffectStart(Actor akTarget, Actor akCaster)
    Actor WHA_SentryRef = akCaster.PlaceActorAtMe(WHA_Sentry) ;place one sentry at caster
    (WHA_SentryRef as TWHA_SentryCombatScript).Owner = akCaster ;Set owner of sentry to the caster.
    Float A = akCaster.GetAngleZ()
    Float XDist = Math.Sin(A)
    Float YDist = math.Cos(A)
    YDist *= Distance
    XDist *= Distance
    
    WHA_SentryRef.MoveTo(akCaster, XDist, YDist, 50, True)
EndEvent

That will move the sentry 100 units in front of you and 50 units higher. If it has collision though it will probably just fall to the floor.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...