Starting to fall into the “code before blog pattern” that I got into last time I tried to run a development blog on the Ikosa Framework. Basically I have been fixing some things that my son and myself noticed during some testing, and I’ve been adding support for manipulating a targetting cell around the view window.
I’m probablly going to find a good home inthe UI for spell casting (and complex action aiming) so I can introduce a sorcerer-classed character to a test map. I’ll probably also add a spontaneous divine caster so I can get a little more magic flavor into the mix.
I’ve put ClickOnce installers for the Ikosa Host and Ikosa Client over on the Guildsmanship (aka, the Ikosa Framework) site. Currently putting together documentation for these framework tools, while biding my time waiting for the glacial pace of the state of Pennsylvania to finalize Turn-Based Realities, LLC.
I’ll probably have to make some clearer organization of what is the Ikosa Framework, what is Guildsmanship, what is Guildsmanship: Battle-Scapes; and what Turn-Based Realities, LLC is.
Last time I mentioned I had to handle exceptions from the free-threaded ProxyModel. Now I do. All of the callback members (NewMessage, UserListChanged, MapChanged, Redraw, ExpectingPrerequisites, StepStatuses, TimeChanged and CurrentStep) now catch exceptions within the whatever Task they launch, and call an internal member called MarkException with whatever exception is caught.
MarkException updates an _Exceptions list (which only holds the DateTime.Now value and the exception.Message of all exceptions) for the ProxyModel, and also calls an ObserveException Action delegate (if assigned) to pass the full exception info.
I probably need to examine some of the exceptions and make decisions about tearing down the ProxyModel, or the actual communication proxies, but otherwise, I do not seem to get the same bad crashes on authentication failures.
I also cobbled together a WCF customBinding that uses tcpTransport without any channel privacy, but uses clear-text passwords. Not ideal, but suitable for LAN host testing without having to get testers mucking about with certificates.
I have also had some issues with the Grasp/Probe action when I aim the actor at another actor (I had previously tested on doors, walls and empty space without problems). I get some exceptions on the host, and eventually (if I keep trying) the client stops responding as well. I’ll try to isolate this before further cleaning up the host and client for ClickOnce packaging.
Awhile back I converted most of the client framework to be much more MVVM-ish. Part of this turned over proxy management to a ProxyModel class. In so doing, the mechanisms for getting the server’s user list and latest text-chat messages for the user were converted to functions designed to work in a free-threaded manner (in response to callbacks from the server).
Since all the communication between the server and the client is now handled without the WPF dispatcher thread getting involved (and better, the Login Dialog uses a call to the ProxyModel that invokes UserList and GetMessages through a TaskFactory.StartNew), it has come to my attention that I am not observing exceptions thrown from within the confines of the task-scheduler created threads.
What used to pop-up a “friendly” Ikosa exception dialog on a failed login attempt now simply crashes the client process as the when the task is garbage collected, the thrown (unobserved) exceptions are AppDomain poison. This has become my next “must-fix”…
I had gotten to the point over the weekend where I was fairly comfortable with the final state of melee cover checks (with its weird alternate source points when attacking downward while standing on a ledge), and really began testing the ranged cover checks. What helped me in testing was adding the interaction alterations (for the attack interaction) to the status feedback so that the client could see cover and concealment affecting the attack. I’m going to need to examine the StepStatus a lot more closely to “pretty-up” the structure, and ensure that the right amount of information is sent to each client. I’m also going to need to put a facility to always send observed-activity info to various clients when an actor acts (right now, I only use ObservedActivityInfo when making an OpportunisticInquiry).
But anyway, back to ranged attacks. I noticed that a creature whose feet were blocked by only a small step was getting a lot of cover lines flagged (so that they could get a +4 cover bonus to armor-rating). I tried to compensate for this at first by proportionally moving the bottom points of the lowest cells upwards towards the top points, but this still kept them behind the step in certain cases.
Then, I planned to do some magic with checking the back-most low point(s) if the front-most low points were blocked. But I finally decided on boosting the low points upward again by an “absolute” amount relative to a fraction of the creature size (similar to how land movement has a maximum up-step size beyond which a climb check is needed, and representing the “bulk/core” of the creature’s body), rather than a fraction of the vector between low and high. If the low point boost is longer than the vector between low and high points, than the low point is simply omitted from the target corner set.
In the light amount of testing I performed, this seems like the best balance so far. But I’ll need more testing, and ultimately I need to vary the amount of low-point boost by creature body type, and whether the creature is prone or not.
Returning to the Ikosa Framework’s rules for cover; in addition to the special point identification mechanism for downward melee strikes, there are some special adjustments made to melee source corner points when melee attacks are made on the same level.
The main reason for adjustments to handle the cases when the source and target cell are on the same level, but the target is on a “slightly” higher step. In this case, the “front”-lower corner(s) of the source cell must go through the low step, creating cover. When attacking a target cell on the same level (based on cell-specific gravity), Ikosa adjusts the lower corners upward by 30% towards the upper corners on the same up-down edge. (It also adjusts the upper corners down 5%).
Currently these percent factors are hard-coded, but may likely be calculated by other factors in the future.
The “modeled” result is that a melee attack against a target on a platform less than 1.5 feet higher than the attacker does not automatically get penalized by cover.
(Note: when any component of a melee attack is upward or downward, these adjustments are not applied. Also, reach/ranged attacks originate from a single point, so there is no need to adjust source corners).
Just started the process to create a business in Pennsylvania (about 35 days, since I didn’t take LegalZoom up on their “gold package” 7-10 day hand-delivered to state offices offer).
I grow weary of waiting; so as soon as I can (a song I’ve sung before), I’m going to open up free downloads of the client and host packages I use in testing the Ikosa Framework. I just need to (re-)finish the melee and ranged tactical cover checks using the new source/target corners strategies, strip out the channel security from the Net.TCP channel configuration (so clients don’t need to muck about with certificates for encryption), and build some ClickOnce installers for client and server.
…and find some time to do all that 🙂
Traditional PnP tactical cover rules have some gray areas when it comes to complex 3-dimensional topography and large creatures. Mostly these are swept under the generalizations from the “flatness” of tradition PnP play. However, the Ikosa Framework must calculate cover within predictable constraints and more highly variable conditions.
For instance, melee cover (which can only occur when attacking into an adjacent cell) generally requires all “corners” of the source cell to have unhindered line of effect to the target cell. Assuming an attacking creature stands on a block of solid ground 5 foot higher than an adjacent target creature (such that the target creature is “diagonally-down” from the attacker), then lines from the back of the attacker must be blocked by the solid ground to attack the target; in exactly the same way as when attacking around a corner. It is unlikely that a game-master would rule the lower target had cover from the attacker standing on a higher platform, especially since attacking from higher ground typically gives a +1 to attack.
The Ikosa Framework has strategies to deal with this situation (and some processing optimizations).
Optimization first: When calculating cover (melee or reach/ranged) Ikosa must check lines between “corners” of the source (cell or point) and target (cell or cells) for terrain blockage or cover inducing effects in the cells being traversed by the lines.
To reduce processing, Ikosa only examines points that will reach from source to target without going through the source or target (thus culling certain points from consideration). This can be determined by looking at the relative integer cell coordinates between source and target cells to determine which faces are exposed to each other. When two cells are face to face, 4 points from the source and 4 points from the target are considered. When edge to edge, 6 and 6, and when corner to corner, 7 points each. Also, for reach/ranged attacks, there are additional target points possible (since for larger creatures the entire creature is being targeted, which spans many cells), but also additional culling (so that only points exposed to the source point) are considered.
For the downward attack mentioned above, Ikosa detects the gravity direction of the attacker and whether the terrain supports the attacker (thus creatures in flight above the surface are excluded from this test) and then excludes those faces from consideration if they would otherwise be needed. As a result, only attacker points that face-outward toward the target on the non gravitationally bound attacker face are used. In this case, only 4 points are considered (if the target is adjacent and down) or 6 (if target is diagonal and down).
If the attacker were in a cell 5 feet lower, however, the gravitationally bound face isn’t facing the target anyway, and since the all the target’s points are still usable, the higher target would have cover.