1
0
Fork 0

Removed references from battle state to universe state, causing large serialized data, slowing down AI work

This commit is contained in:
Michaël Lemaire 2018-01-16 01:08:24 +01:00
parent 4e155b8556
commit fa98a57ee2
44 changed files with 456 additions and 253 deletions

View File

@ -102,7 +102,6 @@ Common UI
Technical
---------
* Remove references from battle internals (ships, fleets...) to universe (it causes large serialized battles in campaign mode)
* Pack all images in atlases, and split them by stage
* Pack sounds
* Add toggles for shaders, automatically disable them if too slow, and initially disable them on mobile

View File

@ -269,7 +269,7 @@ module TK.SpaceTac {
check.equals(battle.canPlay(player), false);
ship.fleet.player = player;
ship.fleet.setPlayer(player);
check.equals(battle.canPlay(player), true);
});
@ -358,9 +358,19 @@ module TK.SpaceTac {
let loaded = serializer.unserialize(data);
check.equals(loaded.ai_playing, false);
check.equals(loaded.ai_playing, false, "ai playing is reset");
battle.ai_playing = false;
check.equals(loaded, battle);
check.equals(loaded, battle, "unserialized == initial");
let session = new GameSession();
session.startNewGame();
session.start_location.setupEncounter();
session.start_location.enterLocation(session.player.fleet);
let battle1 = nn(session.getBattle());
let data1 = serializer.serialize(battle1);
let ratio = data.length / data1.length;
check.greaterorequal(ratio, 1.2, `quick battle serialized size (${data.length}) should be larger than campaign's (${data1.length})`);
});
test.case("can revert the last action", check => {

View File

@ -6,9 +6,6 @@ module TK.SpaceTac {
// Battle outcome, if the battle has ended
outcome: BattleOutcome | null = null
// Battle cheats
cheats: BattleCheats
// Statistics
stats: BattleStats
@ -43,7 +40,7 @@ module TK.SpaceTac {
// Indicator that an AI is playing
ai_playing = false
constructor(fleet1 = new Fleet(new Player(undefined, "Attacker")), fleet2 = new Fleet(new Player(undefined, "Defender")), width = 1808, height = 948) {
constructor(fleet1 = new Fleet(new Player("Attacker")), fleet2 = new Fleet(new Player("Defender")), width = 1808, height = 948) {
this.fleets = [fleet1, fleet2];
this.ships = new RObjectContainer(fleet1.ships.concat(fleet2.ships));
this.play_order = [];
@ -52,7 +49,6 @@ module TK.SpaceTac {
this.log = new BattleLog();
this.stats = new BattleStats();
this.cheats = new BattleCheats(this, fleet1.player);
this.fleets.forEach((fleet: Fleet) => {
fleet.setBattle(this);
@ -123,23 +119,26 @@ module TK.SpaceTac {
/**
* Return an iterator over ships allies of (or owned by) a player
*/
iallies(player: Player, alive_only = false): Iterator<Ship> {
return ifilter(this.iships(alive_only), ship => ship.getPlayer() === player);
iallies(ship: Ship, alive_only = false): Iterator<Ship> {
return ifilter(this.iships(alive_only), iship => iship.fleet.player.is(ship.fleet.player));
}
/**
* Return an iterator over ships enemy of a player
*/
ienemies(player: Player, alive_only = false): Iterator<Ship> {
return ifilter(this.iships(alive_only), ship => ship.getPlayer() !== player);
ienemies(ship: Ship, alive_only = false): Iterator<Ship> {
return ifilter(this.iships(alive_only), iship => !iship.fleet.player.is(ship.fleet.player));
}
// Check if a player is able to play
// This can be used by the UI to determine if player interaction is allowed
/**
* Check if a player is able to play
*
* This can be used by the UI to determine if player interaction is allowed
*/
canPlay(player: Player): boolean {
if (this.ended) {
return false;
} else if (this.playing_ship && this.playing_ship.getPlayer() == player) {
} else if (this.playing_ship && player.is(this.playing_ship.fleet.player)) {
return this.playing_ship.isAbleToPlay(false);
} else {
return false;

View File

@ -2,8 +2,10 @@ module TK.SpaceTac.Specs {
testing("BattleCheats", test => {
test.case("wins a battle", check => {
let battle = Battle.newQuickRandom();
let cheats = new BattleCheats(battle, battle.fleets[0].player);
cheats.win();
battle.cheats.win();
check.equals(battle.ended, true, "ended");
check.same(nn(battle.outcome).winner, battle.fleets[0], "winner");
check.equals(any(battle.fleets[1].ships, ship => ship.alive), false, "all enemies dead");
@ -11,8 +13,10 @@ module TK.SpaceTac.Specs {
test.case("loses a battle", check => {
let battle = Battle.newQuickRandom();
let cheats = new BattleCheats(battle, battle.fleets[0].player);
cheats.lose();
battle.cheats.lose();
check.equals(battle.ended, true, "ended");
check.same(nn(battle.outcome).winner, battle.fleets[1], "winner");
check.equals(any(battle.fleets[0].ships, ship => ship.alive), false, "all allies dead");
@ -23,9 +27,12 @@ module TK.SpaceTac.Specs {
let ship = new Ship();
TestTools.setShipPlaying(battle, ship);
ship.upgradeSkill("skill_materials");
let cheats = new BattleCheats(battle, battle.fleets[0].player);
check.equals(ship.listEquipment(), []);
battle.cheats.equip("Iron Hull");
cheats.equip("Iron Hull");
let result = ship.listEquipment();
check.equals(result.length, 1);
check.containing(result[0], { name: "Iron Hull", level: 1 });

View File

@ -18,7 +18,7 @@ module TK.SpaceTac {
*/
win(): void {
iforeach(this.battle.iships(), ship => {
if (ship.fleet.player != this.player) {
if (!this.player.is(ship.fleet.player)) {
ship.setDead();
}
});
@ -30,11 +30,11 @@ module TK.SpaceTac {
*/
lose(): void {
iforeach(this.battle.iships(), ship => {
if (ship.fleet.player == this.player) {
if (this.player.is(ship.fleet.player)) {
ship.setDead();
}
});
this.battle.endBattle(first(this.battle.fleets, fleet => fleet.player != this.player));
this.battle.endBattle(first(this.battle.fleets, fleet => !this.player.is(fleet.player)));
}
/**

View File

@ -27,7 +27,7 @@ module TK.SpaceTac {
this.loot = [];
battle.fleets.forEach(fleet => {
if (this.winner && this.winner.player != fleet.player) {
if (this.winner && !this.winner.player.is(fleet.player)) {
fleet.ships.forEach(ship => {
var luck = random.random();
if (luck > 0.9) {

View File

@ -49,37 +49,92 @@ module TK.SpaceTac {
test.case("changes location, only using jumps to travel between systems", check => {
let fleet = new Fleet();
let system1 = new Star();
let system2 = new Star();
let jump1 = new StarLocation(system1, StarLocationType.WARP);
let jump2 = new StarLocation(system2, StarLocationType.WARP);
let universe = new Universe();
let system1 = universe.addStar();
let system2 = universe.addStar();
let jump1 = system1.addLocation(StarLocationType.WARP);
let jump2 = system2.addLocation(StarLocationType.WARP);
jump1.setJumpDestination(jump2);
jump2.setJumpDestination(jump1);
let other1 = new StarLocation(system1, StarLocationType.PLANET);
let other1 = system1.addLocation(StarLocationType.PLANET);
universe.updateLocations();
let result = fleet.setLocation(other1);
check.equals(result, true);
check.same(fleet.location, other1);
let result = fleet.move(other1);
check.in("cannot move from nowhere", check => {
check.equals(result, false);
check.equals(fleet.location, null);
});
result = fleet.setLocation(jump2);
check.equals(result, false);
check.same(fleet.location, other1);
fleet.setLocation(other1);
check.in("force set to other1", check => {
check.equals(fleet.location, other1.id);
});
result = fleet.setLocation(jump1);
check.equals(result, true);
check.same(fleet.location, jump1);
result = fleet.move(jump2);
check.in("other1=>jump2", check => {
check.equals(result, false);
check.equals(fleet.location, other1.id);
});
result = fleet.setLocation(jump2);
check.equals(result, true);
check.same(fleet.location, jump2);
result = fleet.move(jump1);
check.in("other1=>jump1", check => {
check.equals(result, true);
check.equals(fleet.location, jump1.id);
});
result = fleet.setLocation(other1);
check.equals(result, false);
check.same(fleet.location, jump2);
result = fleet.move(jump2);
check.in("jump1=>jump2", check => {
check.equals(result, true);
check.equals(fleet.location, jump2.id);
});
result = fleet.setLocation(jump1);
check.equals(result, true);
check.same(fleet.location, jump1);
result = fleet.move(other1);
check.in("jump2=>other1", check => {
check.equals(result, false);
check.equals(fleet.location, jump2.id);
});
result = fleet.move(jump1);
check.in("jump2=>jump1", check => {
check.equals(result, true);
check.equals(fleet.location, jump1.id);
});
});
test.case("registers presence in locations, and keeps track of visited locations", check => {
let fleet = new Fleet();
let universe = new Universe();
let star = universe.addStar();
let loc1 = star.addLocation(StarLocationType.PLANET);
let loc2 = star.addLocation(StarLocationType.PLANET);
let loc3 = star.addLocation(StarLocationType.PLANET);
universe.updateLocations();
function checks(desc: string, fleets1: Fleet[], fleets2: Fleet[], fleets3: Fleet[], visited: RObjectId[]) {
check.in(desc, check => {
check.equals(loc1.fleets, fleets1, "loc1 fleets");
check.equals(loc2.fleets, fleets2, "loc2 fleets");
check.equals(loc3.fleets, fleets3, "loc3 fleets");
check.equals(fleet.visited, visited, "visited");
});
}
checks("initial", [], [], [], []);
fleet.setLocation(loc1);
checks("first move to loc1", [fleet], [], [], [loc1.id]);
fleet.setLocation(loc1);
checks("already in loc1", [fleet], [], [], [loc1.id]);
fleet.setLocation(loc2);
checks("first move to loc2", [], [fleet], [], [loc2.id, loc1.id]);
fleet.setLocation(loc3);
checks("first move to loc3", [], [], [fleet], [loc3.id, loc2.id, loc1.id]);
fleet.setLocation(loc2);
checks("go back to loc2", [], [fleet], [], [loc2.id, loc3.id, loc1.id]);
});
test.case("checks if a fleet is alive", check => {

View File

@ -4,58 +4,98 @@ module TK.SpaceTac {
*/
export class Fleet {
// Fleet owner
player: Player;
player: Player
// Fleet name
name: string
// List of ships
ships: Ship[];
ships: Ship[]
// Current fleet location
location: StarLocation | null = null;
previous_location: StarLocation | null = null;
location: RObjectId | null = null
// Visited locations (ordered by last visited)
visited: RObjectId[] = []
// Current battle in which the fleet is engaged (null if not fighting)
battle: Battle | null = null;
battle: Battle | null = null
// Amount of credits available
credits = 0;
credits = 0
// Create a fleet, bound to a player
constructor(player = new Player()) {
this.player = player;
this.name = player ? player.name : "Fleet";
this.ships = [];
}
jasmineToString(): string {
return `${this.player.name}'s fleet [${this.ships.map(ship => ship.getName()).join(",")}]`;
return `${this.name} [${this.ships.map(ship => ship.getName()).join(",")}]`;
}
/**
* Set the current location of the fleet
* Set the owner player
*/
setPlayer(player: Player): void {
this.player = player;
}
/**
* Set a location as visited
*/
setVisited(location: StarLocation): void {
remove(this.visited, location.id);
this.visited.unshift(location.id);
}
/**
* Move the fleet to another location, checking that the move is physically possible
*
* Returns true on success
*/
setLocation(location: StarLocation, force = false): boolean {
if (!force && this.location && location.star != this.location.star && (this.location.type != StarLocationType.WARP || this.location.jump_dest != location)) {
move(to: StarLocation): boolean {
if (!this.location) {
return false;
}
this.previous_location = this.location;
this.location = location;
this.player.setVisited(this.location);
// Check encounter
var battle = this.location.enterLocation(this.player.fleet);
if (battle) {
this.player.setBattle(battle);
let source = to.universe.locations.get(this.location);
if (!source) {
return false;
}
if (source.star != to.star) {
// Need to jump, check conditions
if (source.type != StarLocationType.WARP || source.jump_dest != to) {
return false;
}
}
this.setLocation(to);
return true;
}
/**
* Set the current location of the fleet, without condition
*/
setLocation(location: StarLocation): void {
if (this.location) {
let previous = location.universe.locations.get(this.location);
if (previous) {
previous.removeFleet(this);
}
}
this.location = location.id;
this.setVisited(location);
location.addFleet(this);
}
/**
* Add a ship this fleet
*/
addShip(ship = new Ship(null, `${this.player.name} ${this.ships.length + 1}`)): Ship {
addShip(ship = new Ship(null, `${this.name} ${this.ships.length + 1}`)): Ship {
if (ship.fleet && ship.fleet != this) {
remove(ship.fleet.ships, ship);
}

View File

@ -40,8 +40,11 @@ module TK.SpaceTac.Specs {
let session = new GameSession();
check.equals(session.getBattle(), null);
// Victory case
let location1 = new StarLocation();
let location2 = new StarLocation(location1.star);
session.universe.locations = new RObjectContainer([location1, location2]);
// Victory case
location1.encounter = new Fleet();
session.player.fleet.setLocation(location1);
check.notequals(session.getBattle(), null);
@ -56,7 +59,6 @@ module TK.SpaceTac.Specs {
check.called(spyloot, 1);
// Defeat case
let location2 = new StarLocation(location1.star);
location2.encounter = new Fleet();
session.player.fleet.setLocation(location2);
check.notequals(session.getBattle(), null);
@ -78,7 +80,7 @@ module TK.SpaceTac.Specs {
check.notequals(session.player, null);
check.equals(session.player.fleet.ships.length, 0);
check.equals(session.player.fleet.credits, 0);
check.equals(session.player.universe.stars.length, 50);
check.equals(session.universe.stars.length, 50);
check.equals(session.getBattle(), null);
check.equals(session.start_location.shop, null);
check.equals(session.start_location.encounter, null);
@ -87,7 +89,47 @@ module TK.SpaceTac.Specs {
session.setCampaignFleet();
check.equals(session.player.fleet.ships.length, 2);
check.equals(session.player.fleet.credits, 0);
check.same(session.player.fleet.location, session.start_location);
check.equals(session.player.fleet.location, session.start_location.id);
});
test.case("can revert battle", check => {
let session = new GameSession();
let star = session.universe.addStar();
let loc1 = star.addLocation(StarLocationType.PLANET);
loc1.clearEncounter();
let loc2 = star.addLocation(StarLocationType.PLANET);
loc2.encounter_random = new SkewedRandomGenerator([0], true);
session.universe.updateLocations();
session.fleet.setLocation(loc1);
check.in("init in loc1", check => {
check.equals(session.getBattle(), null, "bound battle");
check.equals(session.fleet.location, loc1.id, "fleet location");
check.equals(session.player.hasVisitedLocation(loc2), false, "visited");
});
session.fleet.setLocation(loc2);
check.in("move to loc2", check => {
check.notequals(session.getBattle(), null, "bound battle");
check.equals(session.fleet.location, loc2.id, "fleet location");
check.equals(session.player.hasVisitedLocation(loc2), true, "visited");
});
let enemy = loc2.encounter;
session.revertBattle();
check.in("reverted", check => {
check.equals(session.getBattle(), null, "bound battle");
check.equals(session.fleet.location, loc1.id, "fleet location");
check.equals(session.player.hasVisitedLocation(loc2), true, "visited");
});
session.fleet.setLocation(loc2);
check.in("move to loc2 again", check => {
check.notequals(session.getBattle(), null, "bound battle");
check.equals(session.fleet.location, loc2.id, "fleet location");
check.equals(session.player.hasVisitedLocation(loc2), true, "visited");
check.same(nn(session.getBattle()).fleets[1], nn(enemy), "same enemy");
});
});
/*test.case("can generate lots of new games", check => {

View File

@ -32,11 +32,18 @@ module TK.SpaceTac {
constructor() {
this.id = RandomGenerator.global.id(20);
this.universe = new Universe();
this.player = new Player(this.universe);
this.player = new Player();
this.reactions = new PersonalityReactions();
this.start_location = new StarLocation();
}
/**
* Get the currently played fleet
*/
get fleet(): Fleet {
return this.player.fleet;
}
/**
* Get an indicative description of the session (to help identify game saves)
*/
@ -71,7 +78,7 @@ module TK.SpaceTac {
this.start_location.clearEncounter();
this.start_location.removeShop();
this.player = new Player(this.universe);
this.player = new Player();
this.reactions = new PersonalityReactions();
@ -88,34 +95,52 @@ module TK.SpaceTac {
setCampaignFleet(fleet: Fleet | null = null, story = true) {
if (fleet) {
this.player.fleet = fleet;
fleet.player = this.player;
fleet.setPlayer(this.player);
} else {
let fleet_generator = new FleetGenerator();
this.player.fleet = fleet_generator.generate(1, this.player, 2);
}
this.player.fleet.setLocation(this.start_location, true);
this.player.fleet.setLocation(this.start_location);
if (story) {
this.player.missions.startMainStory(this.universe, this.player.fleet);
}
}
// Start a new "quick battle" game
/**
* Start a new "quick battle" game
*/
startQuickBattle(with_ai: boolean = false): void {
this.universe = new Universe();
let battle = Battle.newQuickRandom(true, RandomGenerator.global.randInt(1, 10));
this.player = battle.fleets[0].player;
battle.fleets[0].setPlayer(this.player);
this.player.setBattle(battle);
this.reactions = new PersonalityReactions();
}
// Get currently played battle, null when none is in progress
/**
* Get currently played battle, null when none is in progress
*/
getBattle(): Battle | null {
return this.player.getBattle();
}
/**
* Set the end of current battle
* Get the main fleet's location
*/
getLocation(): StarLocation {
return this.universe.getLocation(this.player.fleet.location) || new StarLocation();
}
/**
* Set the end of current battle.
*
* This will reset the fleet, grant experience, and create loot.
*
* The battle will still be bound to the session (exitBattle or revertBattle should be called after).
*/
setBattleEnded() {
let battle = this.getBattle();
@ -133,13 +158,34 @@ module TK.SpaceTac {
}
// If the battle happened in a star location, keep it informed
let location = this.player.fleet.location;
let location = this.universe.getLocation(this.player.fleet.location);
if (location) {
location.resolveEncounter(battle.outcome);
}
}
}
/**
* Exit the current battle unconditionally, if any
*
* This does not apply retreat penalties, or battle outcome, only unbind the battle from current session
*/
exitBattle(): void {
this.player.setBattle(null);
}
/**
* Revert current battle, and put the player's fleet to its previous location, as if the battle never happened
*/
revertBattle(): void {
this.exitBattle();
let previous_location = this.universe.getLocation(this.fleet.visited[1]);
if (previous_location) {
this.fleet.setLocation(previous_location);
}
}
/**
* Returns true if the session has an universe to explore (campaign mode)
*/

View File

@ -51,15 +51,17 @@ module TK.SpaceTac.Specs {
test.case("checks for friendly fire", check => {
let condition = BUILTIN_REACTION_POOL['friendly_fire'][0];
let battle = new Battle();
let player = new Player();
battle.fleets[0].setPlayer(player);
let ship1a = battle.fleets[0].addShip();
let ship1b = battle.fleets[0].addShip();
let ship2a = battle.fleets[1].addShip();
let ship2b = battle.fleets[1].addShip();
check.equals(condition(ship1a.getPlayer(), battle, ship1a, new ShipDamageDiff(ship1a, 50, 10)), [], "self shoot");
check.equals(condition(ship1a.getPlayer(), battle, ship1a, new ShipDamageDiff(ship1b, 50, 10)), [ship1b, ship1a]);
check.equals(condition(ship1a.getPlayer(), battle, ship1a, new ShipDamageDiff(ship2a, 50, 10)), [], "enemy shoot");
check.equals(condition(ship1a.getPlayer(), battle, ship2a, new ShipDamageDiff(ship2a, 50, 10)), [], "other player event");
check.equals(condition(player, battle, ship1a, new ShipDamageDiff(ship1a, 50, 10)), [], "self shoot");
check.equals(condition(player, battle, ship1a, new ShipDamageDiff(ship1b, 50, 10)), [ship1b, ship1a]);
check.equals(condition(player, battle, ship1a, new ShipDamageDiff(ship2a, 50, 10)), [], "enemy shoot");
check.equals(condition(player, battle, ship2a, new ShipDamageDiff(ship2a, 50, 10)), [], "other player event");
})
})
}

View File

@ -93,9 +93,9 @@ module TK.SpaceTac {
*/
function cond_friendly_fire(player: Player, battle: Battle | null, ship: Ship | null, event: BaseBattleDiff | null): Ship[] {
if (battle && ship && event) {
if (event instanceof ShipDamageDiff && player.is(ship.getPlayer()) && !ship.is(event.ship_id)) {
if (event instanceof ShipDamageDiff && player.is(ship.fleet.player) && !ship.is(event.ship_id)) {
let hurt = battle.getShip(event.ship_id);
return (hurt && hurt.getPlayer().is(player)) ? [hurt, ship] : [];
return (hurt && player.is(hurt.fleet.player)) ? [hurt, ship] : [];
} else {
return [];
}

View File

@ -2,12 +2,14 @@ module TK.SpaceTac {
testing("Player", test => {
test.case("keeps track of visited locations", check => {
let player = new Player();
let star1 = new Star();
let star2 = new Star();
let loc1a = new StarLocation(star1);
let loc1b = new StarLocation(star1);
let loc2a = new StarLocation(star2);
let loc2b = new StarLocation(star2);
let universe = new Universe();
let star1 = universe.addStar();
let star2 = universe.addStar();
let loc1a = star1.addLocation(StarLocationType.PLANET);
let loc1b = star1.addLocation(StarLocationType.PLANET);
let loc2a = star2.addLocation(StarLocationType.PLANET);
let loc2b = star2.addLocation(StarLocationType.PLANET);
universe.updateLocations();
function checkVisited(s1 = false, s2 = false, v1a = false, v1b = false, v2a = false, v2b = false) {
check.same(player.hasVisitedSystem(star1), s1);
@ -20,51 +22,17 @@ module TK.SpaceTac {
checkVisited();
player.setVisited(loc1b);
player.fleet.setLocation(loc1b);
checkVisited(true, false, false, true, false, false);
player.setVisited(loc1a);
player.fleet.setLocation(loc1a);
checkVisited(true, false, true, true, false, false);
player.setVisited(loc2a);
player.fleet.setLocation(loc2a);
checkVisited(true, true, true, true, true, false);
player.setVisited(loc2a);
player.fleet.setLocation(loc2a);
checkVisited(true, true, true, true, true, false);
});
test.case("reverts battle", check => {
let player = new Player();
let star = new Star();
let loc1 = new StarLocation(star);
loc1.clearEncounter();
let loc2 = new StarLocation(star);
loc2.encounter_random = new SkewedRandomGenerator([0], true);
player.fleet.setLocation(loc1);
check.equals(player.getBattle(), null);
check.same(player.fleet.location, loc1);
player.fleet.setLocation(loc2);
check.notequals(player.getBattle(), null);
check.same(player.fleet.location, loc2);
check.equals(player.hasVisitedLocation(loc2), true);
let enemy = loc2.encounter;
player.revertBattle();
check.equals(player.getBattle(), null);
check.same(player.fleet.location, loc1);
check.equals(player.hasVisitedLocation(loc2), true);
player.fleet.setLocation(loc2);
check.notequals(player.getBattle(), null);
check.same(player.fleet.location, loc2);
check.equals(player.hasVisitedLocation(loc2), true);
check.same(nn(player.getBattle()).fleets[1], nn(enemy));
});
});
}

View File

@ -8,57 +8,54 @@ module TK.SpaceTac {
// Player's name
name: string
// Universe in which we are playing
universe: Universe
// Current fleet
// Bound fleet
fleet: Fleet
// List of visited star systems
visited: StarLocation[] = []
// Active missions
missions = new ActiveMissions()
// Create a player, with an empty fleet
constructor(universe: Universe = new Universe(), name = "Player") {
constructor(name = "Player", fleet?: Fleet) {
super();
this.universe = universe;
this.name = name;
this.fleet = new Fleet(this);
this.fleet = fleet || new Fleet(this);
this.fleet.setPlayer(this);
}
// Create a quick random player, with a fleet, for testing purposes
static newQuickRandom(name: string, level = 1, shipcount = 4, upgrade = false): Player {
let player = new Player(new Universe(), name);
let player = new Player(name);
let generator = new FleetGenerator();
player.fleet = generator.generate(level, player, shipcount, upgrade);
return player;
}
/**
* Get a cheats object
*/
getCheats(): BattleCheats | null {
let battle = this.getBattle();
if (battle) {
return new BattleCheats(battle, this);
} else {
return null;
}
}
/**
* Return true if the player has visited at least one location in a given system.
*/
hasVisitedSystem(system: Star): boolean {
return any(this.visited, location => location.star == system);
return intersection(this.fleet.visited, system.locations.map(loc => loc.id)).length > 0;
}
/**
* Return true if the player has visited a given star location.
*/
hasVisitedLocation(location: StarLocation): boolean {
return contains(this.visited, location);
}
/**
* Set a star location as visited.
*
* This should always be called for any location, even if it was already marked visited.
*/
setVisited(location: StarLocation): void {
add(this.visited, location);
this.missions.checkStatus();
return contains(this.fleet.visited, location.id);
}
// Get currently played battle, null when none is in progress
@ -69,25 +66,5 @@ module TK.SpaceTac {
this.fleet.setBattle(battle);
this.missions.checkStatus();
}
/**
* Exit the current battle unconditionally, if any
*
* This does not apply retreat penalties, or battle outcome, only unbind the battle from current session
*/
exitBattle(): void {
this.setBattle(null);
}
/**
* Revert current battle, and put the player's fleet to its previous location, as if the battle never happened
*/
revertBattle(): void {
this.exitBattle();
if (this.fleet.previous_location) {
this.fleet.setLocation(this.fleet.previous_location);
}
}
}
}

View File

@ -120,7 +120,9 @@ module TK.SpaceTac {
this.play_priority = gen.random() * this.attributes.maneuvrability.get();
}
// Return the player owning this ship
/**
* Return the player that plays this ship
*/
getPlayer(): Player {
return this.fleet.player;
}
@ -129,7 +131,7 @@ module TK.SpaceTac {
* Check if a player is playing this ship
*/
isPlayedBy(player: Player): boolean {
return this.getPlayer().is(player);
return player.is(this.fleet.player);
}
// get the current battle this ship is engaged in

View File

@ -1,3 +1,5 @@
/// <reference path="../common/RObject.ts" />
module TK.SpaceTac {
export enum StarLocationType {
STAR,
@ -7,34 +9,41 @@ module TK.SpaceTac {
STATION
}
// Point of interest in a star system
export class StarLocation {
/**
* Point of interest in a star system
*/
export class StarLocation extends RObject {
// Parent star system
star: Star;
star: Star
// Type of location
type: StarLocationType;
type: StarLocationType
// Location in the star system
x: number;
y: number;
x: number
y: number
// Absolute location in the universe
universe_x: number;
universe_y: number;
universe_x: number
universe_y: number
// Destination for jump, if its a WARP location
jump_dest: StarLocation | null;
jump_dest: StarLocation | null
// Fleets present at this location (excluding the encounter for now)
fleets: Fleet[] = []
// Enemy encounter
encounter: Fleet | null = null;
encounter_gen = false;
encounter_random = RandomGenerator.global;
encounter: Fleet | null = null
encounter_gen = false
encounter_random = RandomGenerator.global
// Shop to buy/sell equipment
shop: Shop | null = null;
shop: Shop | null = null
constructor(star = new Star(), type: StarLocationType = StarLocationType.PLANET, x: number = 0, y: number = 0) {
super();
this.star = star;
this.type = type;
this.x = x;
@ -44,6 +53,13 @@ module TK.SpaceTac {
this.jump_dest = null;
}
/**
* Get the universe containing this location
*/
get universe(): Universe {
return this.star.universe;
}
/**
* Add a shop in this location
*/
@ -58,6 +74,22 @@ module TK.SpaceTac {
this.shop = null;
}
/**
* Add a fleet to the list of fleets present in this system
*/
addFleet(fleet: Fleet): void {
if (add(this.fleets, fleet)) {
this.enterLocation(fleet);
}
}
/**
* Remove a fleet from the list of fleets present in this system
*/
removeFleet(fleet: Fleet): void {
remove(this.fleets, fleet);
}
/**
* Check if the location is clear of encounter
*/
@ -134,7 +166,7 @@ module TK.SpaceTac {
variations = [[this.star.level, 4], [this.star.level - 1, 5], [this.star.level + 1, 3], [this.star.level + 3, 2]];
}
let [level, enemies] = this.encounter_random.choice(variations);
this.encounter = fleet_generator.generate(level, new Player(this.star.universe, "Enemy"), enemies, true);
this.encounter = fleet_generator.generate(level, new Player("Enemy"), enemies, true);
}
/**

View File

@ -4,8 +4,8 @@ module TK.SpaceTac {
// Create a battle between two fleets, with a fixed play order (owned ships, then enemy ships)
static createBattle(own_ships = 1, enemy_ships = 1): Battle {
var fleet1 = new Fleet(new Player(undefined, "Attacker"));
var fleet2 = new Fleet(new Player(undefined, "Defender"));
var fleet1 = new Fleet(new Player("Attacker"));
var fleet2 = new Fleet(new Player("Defender"));
while (own_ships--) {
fleet1.addShip();

View File

@ -9,6 +9,9 @@ module TK.SpaceTac {
// List of links between star systems
starlinks: StarLink[] = []
// Collection of all star locations
locations = new RObjectContainer<StarLocation>()
// Radius of the universe
radius = 5
@ -25,6 +28,13 @@ module TK.SpaceTac {
return result;
}
/**
* Update the locations list
*/
updateLocations(): void {
this.locations = new RObjectContainer(flatten(this.stars.map(star => star.locations)));
}
/**
* Generates a random universe, with star systems and locations of interest
*
@ -54,6 +64,7 @@ module TK.SpaceTac {
this.stars.forEach((star: Star) => {
star.generate(this.random);
});
this.updateLocations();
this.addShops();
}
@ -256,5 +267,12 @@ module TK.SpaceTac {
let star = minBy(this.stars, star => star.level);
return star.locations[0];
}
/**
* Get a location from its ID
*/
getLocation(id: RObjectId | null): StarLocation | null {
return id === null ? null : this.locations.get(id);
}
}
}

View File

@ -58,8 +58,7 @@ module TK.SpaceTac {
let battle = ship.getBattle();
if (battle) {
let harmful = any(this.effects, effect => !effect.isBeneficial());
let player = ship.getPlayer();
let ships = imaterialize(harmful ? battle.ienemies(player, true) : ifilter(battle.iallies(player, true), iship => iship != ship));
let ships = imaterialize(harmful ? battle.ienemies(ship, true) : ifilter(battle.iallies(ship, true), iship => !iship.is(ship)));
let nearest = minBy(ships, iship => arenaDistance(ship.location, iship.location));
return Target.newFromShip(nearest);
} else {

View File

@ -66,7 +66,7 @@ module TK.SpaceTac {
* Produce all "direct hit" weapon shots.
*/
static produceDirectShots(ship: Ship, battle: Battle): TacticalProducer {
let enemies = ifilter(battle.iships(), iship => iship.alive && iship.getPlayer() !== ship.getPlayer());
let enemies = battle.ienemies(ship, true);
let weapons = ifilter(getPlayableActions(ship), action => action instanceof TriggerAction);
return imap(icombine(enemies, weapons), ([enemy, weapon]) => new Maneuver(ship, weapon, Target.newFromShip(enemy)));
}
@ -88,7 +88,7 @@ module TK.SpaceTac {
static produceInterestingBlastShots(ship: Ship, battle: Battle): TacticalProducer {
// TODO Work with groups of 3, 4 ...
let weapons = <Iterator<TriggerAction>>ifilter(getPlayableActions(ship), action => action instanceof TriggerAction && action.blast > 0);
let enemies = battle.ienemies(ship.getPlayer(), true);
let enemies = battle.ienemies(ship, true);
// FIXME This produces duplicates (x, y) and (y, x)
let couples = ifilter(icombine(enemies, enemies), ([e1, e2]) => e1 != e2);
let candidates = ifilter(icombine(weapons, couples), ([weapon, [e1, e2]]) => Target.newFromShip(e1).getDistanceTo(Target.newFromShip(e2)) < weapon.blast * 2);
@ -173,7 +173,7 @@ module TK.SpaceTac {
* Evaluate the effect on health to the enemy, between -1 and 1
*/
static evaluateEnemyHealth(ship: Ship, battle: Battle, maneuver: Maneuver): number {
let enemies = imaterialize(battle.ienemies(ship.getPlayer(), true));
let enemies = imaterialize(battle.ienemies(ship, true));
return -TacticalAIHelpers.evaluateHealthEffect(maneuver, enemies);
}
@ -181,7 +181,7 @@ module TK.SpaceTac {
* Evaluate the effect on health to allied ships, between -1 and 1
*/
static evaluateAllyHealth(ship: Ship, battle: Battle, maneuver: Maneuver): number {
let allies = imaterialize(battle.iallies(ship.getPlayer(), true));
let allies = imaterialize(battle.iallies(ship, true));
return TacticalAIHelpers.evaluateHealthEffect(maneuver, allies);
}

View File

@ -60,7 +60,7 @@ module TK.SpaceTac.Specs {
let universe = new Universe();
universe.generate(4);
let fleet = new Fleet();
fleet.setLocation(universe.getStartLocation(), true);
fleet.setLocation(universe.getStartLocation());
let missions = new ActiveMissions();
let hash = missions.getHash();

View File

@ -10,15 +10,17 @@ module TK.SpaceTac.Specs {
});
}
function goTo(fleet: Fleet, location: StarLocation, win_encounter = true) {
fleet.setLocation(location, true);
if (fleet.battle) {
fleet.battle.endBattle(win_encounter ? fleet : fleet.battle.fleets[1]);
function goTo(session: GameSession, location: StarLocation, win_encounter = true) {
session.fleet.setLocation(location);
let battle = session.getBattle();
if (battle) {
battle.endBattle(win_encounter ? session.fleet : battle.fleets[1]);
if (win_encounter) {
fleet.player.exitBattle();
session.exitBattle();
location.clearEncounter();
} else {
fleet.player.revertBattle();
session.revertBattle();
}
}
}
@ -36,7 +38,7 @@ module TK.SpaceTac.Specs {
(<MissionPartConversation>story.current_part).skip();
checkPart(story, 1, /^Find your contact in .*$/);
goTo(fleet, (<MissionPartGoTo>story.current_part).destination);
goTo(session, (<MissionPartGoTo>story.current_part).destination);
checkPart(story, 2, /^Speak with your contact/);
(<MissionPartConversation>story.current_part).skip();
@ -45,7 +47,7 @@ module TK.SpaceTac.Specs {
check.same(fleet.ships.length, fleet_size + 1);
check.same(fleet.ships[fleet_size].critical, true);
check.greater(fleet.ships[fleet_size].getAttribute("hull_capacity"), 0);
goTo(fleet, (<MissionPartEscort>story.current_part).destination);
goTo(session, (<MissionPartEscort>story.current_part).destination);
checkPart(story, 4, /^Listen to .*$/);
(<MissionPartConversation>story.current_part).skip();

View File

@ -14,7 +14,7 @@ module TK.SpaceTac {
super(universe, fleet, true);
let random = RandomGenerator.global;
let start_location = nn(fleet.location);
let start_location = nn(universe.getLocation(fleet.location));
let mission_generator = new MissionGenerator(universe, start_location);
// Arrival
@ -26,7 +26,7 @@ module TK.SpaceTac {
// Get in touch with our contact
let contact_location = randomLocation(random, [start_location.star], [start_location]);
let contact_character = mission_generator.generateShip(1);
contact_character.fleet.setLocation(contact_location, true);
contact_character.fleet.setLocation(contact_location);
this.addPart(new MissionPartGoTo(this, contact_location, `Find your contact in ${contact_location.star.name}`, MissionPartDestinationHint.SYSTEM));
conversation = this.addPart(new MissionPartConversation(this, [contact_character], "Speak with your contact"));
conversation.addPiece(contact_character, "Finally, you came!");

View File

@ -15,7 +15,7 @@ module TK.SpaceTac.Specs {
part.onStarted();
check.equals(destination.isClear(), false);
fleet.setLocation(destination, true);
fleet.setLocation(destination);
check.same(part.checkCompleted(), false, "Encounter not clear");
destination.clearEncounter();
@ -28,7 +28,7 @@ module TK.SpaceTac.Specs {
let universe = new Universe();
let fleet = new Fleet();
fleet.setLocation(destination, true);
fleet.setLocation(destination);
let part = new MissionPartCleanLocation(new Mission(universe, fleet), destination);
check.equals(fleet.battle, null);

View File

@ -18,7 +18,7 @@ module TK.SpaceTac {
onStarted(): void {
this.destination.setupEncounter();
if (this.fleet.location == this.destination) {
if (this.destination.is(this.fleet.location)) {
// Already there, re-enter the location to start the fight
let battle = this.destination.enterLocation(this.fleet);
if (battle) {

View File

@ -16,16 +16,16 @@ module TK.SpaceTac.Specs {
part.onStarted();
check.contains(fleet.ships, ship);
fleet.setLocation(destination, true);
fleet.setLocation(destination);
check.same(part.checkCompleted(), false, "Encounter not clear");
destination.clearEncounter();
check.same(part.checkCompleted(), true, "Encouter cleared");
fleet.setLocation(new StarLocation(), true);
fleet.setLocation(new StarLocation());
check.same(part.checkCompleted(), false, "Went to another system");
fleet.setLocation(destination, true);
fleet.setLocation(destination);
check.same(part.checkCompleted(), true, "Back at destination");
check.contains(fleet.ships, ship);

View File

@ -11,16 +11,16 @@ module TK.SpaceTac.Specs {
check.equals(part.title, "Go to Atanax system");
check.same(part.checkCompleted(), false, "Init location");
fleet.setLocation(destination, true);
fleet.setLocation(destination);
check.same(part.checkCompleted(), false, "Encounter not clear");
destination.clearEncounter();
check.same(part.checkCompleted(), true, "Encouter cleared");
fleet.setLocation(new StarLocation(), true);
fleet.setLocation(new StarLocation());
check.same(part.checkCompleted(), false, "Went to another system");
fleet.setLocation(destination, true);
fleet.setLocation(destination);
check.same(part.checkCompleted(), true, "Back at destination");
})

View File

@ -25,12 +25,12 @@ module TK.SpaceTac {
}
checkCompleted(): boolean {
return this.fleet.location === this.destination && this.destination.isClear();
return this.destination.is(this.fleet.location) && this.destination.isClear();
}
forceComplete(): void {
this.destination.clearEncounter();
this.fleet.setLocation(this.destination, true);
this.fleet.setLocation(this.destination);
}
getLocationHint(): Star | StarLocation | null {

View File

@ -90,7 +90,8 @@ module TK.SpaceTac.UI.Specs {
view.splash = false;
let battle = Battle.newQuickRandom();
let player = battle.playing_ship ? battle.playing_ship.getPlayer() : new Player();
let player = new Player();
nn(battle.playing_ship).fleet.setPlayer(player);
return [view, [player, battle]];
});

View File

@ -13,7 +13,9 @@ module TK.SpaceTac.UI.Specs {
check.equals(bar.action_icons.length, 0);
// Ship with no equipment (only endturn action)
testgame.view.player = ship.getPlayer();
let player = new Player();
ship.fleet.setPlayer(player);
testgame.view.player = player;
bar.setShip(ship);
check.equals(bar.action_icons.length, 1);
check.equals(bar.action_icons[0].action.code, "endturn");

View File

@ -225,7 +225,7 @@ module TK.SpaceTac.UI {
setShip(ship: Ship | null): void {
this.clearAll();
if (ship && ship.getPlayer().is(this.battleview.player) && ship.alive) {
if (ship && this.battleview.player.is(ship.fleet.player) && ship.alive) {
var actions = ship.getAvailableActions();
actions.forEach((action: BaseAction) => {
this.addAction(ship, action);

View File

@ -46,7 +46,7 @@ module TK.SpaceTac.UI {
this.battleview = parent.view;
this.ship = ship;
this.enemy = !this.ship.getPlayer().is(this.battleview.player);
this.enemy = !this.battleview.player.is(this.ship.fleet.player);
// Add effects radius
this.effects_radius = new Phaser.Graphics(this.game);
@ -121,7 +121,7 @@ module TK.SpaceTac.UI {
this.updateEffectsRadius();
// Set location
if (this.battleview.battle.cycle == 1 && this.battleview.battle.play_index == 0 && ship.alive && ship.fleet.player === this.battleview.player) {
if (this.battleview.battle.cycle == 1 && this.battleview.battle.play_index == 0 && ship.alive && this.battleview.player.is(ship.fleet.player)) {
this.position.set(ship.arena_x - 500 * Math.cos(ship.arena_angle), ship.arena_y - 500 * Math.sin(ship.arena_angle));
this.moveTo(ship.arena_x, ship.arena_y, ship.arena_angle);
} else {

View File

@ -20,7 +20,7 @@ module TK.SpaceTac.UI {
this.player1.visible = false;
this.message.addChild(this.player1);
let player1_name = view.game.add.text(-240, 22, fleet1.player.name, { font: `bold 22pt SpaceTac`, fill: "#154d13" });
let player1_name = view.game.add.text(-240, 22, fleet1.name, { font: `bold 22pt SpaceTac`, fill: "#154d13" });
player1_name.anchor.set(0.5);
player1_name.angle = -48;
this.player1.addChild(player1_name);
@ -41,7 +41,7 @@ module TK.SpaceTac.UI {
this.player2.visible = false;
this.message.addChild(this.player2);
let player2_name = view.game.add.text(-240, 22, fleet2.player.name, { font: `bold 22pt SpaceTac`, fill: "#651713" });
let player2_name = view.game.add.text(-240, 22, fleet2.name, { font: `bold 22pt SpaceTac`, fill: "#651713" });
player2_name.anchor.set(0.5);
player2_name.angle = -228;
this.player2.addChild(player2_name);

View File

@ -136,8 +136,8 @@ module TK.SpaceTac.UI {
this.inputs.bind("Escape", "Cancel action", () => this.action_bar.actionEnded());
range(10).forEach(i => this.inputs.bind(`Numpad${i % 10}`, `Action/target ${i}`, () => this.numberPressed(i)));
range(10).forEach(i => this.inputs.bind(`Digit${i % 10}`, `Action/target ${i}`, () => this.numberPressed(i)));
this.inputs.bindCheat("w", "Win current battle", () => this.actual_battle.cheats.win());
this.inputs.bindCheat("x", "Lose current battle", () => this.actual_battle.cheats.lose());
this.inputs.bindCheat("w", "Win current battle", () => nn(this.player.getCheats()).win());
this.inputs.bindCheat("x", "Lose current battle", () => nn(this.player.getCheats()).lose());
this.inputs.bindCheat("a", "Use AI to play", () => this.playAI());
// "Battle" animation, then start processing the log
@ -286,7 +286,7 @@ module TK.SpaceTac.UI {
cursorClicked(): void {
if (this.targetting.active) {
this.validationPressed();
} else if (this.ship_hovered && this.ship_hovered.getPlayer().is(this.player) && this.interacting) {
} else if (this.ship_hovered && this.player.is(this.ship_hovered.fleet.player) && this.interacting) {
this.character_sheet.show(this.ship_hovered, undefined, undefined, false);
this.setShipHovered(null);
}
@ -351,7 +351,7 @@ module TK.SpaceTac.UI {
if (battle.outcome) {
this.setInteractionEnabled(false);
this.gameui.session.setBattleEnded();
this.session.setBattleEnded();
battle.stats.processLog(battle.log, this.player.fleet);
@ -365,7 +365,7 @@ module TK.SpaceTac.UI {
* Exit the battle, and go back to map
*/
exitBattle() {
this.player.exitBattle();
this.session.exitBattle();
this.game.state.start('router');
}
@ -373,7 +373,7 @@ module TK.SpaceTac.UI {
* Revert the battle, and go back to map
*/
revertBattle() {
this.player.revertBattle();
this.session.revertBattle();
this.game.state.start('router');
}
}

View File

@ -35,7 +35,7 @@ module TK.SpaceTac.UI {
refreshContent(): void {
let parent = this.battleview;
let outcome = this.outcome;
let victory = outcome.winner && (outcome.winner.player == this.player);
let victory = outcome.winner && this.player.is(outcome.winner.player);
this.clearContent();

View File

@ -7,13 +7,15 @@ module TK.SpaceTac.UI.Specs {
function createList(): ShipList {
let view = testgame.view;
let battle = new Battle();
let player = new Player();
battle.fleets[0].setPlayer(player);
let tactical_mode = new Toggle();
let ship_buttons = {
cursorOnShip: nop,
cursorOffShip: nop,
cursorClicked: nop,
};
let list = new ShipList(view, battle, battle.fleets[0].player, tactical_mode, ship_buttons);
let list = new ShipList(view, battle, player, tactical_mode, ship_buttons);
return list;
}

View File

@ -5,7 +5,6 @@ module TK.SpaceTac.UI.Specs {
test.case("fills ship details", check => {
let tooltip = new ShipTooltip(testgame.view);
let ship = testgame.view.battle.play_order[2];
ship.fleet.player.name = "Phil";
ship.name = "Fury";
ship.model = new ShipModel("fake", "Fury");
ship.listEquipment().forEach(equ => equ.detach());

View File

@ -30,7 +30,7 @@ module TK.SpaceTac.UI {
portrait.scale.set(0.5);
});
let enemy = !ship.getPlayer().is(this.battleview.player);
let enemy = !this.battleview.player.is(ship.fleet.player);
builder.text(ship.getName(), 168, 0, { color: enemy ? "#cc0d00" : "#ffffff", size: 22, bold: true });
if (ship.alive) {

View File

@ -139,7 +139,7 @@ module TK.SpaceTac.UI {
style.image_caption = ship.getName(false);
style.image_size = 256;
let own = ship.getPlayer() == this.view.gameui.session.player;
let own = this.view.gameui.session.player.is(ship.fleet.player);
this.setCurrentMessage(style, content, 900, 300, own ? 0.1 : 0.9, own ? 0.2 : 0.8);
}

View File

@ -26,8 +26,9 @@ module TK.SpaceTac.UI {
this.updateShipSprites();
if (fleet.location) {
this.position.set(fleet.location.star.x + fleet.location.x, fleet.location.star.y + fleet.location.y);
let location = this.map.universe.getLocation(fleet.location);
if (location) {
this.position.set(location.star.x + location.x, location.star.y + location.y);
}
this.scale.set(SCALING, SCALING);
@ -54,7 +55,7 @@ module TK.SpaceTac.UI {
}
get location(): StarLocation {
return this.fleet.location || new StarLocation();
return this.map.universe.getLocation(this.fleet.location) || new StarLocation();
}
/**
@ -90,9 +91,10 @@ module TK.SpaceTac.UI {
* Make the fleet move to another location in the same system
*/
moveToLocation(location: StarLocation, speed = 1, on_leave: ((duration: number) => any) | null = null, on_finished: Function | null = null) {
if (this.fleet.location && location != this.fleet.location) {
let dx = location.universe_x - this.fleet.location.universe_x;
let dy = location.universe_y - this.fleet.location.universe_y;
let fleet_location = this.map.universe.getLocation(this.fleet.location);
if (fleet_location && this.fleet.move(location)) {
let dx = location.universe_x - fleet_location.universe_x;
let dy = location.universe_y - fleet_location.universe_y;
let distance = Math.sqrt(dx * dx + dy * dy);
let angle = Math.atan2(dx, dy);
this.map.current_location.setFleetMoving(true);
@ -103,7 +105,6 @@ module TK.SpaceTac.UI {
}
let tween = this.game.tweens.create(this.position).to({ x: this.x + dx, y: this.y + dy }, duration, Phaser.Easing.Cubic.Out);
tween.onComplete.addOnce(() => {
this.fleet.setLocation(location);
if (this.fleet.battle) {
this.game.state.start("router");
} else {

View File

@ -13,7 +13,7 @@ module TK.SpaceTac.UI {
this.shop = shop;
this.player = player;
this.location = player.fleet.location || new StarLocation();
this.location = view.session.getLocation();
this.on_change = on_change || (() => null);
this.refresh();

View File

@ -4,7 +4,7 @@ module TK.SpaceTac.UI.Specs {
test.case("displays a badge with the current state for a star location", check => {
let mapview = testgame.view;
let location = nn(mapview.player.fleet.location);
let location = mapview.player_fleet.location;
let ssdisplay = nn(first(mapview.starsystems, ss => ss.starsystem == location.star));
@ -15,7 +15,7 @@ module TK.SpaceTac.UI.Specs {
ssdisplay.updateInfo(2, true);
check.equals(ldisplay[2].name, "map-status-unvisited");
mapview.player.setVisited(ldisplay[0]);
mapview.player.fleet.visited.push(ldisplay[0].id);
ssdisplay.updateInfo(2, true);
check.equals(ldisplay[2].name, "map-status-enemy");

View File

@ -50,7 +50,7 @@ module TK.SpaceTac.UI {
let visited = this.player.hasVisitedLocation(location);
let shop = (visited && !location.encounter && location.shop) ? " (dockyard present)" : "";
if (location == this.player.fleet.location) {
if (location.is(this.player.fleet.location)) {
return `Current fleet location${shop}`;
} else {
let loctype = StarLocationType[location.type].toLowerCase();

View File

@ -210,7 +210,7 @@ module TK.SpaceTac.UI {
this.starsystems.forEach(system => system.updateInfo(this.zoom, system.starsystem == current_star));
this.actions.setFromLocation(this.player.fleet.location, this);
this.actions.setFromLocation(this.session.getLocation(), this);
this.missions.checkUpdate();
this.conversation.updateFromMissions(this.player.missions, () => this.checkMissionsUpdate());
@ -226,7 +226,7 @@ module TK.SpaceTac.UI {
revealAll(): void {
this.universe.stars.forEach(star => {
star.locations.forEach(location => {
this.player.setVisited(location);
this.player.fleet.setVisited(location);
});
});
this.refresh();
@ -276,7 +276,7 @@ module TK.SpaceTac.UI {
* Set the current zoom level (0, 1 or 2)
*/
setZoom(level: number, duration = 500) {
let current_star = this.player.fleet.location ? this.player.fleet.location.star : null;
let current_star = this.session.getLocation().star;
if (!current_star || level <= 0) {
this.setCamera(0, 0, this.universe.radius * 2, duration);
this.setLinksAlpha(1, duration);
@ -300,7 +300,7 @@ module TK.SpaceTac.UI {
* This will only work if current location is a warp
*/
doJump(): void {
let location = this.player.fleet.location;
let location = this.session.getLocation();
if (this.interactive && location && location.type == StarLocationType.WARP && location.jump_dest) {
let dest_location = location.jump_dest;
let dest_star = dest_location.star;
@ -321,7 +321,7 @@ module TK.SpaceTac.UI {
* This will only work if current location has a dockyard
*/
openShop(): void {
let location = this.player.fleet.location;
let location = this.session.getLocation();
if (this.interactive && location && location.shop) {
this.character_sheet.setShop(location.shop);
this.character_sheet.show(this.player.fleet.ships[0]);
@ -334,7 +334,7 @@ module TK.SpaceTac.UI {
* This will only work if current location has a dockyard
*/
openMissions(): void {
let location = this.player.fleet.location;
let location = this.session.getLocation();
if (this.interactive && location && location.shop) {
new MissionsDialog(this, location.shop, this.player, () => this.checkMissionsUpdate());
}
@ -344,7 +344,7 @@ module TK.SpaceTac.UI {
* Move the fleet to another location
*/
moveToLocation(dest: StarLocation): void {
if (this.interactive && dest != this.player.fleet.location) {
if (this.interactive && !dest.is(this.player.fleet.location)) {
this.setInteractionEnabled(false);
this.player_fleet.moveToLocation(dest, 1, null, () => {
this.setInteractionEnabled(true);