D = 500 (in Roman Numerals)

500th Check-In since moving to TFS

500th Check-In since moving to TFS

A change to ITrackTime interface (and implementations and usages) so that a distinction can be made between the “beginning” of a time-tick and the “end: of a time-tick.  Basically I want some things to happen as the time is changing to something else as opposed to when it is changing from something else.  Ah, prepositions!

Taking the Plunge

One of the other things I’d been working on was swimming (haven’t really tested it yet), and in the course of working on it I revisited falling, which I had worked on years ago when coding flight movement.  In the Ikosa framework, falling is a type of movement, albeit a (largely) uncontrolled one.  What I was trying to bridge recently was the transition between falling and falling into water (and falling through water), and ultimately sinking (that is, if you aren’t swimming, but are in water).

So, here’s the narrative:

1) i had to alter my playground setting to add water and a big diving board platform; and move my test creatures (wizard, spider and animated object) up to it.  The following picture is from the POV of the “wizard” (using a largely unpainted greatsword wielder figure) standing at the edge, waiting to step off the platform

Deepest water I've made yet.  I had to make it in two layers to get different light levels.  Logically the water, walls and ground extend outward "forever", only my viewport is clipped

quite a drop, at least the water’s fairly deep

2) the character takes a step off the edge (into a region unsupported by gravity), and immediately gets to roll a reflex save to avoid falling.  If she succeeds, she gets to void the movement.

I could hit the roll button, but then i'm not guaranteed a fail

she’s going to fail anyway, i wanted to test falling

3) Like climbing, the falling is sent as status back the the user controlling the character.

They are actually queued per user and shipped once the processing engine goes idle, like when it has additional prerequisites for step to continue

Since there’s nothing stopping the sequence of steps, these seem to appear all at once (more or less)

4) There’s actually a couple of falling steps and pathways depending on whether the liquid falling continues past a single 5 foot cube, but in this case the water is deep enough that damage is requested and (potentially) applied on the entry into the second 5 foot cube.  At this point the system uses the fall distance accumulated from the original falling movement to determine how much damage to give.

The platform is 40 feet high

In this case: 2d3 non-lethal. Falling into at least 10 feet of water reduces fall distance by 20 feet, and converts the next 20 into non-lethal with reduced dice size.

5) This UI shows (but doesn’t pop) on the host UI at the moment.  I haven’t worked client-server mechanics for a game-master specific UI notification as of yet.  The GM needs to click “Edit” (very old UI I haven’t played with in years) to get an editor dialog as shown next.

I already took a big step toward a GM client in making a client that could handle multiple characters

a bit bare bones, but presumably the GM has been following the action so far and know why he’s clicking the button

6) After clicking OK, the damage prerequisite is met, the damage application step is processed and the client is notified, with the result’s showing on the log and the character sheet.

There's probably a post I could write about conditions and health points...

Just a (damp and brusing) flesh wound

7) Finally a visual from the character after plunging and sinking.  This image exposes a small deficiency in the visualization system…namely that under water screen masks (should be a bluish hue) are only applied directly against a surface boundary at the moment, and the character is actually only adjacent to a surface edge (the edge of the platform)

My previous underwater tests were based on very narrow and shallow water in which every cell was next to a boundary surface

those shadings on the side of the wall are light levels diminishing with depth

Heavily Nested MarkupExtensions

<GeometryModel3D Material="{uzi:VisualEffectMaterial Key=Arm, VisualEffect={uzi:SenseEffectExtension}}"
                 Geometry="{uzi:CylinderMesh CacheKey=1,
                 P1={uzi:Point3DVal Z={uzi:DoubleSum A={uzi:DoubleProduct A={uzi:DoubleVal Key=Length,Value=0.75, MinValue=0.1, MaxValue=1.5}, B=-1}, B=-0.09}},
                 P2={uzi:Point3DVal Z=0.16},
                 Diameter={uzi:DoubleVal Key=Diameter,Value=0.4, MinValue=0.05, MaxValue=1.0},
                 ThetaDiv={uzi:IntVal Key=Theta,Value=16, MinValue=8, MaxValue=20},

This is a bit of the part for an Arm model fragment. I use a lot of markup extensions to get the GeometryModel3D to be flexible enough for composition and environment shading.

First, the Material is a VisualEffectMaterial, which uses the Key to work with the Meta-Model system to figure out which texture to apply. The VisualEffect is mapped to the standard SenseEffectExtension, so that creature senses can be applied at render time.

The next big piece is the CylinderMesh used to provide the Geometry. This uses the HelixToolkit’s MeshBuilder to define parameters for creating a cylinder mesh. The Point3DVals are extensions to defined points (obviously), and the DoubleVals and IntVals define parameters that can be overriden when composing in a MetaModel. Lastly, the DoubleProduct (there’s also a DoubleSum) define mathematical functions on DoubleVals so that a same parameter can be re-used in multiple places as a factor (or sum) of other values.

