- Addied triggers for keying to adding and removing culture tokens
- Added player parameter to PlayCardFromDiscard; this could probably stand to go on the other PlayCardFromX effects as well
- Added oneperbearer filter so we can stop reimplementing the same logic on all these cards
- Added CanSpotDifferentCultures for supporting "Spot X cards of different cultures" text
- Added ActivatedInDrawDeck as a mirror to ActivatedInDiscard and ActivatedFromStacked
- Fixed the V2 Jetsam unit tests
- Added SiteLiberated trigger with associated helper classes
- Renamed trigger TakenControlOfSite -> SiteControlled
- Renamed result TakeControlOfSiteResult -> SiteControlledResult
- Renamed trigger enum TAKE_CONTROL_OF_SITE -> CONTROL_SITE
- Implemented V2_1 Driven Into The Hills, which uses a liberate trigger, with associated tests
- Fixed Rapt Hillman liberation not being optional
- Updated ChooseAKeyword to accept an array of keyword strings instead of a comma-delimited list.
- Updated TurnIntoMinions to accept an array of keyword strings instead of a comma-delimited list.
- Added keyword checking for both above effects to ensure the keywords requested don't crash at runtime
- Overhauled ally home site definition. Blueprint now stores an array of HomeSite objects, which are records storing a SiteBlock/SiteNumber pair apiece.
- Ally home sites can now be defined in one of two ways: a short string like "2F" indicating "Fellowship block site 2", or in a more explicit JSON object defining both Block and Site as separate fields. Both of these can be present in an array (even mixed) for multiple home sites.
- Renamed RemoveTokens -> RemoveCultureTokens to match the corresponding Add effect
- in DoWhile, renamed parameter condition -> check
- Rearranged order of effects to put meta/control-flow effects at the top.
- Converted PreventExert to a generic PreventCardEffectAppender
- Deleted ReduceArcheryTotal and converted the relevant cards to use a choosenumber/modifyarchery effect combo
- Altered PlaySite to use SiteBlock's existing parsing instead of the generic enum parse
- Deleted unused parameter on RemoveAllTokens
- Renamed play -> playCardFromHand to match the other playCardFromX effects.
- Renamed cost -> discount for all PlayCardFromX effects
- Pared down PlayCardFromDeadPile to not have so many unusable parameters