Programmable Spell Effects
Note[edit | edit source]
Most, if not all, of this is easier to do with OBSE's Active Effect functions
PROGRAMMABLE SPELL EFFECTS
Er? Can't I program my own spells using script effects already?
Well of course you can but there are several limitations. For example, what if you wished to do some combination of the following:
1) 'Silently' damage an NPC, i.e. without seeing any magic effects.
2) To turn the player invisible without raising his/her arm to cast.
3) XXX spell to be considered hostile only when a guard sees me cast it.
4) Cast a Morrowind-like spell that may fail and/or do a random amount of weapon damage.
5) Cast a spell that does fire damage to frost atronarchs but frost damage to flame atronarchs.
6) Know who cast that spell at me or some other actor.
Well now you can! The following procedures are built on the fact that Ability spell effects are cast on the target the moment they are added and do not cause any visible effects on the target nor caster. Of course you can add whatever effects you do want to see with PlayMagicShaderEffects or PlayMagicVisualEffects, etc.
Here is a BASIC example of how to create a 'silent' spell effect that does an instant 10 damage to the target:
Step 1: create an Ability spell, lets say 'SilentDm10' with:
Std Effect: Health Damage 10
Script Effect: StopSilentDm10
Step 2: create and attach the following magic effect script 'StopSilentDm10':
scn StopSilectDm10 Begin ScriptEffectStart RemoveSpell SilentDm10 End
Step 3: actually use the spell in some other script:
; target here is a reference to some actor (or player) target.AddSpell SilentDm10
Notice that using this spell is actually a neater syntax than that for Cast.
NOTE: Adding an ability to the player will produce message spam and so in this case this effect is not so silent. I would recommend changing the actual name of the spell to be something appropriate, e.g. "Poison damage". You wont see more than one "Posion damage added" message so long as all of your equivalent ability-cast effects have the same name.
True programmable spells are more useful. They are in effect (in-game) function wrappers for several silent and standard (area-effect targetting) spells.
Here is one example to show the BASIC principle. This one allows you to do X-fixed plus Y-random damage to a target:
scn WildDamageSpell ; this is an in-game function attached to object 'FIGWildDamageSpell' ; - refer to the 2nd post and other posts of this thread ref target short baseDamage short wildDamage short isPlayerHostile short dam Begin Activate ; get/check the target set target to GetActionRef if target.IsActor == 0 || target.GetDead == 1 Return endif ; calculate damage apply to target set dam to baseDamage+wildDamage*0.01*GetRandomPercent ; activate hostile - very primative version to give an idea ; - does not check in town, guard vacinity/sight, current bounty, etc. if dam > 0 && isPlayerHostile > 0 if target.IsGuard == 0 target.Startcombat player endif SendTrespassAlarm player player.ModCrimeGold 35 endif ; add some (un-typical) spell graphic(s) (optional!) if dam > 0 target.PME DTCT 1 endif ; apply damage - here it is limited to 0-31 points per cast ; - dam <= 0 does nothing, dam > 31 does 31 if dam >= 16 target.AddSpell SilentDm16; same as SilentDm10 in last example but does 16 damage set dam to (dam)-16 endif if dam >= 8 target.AddSpell SilentDm08; ditto for 8 damage, and so on... set dam to (dam)-8 endif if dam >= 4 target.AddSpell SilentDm04 set dam to (dam)-4 endif if dam >= 2 target.AddSpell SilentDm02 set dam to (dam)-2 endif if dam >= 1 target.AddSpell SilentDm01 endif End
To cast this spell, since it is an in-game function:
; target here is a reference to some actor - player is assumed to be the caster set FIGWildDamageSpell.baseDamage to 10 set FIGWildDamageSpell.wildDamage to 20 set FIGWildDamageSpell.isPlayerHostile to 1 FIGWildDamageSpell.Activate target 1
Advanced programable spell effects
Basically the sky's-the-limit here, or rather a matter of your imagination and scripting experience. Here are just a few things to expand the range of programmable spell functions:
1) Timed spells: Since in-game functions have the ability to trigger their own GameMode, a small modification of your spell function can be made to trigger every second (or every frame) for any variable time.
2) Touch/Target/Area effects: Since in-game functions can be called from anywhere, create a standard spell with the scope effect you want and add a script ability that just calls the function on the target(s).
3) Player-area/fast-target spells: Area effect spells cast from an activator/marker on to the player (caster) have been used by several people and are discussed on the CS Wiki and various threads. However, now you can wrap these effects nicely in your programmable spell function and have full control.
4) Caster tracking: Just add a reference variable to your function script called 'caster' and set before calling the function. (It may be appropriate to do this for the target ref(s) too.)
5) Simulating resistance, casting cost, etc.: These can all be done as checks, etc., in your spell function before the silent spell effect(s) are added. It's all up to you!
6) NPC cast spells: To force actor X to immediately cast on target Y is simple. Having it cast as it would be by RAI may take a bit of work. You could add a (hostile) spell to the actor directly that then adds your effect the target (as in 2 above). However, this will add to the base actor object. You can also simulate the AI yourself (AAI) with a permanent spell effect. This has a similar issue and solution, as described below.
Permanent Spell Effects
Ironically enough, the thing that Ability spells are not a good idea for is adding permanent effects to targets - including the player! The problem is that abilities get cancelled/re-cast when the target enters or leaves the player cell, and any scripted variables are reset. This also applies to abilities on the player when he/she changes cell, although here it is not so bad if you employ all global variable in the ScriptEffectUpdate block. An even less desirable issue is that the ability is added to the base actor object so any spawned generic characters will inherit the same ability. (This is partly why the recipe for silent spells always removes the ability after 1 frame.)
This is not an issue if you want your script to affect all base models and may actually be appropriate since the ability will only be in effect when the affected actor(s) are in the same cell as the player.
However, for true permanent (spell) effects on targets or invisible abilities on the player you really need to use Token Effects.