1
0
Fork 0

Display simulated ship displacement effects while targetting

This commit is contained in:
Michaël Lemaire 2018-06-13 23:52:36 +02:00
parent 7d586d5a2b
commit 4e624dc9db
14 changed files with 108 additions and 29 deletions

View File

@ -43,7 +43,7 @@ Battle
* Improve arena ships layering (sometimes information is displayed behind other sprites)
* In the ship tooltip, show power cost, toggled and overheat states
* Display shield (and its (dis)appearance)
* Display estimated damage and displacement in targetting mode
* Display estimated damage in targetting mode
* Add a voluntary retreat option
* Toggle bar/text display in power section of action bar
* Show a cooldown indicator on move action icon, if the simulation would cause the engine to overheat

View File

@ -148,7 +148,7 @@ module TK.SpaceTac {
let diff = battle.log.get(battle.log.count() - 1);
if (diff instanceof EndBattleDiff) {
check.notequals(diff.outcome.winner, null);
check.same(diff.outcome.winner, fleet2);
check.same(diff.outcome.winner, fleet2.id);
} else {
check.fail("Not an EndBattleDiff");
}

View File

@ -349,10 +349,12 @@ module TK.SpaceTac {
/**
* Perform all battle checks to ensure the state is consistent
*
* Returns all applied diffs
*/
performChecks(): void {
performChecks(): BaseBattleDiff[] {
let checks = new BattleChecks(this);
checks.apply();
return checks.apply();
}
/**

View File

@ -7,7 +7,7 @@ module TK.SpaceTac.Specs {
cheats.win();
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].id, "winner");
check.equals(any(battle.fleets[1].ships, ship => ship.alive), false, "all enemies dead");
})
@ -18,7 +18,7 @@ module TK.SpaceTac.Specs {
cheats.lose();
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].id, "winner");
check.equals(any(battle.fleets[0].ships, ship => ship.alive), false, "all allies dead");
})
})

View File

@ -13,7 +13,8 @@ module TK.SpaceTac {
/**
* Apply all the checks
*/
apply(): void {
apply(): BaseBattleDiff[] {
let all: BaseBattleDiff[] = [];
let diffs: BaseBattleDiff[];
let loops = 0;
@ -23,6 +24,7 @@ module TK.SpaceTac {
if (diffs.length > 0) {
//console.log("Battle checks diffs", diffs);
this.battle.applyDiffs(diffs);
all = all.concat(diffs);
}
loops += 1;
@ -31,6 +33,8 @@ module TK.SpaceTac {
break;
}
} while (diffs.length > 0);
return all;
}
/**

View File

@ -9,10 +9,10 @@ module TK.SpaceTac {
draw: boolean
// Victorious fleet
winner: Fleet | null
winner: RObjectId | null
constructor(winner: Fleet | null) {
this.winner = winner;
this.winner = winner ? winner.id : null;
this.draw = winner ? false : true;
}
@ -21,7 +21,7 @@ module TK.SpaceTac {
*/
grantExperience(fleets: Fleet[]) {
fleets.forEach(fleet => {
let winfactor = (fleet == this.winner) ? 0.03 : (this.draw ? 0.01 : 0.005);
let winfactor = (fleet.is(this.winner)) ? 0.03 : (this.draw ? 0.01 : 0.005);
let enemies = flatten(fleets.filter(f => f !== fleet).map(f => f.ships));
let difficulty = sum(enemies.map(enemy => 100 + enemy.level.getExperience()));
fleet.ships.forEach(ship => {

View File

@ -2,7 +2,7 @@ module TK.SpaceTac {
/**
* A fleet of ships, all belonging to the same player
*/
export class Fleet {
export class Fleet extends RObject {
// Fleet owner
player: Player
@ -26,6 +26,8 @@ module TK.SpaceTac {
// Create a fleet, bound to a player
constructor(player = new Player()) {
super();
this.player = player;
this.name = player ? player.name : "Fleet";
this.ships = [];

View File

@ -172,5 +172,36 @@ module TK.SpaceTac.Specs {
check.equals(result.need_move, true);
check.equals(result.move_location, new Target(ship.arena_x + 6, ship.arena_y));
});
test.case("simulates the results on a fake battle, to provide a list of expected diffs", check => {
let battle = TestTools.createBattle();
let ship = battle.fleets[0].ships[0];
let enemy = battle.fleets[1].ships[0];
ship.setArenaPosition(100, 100);
enemy.setArenaPosition(300, 100);
TestTools.setShipModel(ship, 1, 1, 3);
TestTools.setShipModel(enemy, 2, 1);
let engine = TestTools.addEngine(ship, 80);
let weapon = TestTools.addWeapon(ship, 5, 1, 150);
let simulator = new MoveFireSimulator(ship);
let result = simulator.simulateAction(weapon, Target.newFromShip(enemy), 5);
let diffs = simulator.getExpectedDiffs(nn(ship.getBattle()), result);
check.equals(diffs, [
new ShipActionUsedDiff(ship, engine, Target.newFromLocation(155, 100)),
new ShipValueDiff(ship, "power", -1),
new ShipMoveDiff(ship, ship.location, new ArenaLocationAngle(155, 100), engine),
new ShipActionUsedDiff(ship, weapon, Target.newFromShip(enemy)),
new ShipValueDiff(ship, "power", -1),
new ProjectileFiredDiff(ship, weapon, Target.newFromShip(enemy)),
new ShipDamageDiff(enemy, 2, 1, 0, 5),
new ShipValueDiff(enemy, "shield", -1),
new ShipValueDiff(enemy, "hull", -2),
new ShipDeathDiff(battle, enemy),
new EndBattleDiff(battle.fleets[0], 0)
]);
check.equals(enemy.getValue("hull"), 2);
check.equals(enemy.getValue("hull"), 2);
});
});
}

View File

@ -187,5 +187,25 @@ module TK.SpaceTac {
return result;
}
/**
* Apply a move-fire simulation result, and predict the diffs it will apply on a battle
*
* The original battle passed as parameter will be duplicated, and not altered
*/
getExpectedDiffs(battle: Battle, simulation: MoveFireResult): BaseBattleDiff[] {
let sim_battle = duplicate(battle, TK.SpaceTac);
let sim_ship = nn(sim_battle.getShip(this.ship.id));
let results: BaseBattleDiff[] = [];
simulation.parts.forEach(part => {
let diffs = part.action.getDiffs(sim_ship, battle, part.target);
results = results.concat(diffs);
sim_battle.applyDiffs(diffs);
diffs = sim_battle.performChecks();
results = results.concat(diffs);
});
return results;
}
}
}

View File

@ -173,7 +173,7 @@ module TK.SpaceTac {
* Resolves the encounter from a battle outcome
*/
resolveEncounter(outcome: BattleOutcome) {
if (this.encounter && outcome.winner && outcome.winner != this.encounter) {
if (this.encounter && outcome.winner && !this.encounter.is(outcome.winner)) {
this.clearEncounter();
}
}

View File

@ -17,7 +17,7 @@ module TK.SpaceTac.Specs {
},
check => {
check.equals(battle.ended, true, "battle is ended");
check.same(nn(battle.outcome).winner, battle.fleets[1], "battle has an outcome");
check.same(nn(battle.outcome).winner, battle.fleets[1].id, "battle has an outcome");
},
]);
});

View File

@ -62,7 +62,7 @@ module TK.SpaceTac.Specs {
ship.setDead();
battle.performChecks();
check.equals(battle.ended, true);
check.notsame(nn(battle.outcome).winner, fleet);
check.notsame(nn(battle.outcome).winner, fleet.id);
})
})
}

View File

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

View File

@ -16,7 +16,7 @@ module TK.SpaceTac.UI {
// Simulated result
simulation = new MoveFireResult()
effects: BaseBattleDiff[] = []
simulated_diffs: BaseBattleDiff[] = []
// Move and fire lines
drawn_info: UIGraphics
@ -27,6 +27,9 @@ module TK.SpaceTac.UI {
impact_area: UIGraphics
impact_indicators: UIContainer
// Diffs display
diffs_move: UIGraphics
// Collaborators to update
actionbar: ActionBar
range_hint: RangeHint
@ -46,18 +49,16 @@ module TK.SpaceTac.UI {
builder = builder.in(this.container);
// Visual effects
this.impact_area = builder.graphics("impact-area");
this.impact_area.setVisible(false);
this.drawn_info = builder.graphics("lines");
this.drawn_info.setVisible(false);
this.impact_area = builder.graphics("impact-area", 0, 0, false);
this.diffs_move = builder.graphics("effects-move");
this.drawn_info = builder.graphics("lines", 0, 0, false);
this.move_ghost = builder.image("common-transparent", 0, 0, true);
this.move_ghost.setAlpha(0.8);
this.move_ghost.setVisible(false);
this.fire_arrow = builder.image("battle-hud-simulator-ok");
this.fire_arrow.setOrigin(1, 0.5);
this.fire_arrow.setVisible(false);
this.impact_indicators = builder.container("impact-indicators");
this.impact_indicators.setVisible(false);
this.impact_indicators = builder.container("impact-indicators", 0, 0, false);
}
/**
@ -200,6 +201,25 @@ module TK.SpaceTac.UI {
}
}
/**
* Update information about simulated diffs
*/
updateDiffsDisplay(): void {
this.diffs_move.clear();
this.simulated_diffs.forEach(diff => {
if (diff instanceof ShipMoveDiff) {
this.diffs_move.addLine({
start: diff.start,
end: diff.end,
width: 4,
color: 0xFFFFFF,
alpha: 0.5
});
}
});
}
/**
* Update visual effects to show the simulation of current action/target
*/
@ -259,6 +279,9 @@ module TK.SpaceTac.UI {
this.fire_arrow.visible = true;
this.impact_area.visible = false;
}
this.updateDiffsDisplay();
this.container.visible = true;
} else {
this.container.visible = false;
@ -305,16 +328,13 @@ module TK.SpaceTac.UI {
*/
simulate(): void {
if (this.ship && this.action && this.target) {
let ship = this.ship;
let simulator = new MoveFireSimulator(ship);
let battle = nn(this.ship.getBattle());
let simulator = new MoveFireSimulator(this.ship);
this.simulation = simulator.simulateAction(this.action, this.target, 1);
this.effects = flatten(this.simulation.parts.map(part =>
part.action.getDiffs(ship, nn(ship.getBattle()), part.target)
));
this.simulated_diffs = simulator.getExpectedDiffs(battle, this.simulation);
} else {
this.simulation = new MoveFireResult();
this.effects = [];
this.simulated_diffs = [];
}
}