Object: Animated

I had tagged my son with creating an adventure module (for low level characters) a little while back, and he got back to me telling me had included animated objects and zombies.  Zombies (in the OGL world) are created by templates, so I knew I’d have to tackle them eventually.  Animated objects seemed like a relatively simple thing, but the more I dug into it, the murkier it became.

So far, the only “species” I had worked on were a gaggle of humanoid-type classes suitable for player characters (including the goblin), and a gargoyle, since he’s a good testbed for flight, increased size by power-dice, and can take class levels.

In all of these I had a single abstract method that had to be overridden when connecting the species to a creature, and another when disconnecting the species.  I refactored this into a whole slew of overridable functions, one for each major area, like body construction, abilities, requirements, senses, and movements (etc. etc.)

I also defined a Slam natural weapon and a slam item slot (animated objects use slam).  So far, this was some simple refactoring to help guide future species construction, but then the oddities set in…

Animated Objects have no Constitution score, they do not gain feats or skill points per power die (in fact they don’t really “gain” anything, as they are almost like a template applied to objects).  While not as obvious, it was just as simple to make them not gain ability boosts every 4 power die.

The lack of CON and the immunities required some validation and creation of lots of little handlers and filters to block interactions from things like poison, or handle the absence of non-lethal damage.  Also I defined some adjuncts that can filter out other adjuncts by explicit type, source magic type or source magic power descriptor and prevent them from anchoring to the creature.  I revamped the way adjuncts bind and defined that adjunct binding was an interaction so that it could use the HandleInteraction-style of monitoring, prevention and alteration.  Previously I used a ChangeMonitor class that allowed other things to connect and signal their intention to veto the change.

Also, the size-ranges for animated objects as they “progress” in power dice don’t work like the standard set, so I had to factor in custom size ranges.  The ability scores and natural armor follow their own path for animated objects.  Weapon damage for animated objects also doesn’t follow any normal weapon progression, so I had to virtualize the roller lookup and retain the standard as a default when no custom lookup by size is supplied.

And…animated objects come in different forms, materials and aspect ratios (tall versus long), exposing some weaknesses in my original model of dealing with reach squares upon size changes.  I had to provide level 1 advancement requirements for some of these, but some others (such as aspect ratio and partial power die) I deemed reusable enough to be in the BaseMonsterClass.  Dealing with a creature that can have a fractional power die proved a bit problematic, but ultimately resolved (as a level 1 requirement flag that prevents advancement past 1 until the flag is set to non-fractional).  This also led me to having the functions to “count” creature power dice accounting for fractions when the number of power-dice affected becomes relevant to a magic power.

I also cleaned up some code that made refreshing the character sheet in WPF workshop a bit easier (except for attack modifiers which are still a bit wonky right now).

Not quite “done” with the animated object, but definitely past the bulk of it.

Docked at the Island of Avalon

Quick peek at a screen-grab of the host application after I refactored it through AvalonDock from Xceed.  It was my “get the feet wet” implementation, as I have been doing much the same for the client application (I’ll get some grabs of them a little later).

Fade-Out, Fade-In

Since January, I have actually been a bit busy; I just haven’t been posting as much.

I had previously gotten a solid animations (TransientVisualizations) implemented and tested for Magic Missile. I hadn’t, at that time, done much with the Disabled/Dying/Recovery sequence of conditions (which became apparent when I Magic Missiled my target dummy to negative health points). It turns out to be a bit convoluted, but I managed to re-do some stuff and make it all work.

During that core-rules sweep, I started getting a bit wrapped up with fatigue and exhaustion (the game conditions, not me personally), and noticed that sleep wasn’t required or forced by game-mechanics (*sigh*) not entirely sure on what that will mean going forward. Certainly sleep is needed for spell-casters, but non-casters could theoretically stay awake for-ever without any game-mechanic penalty. I’ve read some ideas, but I think I’ll defer for now.

Anyway, after that I planned to work on action aiming, which would require some substantial client-UI work and view-models. I had been planning on adding multi-character capabilities in the “test client” for some-time, and it seemed like I should do that before adding the aiming UI. I also wanted a more-flexible UI and decided (eventually) to use AvalonDock, as it would allow dockable and floatable windows.

I started working with AvalonDock on the host application, and had enough success and knowledge gain to begin the same with the client. The main challenges have been converting the control-routed-event model I originally used years ago, and converting it to a more MVVM-ish model. I had already moved a good part of the client to MVVM, but now saw that I had much more to do (commands in the model!)

After I get the UI re-factor done (and add multi-character login support), I’ll include some screenshots here.

Direct Line

