Jump to content

spell script not working as intended...


cscottydont

Recommended Posts

Preface: I'm a complete noob.

 

I'm trying to create a concentration type spell that increases in intensity the longer the target is affected by it.

I currently have 2 scripted magic effects on my spell.

1. adds a counter item every time it ticks which is working as intended

2. "watches" how many items have built up so it can clean up afterward.

 

I'm having issues with #2. I want the items to build up as long as the target is taking continuous damage from the spell. So, if the player's aim strays for long enough for the damage to stop, or the target dies, or the watcher spell expires (the "No Death Dispel" box is unchecked so the last 2 should always happen eventually...?) the items get removed from the target.

 

Here's the script I'm working with

 

 

Scriptname testscript3 extends activemagiceffect  

MagicEffect Property csdFireDamageConcAimed00 auto
Spell Property csdfirewatcherspell auto
Armor Property csdringfirecount auto 

int Property firecount auto

Event OnEffectStart(Actor akTarget, Actor akCaster)
  
;   Debug.Notification("effect started should end in 10 sec")  
  
 while akTarget.HasMagicEffect(csdFireDamageConcAimed00) == 1
 
Debug.Notification("target is affected by magic effect")

 endwhile
 
 ;when target is no longer affected by MagicEffect, clean up
 firecount = akTarget.GetItemCount(csdringfirecount)
 akTarget.RemoveItem(csdringfirecount, firecount)
 akTarget.DispelSpell(csdfirewatcherspell)
 Debug.Notification("done")
 
EndEvent 

Event OnEffectFinish(Actor akTarget, Actor akCaster)

  Debug.Notification("effect ended")

 ;when target is no longer affected by MagicEffect, clean up
 firecount = akTarget.GetItemCount(csdringfirecount)
 akTarget.RemoveItem(csdringfirecount, firecount)
 akTarget.DispelSpell(csdfirewatcherspell)  	

EndEvent 

 

 

 

The OnEffectFinish event works fine.

I had thought that "while akTarget.HasMagicEffect(csdFireDamageConcAimed00) == 1" would remain true for as long as the target was affected by the MagicEffect, but it only remains true for 1 tick of the spell (possibly because its a "concentration" type effect?).

 

So what I need is a better way to tell if the target is taking continuous damage from the spell.

Link to comment
Share on other sites

Hi cscottydont :)

 

OnUpdate could be worth trying. In order to get it to fire, you'll want to call RegisterForUpdate inside your OnEffectStart event.

 

If HasMagicEffect wasn't working in your loop, perhaps try giving your effect a small duration - enough to make it last until the next "tick". I'm not particularly familiar with how different ways of casting spells are handled like this, but that might enable your loop to work as you want.

 

Cipscis

Link to comment
Share on other sites

disappointing report:

 

I don't think what I'm trying to do is possible right now...

 

Here's the script I ended up with.

 

 

Scriptname testscript3 extends activemagiceffect  

MagicEffect Property csdFireDamageConcAimed00 auto
Spell Property csdfirewatcherspell auto
Armor Property csdringfirecount auto 

int firecount = 0
Actor Target

Event OnEffectStart(Actor akTarget, Actor akCaster)
  
   RegisterForSingleUpdate(1)
  
Target = akTarget  

  Debug.Notification("effect started")  
  
EndEvent 

Event OnUpdate()

 if Target.HasMagicEffect(csdFireDamageConcAimed00) == 1
   
   RegisterForSingleUpdate(1)
   Debug.Notification("spell still going1")

 elseif Target.HasMagicEffect(csdFireDamageConcAimed00) == 0
 
 	Debug.Notification("target no longer effected1")

RegisterForSingleUpdate(1)
   firecount = Target.GetItemCount(csdringfirecount)
   Target.RemoveItem(csdringfirecount, firecount)
   Target.DispelSpell(csdfirewatcherspell) 

 endIf
 
;  Debug.Notification("nothing is true!")
 
endEvent

Event OnEffectFinish(Actor akTarget, Actor akCaster)

  Debug.Notification("effect ended")

 ;when target is no longer affected by MagicEffect, clean up
 firecount = akTarget.GetItemCount(csdringfirecount)
 akTarget.RemoveItem(csdringfirecount, firecount)
 akTarget.RemoveSpell(csdfirewatcherspell)
 akTarget.DispelSpell(csdfirewatcherspell)  	

