Skip to content

Commit

Permalink
UPDATE: new Floating Fortress
Browse files Browse the repository at this point in the history
  • Loading branch information
lsocrate committed Jan 1, 2024
1 parent e0e60a9 commit 5953182
Show file tree
Hide file tree
Showing 25 changed files with 460 additions and 358 deletions.
64 changes: 0 additions & 64 deletions server/game/Effects/CopyCharacter.js

This file was deleted.

77 changes: 77 additions & 0 deletions server/game/Effects/Library/copyCard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import type BaseCard from '../../basecard';
import { AbilityTypes, Locations, CardTypes, EffectNames } from '../../Constants';
import EffectBuilder from '../EffectBuilder';
import EffectValue from '../EffectValue';
import GainAbility from '../GainAbility';

class CopyCard extends EffectValue {
actions: Array<GainAbility>;
reactions: Array<GainAbility>;
persistentEffects: Array<any>;
abilitiesForTargets = new WeakMap<
BaseCard,
{
actions: Array<GainAbility>;
reactions: Array<GainAbility>;
}
>();

constructor(card: BaseCard) {
super(card);
this.actions = card.abilities.actions.map((action) => new GainAbility(AbilityTypes.Action, action));
this.reactions = card.abilities.reactions.map((ability) => new GainAbility(ability.abilityType, ability));
this.persistentEffects = card.abilities.persistentEffects.map((effect) => Object.assign({}, effect));
}

apply(target: BaseCard) {
this.abilitiesForTargets.set(target, {
actions: this.actions.map((value) => {
value.apply(target);
return value.getValue();
}),
reactions: this.reactions.map((value) => {
value.apply(target);
return value.getValue();
})
});
for (const effect of this.persistentEffects) {
if (
effect.location === Locations.Any ||
(target.getType() === CardTypes.Character && effect.location === Locations.PlayArea) ||
(target.getType() === CardTypes.Holding && effect.location === Locations.Provinces)
) {
effect.ref = target.addEffectToEngine(effect);
}
}
}

unapply(target: BaseCard) {
for (const value of this.getReactions(target)) {
// @ts-ignore
value.unregisterEvents();
}
for (const effect of this.persistentEffects) {
if (effect.ref) {
target.removeEffectFromEngine(effect.ref);
delete effect.ref;
}
}
this.abilitiesForTargets.delete(target);
}

getActions(target: BaseCard) {
return this.abilitiesForTargets.get(target)?.actions ?? [];
}

getReactions(target: BaseCard) {
return this.abilitiesForTargets.get(target)?.reactions ?? [];
}

getPersistentEffects() {
return this.persistentEffects;
}
}

export function copyCard(character: BaseCard) {
return EffectBuilder.card.static(EffectNames.CopyCharacter, new CopyCard(character));
}
26 changes: 26 additions & 0 deletions server/game/Effects/Library/gainAbility.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { type AbilityTypes, EffectNames } from '../../Constants';
import type {
ActionProps,
PersistentEffectProps,
TriggeredAbilityProps,
TriggeredAbilityWhenProps
} from '../../Interfaces';
import type CardEffect from '../CardEffect';
import EffectBuilder from '../EffectBuilder';
import GainAbility from '../GainAbility';

type Res = (game: any, source: any, props: any) => CardEffect;
export function gainAbility(abilityType: AbilityTypes.Action, properties: ActionProps): Res;
export function gainAbility(abilityType: AbilityTypes.DuelReaction, properties: TriggeredAbilityWhenProps): Res;
export function gainAbility(abilityType: AbilityTypes.Persistent, properties: PersistentEffectProps): Res;
export function gainAbility(abilityType: AbilityTypes.Reaction, properties: TriggeredAbilityProps): Res;
export function gainAbility(abilityType: AbilityTypes.WouldInterrupt, properties: TriggeredAbilityProps): Res;
export function gainAbility(abilityType: AbilityTypes.Interrupt, properties: TriggeredAbilityProps): Res;
export function gainAbility(abilityType: AbilityTypes.ForcedReaction, properties: TriggeredAbilityProps): Res;
export function gainAbility(abilityType: AbilityTypes.ForcedInterrupt, properties: TriggeredAbilityProps): Res;
export function gainAbility(
abilityType: AbilityTypes,
properties: ActionProps | TriggeredAbilityWhenProps | TriggeredAbilityProps | PersistentEffectProps
) {
return EffectBuilder.card.static(EffectNames.GainAbility, new GainAbility(abilityType, properties));
}
73 changes: 70 additions & 3 deletions server/game/Effects/Library/gainAllAbilities.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,76 @@
import type BaseCard from '../../basecard';
import { EffectNames } from '../../Constants';
import { AbilityTypes, EffectNames, Locations } from '../../Constants';
import EffectBuilder from '../EffectBuilder';
import GainAllAbilities from '../GainAllAbilities';
import EffectValue from '../EffectValue';
import GainAbility from '../GainAbility';

