diff --git a/agot-bg-game-server/src/client/houseCardImages.ts b/agot-bg-game-server/src/client/houseCardImages.ts
index b2dcfabaf..5bdc96022 100644
--- a/agot-bg-game-server/src/client/houseCardImages.ts
+++ b/agot-bg-game-server/src/client/houseCardImages.ts
@@ -5,6 +5,7 @@ import aeroImage from "../../public/images/house-cards/Areo.png";
import arianneImage from "../../public/images/house-cards/Arianne.png";
import ashaImage from "../../public/images/house-cards/Asha.png";
import balonImage from "../../public/images/house-cards/Balon.png";
+import balonNervedImage from "../../public/images/house-cards/Balon-nerved.png";
import blackfishImage from "../../public/images/house-cards/Blackfish.png";
import brienneImage from "../../public/images/house-cards/Brienne.png";
import catelynImage from "../../public/images/house-cards/Catelyn.png";
@@ -41,11 +42,13 @@ import theonImage from "../../public/images/house-cards/Theon.png";
import tyrionImage from "../../public/images/house-cards/Tyrion.png";
import tywinImage from "../../public/images/house-cards/Tywin.png";
import victarionImage from "../../public/images/house-cards/Victarion.png";
+
import rayderImage from "../../public/images/house-cards/Rayder.png";
import melisandreDwDImage from "../../public/images/house-cards/Melisandre_DwD.png";
import jonSnow from "../../public/images/house-cards/JonSnow.png";
import stannisDwDImage from "../../public/images/house-cards/StannisBaratheonDwD.png";
import aeronDwDImage from "../../public/images/house-cards/AeronDamphairDwD.png";
+import aeronDwDNervedImage from "../../public/images/house-cards/AeronDamphairDwD-nerved.png";
import qarlTheMaidImage from "../../public/images/house-cards/QarlTheMaid.png";
import rodrikTheReaderImage from "../../public/images/house-cards/RodrikTheReader.png";
import euronDwDImage from "../../public/images/house-cards/EuronCrowsEye.png";
@@ -61,30 +64,24 @@ import ramsayBoltonImage from "../../public/images/house-cards/RamsayBolton.png"
import queenOfThornsDwDImage from "../../public/images/house-cards/QueenOfThorns.png";
import paxterRedwyneImage from "../../public/images/house-cards/PaxterRedwyne.png";
import margaeryTyrellDwDImage from "../../public/images/house-cards/MargaeryTyrell.png";
-
import maceTyrellDwDImage from "../../public/images/house-cards/MaceTyrell.png";
import randyllTarlyDwDImage from "../../public/images/house-cards/RandyllTarly.png";
import willasTyrellImage from "../../public/images/house-cards/WillasTyrell.png";
import serJonFossowayImage from "../../public/images/house-cards/SerJonFossoway.png";
-
import nymeriaSandDwDImage from "../../public/images/house-cards/NymeriaSand.png";
import areoHotahDwDImage from "../../public/images/house-cards/AreoHotah.png";
import bastardOfGodsgraceImage from "../../public/images/house-cards/BastardOfGodsgrace.png";
import bigManImage from "../../public/images/house-cards/BigMan.png";
-
import serHarrasHarlawImage from "../../public/images/house-cards/SerHarrasHarlaw.png";
import victarionGreyjoyDwDImage from "../../public/images/house-cards/VictarionGreyjoy.png";
import ashaGreyjoyDwDImage from "../../public/images/house-cards/AshaGreyjoy.png";
-
import bastardOfNightsongImage from "../../public/images/house-cards/BastardOfNightsong.png";
import serDavosSeaworthDwDImage from "../../public/images/house-cards/SerDavosSeaworth.png";
import serAxellFlorentImage from "../../public/images/house-cards/SerAxellFlorent.png";
-
import blackWalderImage from "../../public/images/house-cards/BlackWalder.png";
import steelshanksWaltonImage from "../../public/images/house-cards/SteelshanksWalton.png";
import damonDanceForMeImage from "../../public/images/house-cards/DamonDanceForMe.png";
import rooseBoltonDwDImage from "../../public/images/house-cards/RooseBolton.png";
-
import cerseiLannisterDwDImage from "../../public/images/house-cards/CerseiLannister.png";
import serJaimeLannisterDwDImage from "../../public/images/house-cards/SerJaimeLannister.png";
import serKevanLannisterDwDImage from "../../public/images/house-cards/SerKevanLannister.png";
@@ -178,6 +175,7 @@ const houseCardImages = new BetterMap([
["areo-hotah", aeroImage],
["asha-greyjoy", ashaImage],
["balon-greyjoy", balonImage],
+ ["balon-greyjoy-nerved", balonNervedImage],
["the-blackfish", blackfishImage],
["brienne-of-tarth", brienneImage],
["catelyn-stark", catelynImage],
@@ -219,6 +217,7 @@ const houseCardImages = new BetterMap([
["jon-snow", jonSnow],
["stannis-baratheon-dwd", stannisDwDImage],
["aeron-damphair-dwd", aeronDwDImage],
+ ["aeron-damphair-dwd-nerved", aeronDwDNervedImage],
["qarl-the-maid", qarlTheMaidImage],
["rodrik-the-reader", rodrikTheReaderImage],
["euron-crows-eye-dwd", euronDwDImage],
diff --git a/agot-bg-game-server/src/client/unitImages.ts b/agot-bg-game-server/src/client/unitImages.ts
index 3a4a0e49d..3142369df 100644
--- a/agot-bg-game-server/src/client/unitImages.ts
+++ b/agot-bg-game-server/src/client/unitImages.ts
@@ -1,17 +1,17 @@
import BetterMap from "../utils/BetterMap";
import {dragon, footman, knight, ship, siegeEngine} from "../common/ingame-game-state/game-data-structure/unitTypes";
-import barathFoot from "../../public/images/units/BarathFoot.png";
-import barathKnight from "../../public/images/units/BarathKnight.png";
-import barathSiege from "../../public/images/units/BarathSeige.png";
-import barathShip from "../../public/images/units/BarathShip.png";
-import boltonFoot from "../../public/images/units/BoltonFoot.png";
-import boltonKnight from "../../public/images/units/BoltonKnight.png";
-import boltonSiege from "../../public/images/units/BoltonSiege.png";
-import boltonShip from "../../public/images/units/BoltonShip.png";
-import lanFoot from "../../public/images/units/LanFoot.png";
-import lanKnight from "../../public/images/units/LanKnight.png";
-import lanSiege from "../../public/images/units/LanSeige.png";
-import lanShip from "../../public/images/units/LanShip.png";
+import baraFoot from "../../public/images/units/BarathFoot.png";
+import baraKnight from "../../public/images/units/BarathKnight.png";
+import baraSiege from "../../public/images/units/BarathSeige.png";
+import baraShip from "../../public/images/units/BarathShip.png";
+import boltFoot from "../../public/images/units/BoltonFoot.png";
+import boltKnight from "../../public/images/units/BoltonKnight.png";
+import boltSiege from "../../public/images/units/BoltonSiege.png";
+import boltShip from "../../public/images/units/BoltonShip.png";
+import lannFoot from "../../public/images/units/LanFoot.png";
+import lannKnight from "../../public/images/units/LanKnight.png";
+import lannSiege from "../../public/images/units/LanSeige.png";
+import lannShip from "../../public/images/units/LanShip.png";
import starFoot from "../../public/images/units/StarFoot.png";
import starKnight from "../../public/images/units/StarKnight.png";
import starSiege from "../../public/images/units/StarSeige.png";
@@ -28,70 +28,86 @@ import tyrFoot from "../../public/images/units/TyrFoot.png";
import tyrKnight from "../../public/images/units/TyrKnight.png";
import tyrSiege from "../../public/images/units/TyrSeige.png";
import tyrShip from "../../public/images/units/TyrShip.png";
-import arrynFoot from "../../public/images/units/ArrynFoot.png"
-import arrynKnight from "../../public/images/units/ArrynKnight.png";
-import arrynSiege from "../../public/images/units/ArrynSiege.png";
-import arrynShip from "../../public/images/units/ArrynShip.png";
-import targaryenShip from "../../public/images/units/TargShip.png";
-import targaryenFoot from "../../public/images/units/TargFoot.png";
+import arrFoot from "../../public/images/units/ArrynFoot.png"
+import arrKnight from "../../public/images/units/ArrynKnight.png";
+import arrSiege from "../../public/images/units/ArrynSiege.png";
+import arrShip from "../../public/images/units/ArrynShip.png";
+import targShip from "../../public/images/units/TargShip.png";
+import targFoot from "../../public/images/units/TargFoot.png";
import targKnight from "../../public/images/units/TargKnight.png";
import targDragon from "../../public/images/units/TargDragon.png";
+import baraDragon from "../../public/images/units/BaraDragon.png";
+import lannDragon from "../../public/images/units/LannDragon.png";
+import starDragon from "../../public/images/units/StarDragon.png";
+import boltDragon from "../../public/images/units/BoltDragon.png";
+import greyDragon from "../../public/images/units/GreyDragon.png";
+import martDragon from "../../public/images/units/MartDragon.png";
+import tyrDragon from "../../public/images/units/TyrDragon.png";
+import arrDragon from "../../public/images/units/ArrDragon.png";
const unitImages = new BetterMap([
["baratheon", new BetterMap([
- [footman.id, barathFoot],
- [knight.id, barathKnight],
- [siegeEngine.id, barathSiege],
- [ship.id, barathShip]
+ [footman.id, baraFoot],
+ [knight.id, baraKnight],
+ [siegeEngine.id, baraSiege],
+ [ship.id, baraShip],
+ [dragon.id, baraDragon]
])],
["lannister", new BetterMap([
- [footman.id, lanFoot],
- [knight.id, lanKnight],
- [siegeEngine.id, lanSiege],
- [ship.id, lanShip]
+ [footman.id, lannFoot],
+ [knight.id, lannKnight],
+ [siegeEngine.id, lannSiege],
+ [ship.id, lannShip],
+ [dragon.id, lannDragon]
])],
["stark", new BetterMap([
[footman.id, starFoot],
[knight.id, starKnight],
[siegeEngine.id, starSiege],
- [ship.id, starShip]
+ [ship.id, starShip],
+ [dragon.id, starDragon]
])],
["greyjoy", new BetterMap([
[footman.id, greyFoot],
[knight.id, greyKnight],
[siegeEngine.id, greySiege],
- [ship.id, greyShip]
+ [ship.id, greyShip],
+ [dragon.id, greyDragon]
])],
["martell", new BetterMap([
[footman.id, martFoot],
[knight.id, martKnight],
[siegeEngine.id, martSiege],
- [ship.id, martShip]
+ [ship.id, martShip],
+ [dragon.id, martDragon]
])],
["tyrell", new BetterMap([
[footman.id, tyrFoot],
[knight.id, tyrKnight],
[siegeEngine.id, tyrSiege],
- [ship.id, tyrShip]
+ [ship.id, tyrShip],
+ [dragon.id, tyrDragon]
])],
["arryn", new BetterMap([
- [footman.id, arrynFoot],
- [knight.id, arrynKnight],
- [siegeEngine.id, arrynSiege],
- [ship.id, arrynShip]
+ [footman.id, arrFoot],
+ [knight.id, arrKnight],
+ [siegeEngine.id, arrSiege],
+ [ship.id, arrShip],
+ [dragon.id, arrDragon]
])],
["bolton", new BetterMap([
- [footman.id, boltonFoot],
- [knight.id, boltonKnight],
- [siegeEngine.id, boltonSiege],
- [ship.id, boltonShip]
+ [footman.id, boltFoot],
+ [knight.id, boltKnight],
+ [siegeEngine.id, boltSiege],
+ [ship.id, boltShip],
+ [dragon.id, boltDragon]
])],
["targaryen", new BetterMap([
- [footman.id, targaryenFoot],
+ [footman.id, targFoot],
[knight.id, targKnight],
[dragon.id, targDragon],
- [ship.id, targaryenShip]
+ [ship.id, targShip]
])]
]);
diff --git a/agot-bg-game-server/src/client/utils/SfxManager.ts b/agot-bg-game-server/src/client/utils/SfxManager.ts
index 2c8784b56..6e4629f1e 100644
--- a/agot-bg-game-server/src/client/utils/SfxManager.ts
+++ b/agot-bg-game-server/src/client/utils/SfxManager.ts
@@ -105,6 +105,10 @@ class SfxManager {
currentlyPlayingNotifications: HTMLAudioElement[] = [];
currentlyPlayingSfx: HTMLAudioElement[] = [];
+ get currentDragonStrengthIsLessOrEqualThanTwo(): boolean {
+ return (this.gameClient.entireGame?.ingameGameState?.game.currentDragonStrength ?? -1) <= 2;
+ }
+
constructor(private gameClient: GameClient) {}
notificationVolumeChanged(newVal: number): void {
@@ -167,72 +171,12 @@ class SfxManager {
this.fadeOutMusic(4000, 40);
}
- private fadeOutMusic(fadeOutDuration: number, fadeOutSteps: number): void {
- if (this.currentlyPlayingMusic.length === 0) {
- return;
- }
-
- const fadeOutInterval = fadeOutDuration / fadeOutSteps;
- const volumeStep = this.gameClient.musicVolume / fadeOutSteps;
-
- let interval = window.setInterval(() => {
- if (this.currentlyPlayingMusic.length === 0 && interval > 0) {
- clearInterval(interval);
- interval = 0;
- return;
- }
-
- this.currentlyPlayingMusic.forEach(audio => {
- if (audio.volume - volumeStep > 0) {
- audio.volume -= volumeStep;
- } else {
- audio.volume = 0;
- if (!audio.paused) {
- audio.pause();
- audio.currentTime = 0;
- }
- audio.dispatchEvent(new Event('ended'));
- }
- });
- }, fadeOutInterval);
- }
-
- private fadeOutSfx(fadeOutDuration: number, fadeOutSteps: number): void {
- if (this.currentlyPlayingSfx.length === 0) {
- return;
- }
-
- const fadeOutInterval = fadeOutDuration / fadeOutSteps;
- const volumeStep = this.gameClient.sfxVolume / fadeOutSteps;
-
- let interval = window.setInterval(() => {
- if (this.currentlyPlayingSfx.length === 0 && interval > 0) {
- clearInterval(interval);
- interval = 0;
- return;
- }
-
- this.currentlyPlayingSfx.forEach(audio => {
- if (audio.volume - volumeStep > 0) {
- audio.volume -= volumeStep;
- } else {
- audio.volume = 0;
- if (!audio.paused) {
- audio.pause();
- audio.currentTime = 0;
- }
- audio.dispatchEvent(new Event('ended'));
- }
- });
- }, fadeOutInterval);
- }
-
playNotificationSound(): Promise {
if (this.gameClient.muted) {
return Promise.resolve();
}
- return this.playNotification(notificationSound, this.gameClient.notificationsVolume);
+ return this.playNotification(notificationSound);
}
playVoteNotificationSound(): Promise {
@@ -240,7 +184,7 @@ class SfxManager {
return Promise.resolve();
}
- return this.playNotification(voteSound, this.gameClient.notificationsVolume);
+ return this.playNotification(voteSound);
}
playNewMessageReceivedSound(): Promise {
@@ -248,7 +192,7 @@ class SfxManager {
return Promise.resolve();
}
- return this.playNotification(ravenCallSound, this.gameClient.notificationsVolume);
+ return this.playNotification(ravenCallSound);
}
playGotTheme(): Promise {
@@ -256,7 +200,7 @@ class SfxManager {
return Promise.resolve();
}
- return this.playMusic(introSound, this.gameClient.musicVolume);
+ return this.playMusic(introSound);
}
playCombatSound(attackerId?: string): Promise {
@@ -265,7 +209,7 @@ class SfxManager {
}
const sound = attackerId ? houseThemes.tryGet(attackerId, combatSound) : combatSound;
- return this.playMusic(sound, this.gameClient.musicVolume);
+ return this.playMusic(sound);
}
playSoundWhenClickingMarchOrder(region: Region): Promise {
@@ -280,7 +224,7 @@ class SfxManager {
const hasSiegeEngines = army.some(u => u.type == siegeEngine);
const hasDragons = army.some(u => u.type == dragon);
- const files = hasDragons && (this.gameClient.entireGame?.ingameGameState?.game.currentDragonStrength ?? -1) <= 2
+ const files = hasDragons && this.currentDragonStrengthIsLessOrEqualThanTwo
? soundsForSmallDragons
: hasDragons
? soundsForBigDragons
@@ -292,7 +236,7 @@ class SfxManager {
? soundsForShips
: soundsForFootmenOnly;
- return this.playRandomEffect(files, this.gameClient.sfxVolume, true);
+ return this.playRandomEffect(files, true);
}
playSoundForLogEvent(log: GameLogData): Promise {
@@ -303,14 +247,14 @@ class SfxManager {
switch(log.type) {
case "doran-martell-asos-used":
case "doran-used":
- this.playEffect(hystericalLaughSound, this.gameClient.musicVolume, false);
+ this.playEffect(hystericalLaughSound, false);
break;
case "killed-after-combat": {
const units = log.killed.map(ut => unitTypes.get(ut));
if (units.includes(dragon)) {
- return this.playRandomEffect(soundsWhenDragonsAreDestroyed, this.gameClient.musicVolume, false);
+ return this.playRandomEffect(soundsWhenDragonsAreDestroyed, false);
} else {
- return this.playRandomEffect(soundsWhenUnitsAreDestroyedBySwords, this.gameClient.musicVolume, false);
+ return this.playRandomEffect(soundsWhenUnitsAreDestroyedBySwords, false);
}
break;
}
@@ -318,56 +262,124 @@ class SfxManager {
const killed = _.concat(log.killedBecauseCantRetreat, log.killedBecauseWounded);
const units = killed.map(ut => unitTypes.get(ut));
if (units.includes(dragon)) {
- return this.playRandomEffect(soundsWhenDragonsAreDestroyed, this.gameClient.musicVolume, false);
+ return this.playRandomEffect(soundsWhenDragonsAreDestroyed, false);
}
break;
}
case "retreat-casualties-suffered": {
const units = log.units.map(ut => unitTypes.get(ut));
if (units.includes(dragon)) {
- return this.playRandomEffect(soundsWhenDragonsAreDestroyed, this.gameClient.musicVolume, false);
+ return this.playRandomEffect(soundsWhenDragonsAreDestroyed, false);
}
break;
}
+ case "last-land-unit-transformed-to-dragon": {
+ this.playRandomEffect(
+ this.currentDragonStrengthIsLessOrEqualThanTwo
+ ? soundsForSmallDragons
+ : soundsForBigDragons
+ , false);
+ break;
+ }
}
return Promise.resolve();
}
- private playRandomEffect(files: string[], volume: number, withCurrentPlayingCheck: boolean): Promise {
+ private playRandomEffect(files: string[], withCurrentPlayingCheck: boolean): Promise {
const randomFile = pickRandom(files);
if (!randomFile) {
return Promise.resolve();
}
- return this.playEffect(randomFile, volume, withCurrentPlayingCheck);
+ return this.playEffect(randomFile, withCurrentPlayingCheck);
}
- private playEffect(file: string, volume: number, withCurrentPlayingCheck: boolean): Promise {
+ private playEffect(file: string, withCurrentPlayingCheck: boolean): Promise {
if (withCurrentPlayingCheck && this.currentlyPlayingSfx.length > 0) {
return Promise.resolve();
}
const audio = new Audio(file);
this.currentlyPlayingSfx.push(audio);
audio.onended = () => _.pull(this.currentlyPlayingSfx, audio);
- audio.volume = volume;
+ audio.volume = this.gameClient.sfxVolume;
return audio.play();
}
- private playMusic(file: string, volume: number): Promise {
+ private playMusic(file: string): Promise {
const audio = new Audio(file);
this.currentlyPlayingMusic.push(audio);
audio.onended = () => _.pull(this.currentlyPlayingMusic, audio);
- audio.volume = volume;
+ audio.volume = this.gameClient.musicVolume;
return audio.play();
}
- private playNotification(file: string, volume: number): Promise {
+ private playNotification(file: string): Promise {
const audio = new Audio(file);
this.currentlyPlayingNotifications.push(audio);
audio.onended = () => _.pull(this.currentlyPlayingNotifications, audio);
- audio.volume = volume;
+ audio.volume = this.gameClient.notificationsVolume;
return audio.play();
}
+
+ private fadeOutMusic(fadeOutDuration: number, fadeOutSteps: number): void {
+ if (this.currentlyPlayingMusic.length === 0) {
+ return;
+ }
+
+ const fadeOutInterval = fadeOutDuration / fadeOutSteps;
+ const volumeStep = this.gameClient.musicVolume / fadeOutSteps;
+
+ let interval = window.setInterval(() => {
+ if (this.currentlyPlayingMusic.length === 0 && interval > 0) {
+ clearInterval(interval);
+ interval = 0;
+ return;
+ }
+
+ this.currentlyPlayingMusic.forEach(audio => {
+ if (audio.volume - volumeStep > 0) {
+ audio.volume -= volumeStep;
+ } else {
+ audio.volume = 0;
+ if (!audio.paused) {
+ audio.pause();
+ audio.currentTime = 0;
+ }
+ audio.dispatchEvent(new Event('ended'));
+ }
+ });
+ }, fadeOutInterval);
+ }
+
+ private fadeOutSfx(fadeOutDuration: number, fadeOutSteps: number): void {
+ if (this.currentlyPlayingSfx.length === 0) {
+ return;
+ }
+
+ const fadeOutInterval = fadeOutDuration / fadeOutSteps;
+ const volumeStep = this.gameClient.sfxVolume / fadeOutSteps;
+
+ let interval = window.setInterval(() => {
+ if (this.currentlyPlayingSfx.length === 0 && interval > 0) {
+ clearInterval(interval);
+ interval = 0;
+ return;
+ }
+
+ this.currentlyPlayingSfx.forEach(audio => {
+ if (audio.volume - volumeStep > 0) {
+ audio.volume -= volumeStep;
+ } else {
+ audio.volume = 0;
+ if (!audio.paused) {
+ audio.pause();
+ audio.currentTime = 0;
+ }
+ audio.dispatchEvent(new Event('ended'));
+ }
+ });
+ }, fadeOutInterval);
+ }
}
export default SfxManager;
diff --git a/agot-bg-game-server/src/common/EntireGame.ts b/agot-bg-game-server/src/common/EntireGame.ts
index 3f77b275d..748a576a4 100644
--- a/agot-bg-game-server/src/common/EntireGame.ts
+++ b/agot-bg-game-server/src/common/EntireGame.ts
@@ -54,7 +54,7 @@ export default class EntireGame extends GameState void;
@@ -820,4 +820,6 @@ export interface GameSettings {
fixedClock: boolean;
holdVictoryPointsUntilEndOfRound: boolean;
fogOfWar: boolean;
+ dragonWar: boolean;
+ dragonRevenge: boolean;
}
diff --git a/agot-bg-game-server/src/common/ingame-game-state/IngameGameState.ts b/agot-bg-game-server/src/common/ingame-game-state/IngameGameState.ts
index 794c5ed17..f2f80a103 100644
--- a/agot-bg-game-server/src/common/ingame-game-state/IngameGameState.ts
+++ b/agot-bg-game-server/src/common/ingame-game-state/IngameGameState.ts
@@ -11,7 +11,7 @@ import ActionGameState, {SerializedActionGameState} from "./action-game-state/Ac
import Order from "./game-data-structure/Order";
import Game, {SerializedGame} from "./game-data-structure/Game";
import WesterosGameState, {SerializedWesterosGameState} from "./westeros-game-state/WesterosGameState";
-import createGame, { applyChangesForDanceWithMotherOfDragons } from "./game-data-structure/createGame";
+import createGame, { applyChangesForDanceWithMotherOfDragons, applyChangesForDragonWar } from "./game-data-structure/createGame";
import BetterMap from "../../utils/BetterMap";
import House from "./game-data-structure/House";
import Unit from "./game-data-structure/Unit";
@@ -46,6 +46,8 @@ import orders from "./game-data-structure/orders";
import { OrderOnMapProperties, UnitOnMapProperties } from "../../client/MapControls";
import houseCardAbilities from "./game-data-structure/house-card/houseCardAbilities";
import SnrError from "../../utils/snrError";
+import { TakeOverPort, findOrphanedShipsAndDestroyThem, isTakeControlOfEnemyPortRequired } from "./port-helper/PortHelper";
+import { dragon } from "./game-data-structure/unitTypes";
export const NOTE_MAX_LENGTH = 5000;
@@ -54,6 +56,11 @@ export const enum ReplacementReason {
CLOCK_TIMEOUT
}
+export interface UnitLossConsequence {
+ victoryConditionsFulfilled?: true;
+ takeOverPort?: TakeOverPort;
+}
+
export default class IngameGameState extends GameState<
EntireGame,
WesterosGameState | PlanningGameState | ActionGameState | CancelledGameState | GameEndedGameState
@@ -122,6 +129,12 @@ export default class IngameGameState extends GameState<
return this.entireGame.gameSettings.fogOfWar;
}
+ get isDragonGame(): boolean {
+ return this.entireGame.gameSettings.playerCount == 8 ||
+ this.entireGame.gameSettings.dragonWar ||
+ this.entireGame.gameSettings.dragonRevenge;
+ }
+
constructor(entireGame: EntireGame) {
super(entireGame);
@@ -146,6 +159,10 @@ export default class IngameGameState extends GameState<
applyChangesForDanceWithMotherOfDragons(this);
}
+ if (this.entireGame.gameSettings.dragonWar) {
+ applyChangesForDragonWar(this);
+ }
+
if (this.entireGame.gameSettings.onlyLive) {
this.players.values.forEach(p => p.liveClockData = {
remainingSeconds: this.entireGame.gameSettings.initialLiveClock * 60,
@@ -1086,6 +1103,65 @@ export default class IngameGameState extends GameState<
}
}
+ // returns true, if game is over and calling state needs to exit from processing
+ processPossibleConsequencesOfUnitLoss(): UnitLossConsequence {
+ // Check for last unit in dragon revenge
+ if (this.entireGame.gameSettings.dragonRevenge) {
+ for (const house of this.game.houses.values) {
+ const noCastles = this.world.regions.values.filter(r => r.castleLevel > 0 && r.getController() == house).length == 0;
+
+ if (noCastles) {
+ const nonDragonLandUnits = this.world.getUnitsOfHouse(house).filter(u => u.type.id != "ship" && u.type.id != "dragon");
+ if (nonDragonLandUnits.length == 1) {
+ const unit = nonDragonLandUnits[0];
+ this.log({
+ type: "last-land-unit-transformed-to-dragon",
+ house: house.id,
+ transformedUnitType: unit.type.id,
+ region: unit.region.id
+ }, true);
+ this.transformUnits(unit.region, [unit], dragon);
+ }
+ }
+ }
+ }
+
+ // Restore Pentos garrison
+ this.world.regionsThatRegainGarrison.forEach(staticRegion => {
+ const region = this.world.getRegion(staticRegion);
+ if (region.getController() == region.superControlPowerToken && region.garrison != staticRegion.startingGarrison) {
+ region.garrison = staticRegion.startingGarrison;
+ this.sendMessageToUsersWhoCanSeeRegion({
+ type: "change-garrison",
+ region: region.id,
+ newGarrison: region.garrison
+ }, region);
+ this.log({
+ type: "garrison-returned",
+ region: region.id,
+ strength: region.garrison
+ });
+ }
+ });
+
+ // Destroy orphaned ships in ports
+ findOrphanedShipsAndDestroyThem(this, this.actionState);
+
+ // Check for Port take over
+ const takeOverRequired = isTakeControlOfEnemyPortRequired(this);
+ if (takeOverRequired) {
+ return { takeOverPort: takeOverRequired };
+ }
+
+ // A unit loss may result in a win, if the lost unit
+ // was located in an enemy capital => check winning conditions
+ if (this.checkVictoryConditions()) {
+ return { victoryConditionsFulfilled: true };
+ }
+
+ return { };
+ }
+
onServerMessage(message: ServerMessage): void {
if (message.type == "supply-adjusted") {
const supplies: [House, number][] = message.supplies.map(([houseId, supply]) => [this.game.houses.get(houseId), supply]);
diff --git a/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-consolidate-power-game-state/execute-loan-game-state/ExecuteLoanGameState.ts b/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-consolidate-power-game-state/execute-loan-game-state/ExecuteLoanGameState.ts
index bf6ba99eb..96b98b2c0 100644
--- a/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-consolidate-power-game-state/execute-loan-game-state/ExecuteLoanGameState.ts
+++ b/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-consolidate-power-game-state/execute-loan-game-state/ExecuteLoanGameState.ts
@@ -17,7 +17,7 @@ import LoyalMaesterGameState, { SerializedLoyalMaesterGameState } from "./loyal-
import MasterAtArmsGameState, { SerializedMasterAtArmsGameState } from "./master-at-arms-game-state/MasterAtArmsGameState";
import SavvyStewardGameState, { SerializedSavvyStewardGameState } from "./savvy-steward-game-state/SavvyStewardGameState";
import SpymasterGameState, { SerializedSpymasterGameState } from "./spymaster-game-state/SpymasterGameState";
-import { findOrphanedShipsAndDestroyThem, isTakeControlOfEnemyPortGameStateRequired } from "../../../../../common/ingame-game-state/port-helper/PortHelper";
+import { isTakeControlOfEnemyPortRequired } from "../../../../../common/ingame-game-state/port-helper/PortHelper";
import TakeControlOfEnemyPortGameState, { SerializedTakeControlOfEnemyPortGameState } from "../../../take-control-of-enemy-port-game-state/TakeControlOfEnemyPortGameState";
import ActionGameState from "../../ActionGameState";
@@ -86,19 +86,12 @@ export default class ExecuteLoanGameState extends GameState {
- const region = this.world.getRegion(staticRegion);
- if (region.getController() == region.superControlPowerToken && region.garrison != staticRegion.startingGarrison) {
- region.garrison = staticRegion.startingGarrison;
- this.ingame.sendMessageToUsersWhoCanSeeRegion({
- type: "change-garrison",
- region: region.id,
- newGarrison: region.garrison
- }, region);
- this.ingameGameState.log({
- type: "garrison-returned",
- region: region.id,
- strength: region.garrison
- });
- }
- })
-
// Gain Loyalty tokens
this.ingameGameState.gainLoyaltyTokens();
- // ... destroy orphaned ships (e.g. caused by Arianne)
- findOrphanedShipsAndDestroyThem(this.ingameGameState, this.actionGameState);
- // ... check if ships can be converted
- const analyzePortResult = isTakeControlOfEnemyPortGameStateRequired(this.ingameGameState);
- if (analyzePortResult) {
- this.setChildGameState(new TakeControlOfEnemyPortGameState(this)).firstStart(analyzePortResult.port, analyzePortResult.newController, house);
+ // Handle possible unit loss consequences (checks winning condition)
+ const consequence = this.ingame.processPossibleConsequencesOfUnitLoss();
+ if (consequence.victoryConditionsFulfilled) {
return;
- }
-
- // ... check victory conditions
- if (this.ingameGameState.checkVictoryConditions()) {
+ } else if (consequence.takeOverPort) {
+ this.setChildGameState(new TakeControlOfEnemyPortGameState(this))
+ .firstStart(consequence.takeOverPort.port, consequence.takeOverPort.newController, house);
return;
}
- // ... check if an other march order can be resolved
+ // Find next march order to resolve
this.proceedNextResolveSingleMarchOrder();
}
diff --git a/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-march-order-game-state/resolve-single-march-order-game-state/ResolveSingleMarchOrderGameState.ts b/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-march-order-game-state/resolve-single-march-order-game-state/ResolveSingleMarchOrderGameState.ts
index 09f9f029a..8db363692 100644
--- a/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-march-order-game-state/resolve-single-march-order-game-state/ResolveSingleMarchOrderGameState.ts
+++ b/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-march-order-game-state/resolve-single-march-order-game-state/ResolveSingleMarchOrderGameState.ts
@@ -144,10 +144,10 @@ export default class ResolveSingleMarchOrderGameState extends GameState (_.last(this.dragonStrengthTokens) as number)) {
+ if (this.turn > (_.last(dragonTokens) as number)) {
return 5;
}
// If a dragon strength token has been removed from the round track
// the initial value is 1 instead of 0
- const result = this.ingame.entireGame.isDanceWithMotherOfDragons
- ? this.removedDragonStrengthToken == 0
+ const result = isADwMoD
+ ? removedToken == 0
? 1
: 2
- : this.removedDragonStrengthToken == 0
+ : removedToken == 0
? 0
: 1;
- for (let i=0; i this.turn) {
+ if (dragonTokens[i] > this.turn) {
// If the current token value is greater than current round we add the current index,
// which is the value of the previous dragon strength token on the round track (0-based index)
return result + i;
diff --git a/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/GameLog.ts b/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/GameLog.ts
index 071f611a6..c7888e76f 100644
--- a/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/GameLog.ts
+++ b/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/GameLog.ts
@@ -50,7 +50,7 @@ export type GameLogData = TurnBegin | SupportDeclared | SupportRefused | Attack
| BalonGreyjoyASoSPowerTokensGained | MaceTyrellASoSOrderPlaced | BranStarkUsed | CerseiLannisterASoSPowerTokensDiscarded
| DoranMartellASoSUsed | MelisandreOfAsshaiPowerTokensGained | SalladharSaanASoSPowerTokensChanged | SerDavosSeaworthASoSFortificationGained
| CasualtiesPrevented | SerIlynPayneASoSCasualtySuffered | StannisBaratheonASoSUsed | AeronDamphairHouseCardChanged | ControlPowerTokenRemoved
- | GamePaused | GameResumed | SupportAttackAgainstNeutralForce | HousesSwapped | NoLoyaltyTokenAvailable;
+ | GamePaused | GameResumed | SupportAttackAgainstNeutralForce | HousesSwapped | NoLoyaltyTokenAvailable | LastLandUnitTransformedToDragon;
export enum PlayerActionType {
ORDERS_PLACED,
@@ -716,6 +716,7 @@ interface JaqenHGharUsed {
affectedHouse: string;
oldHouseCard: string;
newHouseCard: string;
+ usedById: string;
}
interface JonConningtonUsed {
@@ -1173,4 +1174,11 @@ export interface WesterosDeck4Skipped {
export interface NoLoyaltyTokenAvailable {
type: "no-loyalty-token-available";
region: string;
+}
+
+export interface LastLandUnitTransformedToDragon {
+ type: "last-land-unit-transformed-to-dragon";
+ house: string;
+ transformedUnitType: string;
+ region: string;
}
\ No newline at end of file
diff --git a/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/World.ts b/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/World.ts
index 872e1de0a..6b107dc14 100644
--- a/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/World.ts
+++ b/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/World.ts
@@ -24,7 +24,7 @@ export default class World {
return getStaticWorld(this.settings).staticBorders;
}
- get regionsWhichCanRegainGarrison(): StaticRegion[] {
+ get regionsThatRegainGarrison(): StaticRegion[] {
return getStaticWorld(this.settings).staticRegions.values.filter(region => region.canRegainGarrison);
}
@@ -239,9 +239,12 @@ export default class World {
return region.units.get(unitId);
}
- getCapitalOfHouse(house: House): Region | null {
+ getCapitalOfHouse(house: House): Region {
const capital = this.regions.values.filter(r => r.superControlPowerToken == house);
- return capital.length == 1 ? capital[0] : null;
+ if (capital.length != 1) {
+ throw new Error("Every house must have exactly one capital");
+ }
+ return capital[0];
}
getSnapshot(): RegionSnapshot[] {
diff --git a/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/createGame.ts b/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/createGame.ts
index 07f50e884..ab443317a 100644
--- a/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/createGame.ts
+++ b/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/createGame.ts
@@ -5,7 +5,8 @@ import Region from "./Region";
import World from "./World";
import WesterosCard from "./westeros-card/WesterosCard";
import {fireMadeFlesh, westerosCardTypes} from "./westeros-card/westerosCardTypes";
-import unitTypes, { ship } from "./unitTypes";
+import unitTypes from "./unitTypes";
+import Unit from "./Unit";
import Game from "./Game";
import WildlingCard from "./wildling-card/WildlingCard";
import wildlingCardTypes from "./wildling-card/wildlingCardTypes";
@@ -20,7 +21,7 @@ import IronBank from "./IronBank";
import loanCardTypes from "./loan-card/loanCardTypes";
import LoanCard from "./loan-card/LoanCard";
import { specialObjectiveCards } from "./static-data-structure/objectiveCards";
-import popRandom from "../../../utils/popRandom";
+import popRandom, { pickRandom } from "../../../utils/popRandom";
import { HouseCardDecks } from "../../../common/EntireGame";
interface HouseCardContainer {
@@ -103,7 +104,7 @@ function getTrackWithAdjustedVassalPositions(track: House[], playerHouses: strin
return track;
}
-function createHouseCard(id: string, houseCardData: HouseCardData, houseId: string): HouseCard {
+export function createHouseCard(id: string, houseCardData: HouseCardData, houseId: string): HouseCard {
return new HouseCard(
id,
houseCardData.name,
@@ -523,7 +524,7 @@ export default function createGame(ingame: IngameGameState, housesToCreate: stri
const redwyneStraights = game.world.regions.get("redwyne-straights");
const house = redwyneStraights.units.size > 0 ? redwyneStraights.units.values[0].allegiance : null;
if (house && playerHouses.includes(house.id)) {
- const newShip = game.createUnit(redwyneStraights, ship, house);
+ const newShip = game.createUnit(redwyneStraights, unitTypes.get("ship"), house);
redwyneStraights.units.set(newShip.id, newShip);
}
}
@@ -591,4 +592,64 @@ export function applyChangesForDanceWithMotherOfDragons(ingame: IngameGameState)
while (_.some(_.take(game.westerosDecks[3], 2), wc => wc.type == fireMadeFlesh)) {
shuffleInPlace(game.westerosDecks[3]);
}
+}
+
+export function applyChangesForDragonWar(ingame: IngameGameState): void {
+ const game = ingame.game;
+ const houses = _.without(game.houses.values, game.targaryen) as House[];
+
+ for (const house of houses) {
+ let unit = findUnitToReplace(ingame, house, "knight");
+
+ if (!unit) {
+ unit = findUnitToReplace(ingame, house, "footman");
+
+ if (!unit) {
+ throw new Error("Every house starts with at least one footman");
+ }
+ }
+
+ const region = unit.region;
+ region.units.delete(unit.id);
+ const newDragon = game.createUnit(region, unitTypes.get("dragon"), house);
+ region.units.set(newDragon.id, newDragon);
+ }
+
+ if (game.dragonStrengthTokens.length == 0) {
+ game.dragonStrengthTokens = ingame.entireGame.isDanceWithDragons
+ ? [2, 4, 5, 6]
+ : [2, 4, 6, 8, 10];
+ }
+
+ nervHouseCard(game, "balon-greyjoy", "jaqen-h-ghar");
+ nervHouseCard(game, "aeron-damphair-dwd", "aeron-damphair");
+
+ game.world.regions.values.filter(r => r.superControlPowerToken != null && r.garrison == 4).forEach(r => r.garrison = 6);
+ game.world.regions.values.filter(r => r.superControlPowerToken != null && r.garrison == 2).forEach(r => r.garrison = 4);
+}
+
+function findUnitToReplace(ingame: IngameGameState, house: House, unitType: string): Unit | null {
+ const capital = ingame.world.getCapitalOfHouse(house);
+ const unit = _.first(capital.units.values.filter(u => u.type.id == unitType));
+
+ // Return either the first unit in the capital or any random unit on the board.
+ return unit
+ ? unit
+ : pickRandom(ingame.world.getUnitsOfHouse(house).filter(u => u.type.id == unitType));
+}
+
+function nervHouseCard(game: Game, hcId: string, newAbilityId: string): void {
+ const houseCard = game.draftableHouseCards.has(hcId)
+ ? game.draftableHouseCards.get(hcId)
+ : _.flatMap(game.houses.values.map(h => h.houseCards.values)).find(hc => hc.id == hcId);
+
+ if (houseCard) {
+ houseCard.id = hcId + "-nerved";
+ houseCard.ability = houseCardAbilities.get(newAbilityId);
+
+ if (game.draftableHouseCards.has(hcId)) {
+ game.draftableHouseCards.delete(hcId);
+ game.draftableHouseCards.set(hcId + "-nerved", houseCard);
+ }
+ }
}
\ No newline at end of file
diff --git a/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/house-card/AlayneStoneHouseCardAbility.ts b/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/house-card/AlayneStoneHouseCardAbility.ts
index d92b7943e..74ba7360f 100644
--- a/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/house-card/AlayneStoneHouseCardAbility.ts
+++ b/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/house-card/AlayneStoneHouseCardAbility.ts
@@ -9,11 +9,11 @@ export default class AlayneStoneHouseCardAbility extends HouseCardAbility {
afterWinnerDetermination(afterWinnerDetermination: AfterWinnerDeterminationGameState, house: House, _houseCard: HouseCard): void {
const enemy = afterWinnerDetermination.combatGameState.getEnemy(house);
if (afterWinnerDetermination.postCombatGameState.winner == house && !afterWinnerDetermination.combatGameState.ingameGameState.isVassalHouse(enemy)) {
- const capitalOfHouse = afterWinnerDetermination.combatGameState.world.getCapitalOfHouse(house);
+ const capital = afterWinnerDetermination.combatGameState.world.getCapitalOfHouse(house);
// getController() will return the wrong house when the player regains their capital with the current fight
// as the attacking army hasn't moved into the attacked region yet. Therefore we need an extra handling.
- if ((capitalOfHouse && capitalOfHouse.getController() == house) ||
- (afterWinnerDetermination.postCombatGameState.combat.defendingRegion == capitalOfHouse)) {
+ if (capital.getController() == house ||
+ (afterWinnerDetermination.postCombatGameState.combat.defendingRegion == capital)) {
afterWinnerDetermination.childGameState
.setChildGameState(new AlayneStoneAbilityGameState(afterWinnerDetermination.childGameState))
.firstStart(house);
diff --git a/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/house-card/JaqenHGharHouseCardAbility.ts b/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/house-card/JaqenHGharHouseCardAbility.ts
index 9fd0fe8ce..45ce7e968 100644
--- a/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/house-card/JaqenHGharHouseCardAbility.ts
+++ b/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/house-card/JaqenHGharHouseCardAbility.ts
@@ -7,7 +7,7 @@ import shuffleInPlace from "../../../../utils/shuffleInPlace";
import _ from "lodash";
export default class JaqenHGharHouseCardAbility extends HouseCardAbility {
- cancel(cancelResolutionState: CancelHouseCardAbilitiesGameState, house: House, _houseCard: HouseCard): void {
+ cancel(cancelResolutionState: CancelHouseCardAbilitiesGameState, house: House, houseCard: HouseCard): void {
const combat = cancelResolutionState.combatGameState;
const enemy = combat.getEnemy(house);
@@ -19,7 +19,8 @@ export default class JaqenHGharHouseCardAbility extends HouseCardAbility {
house: house.id,
affectedHouse: enemy.id,
oldHouseCard: (combat.houseCombatDatas.get(enemy).houseCard as HouseCard).id,
- newHouseCard: newHouseCard.id
+ newHouseCard: newHouseCard.id,
+ usedById: houseCard.id
});
// Change the new house card to the chosen one
diff --git a/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/house-card/LittlefingerHouseCardAbility.ts b/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/house-card/LittlefingerHouseCardAbility.ts
index fbcec1e7f..f6db13333 100644
--- a/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/house-card/LittlefingerHouseCardAbility.ts
+++ b/agot-bg-game-server/src/common/ingame-game-state/game-data-structure/house-card/LittlefingerHouseCardAbility.ts
@@ -6,8 +6,8 @@ import House from "../House";
export default class LittlefingerHouseCardAbility extends HouseCardAbility {
afterCombat(afterCombat: AfterCombatHouseCardAbilitiesGameState, house: House, _houseCard: HouseCard): void {
- const capitalOfHouse = afterCombat.combatGameState.world.getCapitalOfHouse(house);
- if (capitalOfHouse && capitalOfHouse.getController() == house) {
+ const capital = afterCombat.combatGameState.world.getCapitalOfHouse(house);
+ if (capital.getController() == house) {
const enemy = afterCombat.combatGameState.getEnemy(house);
const enemyHouseCard = afterCombat.combatGameState.houseCombatDatas.get(enemy).houseCard;
const gainedPowerTokens = afterCombat.combatGameState.ingameGameState.changePowerTokens(house, enemyHouseCard ? enemyHouseCard.combatStrength * 2 : 0);
diff --git a/agot-bg-game-server/src/common/ingame-game-state/pay-debts-game-state/PayDebtsGameState.ts b/agot-bg-game-server/src/common/ingame-game-state/pay-debts-game-state/PayDebtsGameState.ts
index 23f236521..8c7089f91 100644
--- a/agot-bg-game-server/src/common/ingame-game-state/pay-debts-game-state/PayDebtsGameState.ts
+++ b/agot-bg-game-server/src/common/ingame-game-state/pay-debts-game-state/PayDebtsGameState.ts
@@ -6,7 +6,6 @@ import {ServerMessage} from "../../../messages/ServerMessage";
import IngameGameState from "../IngameGameState";
import BetterMap from "../../../utils/BetterMap";
import ResolveSinglePayDebtGameState, { SerializedResolveSinglePayDebtGameState } from "./resolve-single-pay-debt-game-state/ResolveSinglePayDebtGameState";
-import { findOrphanedShipsAndDestroyThem, isTakeControlOfEnemyPortGameStateRequired } from "../port-helper/PortHelper";
import TakeControlOfEnemyPortGameState, { SerializedTakeControlOfEnemyPortGameState } from "../take-control-of-enemy-port-game-state/TakeControlOfEnemyPortGameState";
import ActionGameState from "../action-game-state/ActionGameState";
@@ -27,11 +26,12 @@ export default class PayDebtsGameState extends GameState r.type == port
&& r.units.size > 0
@@ -85,7 +85,7 @@ export function isTakeControlOfEnemyPortGameStateRequired(ingame: IngameGameStat
throw new Error(`Port with id '${portRegion.id}' contains orphaned ships which should have been removed before!`);
}
-export interface TakeControlOfEnemyPortResult {
+export interface TakeOverPort {
port: Region;
newController: House;
}
\ No newline at end of file
diff --git a/agot-bg-game-server/src/common/ingame-game-state/westeros-game-state/wildlings-attack-game-state/WildlingCardEffectInTurnOrderGameState.ts b/agot-bg-game-server/src/common/ingame-game-state/westeros-game-state/wildlings-attack-game-state/WildlingCardEffectInTurnOrderGameState.ts
index 1c98c194d..2839a0d92 100644
--- a/agot-bg-game-server/src/common/ingame-game-state/westeros-game-state/wildlings-attack-game-state/WildlingCardEffectInTurnOrderGameState.ts
+++ b/agot-bg-game-server/src/common/ingame-game-state/westeros-game-state/wildlings-attack-game-state/WildlingCardEffectInTurnOrderGameState.ts
@@ -2,7 +2,7 @@ import GameState from "../../../GameState";
import WildlingsAttackGameState from "./WildlingsAttackGameState";
import Game from "../../game-data-structure/Game";
import House from "../../game-data-structure/House";
-import { findOrphanedShipsAndDestroyThem, isTakeControlOfEnemyPortGameStateRequired, TakeControlOfEnemyPortResult } from "../../port-helper/PortHelper";
+import { TakeOverPort } from "../../port-helper/PortHelper";
import IngameGameState from "../../IngameGameState";
/**
@@ -40,13 +40,11 @@ export default abstract class WildlingCardEffectInTurnOrderGameState {
settings.randomVassalAssignment = false;
}
+ if (settings.dragonWar && !this.settings.dragonWar) {
+ settings.dragonRevenge = true;
+ }
+
const hideOrRevealUserNames = settings.faceless != this.settings.faceless;
this.entireGame.gameSettings = settings;
diff --git a/agot-bg-game-server/src/server/serializedGameMigrations.ts b/agot-bg-game-server/src/server/serializedGameMigrations.ts
index 1dfa146f6..387b119ce 100644
--- a/agot-bg-game-server/src/server/serializedGameMigrations.ts
+++ b/agot-bg-game-server/src/server/serializedGameMigrations.ts
@@ -2210,6 +2210,18 @@ const serializedGameMigrations: {version: string; migrate: (serializeGamed: any)
serializedGame.gameSettings.selectedDraftDecks = 7; // Currently All: Base + Dwd / FfC + ASoS
return serializedGame;
}
+ },
+ {
+ version: "115",
+ migrate: (serializedGame: any) => {
+ if (serializedGame.childGameState.type == "ingame") {
+ const ingame = serializedGame.childGameState;
+
+ const jaqenLogs = ingame.gameLogManager.logs.filter((l: any) => l.data.type == "jaqen-h-ghar-house-card-replaced");
+ jaqenLogs.forEach((l: any) => l.data.usedById = "jaqen-h-ghar");
+ }
+ return serializedGame;
+ }
}
];