The Past Week

Opportunistic attacks are now working fairly well. I’ve managed to trigger them off on movement from a threatened cube and by trying to use a ranged weapon in a threatened cube. Also tested: not being able to make an opportunistic attack if the target has cover, and only being able to attack when wielding a weapon that can make such an attack. Haven’t played with reach weapons yet.

I also discovered (and fixed) a problem with some of the attack handlers, in that I had a handler chain defined for a base class (AttackData) that prevented the chains for more specific attack types (MeleeAttackData, ReachAttackData and RangedAttackData) from activating. I ended up changing the interaction handler chain matching algorithm to work with exact type matches, rather than IsAssignableFrom(). Had to also make sure I wasn’t orphaning any use cases.

Lastly (and I still have to fix this), I discovered that a target standing on a low step could trigger a Cover alteration, resulting in a +4 to Armor Rating for the target. This is because the cubic region’s lower corners are blocked by the solid material of the cell. I’m going to look into using adjusted coordinates for determining extents for a target (rather than blindly using the cube corners) based on the IPhysical properties and intra-locator positioning (including Offsets)…and I’m going to put some stuff in to account for low barriers (2′ high or less) by trying some alternate point testing under “certain” conditions.


Model View View-Model

Finally got (most) of the client-side features back together under a more MVVM-like pattern (still haven’t adopted the RelayCommand style yet…). Now, I can more easily get additional data into the Opportunistic Inquiry Prerequisite dialog, since I won’t have to climb through data contexts and control-bound properties to find the data from the framework. I can just bind it in…

I also inched the “bio” part of my Kickstarter project a little bit farther. Every day I see more and more games on Kickstarter, quite a few of which are sandbox and adventure games. There’s an upside and a downside to that, the downside is in launching my project too late (which is comical to me as I “launched” about 7 years ago with the code, or 30+ years ago with the concept), and getting lost in the sea of games. The upside is that the project funds sought looks like they are realistic to keep the developers eating (which is a requirement of mine as well), without having to work in a factory.


Model View Something…

I started the client UI (and proxy code) for the Ikosa Framework quite some time ago. Since the whole framework has been under development since early 2006 (six years) the client UI is probably no younger than about early 2007 (I could look it up in my Vol 1 or 2 of my notebooks if I had the inclination).

Anyway, WPF hit the scene with .NET 3 in late 2006, so I was working in unexplored territory (with my mental models at least, if not in accepted “best practices”). Correspondingly, much of the client-side framework was (and still is) fairly hodgepodge. I slowly came around to RoutedCommands (fantastic things), and DataTemplates (and DataTemplateSelectors!), and some data-binding.

Mainly what held me back from pervasive data-binding was that most of the instances I had to visualize were coming from the proxies as DataContracts. These were not implementing INotifyPropertyChanged, or INotifyCollectionChanged, and it wasn’t obvious (in my bone-headed way) how to make this “work” with a data-model controlled on the other end of the WPF channel. I may also have been reluctant to wrap data-contract classes (yet again) for WPF, since I already had to pack and unpack them in the host-side for processing in the Ikosa setting.

However, once I got around to the opportunistic attack prerequisite, I saw that to visualize the options well, I needed to provide useful information from elsewhere in my data “model”, which could be “found” scattered in a loose-confederation of DataContexts, POCO properties (set via constructor or assigned after an event fired) and some DependencyProperties mostly all parked on various controls of the UI, some templated, some not.

Then I decided to change all that…(or most of it)…over Easter Weekend, while also trying to assist two black belts testing for second degree next weekend, driving back and forth to Reading, PA twice (about 5 hours total), and having a rather pleasant Easter at my parents.

So far, I have a stable build. But am seeing that I’ll have to deal with some ObservableCollections that I (now) understand won’t work across threads. And I have some server-side debugging to do (I also altered the hosting model to allow a single user to control multiple actors, in theory). What I have started as a MVVM, but I started adding more “C” (as in Controller) type functions, since I was moving them off of the UI controls where they were before.

All in all, despite the fact I broke my system (client and host), I am satisfied that the foundation is becoming better.


Three’s Company

In order to really test delaying on one’s turn, I had to add another character to the setting. Red Dude, Blue Dude, and now Green (I forgot to include the last name of Dude). I need to run three clients to test them out. Eventually I’ll make a multi-character client for TB2.

Anyhow…I did find that although I had most of the code to manage the delay list and remove actors from it when they act, I hadn’t added anything to put them into the list when they delay for the first time.

So, I sorted that all out now; and exposed some client-state refresh issues.

Therefore: next up…better signalling from the host to the clients when the delay step is activated. When the DelayTickStep is the current step, the game clock doesn’t tick unless the delaying actor decides to act. Therefore, one of the normal update signals (time-tick) isn’t sent to the clients, like it is during a LocalTickStep or LocalTimeStep.