export type GainAllAbilitiesValue = GainAllAbilities;
export class GainAllAbilities extends EffectValue {
actions: Array<GainAbility>;
reactions: Array<GainAbility>;
persistentEffects: Array<any>;
abilitiesForTargets: Record<string, undefined | { actions: Array<GainAbility>; reactions: Array<GainAbility> }>;

constructor(card: BaseCard) {
super(card);
this.actions = card.abilities.actions.map((action) => new GainAbility(AbilityTypes.Action, action));
//Need to ignore keyword reactions or we double up on the pride / courtesy / sincerity triggers
this.reactions = card.abilities.reactions
.filter((a) => !a.isKeywordAbility())
.map((ability) => new GainAbility(ability.abilityType, ability));
this.persistentEffects = card.abilities.persistentEffects.map((effect) => Object.assign({}, effect));
this.abilitiesForTargets = {};
}

apply(target: BaseCard) {
this.abilitiesForTargets[target.uuid] = {
actions: this.actions.map((value) => {
value.apply(target);
return value.getValue();
}),
reactions: this.reactions.map((value) => {
value.apply(target);
return value.getValue();
})
};
for (const effect of this.persistentEffects) {
if (effect.location === Locations.PlayArea || effect.location === Locations.Any) {
effect.ref = target.addEffectToEngine(effect);
}
}
}

unapply(target: BaseCard) {
for (const value of this.abilitiesForTargets[target.uuid].reactions) {
// @ts-ignore
value.unregisterEvents();
}
for (const effect of this.persistentEffects) {
if (effect.ref) {
target.removeEffectFromEngine(effect.ref);
delete effect.ref;
}
}
delete this.abilitiesForTargets[target.uuid];
}

getActions(target: BaseCard) {
if (this.abilitiesForTargets[target.uuid]) {
return this.abilitiesForTargets[target.uuid].actions;
}
return [];
}

getReactions(target: BaseCard) {
if (this.abilitiesForTargets[target.uuid]) {
return this.abilitiesForTargets[target.uuid].reactions;
}
return [];
}

getPersistentEffects() {
return this.persistentEffects;
}
}

export function gainAllAbilities(character: BaseCard) {
return EffectBuilder.card.static(EffectNames.GainAllAbilities, new GainAllAbilities(character));
Expand Down
1 change: 1 addition & 0 deletions server/game/Interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ export interface PersistentEffectProps<Source = any> {
targetController?: Players;
targetLocation?: Locations;
effect: Function | Function[];
createCopies?: boolean;
}

export type traitLimit = {
Expand Down
8 changes: 4 additions & 4 deletions server/game/basecard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import Player from './player';
import type DrawCard = require('./drawcard');
import Ring = require('./ring');
import type { CardEffect } from './Effects/types';
import type { GainAllAbilitiesValue } from './Effects/Library/gainAllAbilities';
import type { GainAllAbilities } from './Effects/Library/gainAllAbilities';

type Faction = 'neutral' | 'crab' | 'crane' | 'dragon' | 'lion' | 'phoenix' | 'scorpion' | 'unicorn' | 'shadowlands';

Expand Down Expand Up @@ -148,7 +148,7 @@ class BaseCard extends EffectSource {

for (const effect of this.getRawEffects()) {
if (effect.type === EffectNames.GainAllAbilities) {
actions = actions.concat((effect.value as GainAllAbilitiesValue).getActions(this));
actions = actions.concat((effect.value as GainAllAbilities).getActions(this));
}
}
if (!ignoreDynamicGains) {
Expand Down Expand Up @@ -194,7 +194,7 @@ class BaseCard extends EffectSource {
);
for (const effect of this.getRawEffects()) {
if (effect.type === EffectNames.GainAllAbilities) {
reactions = reactions.concat((effect.value as GainAllAbilitiesValue).getReactions(this));
reactions = reactions.concat((effect.value as GainAllAbilities).getReactions(this));
}
}
if (!ignoreDynamicGains) {
Expand Down Expand Up @@ -234,7 +234,7 @@ class BaseCard extends EffectSource {
for (const effect of this.getRawEffects()) {
if (effect.type === EffectNames.GainAllAbilities) {
gainedPersistentEffects = gainedPersistentEffects.concat(
(effect.value as GainAllAbilitiesValue).getPersistentEffects()
(effect.value as GainAllAbilities).getPersistentEffects()
);
}
}
Expand Down
39 changes: 0 additions & 39 deletions server/game/cards/06-CotE/MiyakosUndertaking.js

This file was deleted.

38 changes: 38 additions & 0 deletions server/game/cards/06-CotE/MiyakosUndertaking.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import AbilityDsl from '../../abilitydsl';
import { CardTypes, Locations, Players } from '../../Constants';
import DrawCard from '../../drawcard';
import type { TriggeredAbilityContext } from '../../TriggeredAbilityContext';

export default class MiyakosUndertaking extends DrawCard {
static id = 'miyako-s-undertaking';

setupCardAbilities() {
this.action({
title: 'Make a character a copy',
condition: (context) => context.game.isDuringConflict(),
targets: {
cardToCopy: {
cardType: CardTypes.Character,
controller: Players.Opponent,
location: Locations.DynastyDiscardPile,
cardCondition: (card) => !card.isUnique()
},
myCharacter: {
dependsOn: 'cardToCopy',
cardType: CardTypes.Character,
controller: Players.Self,
cardCondition: (card) => card.isParticipating(),
gameAction: AbilityDsl.actions.cardLastingEffect((context) => ({
effect: AbilityDsl.effects.copyCard(context.targets.cardToCopy)
}))
}
},
effect: 'make {1} into a copy of {2}',
effectArgs: (context) => [context.targets.myCharacter, context.targets.cardToCopy]
});
}

canPlay(context: TriggeredAbilityContext) {
return context.player.honor <= 6 && super.canPlay(context);
}
}
23 changes: 0 additions & 23 deletions server/game/cards/06-CotE/TrueStrikeKenjutsu.js

This file was deleted.

Loading

0 comments on commit 5953182

Please sign in to comment.