EndEvent 

 

 

 

After hours of messing around with this I've come to these conclusions:

 

1.increasing the Duration at all or the Taper Duration over 0.1s on my "watched" spell effect (csdFireDamageConcAimed00) breaks the script effect attached to it

its a 1 Magnitude, 0 Duration, 0.1 Taper Duration, Concentration Magic Effect which has a script attached that adds 1 counter item every time it ticks

increasing the durations at all causes it to instead add 1 counter item every time the spell is initiated on the target (so you could sit there holding down the cast button for an hour and only give the target 1 item)...baffling

 

2. I intended this part of the script

 

 

  if Target.HasMagicEffect(csdFireDamageConcAimed00) == 1
   
   ...

 elseif Target.HasMagicEffect(csdFireDamageConcAimed00) == 0
 
 	...

 endIf

 

 

to keep track of whether or not the target was taking continuous damage from the spell in question

(HasMagicEffect seemed like a really unreliable way to do it in the first place, but was the best solution I could come up with)

(IsSpellTarget sounds like it would be perfect for this but there is no papyrus alternative that I could find)

it does not work as intended

its my understanding that at leas one of those conditions should fire at all times, since one of them has to be true...

however sometimes neither would fire and other times they would both fire in the same OnUpdate check

 

3.I believe 1&2 must stem from the way the game handles concentration type effects

 

without a working method for #2 this spell is impossible to make

Link to comment
Share on other sites

After much poking and prodding, I finally got a functional spell. Unfortunately the damage is all scripted. I was initially trying to use 1 concentration spell that had a bunch of Magic Effects on it, that would activate as the target's number of counter items increased.

 

This was messy 1. because sometimes the watcher script would fail to remove all of the items when the target died and 2. because having 5 separate magic effects with conditionals running constantly on a concentration spell caused a noticeable drop in performance.

 

I wanted to do it that way because the spell would automatically benefit from any casting/spell power buffs the player recieved and I wouldn't have to worry about math at all. (I wouldn't say math is my nemesis, but he has come up with some devious plots in the past...(didja see what I did there?))

 

Here's the script if anyone cares. I'm still not 100% done with it but it works as intended now. I'll eventually get around to working out some level scaling and adding some player magicka damage to go along with the health damage.

 

Scriptname csdFireWatcherScr extends ActiveMagicEffect  
{Watches for damage from flames spell, cleans up afterward}

Spell Property csdFlames auto
Spell Property csdFireWatcherAb auto
int Property DamageCap auto
int Property Damagecurve auto
String Property Health auto

int csdcheck = 0
int csdCount = 0
float fdamage = 0.0
Actor csdSpellTarget

Event OnEffectStart(actor akTarget, actor akCaster)

 csdSpellTarget = akTarget
 RegisterForUpdate(0.2)
 
EndEvent

Event OnDying(actor akKiller)

 UnRegisterForUpdate()  
 csdSpellTarget.RemoveSpell(csdFireWatcherAb)

EndEvent 

Event OnUpdate()

 if csdSpellTarget.IsDead() == 1
 
   UnRegisterForUpdate()
   csdSpellTarget.RemoveSpell(csdFireWatcherAb)
 
 endif

 if csdcheck == 2 ;means OnUpdate fired twice before OnHit so reset counter
   
if csdSpellTarget.IsInCombat()

  csdcount = 0
  
else
  
     UnRegisterForUpdate()
     csdSpellTarget.RemoveSpell(csdFireWatcherAb)	  

endif

 elseif csdcheck == 0 ;means OnUpdate fired before OnHit, wait for one more OnUpdate
 
   csdcheck = 2

 elseif csdcheck == 1 ;means OnHit fired, reset check and go again
   
   csdcheck = 0
csdcount += 1
fDamage = (((csdcount * csdcount) + csdcount + 1)/DamageCurve)

if fDamage >= DamageCap ;caps exponential damage via property

  csdSpellTarget.DamageAV(Health, DamageCap)
  
else

  csdSpellTarget.DamageAV(Health, fDamage)
  
endif

 endif

EndEvent 
 
Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)
 
 if akSource == csdFlames

   csdcheck = 1
 
 endif

EndEvent 

 

Edited by cscottydont
Link to comment
Share on other sites

  • Recently Browsing   0 members

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