I’m designing my first module, have read the entire wiki and designers’ guide through at least once, and probably three times in the areas that apply to my project. I’m getting the hang of traits and able to model some fairly complex behaviors and piece-to-piece communication. For example, I have multiple decks with different back designs and their own discard piles, whose non-rectangular cards correctly flip, rotate, and magnify in any combination, tag and untag themselves with various overlays, discard to the correct piles, auto hide and reveal themselves when required, and even recalculate their own values with simple multiplication and (faked) division. Some of them also fetch a corresponding component from another stack and command it to send itself to them. So I feel like I’m starting to “get” the Vassal paradigm.
One thing that vexes me, though, is that Vassal appears to maintain some kind of ownership model that is not exposed to the developer. It seems that cards and pieces become owned when they are masked, and presumably when added to a player hand or private window, but I can’t seem to set, query, or reset that attribute. So I’ve struck out on my own:
-
Every card and piece in my module has a DP called Owner if its ownership can change, or a Marker called Owner if it cannot (but never both). Ctrl-Alt-O performs Owner = $playerSide$ on demand, and it’s also invoked for pieces ending movement in the player’s hand or private window. I plan to implement ‘Give’ traits later.
-
Ctrl-Alt-Shift-O performs Owner = Nobody. Then via another trigger, this key is trapped to see if the piece should actually have a default Owner, which is overridden with the appropriate string literal for the Side.
-
I have an alternate highlighter corresponding to each player Side that hardcodes color = red when Owner = Red, etc.
Most of this works great, but I have two problems I don’t understand:
-
My alternate highlighters worked like a charm, then abruptly just stopped working (everywhere). At the time I was resequencing traits to get mask, rotate, and non-rectangular to all behave together properly because I had just re-added non-rectangular, so at first I thought this was the culprit. But my alternate highlighters were failing for everything, including pieces in an at-start stack with an Owner marker; not a single thing about these pieces had been changed in days. I wrote a diagnostic Report action to dump out key characteristics and verified that my Owner DPs were indeed flipping around between Red, Yellow, and Nobody exactly as expected … but the highlighters checking for these were being ignored. So I added more highlighters with no conditions at all, or guaranteed-true conditions like Type = Ship (with precise capitalization), but not a single one of them shows up, even when I make the widths extra-large to overcome any possible highlight stacking-order issues. Baffled.
-
I didn’t like the inefficiency of having a ‘disown’ trigger for every Side to check for pieces that should revert to that Side as a default owner. It seemed like I could eliminate the need for conditionals by exploiting Vassal’s attribute hierarchy, so I added a Marker to such pieces called Color, which is basically ‘default owner’ and contains one of the string literals for a Side. Then I modified my original Disown key to set Owner = $Color$, believing that when a piece had no Color marker defined, this would fall back to the GP I had already defined called Color, with a value of Nobody. Instead, my neutral pieces end up with their Owner DP set to the string literal ‘Color’ — and I definitely did not forget the dollar signs.
Any insight on whether I could have actually tapped into some official ownership model, or streamlined this approach to somehow avoid the issues I’m seeing? Or am I just making a dumb mistake somewhere?
FYI, I am building Cosmic Encounter — perhaps one of the most ambitious titles I could have chosen for my first module, due to the fact that virtually every piece behavior and piece-to-piece relationship you could hope to shortcut is a candidate for being overridden by some game effect that may or may not be in the current game. It’s quite a challenge.