Spells: Front-End Graphics

It’s finally time for spells to get the treatment and become a regular feature in Daggerfall Unity. I have decided to approach this feature-set in a more visual way than I did the quest system, which involved several months of back-end work before I could even show a single screenshot. This time around, I want the process to follow the visual diary approach from day one to make it more interesting to watch things unfold. This also helps me stay motivated as it’s a lot more fun to hurl around glowing balls of magical death than build a runtime compiler for the quest system.

There will be some more code-oriented articles later in the series, but for now let’s take a look at the front-end graphics of spell-casting animations and missiles.



Before I can do anything else, I have to implement the basic cast/recast loop. Thanks to Lypyl, a baseline spellbook interface is already in the game. It doesn’t have any actual spells yet, just some temp line items, but that’s all we need right now.

I wired up the spellbook to the “cast” key (default is Backspace) so player can select a spell from their collection. It doesn’t matter which “spell” you choose at this point. Just double-click any item to let the game know you’ve selected something.


After selecting a spell, I then had to create the player’s basic spellcasting loop. For non-immediate spells like firing a missile, this hides any weapons and puts player into a ready-to-fire status for that spell. The player will see a message on the screen saying “press button to fire spell.”.


At this point, player can fire spell (press mouse button) or cancel (default is E key). Once the spell has been fired, they can “recast” that spell (default is Q key) or continue attacking with weapons. Most of the work at this stage was around handling when player was about to cast or cancel, when they had a previous spell to recast, and when weapons and other clicks needed to be directed to spell manager. With all that out of the way for now, we can give the player some magic hands.


Casting Animations

The cast anims are stored as a simple left-hand only set of animation frames. They are played from frame 0 through to 5, then 0 again as hand is retracted at end of cast. Here’s how the raw images look as seen by Daggerfall Imaging 2.


These are very similar to the weapon animations, but have a few unique requirements around how they must be scaled and positioned that are quite different to weapons. They’re also a single-frame CIF record format rather than a multi-frame CIF format. Considering how much they diverge from weapons, I opted to create a new FPS animation class to render these for the player and handle their unique requirements. There’s also a few other little twists, like frame 4 (second from right) not being a consistent type in all anims. In the the cast of frost, frame 4 must scale to side of display, but for fire it must be positioned independently like first and final frames.

The final frame is an interesting one as both sides of the anim must meet in the middle while retaining best possible position and scaling under a range of different aspect ratios. This is something classic Daggerfall didn’t have to worry about as it only ran at 320×200 and all the art was designed for that native resolution. This presented me a few problems, but I think these are solved now. To give you an idea how left and right hands join together, here’s an example with the split between each side exaggerated. You can see how the left hand is mirrored to the right and joins in the middle to form the moment of spell release.


After some work, I had all the casting animations working properly. Here’s a loop of each element type in action (direct link)


Spell Missiles

With casting animations done, it’s time to start hurling around glowing blobs of magical death. Well, setup the graphical side at least, these aren’t real spells yet.

Here’s how the fire and cold missiles appear in Daggerfall Imaging 2. The first set of animations are how the missile looks while moving, the second is played when it hits something and the spell is executed.


These were fairly easy to setup, as Daggerfall Unity already has pretty good billboard support. The only problem encountered was making them emissive (appear lit from within and not affected by surrounding lighting). There was a quirk of my texture loading code that detected spell missile textures as windows and blocked the emission. But once that was solved, I was ready to fire missiles around town. I’ve added some basic lighting to the projectile for that extra bit of magic (direct link).


Timing, Origin, Collisions

Now that I can shoot missiles, a few things had to be cleaned up. As one Twitter user pointed out, it looks like the player is shooting missiles from their pants. This is because origin of missiles is the player capsule, and the origin of capsule happens to be waist-height, which is roughly pants territory. This is enhanced when looking up or down as missiles don’t really appear to be coming from the hands themselves.

I setup a delegate event that allows me to time the release of missile with the exact casting frame where it should be released, and I adjust the origin to chest height and handle the facing vector properly. This needed a little bit of tuning as hands cast slightly below centre-point of display (even in classic) so spells don’t appear to go where you’re looking. And if I make origin too high, spell appears higher than casting point which ruins illusion as well. With a little bit of tuning, I found a good balance between timings, origin, facing, and missile radius.

Next I added collision detection. This allows missile to detect when it impacts scenery or an entity like a monster (or even the player themselves). There are two parts to this, first is the direct impact and second is the radius of any area-of-effect spell on that missile. There’s no easy way to show a screenshot of this, but the missile collects a list of every entity it strikes either directly or with AOE so it can hand this back to whatever system initiated the missile. Keeping things abstract like this allows for missile to be used in other ways (like archery) down the road.

And finally, I added the small explosion anim when missile strikes something. Here’s how it looks in action (direct link).

By the way, if you don’t like the lighting or shadow effects on spell missiles, you can turn these off in settings.ini by setting EnableSpellLighting=False or just EnableSpellShadows=False to disable shadows only. Hopefully this will satisfy both classic purists and those who want a little extra shine to their spellcasting. I’m hoping someday there will be spell missile mods to really amp up the visuals with particles, etc. But this early in development, I’m happy with just some basic lighting effects. I’ll show off a few more of these with other element types in later posts.


Putting It All Together

With all the front-end pieces working, I can simulate a magical brawl with some real enemies. There’s no actual damage happening here, because these aren’t real spells yet, but all the import parts are taking place. The player can select a spell, fire/cancel/recast that spell, see their cast animations, and watch the missile explode against the environment or their foes. Internally, any entity struck by the missile or subsequent AOE is collected for later processing when spells get real.

So here’s that magical brawl with one more lighting enhancement, a brief flash of brighter light when spell explodes (direct link).

Now player can hurl missiles around, the work of implementing real spells & effects can begin. My next article in series will take a deeper look at the inner workings of Daggerfall’s spell system and hopefully some first steps towards real spells in Daggerfall Unity.


For more frequent updates on Daggerfall Unity, follow me on Twitter @gav_clayton.

Posted in Daggerfall Unity, Visual Diary.


  1. Lighting effects of spells being thrown at enemies is mindblowing! Almost forgot they were just sprites!

Leave a Reply

Your email address will not be published. Required fields are marked *