cscottydont Posted February 14, 2012 Share Posted February 14, 2012 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 More sharing options...
cscottydont Posted February 14, 2012 Author Share Posted February 14, 2012 (edited) was looking through the wiki and happened upon the OnUpdate page wiki I think this might be what I'm looking for but I have no idea how to go about it...any ideas/pointers? Edited February 14, 2012 by cscottydont Link to comment Share on other sites More sharing options...
Cipscis Posted February 14, 2012 Share Posted February 14, 2012 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 More sharing options...
cscottydont Posted February 15, 2012 Author Share Posted February 15, 2012 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 itits 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 ticksincreasing 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 intendedits 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 More sharing options...
cscottydont Posted February 19, 2012 Author Share Posted February 19, 2012 (edited) 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 February 19, 2012 by cscottydont Link to comment Share on other sites More sharing options...
Recommended Posts