Removed references from battle state to universe state, causing large serialized data, slowing down AI work
This commit is contained in:
parent
4e155b8556
commit
fa98a57ee2
1
TODO.md
1
TODO.md
|
@ -102,7 +102,6 @@ Common UI
|
||||||
Technical
|
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 all images in atlases, and split them by stage
|
||||||
* Pack sounds
|
* Pack sounds
|
||||||
* Add toggles for shaders, automatically disable them if too slow, and initially disable them on mobile
|
* Add toggles for shaders, automatically disable them if too slow, and initially disable them on mobile
|
||||||
|
|
|
@ -269,7 +269,7 @@ module TK.SpaceTac {
|
||||||
|
|
||||||
check.equals(battle.canPlay(player), false);
|
check.equals(battle.canPlay(player), false);
|
||||||
|
|
||||||
ship.fleet.player = player;
|
ship.fleet.setPlayer(player);
|
||||||
|
|
||||||
check.equals(battle.canPlay(player), true);
|
check.equals(battle.canPlay(player), true);
|
||||||
});
|
});
|
||||||
|
@ -358,9 +358,19 @@ module TK.SpaceTac {
|
||||||
|
|
||||||
let loaded = serializer.unserialize(data);
|
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;
|
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 => {
|
test.case("can revert the last action", check => {
|
||||||
|
|
|
@ -6,9 +6,6 @@ module TK.SpaceTac {
|
||||||
// Battle outcome, if the battle has ended
|
// Battle outcome, if the battle has ended
|
||||||
outcome: BattleOutcome | null = null
|
outcome: BattleOutcome | null = null
|
||||||
|
|
||||||
// Battle cheats
|
|
||||||
cheats: BattleCheats
|
|
||||||
|
|
||||||
// Statistics
|
// Statistics
|
||||||
stats: BattleStats
|
stats: BattleStats
|
||||||
|
|
||||||
|
@ -43,7 +40,7 @@ module TK.SpaceTac {
|
||||||
// Indicator that an AI is playing
|
// Indicator that an AI is playing
|
||||||
ai_playing = false
|
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.fleets = [fleet1, fleet2];
|
||||||
this.ships = new RObjectContainer(fleet1.ships.concat(fleet2.ships));
|
this.ships = new RObjectContainer(fleet1.ships.concat(fleet2.ships));
|
||||||
this.play_order = [];
|
this.play_order = [];
|
||||||
|
@ -52,7 +49,6 @@ module TK.SpaceTac {
|
||||||
|
|
||||||
this.log = new BattleLog();
|
this.log = new BattleLog();
|
||||||
this.stats = new BattleStats();
|
this.stats = new BattleStats();
|
||||||
this.cheats = new BattleCheats(this, fleet1.player);
|
|
||||||
|
|
||||||
this.fleets.forEach((fleet: Fleet) => {
|
this.fleets.forEach((fleet: Fleet) => {
|
||||||
fleet.setBattle(this);
|
fleet.setBattle(this);
|
||||||
|
@ -123,23 +119,26 @@ module TK.SpaceTac {
|
||||||
/**
|
/**
|
||||||
* Return an iterator over ships allies of (or owned by) a player
|
* Return an iterator over ships allies of (or owned by) a player
|
||||||
*/
|
*/
|
||||||
iallies(player: Player, alive_only = false): Iterator<Ship> {
|
iallies(ship: Ship, alive_only = false): Iterator<Ship> {
|
||||||
return ifilter(this.iships(alive_only), ship => ship.getPlayer() === player);
|
return ifilter(this.iships(alive_only), iship => iship.fleet.player.is(ship.fleet.player));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an iterator over ships enemy of a player
|
* Return an iterator over ships enemy of a player
|
||||||
*/
|
*/
|
||||||
ienemies(player: Player, alive_only = false): Iterator<Ship> {
|
ienemies(ship: Ship, alive_only = false): Iterator<Ship> {
|
||||||
return ifilter(this.iships(alive_only), ship => ship.getPlayer() !== player);
|
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 {
|
canPlay(player: Player): boolean {
|
||||||
if (this.ended) {
|
if (this.ended) {
|
||||||
return false;
|
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);
|
return this.playing_ship.isAbleToPlay(false);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -2,8 +2,10 @@ module TK.SpaceTac.Specs {
|
||||||
testing("BattleCheats", test => {
|
testing("BattleCheats", test => {
|
||||||
test.case("wins a battle", check => {
|
test.case("wins a battle", check => {
|
||||||
let battle = Battle.newQuickRandom();
|
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.equals(battle.ended, true, "ended");
|
||||||
check.same(nn(battle.outcome).winner, battle.fleets[0], "winner");
|
check.same(nn(battle.outcome).winner, battle.fleets[0], "winner");
|
||||||
check.equals(any(battle.fleets[1].ships, ship => ship.alive), false, "all enemies dead");
|
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 => {
|
test.case("loses a battle", check => {
|
||||||
let battle = Battle.newQuickRandom();
|
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.equals(battle.ended, true, "ended");
|
||||||
check.same(nn(battle.outcome).winner, battle.fleets[1], "winner");
|
check.same(nn(battle.outcome).winner, battle.fleets[1], "winner");
|
||||||
check.equals(any(battle.fleets[0].ships, ship => ship.alive), false, "all allies dead");
|
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();
|
let ship = new Ship();
|
||||||
TestTools.setShipPlaying(battle, ship);
|
TestTools.setShipPlaying(battle, ship);
|
||||||
ship.upgradeSkill("skill_materials");
|
ship.upgradeSkill("skill_materials");
|
||||||
|
let cheats = new BattleCheats(battle, battle.fleets[0].player);
|
||||||
|
|
||||||
check.equals(ship.listEquipment(), []);
|
check.equals(ship.listEquipment(), []);
|
||||||
battle.cheats.equip("Iron Hull");
|
|
||||||
|
cheats.equip("Iron Hull");
|
||||||
|
|
||||||
let result = ship.listEquipment();
|
let result = ship.listEquipment();
|
||||||
check.equals(result.length, 1);
|
check.equals(result.length, 1);
|
||||||
check.containing(result[0], { name: "Iron Hull", level: 1 });
|
check.containing(result[0], { name: "Iron Hull", level: 1 });
|
||||||
|
|
|
@ -18,7 +18,7 @@ module TK.SpaceTac {
|
||||||
*/
|
*/
|
||||||
win(): void {
|
win(): void {
|
||||||
iforeach(this.battle.iships(), ship => {
|
iforeach(this.battle.iships(), ship => {
|
||||||
if (ship.fleet.player != this.player) {
|
if (!this.player.is(ship.fleet.player)) {
|
||||||
ship.setDead();
|
ship.setDead();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -30,11 +30,11 @@ module TK.SpaceTac {
|
||||||
*/
|
*/
|
||||||
lose(): void {
|
lose(): void {
|
||||||
iforeach(this.battle.iships(), ship => {
|
iforeach(this.battle.iships(), ship => {
|
||||||
if (ship.fleet.player == this.player) {
|
if (this.player.is(ship.fleet.player)) {
|
||||||
ship.setDead();
|
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)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -27,7 +27,7 @@ module TK.SpaceTac {
|
||||||
this.loot = [];
|
this.loot = [];
|
||||||
|
|
||||||
battle.fleets.forEach(fleet => {
|
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 => {
|
fleet.ships.forEach(ship => {
|
||||||
var luck = random.random();
|
var luck = random.random();
|
||||||
if (luck > 0.9) {
|
if (luck > 0.9) {
|
||||||
|
|
|
@ -49,37 +49,92 @@ module TK.SpaceTac {
|
||||||
|
|
||||||
test.case("changes location, only using jumps to travel between systems", check => {
|
test.case("changes location, only using jumps to travel between systems", check => {
|
||||||
let fleet = new Fleet();
|
let fleet = new Fleet();
|
||||||
let system1 = new Star();
|
let universe = new Universe();
|
||||||
let system2 = new Star();
|
let system1 = universe.addStar();
|
||||||
let jump1 = new StarLocation(system1, StarLocationType.WARP);
|
let system2 = universe.addStar();
|
||||||
let jump2 = new StarLocation(system2, StarLocationType.WARP);
|
let jump1 = system1.addLocation(StarLocationType.WARP);
|
||||||
|
let jump2 = system2.addLocation(StarLocationType.WARP);
|
||||||
jump1.setJumpDestination(jump2);
|
jump1.setJumpDestination(jump2);
|
||||||
jump2.setJumpDestination(jump1);
|
jump2.setJumpDestination(jump1);
|
||||||
let other1 = new StarLocation(system1, StarLocationType.PLANET);
|
let other1 = system1.addLocation(StarLocationType.PLANET);
|
||||||
|
universe.updateLocations();
|
||||||
|
|
||||||
let result = fleet.setLocation(other1);
|
let result = fleet.move(other1);
|
||||||
check.equals(result, true);
|
check.in("cannot move from nowhere", check => {
|
||||||
check.same(fleet.location, other1);
|
check.equals(result, false);
|
||||||
|
check.equals(fleet.location, null);
|
||||||
|
});
|
||||||
|
|
||||||
result = fleet.setLocation(jump2);
|
fleet.setLocation(other1);
|
||||||
check.equals(result, false);
|
check.in("force set to other1", check => {
|
||||||
check.same(fleet.location, other1);
|
check.equals(fleet.location, other1.id);
|
||||||
|
});
|
||||||
|
|
||||||
result = fleet.setLocation(jump1);
|
result = fleet.move(jump2);
|
||||||
check.equals(result, true);
|
check.in("other1=>jump2", check => {
|
||||||
check.same(fleet.location, jump1);
|
check.equals(result, false);
|
||||||
|
check.equals(fleet.location, other1.id);
|
||||||
|
});
|
||||||
|
|
||||||
result = fleet.setLocation(jump2);
|
result = fleet.move(jump1);
|
||||||
check.equals(result, true);
|
check.in("other1=>jump1", check => {
|
||||||
check.same(fleet.location, jump2);
|
check.equals(result, true);
|
||||||
|
check.equals(fleet.location, jump1.id);
|
||||||
|
});
|
||||||
|
|
||||||
result = fleet.setLocation(other1);
|
result = fleet.move(jump2);
|
||||||
check.equals(result, false);
|
check.in("jump1=>jump2", check => {
|
||||||
check.same(fleet.location, jump2);
|
check.equals(result, true);
|
||||||
|
check.equals(fleet.location, jump2.id);
|
||||||
|
});
|
||||||
|
|
||||||
result = fleet.setLocation(jump1);
|
result = fleet.move(other1);
|
||||||
check.equals(result, true);
|
check.in("jump2=>other1", check => {
|
||||||
check.same(fleet.location, jump1);
|
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 => {
|
test.case("checks if a fleet is alive", check => {
|
||||||
|
|
|
@ -4,58 +4,98 @@ module TK.SpaceTac {
|
||||||
*/
|
*/
|
||||||
export class Fleet {
|
export class Fleet {
|
||||||
// Fleet owner
|
// Fleet owner
|
||||||
player: Player;
|
player: Player
|
||||||
|
|
||||||
|
// Fleet name
|
||||||
|
name: string
|
||||||
|
|
||||||
// List of ships
|
// List of ships
|
||||||
ships: Ship[];
|
ships: Ship[]
|
||||||
|
|
||||||
// Current fleet location
|
// Current fleet location
|
||||||
location: StarLocation | null = null;
|
location: RObjectId | null = null
|
||||||
previous_location: StarLocation | null = null;
|
|
||||||
|
// Visited locations (ordered by last visited)
|
||||||
|
visited: RObjectId[] = []
|
||||||
|
|
||||||
// Current battle in which the fleet is engaged (null if not fighting)
|
// Current battle in which the fleet is engaged (null if not fighting)
|
||||||
battle: Battle | null = null;
|
battle: Battle | null = null
|
||||||
|
|
||||||
// Amount of credits available
|
// Amount of credits available
|
||||||
credits = 0;
|
credits = 0
|
||||||
|
|
||||||
// Create a fleet, bound to a player
|
// Create a fleet, bound to a player
|
||||||
constructor(player = new Player()) {
|
constructor(player = new Player()) {
|
||||||
this.player = player;
|
this.player = player;
|
||||||
|
this.name = player ? player.name : "Fleet";
|
||||||
this.ships = [];
|
this.ships = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
jasmineToString(): string {
|
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
|
* Returns true on success
|
||||||
*/
|
*/
|
||||||
setLocation(location: StarLocation, force = false): boolean {
|
move(to: StarLocation): boolean {
|
||||||
if (!force && this.location && location.star != this.location.star && (this.location.type != StarLocationType.WARP || this.location.jump_dest != location)) {
|
if (!this.location) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.previous_location = this.location;
|
let source = to.universe.locations.get(this.location);
|
||||||
this.location = location;
|
if (!source) {
|
||||||
this.player.setVisited(this.location);
|
return false;
|
||||||
|
|
||||||
// Check encounter
|
|
||||||
var battle = this.location.enterLocation(this.player.fleet);
|
|
||||||
if (battle) {
|
|
||||||
this.player.setBattle(battle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
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
|
* 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) {
|
if (ship.fleet && ship.fleet != this) {
|
||||||
remove(ship.fleet.ships, ship);
|
remove(ship.fleet.ships, ship);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,8 +40,11 @@ module TK.SpaceTac.Specs {
|
||||||
let session = new GameSession();
|
let session = new GameSession();
|
||||||
check.equals(session.getBattle(), null);
|
check.equals(session.getBattle(), null);
|
||||||
|
|
||||||
// Victory case
|
|
||||||
let location1 = new StarLocation();
|
let location1 = new StarLocation();
|
||||||
|
let location2 = new StarLocation(location1.star);
|
||||||
|
session.universe.locations = new RObjectContainer([location1, location2]);
|
||||||
|
|
||||||
|
// Victory case
|
||||||
location1.encounter = new Fleet();
|
location1.encounter = new Fleet();
|
||||||
session.player.fleet.setLocation(location1);
|
session.player.fleet.setLocation(location1);
|
||||||
check.notequals(session.getBattle(), null);
|
check.notequals(session.getBattle(), null);
|
||||||
|
@ -56,7 +59,6 @@ module TK.SpaceTac.Specs {
|
||||||
check.called(spyloot, 1);
|
check.called(spyloot, 1);
|
||||||
|
|
||||||
// Defeat case
|
// Defeat case
|
||||||
let location2 = new StarLocation(location1.star);
|
|
||||||
location2.encounter = new Fleet();
|
location2.encounter = new Fleet();
|
||||||
session.player.fleet.setLocation(location2);
|
session.player.fleet.setLocation(location2);
|
||||||
check.notequals(session.getBattle(), null);
|
check.notequals(session.getBattle(), null);
|
||||||
|
@ -78,7 +80,7 @@ module TK.SpaceTac.Specs {
|
||||||
check.notequals(session.player, null);
|
check.notequals(session.player, null);
|
||||||
check.equals(session.player.fleet.ships.length, 0);
|
check.equals(session.player.fleet.ships.length, 0);
|
||||||
check.equals(session.player.fleet.credits, 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.getBattle(), null);
|
||||||
check.equals(session.start_location.shop, null);
|
check.equals(session.start_location.shop, null);
|
||||||
check.equals(session.start_location.encounter, null);
|
check.equals(session.start_location.encounter, null);
|
||||||
|
@ -87,7 +89,47 @@ module TK.SpaceTac.Specs {
|
||||||
session.setCampaignFleet();
|
session.setCampaignFleet();
|
||||||
check.equals(session.player.fleet.ships.length, 2);
|
check.equals(session.player.fleet.ships.length, 2);
|
||||||
check.equals(session.player.fleet.credits, 0);
|
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 => {
|
/*test.case("can generate lots of new games", check => {
|
||||||
|
|
|
@ -32,11 +32,18 @@ module TK.SpaceTac {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.id = RandomGenerator.global.id(20);
|
this.id = RandomGenerator.global.id(20);
|
||||||
this.universe = new Universe();
|
this.universe = new Universe();
|
||||||
this.player = new Player(this.universe);
|
this.player = new Player();
|
||||||
this.reactions = new PersonalityReactions();
|
this.reactions = new PersonalityReactions();
|
||||||
this.start_location = new StarLocation();
|
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)
|
* 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.clearEncounter();
|
||||||
this.start_location.removeShop();
|
this.start_location.removeShop();
|
||||||
|
|
||||||
this.player = new Player(this.universe);
|
this.player = new Player();
|
||||||
|
|
||||||
this.reactions = new PersonalityReactions();
|
this.reactions = new PersonalityReactions();
|
||||||
|
|
||||||
|
@ -88,34 +95,52 @@ module TK.SpaceTac {
|
||||||
setCampaignFleet(fleet: Fleet | null = null, story = true) {
|
setCampaignFleet(fleet: Fleet | null = null, story = true) {
|
||||||
if (fleet) {
|
if (fleet) {
|
||||||
this.player.fleet = fleet;
|
this.player.fleet = fleet;
|
||||||
fleet.player = this.player;
|
fleet.setPlayer(this.player);
|
||||||
} else {
|
} else {
|
||||||
let fleet_generator = new FleetGenerator();
|
let fleet_generator = new FleetGenerator();
|
||||||
this.player.fleet = fleet_generator.generate(1, this.player, 2);
|
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) {
|
if (story) {
|
||||||
this.player.missions.startMainStory(this.universe, this.player.fleet);
|
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 {
|
startQuickBattle(with_ai: boolean = false): void {
|
||||||
|
this.universe = new Universe();
|
||||||
|
|
||||||
let battle = Battle.newQuickRandom(true, RandomGenerator.global.randInt(1, 10));
|
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.player.setBattle(battle);
|
||||||
|
|
||||||
this.reactions = new PersonalityReactions();
|
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 {
|
getBattle(): Battle | null {
|
||||||
return this.player.getBattle();
|
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() {
|
setBattleEnded() {
|
||||||
let battle = this.getBattle();
|
let battle = this.getBattle();
|
||||||
|
@ -133,13 +158,34 @@ module TK.SpaceTac {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the battle happened in a star location, keep it informed
|
// 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) {
|
if (location) {
|
||||||
location.resolveEncounter(battle.outcome);
|
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)
|
* Returns true if the session has an universe to explore (campaign mode)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -51,15 +51,17 @@ module TK.SpaceTac.Specs {
|
||||||
test.case("checks for friendly fire", check => {
|
test.case("checks for friendly fire", check => {
|
||||||
let condition = BUILTIN_REACTION_POOL['friendly_fire'][0];
|
let condition = BUILTIN_REACTION_POOL['friendly_fire'][0];
|
||||||
let battle = new Battle();
|
let battle = new Battle();
|
||||||
|
let player = new Player();
|
||||||
|
battle.fleets[0].setPlayer(player);
|
||||||
let ship1a = battle.fleets[0].addShip();
|
let ship1a = battle.fleets[0].addShip();
|
||||||
let ship1b = battle.fleets[0].addShip();
|
let ship1b = battle.fleets[0].addShip();
|
||||||
let ship2a = battle.fleets[1].addShip();
|
let ship2a = battle.fleets[1].addShip();
|
||||||
let ship2b = 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(player, 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(player, 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(player, 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, ship2a, new ShipDamageDiff(ship2a, 50, 10)), [], "other player event");
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,9 +93,9 @@ module TK.SpaceTac {
|
||||||
*/
|
*/
|
||||||
function cond_friendly_fire(player: Player, battle: Battle | null, ship: Ship | null, event: BaseBattleDiff | null): Ship[] {
|
function cond_friendly_fire(player: Player, battle: Battle | null, ship: Ship | null, event: BaseBattleDiff | null): Ship[] {
|
||||||
if (battle && ship && event) {
|
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);
|
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 {
|
} else {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,14 @@ module TK.SpaceTac {
|
||||||
testing("Player", test => {
|
testing("Player", test => {
|
||||||
test.case("keeps track of visited locations", check => {
|
test.case("keeps track of visited locations", check => {
|
||||||
let player = new Player();
|
let player = new Player();
|
||||||
let star1 = new Star();
|
let universe = new Universe();
|
||||||
let star2 = new Star();
|
let star1 = universe.addStar();
|
||||||
let loc1a = new StarLocation(star1);
|
let star2 = universe.addStar();
|
||||||
let loc1b = new StarLocation(star1);
|
let loc1a = star1.addLocation(StarLocationType.PLANET);
|
||||||
let loc2a = new StarLocation(star2);
|
let loc1b = star1.addLocation(StarLocationType.PLANET);
|
||||||
let loc2b = new StarLocation(star2);
|
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) {
|
function checkVisited(s1 = false, s2 = false, v1a = false, v1b = false, v2a = false, v2b = false) {
|
||||||
check.same(player.hasVisitedSystem(star1), s1);
|
check.same(player.hasVisitedSystem(star1), s1);
|
||||||
|
@ -20,51 +22,17 @@ module TK.SpaceTac {
|
||||||
|
|
||||||
checkVisited();
|
checkVisited();
|
||||||
|
|
||||||
player.setVisited(loc1b);
|
player.fleet.setLocation(loc1b);
|
||||||
|
|
||||||
checkVisited(true, false, false, true, false, false);
|
checkVisited(true, false, false, true, false, false);
|
||||||
|
|
||||||
player.setVisited(loc1a);
|
player.fleet.setLocation(loc1a);
|
||||||
|
|
||||||
checkVisited(true, false, true, true, false, false);
|
checkVisited(true, false, true, true, false, false);
|
||||||
|
|
||||||
player.setVisited(loc2a);
|
player.fleet.setLocation(loc2a);
|
||||||
|
|
||||||
checkVisited(true, true, true, true, true, false);
|
checkVisited(true, true, true, true, true, false);
|
||||||
|
|
||||||
player.setVisited(loc2a);
|
player.fleet.setLocation(loc2a);
|
||||||
|
|
||||||
checkVisited(true, true, true, true, true, false);
|
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));
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -8,57 +8,54 @@ module TK.SpaceTac {
|
||||||
// Player's name
|
// Player's name
|
||||||
name: string
|
name: string
|
||||||
|
|
||||||
// Universe in which we are playing
|
// Bound fleet
|
||||||
universe: Universe
|
|
||||||
|
|
||||||
// Current fleet
|
|
||||||
fleet: Fleet
|
fleet: Fleet
|
||||||
|
|
||||||
// List of visited star systems
|
|
||||||
visited: StarLocation[] = []
|
|
||||||
|
|
||||||
// Active missions
|
// Active missions
|
||||||
missions = new ActiveMissions()
|
missions = new ActiveMissions()
|
||||||
|
|
||||||
// Create a player, with an empty fleet
|
// Create a player, with an empty fleet
|
||||||
constructor(universe: Universe = new Universe(), name = "Player") {
|
constructor(name = "Player", fleet?: Fleet) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.universe = universe;
|
|
||||||
this.name = name;
|
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
|
// Create a quick random player, with a fleet, for testing purposes
|
||||||
static newQuickRandom(name: string, level = 1, shipcount = 4, upgrade = false): Player {
|
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();
|
let generator = new FleetGenerator();
|
||||||
player.fleet = generator.generate(level, player, shipcount, upgrade);
|
player.fleet = generator.generate(level, player, shipcount, upgrade);
|
||||||
return player;
|
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.
|
* Return true if the player has visited at least one location in a given system.
|
||||||
*/
|
*/
|
||||||
hasVisitedSystem(system: Star): boolean {
|
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.
|
* Return true if the player has visited a given star location.
|
||||||
*/
|
*/
|
||||||
hasVisitedLocation(location: StarLocation): boolean {
|
hasVisitedLocation(location: StarLocation): boolean {
|
||||||
return contains(this.visited, location);
|
return contains(this.fleet.visited, location.id);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get currently played battle, null when none is in progress
|
// Get currently played battle, null when none is in progress
|
||||||
|
@ -69,25 +66,5 @@ module TK.SpaceTac {
|
||||||
this.fleet.setBattle(battle);
|
this.fleet.setBattle(battle);
|
||||||
this.missions.checkStatus();
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,9 @@ module TK.SpaceTac {
|
||||||
this.play_priority = gen.random() * this.attributes.maneuvrability.get();
|
this.play_priority = gen.random() * this.attributes.maneuvrability.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the player owning this ship
|
/**
|
||||||
|
* Return the player that plays this ship
|
||||||
|
*/
|
||||||
getPlayer(): Player {
|
getPlayer(): Player {
|
||||||
return this.fleet.player;
|
return this.fleet.player;
|
||||||
}
|
}
|
||||||
|
@ -129,7 +131,7 @@ module TK.SpaceTac {
|
||||||
* Check if a player is playing this ship
|
* Check if a player is playing this ship
|
||||||
*/
|
*/
|
||||||
isPlayedBy(player: Player): boolean {
|
isPlayedBy(player: Player): boolean {
|
||||||
return this.getPlayer().is(player);
|
return player.is(this.fleet.player);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the current battle this ship is engaged in
|
// get the current battle this ship is engaged in
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/// <reference path="../common/RObject.ts" />
|
||||||
|
|
||||||
module TK.SpaceTac {
|
module TK.SpaceTac {
|
||||||
export enum StarLocationType {
|
export enum StarLocationType {
|
||||||
STAR,
|
STAR,
|
||||||
|
@ -7,34 +9,41 @@ module TK.SpaceTac {
|
||||||
STATION
|
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
|
// Parent star system
|
||||||
star: Star;
|
star: Star
|
||||||
|
|
||||||
// Type of location
|
// Type of location
|
||||||
type: StarLocationType;
|
type: StarLocationType
|
||||||
|
|
||||||
// Location in the star system
|
// Location in the star system
|
||||||
x: number;
|
x: number
|
||||||
y: number;
|
y: number
|
||||||
|
|
||||||
// Absolute location in the universe
|
// Absolute location in the universe
|
||||||
universe_x: number;
|
universe_x: number
|
||||||
universe_y: number;
|
universe_y: number
|
||||||
|
|
||||||
// Destination for jump, if its a WARP location
|
// 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
|
// Enemy encounter
|
||||||
encounter: Fleet | null = null;
|
encounter: Fleet | null = null
|
||||||
encounter_gen = false;
|
encounter_gen = false
|
||||||
encounter_random = RandomGenerator.global;
|
encounter_random = RandomGenerator.global
|
||||||
|
|
||||||
// Shop to buy/sell equipment
|
// 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) {
|
constructor(star = new Star(), type: StarLocationType = StarLocationType.PLANET, x: number = 0, y: number = 0) {
|
||||||
|
super();
|
||||||
|
|
||||||
this.star = star;
|
this.star = star;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.x = x;
|
this.x = x;
|
||||||
|
@ -44,6 +53,13 @@ module TK.SpaceTac {
|
||||||
this.jump_dest = null;
|
this.jump_dest = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the universe containing this location
|
||||||
|
*/
|
||||||
|
get universe(): Universe {
|
||||||
|
return this.star.universe;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a shop in this location
|
* Add a shop in this location
|
||||||
*/
|
*/
|
||||||
|
@ -58,6 +74,22 @@ module TK.SpaceTac {
|
||||||
this.shop = null;
|
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
|
* 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]];
|
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);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,8 +4,8 @@ module TK.SpaceTac {
|
||||||
|
|
||||||
// Create a battle between two fleets, with a fixed play order (owned ships, then enemy ships)
|
// 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 {
|
static createBattle(own_ships = 1, enemy_ships = 1): Battle {
|
||||||
var fleet1 = new Fleet(new Player(undefined, "Attacker"));
|
var fleet1 = new Fleet(new Player("Attacker"));
|
||||||
var fleet2 = new Fleet(new Player(undefined, "Defender"));
|
var fleet2 = new Fleet(new Player("Defender"));
|
||||||
|
|
||||||
while (own_ships--) {
|
while (own_ships--) {
|
||||||
fleet1.addShip();
|
fleet1.addShip();
|
||||||
|
|
|
@ -9,6 +9,9 @@ module TK.SpaceTac {
|
||||||
// List of links between star systems
|
// List of links between star systems
|
||||||
starlinks: StarLink[] = []
|
starlinks: StarLink[] = []
|
||||||
|
|
||||||
|
// Collection of all star locations
|
||||||
|
locations = new RObjectContainer<StarLocation>()
|
||||||
|
|
||||||
// Radius of the universe
|
// Radius of the universe
|
||||||
radius = 5
|
radius = 5
|
||||||
|
|
||||||
|
@ -25,6 +28,13 @@ module TK.SpaceTac {
|
||||||
return result;
|
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
|
* Generates a random universe, with star systems and locations of interest
|
||||||
*
|
*
|
||||||
|
@ -54,6 +64,7 @@ module TK.SpaceTac {
|
||||||
this.stars.forEach((star: Star) => {
|
this.stars.forEach((star: Star) => {
|
||||||
star.generate(this.random);
|
star.generate(this.random);
|
||||||
});
|
});
|
||||||
|
this.updateLocations();
|
||||||
this.addShops();
|
this.addShops();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,5 +267,12 @@ module TK.SpaceTac {
|
||||||
let star = minBy(this.stars, star => star.level);
|
let star = minBy(this.stars, star => star.level);
|
||||||
return star.locations[0];
|
return star.locations[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a location from its ID
|
||||||
|
*/
|
||||||
|
getLocation(id: RObjectId | null): StarLocation | null {
|
||||||
|
return id === null ? null : this.locations.get(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,8 +58,7 @@ module TK.SpaceTac {
|
||||||
let battle = ship.getBattle();
|
let battle = ship.getBattle();
|
||||||
if (battle) {
|
if (battle) {
|
||||||
let harmful = any(this.effects, effect => !effect.isBeneficial());
|
let harmful = any(this.effects, effect => !effect.isBeneficial());
|
||||||
let player = ship.getPlayer();
|
let ships = imaterialize(harmful ? battle.ienemies(ship, true) : ifilter(battle.iallies(ship, true), iship => !iship.is(ship)));
|
||||||
let ships = imaterialize(harmful ? battle.ienemies(player, true) : ifilter(battle.iallies(player, true), iship => iship != ship));
|
|
||||||
let nearest = minBy(ships, iship => arenaDistance(ship.location, iship.location));
|
let nearest = minBy(ships, iship => arenaDistance(ship.location, iship.location));
|
||||||
return Target.newFromShip(nearest);
|
return Target.newFromShip(nearest);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -66,7 +66,7 @@ module TK.SpaceTac {
|
||||||
* Produce all "direct hit" weapon shots.
|
* Produce all "direct hit" weapon shots.
|
||||||
*/
|
*/
|
||||||
static produceDirectShots(ship: Ship, battle: Battle): TacticalProducer {
|
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);
|
let weapons = ifilter(getPlayableActions(ship), action => action instanceof TriggerAction);
|
||||||
return imap(icombine(enemies, weapons), ([enemy, weapon]) => new Maneuver(ship, weapon, Target.newFromShip(enemy)));
|
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 {
|
static produceInterestingBlastShots(ship: Ship, battle: Battle): TacticalProducer {
|
||||||
// TODO Work with groups of 3, 4 ...
|
// TODO Work with groups of 3, 4 ...
|
||||||
let weapons = <Iterator<TriggerAction>>ifilter(getPlayableActions(ship), action => action instanceof TriggerAction && action.blast > 0);
|
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)
|
// FIXME This produces duplicates (x, y) and (y, x)
|
||||||
let couples = ifilter(icombine(enemies, enemies), ([e1, e2]) => e1 != e2);
|
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);
|
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
|
* Evaluate the effect on health to the enemy, between -1 and 1
|
||||||
*/
|
*/
|
||||||
static evaluateEnemyHealth(ship: Ship, battle: Battle, maneuver: Maneuver): number {
|
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);
|
return -TacticalAIHelpers.evaluateHealthEffect(maneuver, enemies);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +181,7 @@ module TK.SpaceTac {
|
||||||
* Evaluate the effect on health to allied ships, between -1 and 1
|
* Evaluate the effect on health to allied ships, between -1 and 1
|
||||||
*/
|
*/
|
||||||
static evaluateAllyHealth(ship: Ship, battle: Battle, maneuver: Maneuver): number {
|
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);
|
return TacticalAIHelpers.evaluateHealthEffect(maneuver, allies);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ module TK.SpaceTac.Specs {
|
||||||
let universe = new Universe();
|
let universe = new Universe();
|
||||||
universe.generate(4);
|
universe.generate(4);
|
||||||
let fleet = new Fleet();
|
let fleet = new Fleet();
|
||||||
fleet.setLocation(universe.getStartLocation(), true);
|
fleet.setLocation(universe.getStartLocation());
|
||||||
|
|
||||||
let missions = new ActiveMissions();
|
let missions = new ActiveMissions();
|
||||||
let hash = missions.getHash();
|
let hash = missions.getHash();
|
||||||
|
|
|
@ -10,15 +10,17 @@ module TK.SpaceTac.Specs {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function goTo(fleet: Fleet, location: StarLocation, win_encounter = true) {
|
function goTo(session: GameSession, location: StarLocation, win_encounter = true) {
|
||||||
fleet.setLocation(location, true);
|
session.fleet.setLocation(location);
|
||||||
if (fleet.battle) {
|
|
||||||
fleet.battle.endBattle(win_encounter ? fleet : fleet.battle.fleets[1]);
|
let battle = session.getBattle();
|
||||||
|
if (battle) {
|
||||||
|
battle.endBattle(win_encounter ? session.fleet : battle.fleets[1]);
|
||||||
if (win_encounter) {
|
if (win_encounter) {
|
||||||
fleet.player.exitBattle();
|
session.exitBattle();
|
||||||
location.clearEncounter();
|
location.clearEncounter();
|
||||||
} else {
|
} else {
|
||||||
fleet.player.revertBattle();
|
session.revertBattle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +38,7 @@ module TK.SpaceTac.Specs {
|
||||||
(<MissionPartConversation>story.current_part).skip();
|
(<MissionPartConversation>story.current_part).skip();
|
||||||
|
|
||||||
checkPart(story, 1, /^Find your contact in .*$/);
|
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/);
|
checkPart(story, 2, /^Speak with your contact/);
|
||||||
(<MissionPartConversation>story.current_part).skip();
|
(<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.length, fleet_size + 1);
|
||||||
check.same(fleet.ships[fleet_size].critical, true);
|
check.same(fleet.ships[fleet_size].critical, true);
|
||||||
check.greater(fleet.ships[fleet_size].getAttribute("hull_capacity"), 0);
|
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 .*$/);
|
checkPart(story, 4, /^Listen to .*$/);
|
||||||
(<MissionPartConversation>story.current_part).skip();
|
(<MissionPartConversation>story.current_part).skip();
|
||||||
|
|
|
@ -14,7 +14,7 @@ module TK.SpaceTac {
|
||||||
super(universe, fleet, true);
|
super(universe, fleet, true);
|
||||||
|
|
||||||
let random = RandomGenerator.global;
|
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);
|
let mission_generator = new MissionGenerator(universe, start_location);
|
||||||
|
|
||||||
// Arrival
|
// Arrival
|
||||||
|
@ -26,7 +26,7 @@ module TK.SpaceTac {
|
||||||
// Get in touch with our contact
|
// Get in touch with our contact
|
||||||
let contact_location = randomLocation(random, [start_location.star], [start_location]);
|
let contact_location = randomLocation(random, [start_location.star], [start_location]);
|
||||||
let contact_character = mission_generator.generateShip(1);
|
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));
|
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 = this.addPart(new MissionPartConversation(this, [contact_character], "Speak with your contact"));
|
||||||
conversation.addPiece(contact_character, "Finally, you came!");
|
conversation.addPiece(contact_character, "Finally, you came!");
|
||||||
|
|
|
@ -15,7 +15,7 @@ module TK.SpaceTac.Specs {
|
||||||
part.onStarted();
|
part.onStarted();
|
||||||
check.equals(destination.isClear(), false);
|
check.equals(destination.isClear(), false);
|
||||||
|
|
||||||
fleet.setLocation(destination, true);
|
fleet.setLocation(destination);
|
||||||
check.same(part.checkCompleted(), false, "Encounter not clear");
|
check.same(part.checkCompleted(), false, "Encounter not clear");
|
||||||
|
|
||||||
destination.clearEncounter();
|
destination.clearEncounter();
|
||||||
|
@ -28,7 +28,7 @@ module TK.SpaceTac.Specs {
|
||||||
|
|
||||||
let universe = new Universe();
|
let universe = new Universe();
|
||||||
let fleet = new Fleet();
|
let fleet = new Fleet();
|
||||||
fleet.setLocation(destination, true);
|
fleet.setLocation(destination);
|
||||||
let part = new MissionPartCleanLocation(new Mission(universe, fleet), destination);
|
let part = new MissionPartCleanLocation(new Mission(universe, fleet), destination);
|
||||||
|
|
||||||
check.equals(fleet.battle, null);
|
check.equals(fleet.battle, null);
|
||||||
|
|
|
@ -18,7 +18,7 @@ module TK.SpaceTac {
|
||||||
onStarted(): void {
|
onStarted(): void {
|
||||||
this.destination.setupEncounter();
|
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
|
// Already there, re-enter the location to start the fight
|
||||||
let battle = this.destination.enterLocation(this.fleet);
|
let battle = this.destination.enterLocation(this.fleet);
|
||||||
if (battle) {
|
if (battle) {
|
||||||
|
|
|
@ -16,16 +16,16 @@ module TK.SpaceTac.Specs {
|
||||||
part.onStarted();
|
part.onStarted();
|
||||||
check.contains(fleet.ships, ship);
|
check.contains(fleet.ships, ship);
|
||||||
|
|
||||||
fleet.setLocation(destination, true);
|
fleet.setLocation(destination);
|
||||||
check.same(part.checkCompleted(), false, "Encounter not clear");
|
check.same(part.checkCompleted(), false, "Encounter not clear");
|
||||||
|
|
||||||
destination.clearEncounter();
|
destination.clearEncounter();
|
||||||
check.same(part.checkCompleted(), true, "Encouter cleared");
|
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");
|
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.same(part.checkCompleted(), true, "Back at destination");
|
||||||
check.contains(fleet.ships, ship);
|
check.contains(fleet.ships, ship);
|
||||||
|
|
||||||
|
|
|
@ -11,16 +11,16 @@ module TK.SpaceTac.Specs {
|
||||||
check.equals(part.title, "Go to Atanax system");
|
check.equals(part.title, "Go to Atanax system");
|
||||||
check.same(part.checkCompleted(), false, "Init location");
|
check.same(part.checkCompleted(), false, "Init location");
|
||||||
|
|
||||||
fleet.setLocation(destination, true);
|
fleet.setLocation(destination);
|
||||||
check.same(part.checkCompleted(), false, "Encounter not clear");
|
check.same(part.checkCompleted(), false, "Encounter not clear");
|
||||||
|
|
||||||
destination.clearEncounter();
|
destination.clearEncounter();
|
||||||
check.same(part.checkCompleted(), true, "Encouter cleared");
|
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");
|
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.same(part.checkCompleted(), true, "Back at destination");
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -25,12 +25,12 @@ module TK.SpaceTac {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkCompleted(): boolean {
|
checkCompleted(): boolean {
|
||||||
return this.fleet.location === this.destination && this.destination.isClear();
|
return this.destination.is(this.fleet.location) && this.destination.isClear();
|
||||||
}
|
}
|
||||||
|
|
||||||
forceComplete(): void {
|
forceComplete(): void {
|
||||||
this.destination.clearEncounter();
|
this.destination.clearEncounter();
|
||||||
this.fleet.setLocation(this.destination, true);
|
this.fleet.setLocation(this.destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
getLocationHint(): Star | StarLocation | null {
|
getLocationHint(): Star | StarLocation | null {
|
||||||
|
|
|
@ -90,7 +90,8 @@ module TK.SpaceTac.UI.Specs {
|
||||||
view.splash = false;
|
view.splash = false;
|
||||||
|
|
||||||
let battle = Battle.newQuickRandom();
|
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]];
|
return [view, [player, battle]];
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,7 +13,9 @@ module TK.SpaceTac.UI.Specs {
|
||||||
check.equals(bar.action_icons.length, 0);
|
check.equals(bar.action_icons.length, 0);
|
||||||
|
|
||||||
// Ship with no equipment (only endturn action)
|
// 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);
|
bar.setShip(ship);
|
||||||
check.equals(bar.action_icons.length, 1);
|
check.equals(bar.action_icons.length, 1);
|
||||||
check.equals(bar.action_icons[0].action.code, "endturn");
|
check.equals(bar.action_icons[0].action.code, "endturn");
|
||||||
|
|
|
@ -225,7 +225,7 @@ module TK.SpaceTac.UI {
|
||||||
setShip(ship: Ship | null): void {
|
setShip(ship: Ship | null): void {
|
||||||
this.clearAll();
|
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();
|
var actions = ship.getAvailableActions();
|
||||||
actions.forEach((action: BaseAction) => {
|
actions.forEach((action: BaseAction) => {
|
||||||
this.addAction(ship, action);
|
this.addAction(ship, action);
|
||||||
|
|
|
@ -46,7 +46,7 @@ module TK.SpaceTac.UI {
|
||||||
this.battleview = parent.view;
|
this.battleview = parent.view;
|
||||||
|
|
||||||
this.ship = ship;
|
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
|
// Add effects radius
|
||||||
this.effects_radius = new Phaser.Graphics(this.game);
|
this.effects_radius = new Phaser.Graphics(this.game);
|
||||||
|
@ -121,7 +121,7 @@ module TK.SpaceTac.UI {
|
||||||
this.updateEffectsRadius();
|
this.updateEffectsRadius();
|
||||||
|
|
||||||
// Set location
|
// 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.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);
|
this.moveTo(ship.arena_x, ship.arena_y, ship.arena_angle);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -20,7 +20,7 @@ module TK.SpaceTac.UI {
|
||||||
this.player1.visible = false;
|
this.player1.visible = false;
|
||||||
this.message.addChild(this.player1);
|
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.anchor.set(0.5);
|
||||||
player1_name.angle = -48;
|
player1_name.angle = -48;
|
||||||
this.player1.addChild(player1_name);
|
this.player1.addChild(player1_name);
|
||||||
|
@ -41,7 +41,7 @@ module TK.SpaceTac.UI {
|
||||||
this.player2.visible = false;
|
this.player2.visible = false;
|
||||||
this.message.addChild(this.player2);
|
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.anchor.set(0.5);
|
||||||
player2_name.angle = -228;
|
player2_name.angle = -228;
|
||||||
this.player2.addChild(player2_name);
|
this.player2.addChild(player2_name);
|
||||||
|
|
|
@ -136,8 +136,8 @@ module TK.SpaceTac.UI {
|
||||||
this.inputs.bind("Escape", "Cancel action", () => this.action_bar.actionEnded());
|
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(`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)));
|
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("w", "Win current battle", () => nn(this.player.getCheats()).win());
|
||||||
this.inputs.bindCheat("x", "Lose current battle", () => this.actual_battle.cheats.lose());
|
this.inputs.bindCheat("x", "Lose current battle", () => nn(this.player.getCheats()).lose());
|
||||||
this.inputs.bindCheat("a", "Use AI to play", () => this.playAI());
|
this.inputs.bindCheat("a", "Use AI to play", () => this.playAI());
|
||||||
|
|
||||||
// "Battle" animation, then start processing the log
|
// "Battle" animation, then start processing the log
|
||||||
|
@ -286,7 +286,7 @@ module TK.SpaceTac.UI {
|
||||||
cursorClicked(): void {
|
cursorClicked(): void {
|
||||||
if (this.targetting.active) {
|
if (this.targetting.active) {
|
||||||
this.validationPressed();
|
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.character_sheet.show(this.ship_hovered, undefined, undefined, false);
|
||||||
this.setShipHovered(null);
|
this.setShipHovered(null);
|
||||||
}
|
}
|
||||||
|
@ -351,7 +351,7 @@ module TK.SpaceTac.UI {
|
||||||
if (battle.outcome) {
|
if (battle.outcome) {
|
||||||
this.setInteractionEnabled(false);
|
this.setInteractionEnabled(false);
|
||||||
|
|
||||||
this.gameui.session.setBattleEnded();
|
this.session.setBattleEnded();
|
||||||
|
|
||||||
battle.stats.processLog(battle.log, this.player.fleet);
|
battle.stats.processLog(battle.log, this.player.fleet);
|
||||||
|
|
||||||
|
@ -365,7 +365,7 @@ module TK.SpaceTac.UI {
|
||||||
* Exit the battle, and go back to map
|
* Exit the battle, and go back to map
|
||||||
*/
|
*/
|
||||||
exitBattle() {
|
exitBattle() {
|
||||||
this.player.exitBattle();
|
this.session.exitBattle();
|
||||||
this.game.state.start('router');
|
this.game.state.start('router');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,7 +373,7 @@ module TK.SpaceTac.UI {
|
||||||
* Revert the battle, and go back to map
|
* Revert the battle, and go back to map
|
||||||
*/
|
*/
|
||||||
revertBattle() {
|
revertBattle() {
|
||||||
this.player.revertBattle();
|
this.session.revertBattle();
|
||||||
this.game.state.start('router');
|
this.game.state.start('router');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ module TK.SpaceTac.UI {
|
||||||
refreshContent(): void {
|
refreshContent(): void {
|
||||||
let parent = this.battleview;
|
let parent = this.battleview;
|
||||||
let outcome = this.outcome;
|
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();
|
this.clearContent();
|
||||||
|
|
||||||
|
|
|
@ -7,13 +7,15 @@ module TK.SpaceTac.UI.Specs {
|
||||||
function createList(): ShipList {
|
function createList(): ShipList {
|
||||||
let view = testgame.view;
|
let view = testgame.view;
|
||||||
let battle = new Battle();
|
let battle = new Battle();
|
||||||
|
let player = new Player();
|
||||||
|
battle.fleets[0].setPlayer(player);
|
||||||
let tactical_mode = new Toggle();
|
let tactical_mode = new Toggle();
|
||||||
let ship_buttons = {
|
let ship_buttons = {
|
||||||
cursorOnShip: nop,
|
cursorOnShip: nop,
|
||||||
cursorOffShip: nop,
|
cursorOffShip: nop,
|
||||||
cursorClicked: 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;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ module TK.SpaceTac.UI.Specs {
|
||||||
test.case("fills ship details", check => {
|
test.case("fills ship details", check => {
|
||||||
let tooltip = new ShipTooltip(testgame.view);
|
let tooltip = new ShipTooltip(testgame.view);
|
||||||
let ship = testgame.view.battle.play_order[2];
|
let ship = testgame.view.battle.play_order[2];
|
||||||
ship.fleet.player.name = "Phil";
|
|
||||||
ship.name = "Fury";
|
ship.name = "Fury";
|
||||||
ship.model = new ShipModel("fake", "Fury");
|
ship.model = new ShipModel("fake", "Fury");
|
||||||
ship.listEquipment().forEach(equ => equ.detach());
|
ship.listEquipment().forEach(equ => equ.detach());
|
||||||
|
|
|
@ -30,7 +30,7 @@ module TK.SpaceTac.UI {
|
||||||
portrait.scale.set(0.5);
|
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 });
|
builder.text(ship.getName(), 168, 0, { color: enemy ? "#cc0d00" : "#ffffff", size: 22, bold: true });
|
||||||
|
|
||||||
if (ship.alive) {
|
if (ship.alive) {
|
||||||
|
|
|
@ -139,7 +139,7 @@ module TK.SpaceTac.UI {
|
||||||
style.image_caption = ship.getName(false);
|
style.image_caption = ship.getName(false);
|
||||||
style.image_size = 256;
|
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);
|
this.setCurrentMessage(style, content, 900, 300, own ? 0.1 : 0.9, own ? 0.2 : 0.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,9 @@ module TK.SpaceTac.UI {
|
||||||
|
|
||||||
this.updateShipSprites();
|
this.updateShipSprites();
|
||||||
|
|
||||||
if (fleet.location) {
|
let location = this.map.universe.getLocation(fleet.location);
|
||||||
this.position.set(fleet.location.star.x + fleet.location.x, fleet.location.star.y + fleet.location.y);
|
if (location) {
|
||||||
|
this.position.set(location.star.x + location.x, location.star.y + location.y);
|
||||||
}
|
}
|
||||||
this.scale.set(SCALING, SCALING);
|
this.scale.set(SCALING, SCALING);
|
||||||
|
|
||||||
|
@ -54,7 +55,7 @@ module TK.SpaceTac.UI {
|
||||||
}
|
}
|
||||||
|
|
||||||
get location(): StarLocation {
|
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
|
* 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) {
|
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 fleet_location = this.map.universe.getLocation(this.fleet.location);
|
||||||
let dx = location.universe_x - this.fleet.location.universe_x;
|
if (fleet_location && this.fleet.move(location)) {
|
||||||
let dy = location.universe_y - this.fleet.location.universe_y;
|
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 distance = Math.sqrt(dx * dx + dy * dy);
|
||||||
let angle = Math.atan2(dx, dy);
|
let angle = Math.atan2(dx, dy);
|
||||||
this.map.current_location.setFleetMoving(true);
|
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);
|
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(() => {
|
tween.onComplete.addOnce(() => {
|
||||||
this.fleet.setLocation(location);
|
|
||||||
if (this.fleet.battle) {
|
if (this.fleet.battle) {
|
||||||
this.game.state.start("router");
|
this.game.state.start("router");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -13,7 +13,7 @@ module TK.SpaceTac.UI {
|
||||||
|
|
||||||
this.shop = shop;
|
this.shop = shop;
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.location = player.fleet.location || new StarLocation();
|
this.location = view.session.getLocation();
|
||||||
this.on_change = on_change || (() => null);
|
this.on_change = on_change || (() => null);
|
||||||
|
|
||||||
this.refresh();
|
this.refresh();
|
||||||
|
|
|
@ -4,7 +4,7 @@ module TK.SpaceTac.UI.Specs {
|
||||||
|
|
||||||
test.case("displays a badge with the current state for a star location", check => {
|
test.case("displays a badge with the current state for a star location", check => {
|
||||||
let mapview = testgame.view;
|
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));
|
let ssdisplay = nn(first(mapview.starsystems, ss => ss.starsystem == location.star));
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ module TK.SpaceTac.UI.Specs {
|
||||||
ssdisplay.updateInfo(2, true);
|
ssdisplay.updateInfo(2, true);
|
||||||
check.equals(ldisplay[2].name, "map-status-unvisited");
|
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);
|
ssdisplay.updateInfo(2, true);
|
||||||
check.equals(ldisplay[2].name, "map-status-enemy");
|
check.equals(ldisplay[2].name, "map-status-enemy");
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ module TK.SpaceTac.UI {
|
||||||
let visited = this.player.hasVisitedLocation(location);
|
let visited = this.player.hasVisitedLocation(location);
|
||||||
let shop = (visited && !location.encounter && location.shop) ? " (dockyard present)" : "";
|
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}`;
|
return `Current fleet location${shop}`;
|
||||||
} else {
|
} else {
|
||||||
let loctype = StarLocationType[location.type].toLowerCase();
|
let loctype = StarLocationType[location.type].toLowerCase();
|
||||||
|
|
|
@ -210,7 +210,7 @@ module TK.SpaceTac.UI {
|
||||||
|
|
||||||
this.starsystems.forEach(system => system.updateInfo(this.zoom, system.starsystem == current_star));
|
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.missions.checkUpdate();
|
||||||
this.conversation.updateFromMissions(this.player.missions, () => this.checkMissionsUpdate());
|
this.conversation.updateFromMissions(this.player.missions, () => this.checkMissionsUpdate());
|
||||||
|
@ -226,7 +226,7 @@ module TK.SpaceTac.UI {
|
||||||
revealAll(): void {
|
revealAll(): void {
|
||||||
this.universe.stars.forEach(star => {
|
this.universe.stars.forEach(star => {
|
||||||
star.locations.forEach(location => {
|
star.locations.forEach(location => {
|
||||||
this.player.setVisited(location);
|
this.player.fleet.setVisited(location);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
this.refresh();
|
this.refresh();
|
||||||
|
@ -276,7 +276,7 @@ module TK.SpaceTac.UI {
|
||||||
* Set the current zoom level (0, 1 or 2)
|
* Set the current zoom level (0, 1 or 2)
|
||||||
*/
|
*/
|
||||||
setZoom(level: number, duration = 500) {
|
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) {
|
if (!current_star || level <= 0) {
|
||||||
this.setCamera(0, 0, this.universe.radius * 2, duration);
|
this.setCamera(0, 0, this.universe.radius * 2, duration);
|
||||||
this.setLinksAlpha(1, duration);
|
this.setLinksAlpha(1, duration);
|
||||||
|
@ -300,7 +300,7 @@ module TK.SpaceTac.UI {
|
||||||
* This will only work if current location is a warp
|
* This will only work if current location is a warp
|
||||||
*/
|
*/
|
||||||
doJump(): void {
|
doJump(): void {
|
||||||
let location = this.player.fleet.location;
|
let location = this.session.getLocation();
|
||||||
if (this.interactive && location && location.type == StarLocationType.WARP && location.jump_dest) {
|
if (this.interactive && location && location.type == StarLocationType.WARP && location.jump_dest) {
|
||||||
let dest_location = location.jump_dest;
|
let dest_location = location.jump_dest;
|
||||||
let dest_star = dest_location.star;
|
let dest_star = dest_location.star;
|
||||||
|
@ -321,7 +321,7 @@ module TK.SpaceTac.UI {
|
||||||
* This will only work if current location has a dockyard
|
* This will only work if current location has a dockyard
|
||||||
*/
|
*/
|
||||||
openShop(): void {
|
openShop(): void {
|
||||||
let location = this.player.fleet.location;
|
let location = this.session.getLocation();
|
||||||
if (this.interactive && location && location.shop) {
|
if (this.interactive && location && location.shop) {
|
||||||
this.character_sheet.setShop(location.shop);
|
this.character_sheet.setShop(location.shop);
|
||||||
this.character_sheet.show(this.player.fleet.ships[0]);
|
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
|
* This will only work if current location has a dockyard
|
||||||
*/
|
*/
|
||||||
openMissions(): void {
|
openMissions(): void {
|
||||||
let location = this.player.fleet.location;
|
let location = this.session.getLocation();
|
||||||
if (this.interactive && location && location.shop) {
|
if (this.interactive && location && location.shop) {
|
||||||
new MissionsDialog(this, location.shop, this.player, () => this.checkMissionsUpdate());
|
new MissionsDialog(this, location.shop, this.player, () => this.checkMissionsUpdate());
|
||||||
}
|
}
|
||||||
|
@ -344,7 +344,7 @@ module TK.SpaceTac.UI {
|
||||||
* Move the fleet to another location
|
* Move the fleet to another location
|
||||||
*/
|
*/
|
||||||
moveToLocation(dest: StarLocation): void {
|
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.setInteractionEnabled(false);
|
||||||
this.player_fleet.moveToLocation(dest, 1, null, () => {
|
this.player_fleet.moveToLocation(dest, 1, null, () => {
|
||||||
this.setInteractionEnabled(true);
|
this.setInteractionEnabled(true);
|
||||||
|
|
Loading…
Reference in a new issue