Even though I’ve had the warhammer model fragment for awhile, I still think it looks pretty cool when properly painted with gradient materials. I was tightening up some of the other content tools, and also finished the 3D models fragments for the great sword, bastard sword, dart and javelin, as well as tightened up the long sword now that the great sword and bastard sword are around for comparison.
If I feel so inclined I’ll add images of some of them as well.
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).
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.
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.
Here’s a snapshot of pretty much every XAML Icon I have so far. I’ve been a bit busy making sure I could load these into packages as resources and share them between resource referenced packages. I also have built code to associate these with in-game objects and provided mechanisms to override and pass them through from the server to the client. I still need to build the client and add icon display in the client and the workshop.
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.