1
0
Fork 0

Added looting from the battle outcome (WIP)

This commit is contained in:
Michaël Lemaire 2015-02-13 01:00:00 +01:00
parent 728119877b
commit 8354f03cfb
11 changed files with 225 additions and 25 deletions

View file

@ -6,6 +6,9 @@ module SpaceTac.Game {
// Flag indicating if the battle is ended
ended: boolean;
// Battle outcome, if *ended* is true
outcome: BattleOutcome;
// Log of all battle events
log: BattleLog;
@ -84,6 +87,18 @@ module SpaceTac.Game {
return result;
}
// Ends a battle and sets the outcome
endBattle(winner: Fleet, log: boolean = true) {
this.ended = true;
this.outcome = new BattleOutcome(winner);
if (winner) {
this.outcome.createLoot(this);
}
if (log && this.log) {
this.log.add(new EndBattleEvent(this.outcome));
}
}
// Checks end battle conditions, returns true if the battle ended
checkEndBattle(log: boolean = true) {
if (this.ended) {
@ -94,18 +109,16 @@ module SpaceTac.Game {
if (alive_fleets === 0) {
// It's a draw
this.ended = true;
this.log.add(new EndBattleEvent(null));
this.endBattle(null, log);
} else if (alive_fleets === 1) {
// We have a winner
var winner: Player = null;
var winner: Fleet = null;
this.fleets.forEach((fleet: Fleet) => {
if (fleet.isAlive()) {
winner = fleet.player;
winner = fleet;
}
});
this.ended = true;
this.log.add(new EndBattleEvent(winner));
this.endBattle(winner, log);
}
return this.ended;

View file

@ -0,0 +1,50 @@
module SpaceTac.Game {
"use strict";
// Result of an ended battle
export class BattleOutcome {
// Indicates if the battle is a draw (no winner)
draw: boolean;
// Victorious fleet
winner: Fleet;
// Retrievable loot
loot: Equipment[];
constructor(winner: Fleet) {
this.winner = winner;
this.draw = winner ? false : true;
this.loot = [];
}
// Create loot from dead ships
createLoot(battle: Battle, random: RandomGenerator = new RandomGenerator()): void {
this.loot = [];
battle.fleets.forEach((fleet: Fleet) => {
fleet.ships.forEach((ship: Ship) => {
if (!ship.alive) {
if (ship.fleet === this.winner) {
// Member of the winner fleet, salvage a number of equipments
var count = random.throwInt(0, ship.getEquipmentCount());
while (count > 0) {
var salvaged = ship.getRandomEquipment(random);
salvaged.detach();
this.loot.push(salvaged);
count--;
}
} else {
var luck = random.throw();
if (luck > 0.9) {
// TODO Salvage a supposedly transported item
} else if (luck > 0.5) {
// TODO Salvage an equipped item
}
}
}
});
});
}
}
}

View file

@ -3,7 +3,10 @@ module SpaceTac.Game {
// Piece of equipment to attach in slots
export class Equipment {
// Type of slot this equipment will fit in
// Actual slot this equipment is attached to
attached_to: Slot;
// Type of slot this equipment can fit in
slot: SlotType;
// Equipment name
@ -37,7 +40,9 @@ module SpaceTac.Game {
target_effects: BaseEffect[];
// Basic constructor
constructor() {
constructor(slot: SlotType = null, name: string = null) {
this.slot = slot;
this.name = name;
this.requirements = [];
this.permanent_effects = [];
this.target_effects = [];
@ -46,13 +51,25 @@ module SpaceTac.Game {
// Returns true if the equipment can be equipped on a ship
// This checks *requirements* against the ship capabilities
canBeEquipped(ship: Ship): boolean {
var able = true;
this.requirements.forEach((cap: Attribute) => {
if (ship.attributes.getValue(cap.code) < cap.current) {
able = false;
}
});
return able;
if (this.attached_to) {
return false;
} else {
var able = true;
this.requirements.forEach((cap: Attribute) => {
if (ship.attributes.getValue(cap.code) < cap.current) {
able = false;
}
});
return able;
}
}
// Detach from the slot it is attached to
detach(): void {
if (this.attached_to) {
this.attached_to.attached = null;
this.attached_to = null;
}
}
}
}

View file

@ -21,8 +21,10 @@ module SpaceTac.Game {
// Add a ship in this fleet
addShip(ship: Ship): void {
if (this.ships.indexOf(ship) < 0) {
this.ships.push(ship);
}
ship.fleet = this;
this.ships.push(ship);
}
// Set the current battle

View file

@ -8,7 +8,11 @@ module SpaceTac.Game {
// Basic constructor (can specify fake values as arguments)
constructor(...values: number[]) {
this.fake_values = values;
this.fake_values = [];
values.forEach((value: number) => {
this.forceNextValue(value);
});
}
// Generate a value, based on an attribute level
@ -23,7 +27,7 @@ module SpaceTac.Game {
// Generate a random integer value in a range
throwInt(min: number, max: number): number {
var value = this.throw(max - min + 1);
return Math.floor(value) + max;
return Math.floor(value) + min;
}
// Choose a random item from an array
@ -36,6 +40,11 @@ module SpaceTac.Game {
// Call it several times to set future successive values
// This value will replace the 0.0-1.0 random value, not the final one
forceNextValue(value: number): void {
if (value < 0.0) {
value = 0.0;
} else if (value >= 1.0) {
value = 0.999999999;
}
this.fake_values.push(value);
}
}

View file

@ -258,6 +258,38 @@ module SpaceTac.Game {
return result;
}
// Get the number of attached equipments
getEquipmentCount(): number {
var result = 0;
this.slots.forEach((slot: Slot) => {
if (slot.attached) {
result++;
}
});
return result;
}
// Get a random attached equipment, null if no equipment is attached
getRandomEquipment(random: RandomGenerator = new RandomGenerator()): Equipment {
var count = this.getEquipmentCount();
if (count === 0) {
return null;
} else {
var picked = random.throwInt(0, count - 1);
var result: Equipment = null;
var index = 0;
this.slots.forEach((slot: Slot) => {
if (slot.attached) {
if (index === picked) {
result = slot.attached;
}
index++;
}
});
return result;
}
}
// Update attributes, taking into account attached equipment and active effects
updateAttributes(): void {
// TODO Something more generic

View file

@ -32,6 +32,7 @@ module SpaceTac.Game {
attach(equipment: Equipment): void {
if (this.type === equipment.slot && equipment.canBeEquipped(this.ship)) {
this.attached = equipment;
equipment.attached_to = this;
if (this.ship) {
this.ship.updateAttributes();

View file

@ -6,13 +6,13 @@ module SpaceTac.Game {
// Event logged when the battle ended
// This is always the last event of a battle log
export class EndBattleEvent extends BaseLogEvent {
// Winner of the battle
winner: Player;
// Outcome of the battle
outcome: BattleOutcome;
constructor(winner: Player) {
constructor(outcome: BattleOutcome) {
super("endbattle");
this.winner = winner;
this.outcome = outcome;
}
}
}

View file

@ -169,8 +169,8 @@ module SpaceTac.Game {
expect(battle.ended).toBe(true);
expect(battle.log.events.length).toBe(1);
expect(battle.log.events[0].code).toBe("endbattle");
expect((<EndBattleEvent>battle.log.events[0]).winner).not.toBeNull();
expect((<EndBattleEvent>battle.log.events[0]).winner).toBe(fleet2.player);
expect((<EndBattleEvent>battle.log.events[0]).outcome.winner).not.toBeNull();
expect((<EndBattleEvent>battle.log.events[0]).outcome.winner).toBe(fleet2);
});
it("handles a draw in end battle", function () {
@ -196,7 +196,7 @@ module SpaceTac.Game {
expect(battle.ended).toBe(true);
expect(battle.log.events.length).toBe(1);
expect(battle.log.events[0].code).toBe("endbattle");
expect((<EndBattleEvent>battle.log.events[0]).winner).toBeNull();
expect((<EndBattleEvent>battle.log.events[0]).outcome.winner).toBeNull();
});
});
}

View file

@ -0,0 +1,44 @@
/// <reference path="../../definitions/jasmine.d.ts"/>
module SpaceTac.Game.Specs {
"use strict";
describe("BattleOutcome", () => {
it("generates loot from dead ships, for the winner to take", () => {
var fleet1 = new Fleet();
fleet1.addShip(new Ship(fleet1));
fleet1.addShip(new Ship(fleet1));
fleet1.addShip(new Ship(fleet1));
var fleet2 = new Fleet();
fleet2.addShip(new Ship(fleet2));
fleet2.addShip(new Ship(fleet2));
fleet2.addShip(new Ship(fleet2));
fleet1.ships[0].setDead();
fleet1.ships[0].addSlot(SlotType.Armor).attach(new Equipment(SlotType.Armor));
fleet1.ships[1].setDead();
fleet1.ships[1].addSlot(SlotType.Engine).attach(new Equipment(SlotType.Engine, "1.1.1"));
fleet1.ships[1].addSlot(SlotType.Engine).attach(new Equipment(SlotType.Engine, "1.1.2"));
fleet1.ships[1].addSlot(SlotType.Engine).attach(new Equipment(SlotType.Engine, "1.1.3"));
fleet1.ships[1].addSlot(SlotType.Engine).attach(new Equipment(SlotType.Engine, "1.1.4"));
fleet2.ships[0].setDead();
fleet2.ships[1].setDead();
fleet2.ships[2].setDead();
var battle = new Battle(fleet1, fleet2);
var outcome = new BattleOutcome(fleet1);
var random = new RandomGenerator(
0, // leave first ship alone
0.45, // take 2 equipments from the 4 of second ship
1, // - take last equipment
0 // - take first equipment
);
outcome.createLoot(battle, random);
expect(outcome.loot.length).toBe(2);
expect(outcome.loot[0].name).toBe("1.1.4");
expect(outcome.loot[1].name).toBe("1.1.1");
});
});
}

View file

@ -171,5 +171,37 @@ module SpaceTac.Game {
expect(ship.isAbleToPlay()).toBe(false);
expect(ship.isAbleToPlay(false)).toBe(false);
});
it("counts attached equipment", function () {
var ship = new Ship();
expect(ship.getEquipmentCount()).toBe(0);
ship.addSlot(SlotType.Armor).attach(new Equipment(SlotType.Armor));
ship.addSlot(SlotType.Shield);
ship.addSlot(SlotType.Weapon).attach(new Equipment(SlotType.Weapon));
expect(ship.getEquipmentCount()).toBe(2);
});
it("can pick a random attached equipment", function () {
var ship = new Ship();
expect(ship.getRandomEquipment()).toBe(null);
ship.addSlot(SlotType.Armor).attach(new Equipment(SlotType.Armor));
ship.addSlot(SlotType.Shield);
ship.addSlot(SlotType.Weapon).attach(new Equipment(SlotType.Weapon));
var random = new RandomGenerator(0.2);
var picked = ship.getRandomEquipment(random);
expect(picked).not.toBeNull();
expect(picked).toBe(ship.slots[0].attached);
random.forceNextValue(1);
picked = ship.getRandomEquipment(random);
expect(picked).not.toBeNull();
expect(picked).toBe(ship.slots[2].attached);
});
});
}