I also need some better visual cues in the client that they can or cannot act, based on who has the focused budget.

While I’m at it, I might as well get some character models with different colors. I have some…but they’re not dimensioned to work with the auto-scaling features of the creature sizer; yet I should be able to throw a Scale3DTransform around them in the XAML.


Expedition #4

Expedition #3 taught me that in LINQ, you don’t get IEnumerable<???> sequences that evaluate to null. They will always have a value, even if they are empty due to where clauses. Seems pretty obvious, but apparently not to me when I originally wrote the code for opportunistic strike zone geometry culling. Should be fixed now. So expedition #4 will both confirm this, and try to isolate the problems with the missing iniative roll.


Opportunity Knocks You Down

Finally got the basics of turn-tracking running much more smoothly (could still use some better visual cues in the client). After establishing initiative, I moved the creature with the highest initiative.

Immediately, a prerequisite dialog box pops on the client (the server wants me to provide some feedback). No useful data on the screen (a prerequisite for which I haven’t provided a DataTemplate), and no title (I hadn’t put a key or name on it either!).

The host tells the story…I am being asked if I want to make an opportunistic attack. I realize I have provoked an opportunity against myself!

Apparently I hadn’t excluded the actor from the weapon strike zones capturing the location I am moving from. I imagine attacking myself as I leave my own threatened cube.

OK. So I add a filtering expression to the “where” clause of the LINQ. Now I can walk (both actors in alternating turns) until they get to the middle room (within line of sight of each other). About 4 rounds of game-turn time. Then I get another opportunistic inquiry (even though they are a good 40+ feet from each other. I’ll check the LINQ tomorrow in debug mode to see what’s going on.


Resizing a C# UNION

I have been testing out the *basic* BattleScape scenario (two creatures in a map with an initiative-based turn-tracker), and noticed a problem with rendering one of the cell-types in the client. At each I was expecting a step, I was getting a block.  Fortunately I knew from the workshop and host that the map cell-data was correct as it rendered correctly.  Also, since the Uzi.Visualize assembly is shared (currently the only bit of code so shared) between the Client and Core assemblies, it wasn’t a rendering glitch.  The problem had to be in marshaling the data between application domains.

For background, I have divided cell structural types into “Template” and “Parameter” parts.  I build cell-structure templates (indexed) that can be used for multiple cells, and keep a list with the local tactical map.  This is the equivalent of deciding what types of bricks I want to use.  Physical characteristics (materials and relative dimensions from cell edges) are stored in the template.  If I want a 1 foot sliver of rock (the rest being air) bound to a face, and a 2 foot sliver of rock bound to a face, I need 2 templates.  The “Parameter” data contains useful situational data, that varies based on the Template base-class needs.  A solid CellSpace doesn’t rely on parameter data for anything, but a SliverCellSpace needs binding face information to know how to orient itself.  Other cell types (such as CornerCellSpace, WedgeCellSpace, LFrameCellSpace and Stairs) need even more data to orient themselves correctly.

To keep room data fairly compact, the room holds information about the room dimensions, and a three dimensional array of structures that holds both the references to the templates, and the parameters, for each cell in the room.  When I serialize the cell data into a data contract for the room, I yield an array of unsigned values, where each value combines one cell’s template index and its parameter data.  Rather than doing this programmatically, I simply used a structure with explicit layout and jammed the fields next to each other so I could read them with an overlapping larger field (similar to a UNION in C).

Herein lay my problem.  When I created this scheme, I was using unsigned short (ushort) values for the index and parameter values, and the complete value was an unsigned integer (uint):

namespace Uzi.Visualize
{
  [StructLayout(LayoutKind.Explicit, Pack=2)]
  public struct IndexStruct
  {
    [FieldOffset(0)]
    public ushort Index;
    [FieldOffset(2)]
    public ushort StateInfo;
    [FieldOffset(0)]
    public uint ID;
  }
}

At some point I found/felt the need to make the parameter an unsigned integer (uint), so naturally I bumped the index as well.  Keep in mind that this re-sizing happened in many more places than this data contract.  And it all worked well in the Host and Workshop (Core assemblies). What I missed was when I refactored the ushorts to uints was the full impact on this structure. What I was left with is:

namespace Uzi.Visualize
{
  [StructLayout(LayoutKind.Explicit, Pack=4)]
  public struct IndexStruct
  {
    [FieldOffset(0)]
    public uint Index;
    [FieldOffset(2)]
    public uint StateInfo;
    [FieldOffset(0)]
    public uint ID;
  }
}

The correct form is:

namespace Uzi.Visualize
{
  [StructLayout(LayoutKind.Explicit, Pack=4)]
  public struct IndexStruct
  {
    [FieldOffset(0)]
    public uint Index;
    [FieldOffset(4)]
    public uint StateInfo;
    [FieldOffset(0)]
    public ulong ID;
  }
}