I forget to bring my cell-phone with me today (so my wife would have to call on my direct desk-phone line), but that’s not the basis of the title. Instead, after tweaking and prodding the spell target delivery mechanism so that Magic Missile would yield its animations to the local map context, I got a (semi-)successful test working. Unfortunately, since Magic Missile doesn’t use an attack aim, but instead an awareness aim, I only had immediate access to what is called the “PlanLine” when deciding on animation end-points.

The PlanLine is the first line-of-effect between the source and target that is not blocked, which goes from corners to corners (at the moment) and starts testing for lines-of-effect at the “bottom”. So, the “bolt” currently travels right along floor level such that I pretty much missed it the first couple of times I fired a magic missile from a wand. I did, however, see the “splash” of the missile making contact (also at floor level) so I knew animations were being added, transmitted to clients, and rendered. I’ll have to alter the awareness aim animation start and end points to be the centroid of the map-locators holding objects causing the action, and being targeted.

There are some other things to work out on when the animations should be rendered and re-rendered, as the damage roll side-panel (for the spell caster) pops up while the Magic Missile is still visibly flying in the post-action redraw sweep, and if you change target selections the animations are re-run as time hasn’t changed. I’ll probably have to separate “re-run animations” from “scene redraw”.

Visualizing the Future

The last month hasn’t been idle time. I’ve been working towards TransientVisualizers (think animation sequences for certain splashy actions) being associated with certain server-side model activities and being transmitted to the client where they can rendered. I’ve added support for “literal” brush keys, in which the key name represents a solid color or a linear gradient (horizontal or vertical) so that I can encode fail-safe animation colors without having to have mapped brushes defined (in Ikosa packages) for the models.

I’ve also added a storage area in the map for holding transient visualizations for the current tick. When the map time changes the transient visualizations are cleared (hence: transient). This storage area is accessed by an operation contract in the visualization service contract. Well enough to have a place to store and retrieve visualizations, but I also added bits to the power definitions and (by extension) the spell definitions for supporting animation types based on targets and animation style. Turns out that not too many spells (in the 0th to 2nd level range) require flashy animations, as some of them are buffs, divinations, “invisible” effects, or create persistent (not transient) objects such as dancing lights.

I did add one new type of animation over my previous set: namely a flying orb that moves a sphere from point to point. I already had a flying “bolt” (ray bolt), but there are some low level orb-spells that are necessary. I bound animations to the spells that needed it, and fixed a few power and spell issues I noticed along the way.

Finally, the past week or so has been fixing some client-side items (and server-issues that led to them) related to icon imagery, which I never implemented in the client (despite being the reason for doing all my flat XAML icons), but now have.

My next bits of effort are in surfacing wand and spell action selection and targeting in the client (they are defined and should be “working” server-side) so that I can test and fix the animations that should be bound to them.

ILSpy with my Little Eye

Hooray for ILSpy.

I inadvertently reverted an important file that was at the center of a series of changes I was making to fix a model resource bug. I had compiled and tested it, but when I was committing the files via the Ankh SVN integration I saw one file I only changed to troubleshoot. Naturally I wanted to revert the file (or not commit it), but made the “mistake” of attempting it in the commit box (before I had committed anything). I thought I did it all right, but apparently the checkbox and the revert context menu do weird things (and I didn’t double check in the confirmation dialog).

I didn’t discover my problem until the next day. The only good thing was that I still had the compiled assembly, so after trying to hand uncrank the code back to C# source, I found and downloaded ILSpy. Worked wonderfully, only had to polish a few things back up, and add some comments to make it look like the rest of my codebase style-wise.

Crisis averted.

One MeshGeometry3D to Rule them All

I finished off the PanelCellSpace a few weeks ago, and got it pushed through to the service host, proxy client and client UI. One thing I noticed (since I was testing in a large outdoor space) was that the performance was absolutely crappy (client-side…the workshop rendering was mostly OK). I wanted to fix this right away; but knew it would take profiling, though spending $500 around tax time wasn’t a viable alternative. Thus I had to improvise.

Enter good old Debug.WriteLine() statements with timings. I soon narrowed down a major performance problem to calling the full map rendering method 3 times. Basically when anything changed I was redrawing the entire map, locators (game tokens) and overlay graphics (aiming cells and lines). By separating those functions and only calling them when needed, I reduced re-draw time from 4.5 seconds (after making a single 5 foot move) to 1.5 seconds. Pretty good, but I was certain it could go faster.

I toyed with several ideas including caching full frozen Geometry3D models (per thread), and having other mesh collapsing optimizations. I finally settled on an approach of rather than drawing each cell face into a cell Model3DGroup with copious amounts of (frozen) transforms, I’d build aggregate meshes for cell faces using the same material rather than separate models. I had to replace a parameter in my call chains (and retain the old group for those cells I didn’t want to “upgrade” to the new style just yet), and futz around with collecting cell Model3DGroups and the shared MeshGeometry3D, but the end result is about 0.3 seconds from action start on client, through to server processing and updating, back to notification, collection of new map display data (based on senses) and rendering.