diff --git a/graphics/exported/equipment/kelvingenerator.png b/graphics/exported/equipment/kelvingenerator.png new file mode 100644 index 0000000..7625265 Binary files /dev/null and b/graphics/exported/equipment/kelvingenerator.png differ diff --git a/graphics/exported/equipment/prokhorovlaser.png b/graphics/exported/equipment/prokhorovlaser.png new file mode 100644 index 0000000..ff59bbc Binary files /dev/null and b/graphics/exported/equipment/prokhorovlaser.png differ diff --git a/graphics/ui/actions.svg b/graphics/ui/actions.svg index 91eb120..92c568f 100644 --- a/graphics/ui/actions.svg +++ b/graphics/ui/actions.svg @@ -16,13 +16,61 @@ version="1.1" inkscape:version="0.92.1 r15371" sodipodi:docname="actions.svg" - inkscape:export-filename="/home/michael/workspace/perso/spacetac/graphics/exported/equipment/gravitshield.png" + inkscape:export-filename="/home/michael/workspace/perso/spacetac/graphics/exported/equipment/kelvingenerator.png" inkscape:export-xdpi="90" inkscape:export-ydpi="90" viewBox="0 0 256 256" enable-background="new"> + + + + + + + + + + + + + + + @@ -1053,6 +1101,338 @@ y1="154.3677" x2="55.914527" y2="154.3677" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2948,4 +3328,333 @@ height="100%" transform="rotate(-80.838515,124.57679,104.88647)" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/package.json b/package.json index 001ff0e..142d280 100644 --- a/package.json +++ b/package.json @@ -21,11 +21,11 @@ "author": "Michael Lemaire", "license": "MIT", "devDependencies": { - "@types/jasmine": "^2.5.53", - "babel-polyfill": "^6.23.0", + "@types/jasmine": "^2.6.0", + "babel-polyfill": "^6.26.0", "codecov": "^2.3.0", "gamefroot-texture-packer": "Gamefroot/Gamefroot-Texture-Packer.git#f3687111afc94f80ea8f2877c188fb8e2004e8ff", - "jasmine": "^2.7.0", + "jasmine": "^2.8.0", "karma": "^1.7.0", "karma-coverage": "^1.1.1", "karma-jasmine": "^1.1.0", @@ -33,12 +33,12 @@ "karma-spec-reporter": "^0.0.31", "live-server": "^1.2.0", "remap-istanbul": "^0.9.5", - "typescript": "^2.4.2" + "typescript": "^2.5.3" }, "dependencies": { - "jasmine-core": "^2.6.3", + "jasmine-core": "^2.8.0", "parse": "^1.9.2", "phaser": "^2.6.2", "phaser-plugin-scene-graph": "^1.0.4" } -} \ No newline at end of file +} diff --git a/src/core/Battle.ts b/src/core/Battle.ts index 1ce58a3..b3d126c 100644 --- a/src/core/Battle.ts +++ b/src/core/Battle.ts @@ -67,12 +67,14 @@ module TK.SpaceTac { this.ai_playing = false; } - // Create a quick random battle, for testing purposes + /** + * Create a quick random battle, for testing purposes, or quick skirmish + */ static newQuickRandom(start = true, level = 1, shipcount = 5): Battle { - var player1 = Player.newQuickRandom("Player", level, shipcount, true); - var player2 = Player.newQuickRandom("Enemy", level, shipcount, true); + let player1 = Player.newQuickRandom("Player", level, shipcount, true); + let player2 = Player.newQuickRandom("Enemy", level, shipcount, true); - var result = new Battle(player1.fleet, player2.fleet); + let result = new Battle(player1.fleet, player2.fleet); if (start) { result.start(); } diff --git a/src/core/Cooldown.ts b/src/core/Cooldown.ts index 0603cad..221fe9e 100644 --- a/src/core/Cooldown.ts +++ b/src/core/Cooldown.ts @@ -72,10 +72,8 @@ module TK.SpaceTac { /** * Apply one cooling-down step if necessary */ - cool(): void { - if (this.heat > 0) { - this.heat -= 1; - } + cool(steps = 1): void { + this.heat = Math.max(this.heat - steps, 0); if (this.heat == 0) { this.uses = 0; diff --git a/src/core/FleetGenerator.ts b/src/core/FleetGenerator.ts index 35ef161..2e47981 100644 --- a/src/core/FleetGenerator.ts +++ b/src/core/FleetGenerator.ts @@ -18,7 +18,7 @@ module TK.SpaceTac { let models = this.random.sample(ShipModel.getDefaultCollection(), ship_count); range(ship_count).forEach(i => { - var ship = ship_generator.generate(level, models[i] || null, upgrade, i < ship_count * 0.6); + var ship = ship_generator.generate(level, models[i] || null, upgrade); ship.name = ship.model.name; fleet.addShip(ship); }); diff --git a/src/core/GameSession.ts b/src/core/GameSession.ts index 252509e..13c9dc5 100644 --- a/src/core/GameSession.ts +++ b/src/core/GameSession.ts @@ -94,7 +94,7 @@ module TK.SpaceTac { // Start a new "quick battle" game startQuickBattle(with_ai: boolean = false): void { - var battle = Battle.newQuickRandom(); + let battle = Battle.newQuickRandom(true, RandomGenerator.global.randInt(1, 10)); this.player = battle.fleets[0].player; this.player.setBattle(battle); } diff --git a/src/core/LootGenerator.ts b/src/core/LootGenerator.ts index e36f765..f6cb341 100644 --- a/src/core/LootGenerator.ts +++ b/src/core/LootGenerator.ts @@ -67,21 +67,13 @@ module TK.SpaceTac { */ generateHighest(skills: ShipSkills, quality = EquipmentQuality.COMMON, slot: SlotType | null = null): Equipment | null { let templates = this.templates.filter(this.templatefilter).filter(template => slot == null || slot == template.slot); - let candidates: Equipment[] = []; - let level = 1; - - templates.forEach(template => { - let equipment = template.generateHighest(skills, quality, this.random); - if (equipment && equipment.level >= level) { - if (equipment.level > level) { - candidates.splice(0); - level = equipment.level; - } - candidates.push(equipment); - } - }); - - return (candidates.length == 0) ? null : this.random.choice(candidates); + let candidates = nna(templates.map(template => template.generateHighest(skills, quality, this.random))); + if (candidates.length) { + let chosen = this.random.weighted(candidates.map(equ => equ.level)); + return candidates[chosen]; + } else { + return null; + } } } } diff --git a/src/core/LootQualityModifiers.ts b/src/core/LootQualityModifiers.ts index a777b9d..0a14b84 100644 --- a/src/core/LootQualityModifiers.ts +++ b/src/core/LootQualityModifiers.ts @@ -56,6 +56,9 @@ module TK.SpaceTac { simpleFactor(effect, 'factor'); } else if (effect instanceof ValueTransferEffect) { simpleFactor(effect, 'amount'); + } else if (effect instanceof CooldownEffect) { + simpleFactor(effect, 'cooling'); + simpleFactor(effect, 'maxcount'); } } diff --git a/src/core/ShipGenerator.ts b/src/core/ShipGenerator.ts index ec533b8..9ddd230 100644 --- a/src/core/ShipGenerator.ts +++ b/src/core/ShipGenerator.ts @@ -17,7 +17,7 @@ module TK.SpaceTac { * * If *force_damage_equipment, at least one "damaging" weapon will be chosen */ - generate(level: number, model: ShipModel | null = null, upgrade = false, force_damage_equipment = false): Ship { + generate(level: number, model: ShipModel | null = null, upgrade = false, force_damage_equipment = true): Ship { if (!model) { // Get a random model model = ShipModel.getRandomModel(level, this.random); diff --git a/src/core/actions/FireWeaponAction.ts b/src/core/actions/FireWeaponAction.ts index eecf436..af298d2 100644 --- a/src/core/actions/FireWeaponAction.ts +++ b/src/core/actions/FireWeaponAction.ts @@ -20,7 +20,7 @@ module TK.SpaceTac { // Equipment cannot be null equipment: Equipment - constructor(equipment: Equipment, power = 1, range = 0, blast = 0, effects: BaseEffect[] = [], name = "Fire") { + constructor(equipment: Equipment, power = 1, range = 0, blast = 0, effects: BaseEffect[] = [], name = range ? "Fire" : "Trigger") { super("fire-" + equipment.code, name, equipment); this.power = power; @@ -116,9 +116,17 @@ module TK.SpaceTac { return ""; } - let desc = `${this.name} (power usage ${this.power}, max range ${this.range}km)`; + let info: string[] = []; + if (this.power) { + info.push(`power usage ${this.power}`); + } + if (this.range) { + info.push(`max range ${this.range}km`); + } + + let desc = `${this.name} (${info.join(", ")})`; let effects = this.effects.map(effect => { - let suffix = this.blast ? `in ${this.blast}km radius` : "on target"; + let suffix = this.blast ? `in ${this.blast}km radius` : (this.range ? "on target" : "on self"); return "• " + effect.getDescription() + " " + suffix; }); return `${desc}:\n${effects.join("\n")}`; diff --git a/src/core/effects/CooldownEffect.spec.ts b/src/core/effects/CooldownEffect.spec.ts new file mode 100644 index 0000000..d337d37 --- /dev/null +++ b/src/core/effects/CooldownEffect.spec.ts @@ -0,0 +1,34 @@ +module TK.SpaceTac { + describe("CooldownEffect", function () { + it("cools down equipment", function () { + let ship = new Ship(); + let weapons = [TestTools.addWeapon(ship), TestTools.addWeapon(ship), TestTools.addWeapon(ship)]; + weapons.forEach(weapon => weapon.cooldown.configure(1, 3)); + expect(weapons.map(weapon => weapon.cooldown.heat)).toEqual([0, 0, 0]); + + new CooldownEffect(0, 0).applyOnShip(ship, ship); + expect(weapons.map(weapon => weapon.cooldown.heat)).toEqual([0, 0, 0]); + + weapons.forEach(weapon => weapon.cooldown.use()); + expect(weapons.map(weapon => weapon.cooldown.heat)).toEqual([3, 3, 3]); + + new CooldownEffect(0, 0).applyOnShip(ship, ship); + expect(weapons.map(weapon => weapon.cooldown.heat)).toEqual([0, 0, 0]); + + weapons.forEach(weapon => weapon.cooldown.use()); + expect(weapons.map(weapon => weapon.cooldown.heat)).toEqual([3, 3, 3]); + + new CooldownEffect(1, 0).applyOnShip(ship, ship); + expect(weapons.map(weapon => weapon.cooldown.heat)).toEqual([2, 2, 2]); + + new CooldownEffect(1, 2).applyOnShip(ship, ship); + expect(weapons.map(weapon => weapon.cooldown.heat).sort()).toEqual([1, 1, 2]); + }) + + it("builds a textual description", function () { + expect(new CooldownEffect(0, 0).getDescription()).toBe("Full cooling (all equipments)"); + expect(new CooldownEffect(1, 1).getDescription()).toBe("1 cooling (1 equipment)"); + expect(new CooldownEffect(2, 2).getDescription()).toBe("2 cooling (2 equipments)"); + }) + }) +} diff --git a/src/core/effects/CooldownEffect.ts b/src/core/effects/CooldownEffect.ts new file mode 100644 index 0000000..4aab219 --- /dev/null +++ b/src/core/effects/CooldownEffect.ts @@ -0,0 +1,42 @@ +/// + +module TK.SpaceTac { + /** + * Cools down equipment of affected ships + */ + export class CooldownEffect extends BaseEffect { + // Number of cooling steps to apply + cooling: number + + // Maximal number of equipment to cool on one ship (will be chosen at random) + maxcount: number + + constructor(cooling = 0, maxcount = 0) { + super("cooldown"); + + this.cooling = cooling; + this.maxcount = maxcount; + } + + applyOnShip(ship: Ship, source: Ship | Drone): boolean { + let equipments = ship.listEquipment().filter(equ => equ.cooldown.heat > 0); + + if (this.maxcount && equipments.length > this.maxcount) { + let random = RandomGenerator.global; + equipments = random.sample(equipments, this.maxcount); + } + + equipments.forEach(equ => equ.cooldown.cool(this.cooling || equ.cooldown.heat)); + + return true; + } + + isBeneficial(): boolean { + return true; + } + + getDescription(): string { + return `${this.cooling ? this.cooling : "Full"} cooling (${this.maxcount ? this.maxcount : "all"} equipment${this.maxcount != 1 ? "s" : ""})`; + } + } +} diff --git a/src/core/equipments/GatlingGun.spec.ts b/src/core/equipments/GatlingGun.spec.ts deleted file mode 100644 index 6149a01..0000000 --- a/src/core/equipments/GatlingGun.spec.ts +++ /dev/null @@ -1,31 +0,0 @@ -module TK.SpaceTac.Equipments { - describe("GatlingGun", function () { - it("generates equipment based on level", function () { - let template = new GatlingGun(); - - let equipment = template.generate(1); - expect(equipment.requirements).toEqual({ "skill_materials": 1 }); - expect(equipment.action).toEqual(new FireWeaponAction(equipment, 3, 500, 0, [new DamageEffect(30, 20)])); - expect(equipment.price).toEqual(100); - expect(equipment.cooldown).toEqual(new Cooldown(2, 2)); - - equipment = template.generate(2); - expect(equipment.requirements).toEqual({ "skill_materials": 2 }); - expect(equipment.action).toEqual(new FireWeaponAction(equipment, 3, 512, 0, [new DamageEffect(42, 28)])); - expect(equipment.price).toEqual(350); - expect(equipment.cooldown).toEqual(new Cooldown(2, 2)); - - equipment = template.generate(3); - expect(equipment.requirements).toEqual({ "skill_materials": 4 }); - expect(equipment.action).toEqual(new FireWeaponAction(equipment, 3, 526, 0, [new DamageEffect(56, 37)])); - expect(equipment.price).toEqual(850); - expect(equipment.cooldown).toEqual(new Cooldown(2, 2)); - - equipment = template.generate(10); - expect(equipment.requirements).toEqual({ "skill_materials": 23 }); - expect(equipment.action).toEqual(new FireWeaponAction(equipment, 3, 694, 0, [new DamageEffect(224, 149)])); - expect(equipment.price).toEqual(11350); - expect(equipment.cooldown).toEqual(new Cooldown(2, 2)); - }); - }); -} diff --git a/src/core/equipments/GatlingGun.ts b/src/core/equipments/GatlingGun.ts deleted file mode 100644 index 828dafc..0000000 --- a/src/core/equipments/GatlingGun.ts +++ /dev/null @@ -1,15 +0,0 @@ -/// - -module TK.SpaceTac.Equipments { - export class GatlingGun extends LootTemplate { - constructor() { - super(SlotType.Weapon, "Gatling Gun", "Mechanical weapon using loads of metal bullets propelled by guided explosions"); - - this.setSkillsRequirements({ "skill_materials": leveled(1, 1.4) }); - this.setCooldown(irepeat(2), irepeat(2)); - this.addFireAction(irepeat(3), leveled(500, 12), irepeat(0), [ - new EffectTemplate(new DamageEffect(), { base: leveled(30), span: leveled(20) }) - ]); - } - } -} diff --git a/src/core/equipments/Generators.spec.ts b/src/core/equipments/Generators.spec.ts new file mode 100644 index 0000000..3cb4021 --- /dev/null +++ b/src/core/equipments/Generators.spec.ts @@ -0,0 +1,91 @@ +module TK.SpaceTac.Equipments { + describe("Generators", function () { + it("generates NuclearReactor based on level", function () { + let template = new NuclearReactor(); + + let equipment = template.generate(1); + expect(equipment.requirements).toEqual({ "skill_photons": 1 }); + expect(equipment.effects).toEqual([ + new AttributeEffect("maneuvrability", 1), + new AttributeEffect("power_capacity", 7), + new AttributeEffect("power_generation", 4), + ]); + expect(equipment.price).toEqual(395); + + equipment = template.generate(2); + expect(equipment.requirements).toEqual({ "skill_photons": 3 }); + expect(equipment.effects).toEqual([ + new AttributeEffect("maneuvrability", 2), + new AttributeEffect("power_capacity", 7), + new AttributeEffect("power_generation", 5), + ]); + expect(equipment.price).toEqual(1382); + + equipment = template.generate(3); + expect(equipment.requirements).toEqual({ "skill_photons": 5 }); + expect(equipment.effects).toEqual([ + new AttributeEffect("maneuvrability", 3), + new AttributeEffect("power_capacity", 8), + new AttributeEffect("power_generation", 5), + ]); + expect(equipment.price).toEqual(3357); + + equipment = template.generate(10); + expect(equipment.requirements).toEqual({ "skill_photons": 33 }); + expect(equipment.effects).toEqual([ + new AttributeEffect("maneuvrability", 10), + new AttributeEffect("power_capacity", 15), + new AttributeEffect("power_generation", 12), + ]); + expect(equipment.price).toEqual(44832); + }) + + it("generates KelvinGenerator based on level", function () { + let template = new KelvinGenerator(); + + let equipment = template.generate(1); + expect(equipment.requirements).toEqual({ "skill_time": 1 }); + expect(equipment.effects).toEqual([ + new AttributeEffect("power_capacity", 5), + new AttributeEffect("power_generation", 4), + ]); + expect(equipment.action).toEqual(new FireWeaponAction(equipment, 1, 0, 0, [ + new CooldownEffect(1, 1) + ])); + expect(equipment.price).toEqual(420); + + equipment = template.generate(2); + expect(equipment.requirements).toEqual({ "skill_time": 2 }); + expect(equipment.effects).toEqual([ + new AttributeEffect("power_capacity", 6), + new AttributeEffect("power_generation", 4), + ]); + expect(equipment.action).toEqual(new FireWeaponAction(equipment, 1, 0, 0, [ + new CooldownEffect(1, 1) + ])); + expect(equipment.price).toEqual(1470); + + equipment = template.generate(3); + expect(equipment.requirements).toEqual({ "skill_time": 4, "skill_gravity": 1 }); + expect(equipment.effects).toEqual([ + new AttributeEffect("power_capacity", 6), + new AttributeEffect("power_generation", 5), + ]); + expect(equipment.action).toEqual(new FireWeaponAction(equipment, 1, 0, 0, [ + new CooldownEffect(1, 1) + ])); + expect(equipment.price).toEqual(3570); + + equipment = template.generate(10); + expect(equipment.requirements).toEqual({ "skill_time": 28, "skill_gravity": 6 }); + expect(equipment.effects).toEqual([ + new AttributeEffect("power_capacity", 13), + new AttributeEffect("power_generation", 12), + ]); + expect(equipment.action).toEqual(new FireWeaponAction(equipment, 7, 0, 0, [ + new CooldownEffect(4, 7) + ])); + expect(equipment.price).toEqual(47670); + }) + }) +} diff --git a/src/core/equipments/Generators.ts b/src/core/equipments/Generators.ts new file mode 100644 index 0000000..9d9e92b --- /dev/null +++ b/src/core/equipments/Generators.ts @@ -0,0 +1,27 @@ +/// + +module TK.SpaceTac.Equipments { + export class NuclearReactor extends LootTemplate { + constructor() { + super(SlotType.Power, "Nuclear Reactor", "A standard nuclear power core, drawing power from atom fusion cycles", 395); + + this.setSkillsRequirements({ "skill_photons": leveled(1, 2) }); + this.addAttributeEffect("maneuvrability", leveled(1, 1, 0)); + this.addAttributeEffect("power_capacity", leveled(7, 0.5)); + this.addAttributeEffect("power_generation", leveled(4.5, 0.5)); + } + } + + export class KelvinGenerator extends LootTemplate { + constructor() { + super(SlotType.Power, "Kelvin Generator", "A power generator operating at ultra-low temperature, improving equipment cooldown", 420); + + this.setSkillsRequirements({ "skill_time": leveled(1, 1.7), "skill_gravity": leveled(0.3, 0.4) }); + this.addAttributeEffect("power_capacity", leveled(5.5, 0.5)); + this.addAttributeEffect("power_generation", leveled(4, 0.5)); + this.addFireAction(leveled(1, 0.4), irepeat(0), irepeat(0), [ + new EffectTemplate(new CooldownEffect(), { cooling: leveled(1, 0.2), maxcount: leveled(1, 0.4) }) + ]) + } + } +} diff --git a/src/core/equipments/NuclearReactor.spec.ts b/src/core/equipments/NuclearReactor.spec.ts deleted file mode 100644 index 8ec2af5..0000000 --- a/src/core/equipments/NuclearReactor.spec.ts +++ /dev/null @@ -1,43 +0,0 @@ -module TK.SpaceTac.Equipments { - describe("NuclearReactor", function () { - it("generates equipment based on level", function () { - let template = new NuclearReactor(); - - let equipment = template.generate(1); - expect(equipment.requirements).toEqual({ "skill_photons": 1 }); - expect(equipment.effects).toEqual([ - new AttributeEffect("maneuvrability", 1), - new AttributeEffect("power_capacity", 7), - new AttributeEffect("power_generation", 4), - ]); - expect(equipment.price).toEqual(395); - - equipment = template.generate(2); - expect(equipment.requirements).toEqual({ "skill_photons": 3 }); - expect(equipment.effects).toEqual([ - new AttributeEffect("maneuvrability", 2), - new AttributeEffect("power_capacity", 7), - new AttributeEffect("power_generation", 5), - ]); - expect(equipment.price).toEqual(1382); - - equipment = template.generate(3); - expect(equipment.requirements).toEqual({ "skill_photons": 5 }); - expect(equipment.effects).toEqual([ - new AttributeEffect("maneuvrability", 3), - new AttributeEffect("power_capacity", 8), - new AttributeEffect("power_generation", 5), - ]); - expect(equipment.price).toEqual(3357); - - equipment = template.generate(10); - expect(equipment.requirements).toEqual({ "skill_photons": 33 }); - expect(equipment.effects).toEqual([ - new AttributeEffect("maneuvrability", 10), - new AttributeEffect("power_capacity", 15), - new AttributeEffect("power_generation", 12), - ]); - expect(equipment.price).toEqual(44832); - }); - }); -} diff --git a/src/core/equipments/NuclearReactor.ts b/src/core/equipments/NuclearReactor.ts deleted file mode 100644 index fdee608..0000000 --- a/src/core/equipments/NuclearReactor.ts +++ /dev/null @@ -1,14 +0,0 @@ -/// - -module TK.SpaceTac.Equipments { - export class NuclearReactor extends LootTemplate { - constructor() { - super(SlotType.Power, "Nuclear Reactor", "A standard nuclear power core, drawing power from atom fusion cycles", 395); - - this.setSkillsRequirements({ "skill_photons": leveled(1, 2) }); - this.addAttributeEffect("maneuvrability", leveled(1, 1, 0)); - this.addAttributeEffect("power_capacity", leveled(7, 0.5)); - this.addAttributeEffect("power_generation", leveled(4.5, 0.5)); - } - } -} diff --git a/src/core/equipments/RawWeapons.spec.ts b/src/core/equipments/RawWeapons.spec.ts new file mode 100644 index 0000000..6a504e4 --- /dev/null +++ b/src/core/equipments/RawWeapons.spec.ts @@ -0,0 +1,87 @@ +module TK.SpaceTac.Equipments { + describe("RawWeapons", function () { + it("generates GatlingGun based on level", function () { + let template = new GatlingGun(); + + let equipment = template.generate(1); + expect(equipment.requirements).toEqual({ "skill_materials": 1 }); + expect(equipment.action).toEqual(new FireWeaponAction(equipment, 3, 500, 0, [new DamageEffect(30, 20)])); + expect(equipment.price).toEqual(100); + expect(equipment.cooldown).toEqual(new Cooldown(2, 2)); + + equipment = template.generate(2); + expect(equipment.requirements).toEqual({ "skill_materials": 2 }); + expect(equipment.action).toEqual(new FireWeaponAction(equipment, 3, 512, 0, [new DamageEffect(42, 28)])); + expect(equipment.price).toEqual(350); + expect(equipment.cooldown).toEqual(new Cooldown(2, 2)); + + equipment = template.generate(3); + expect(equipment.requirements).toEqual({ "skill_materials": 4 }); + expect(equipment.action).toEqual(new FireWeaponAction(equipment, 3, 526, 0, [new DamageEffect(56, 37)])); + expect(equipment.price).toEqual(850); + expect(equipment.cooldown).toEqual(new Cooldown(2, 2)); + + equipment = template.generate(10); + expect(equipment.requirements).toEqual({ "skill_materials": 23 }); + expect(equipment.action).toEqual(new FireWeaponAction(equipment, 3, 694, 0, [new DamageEffect(224, 149)])); + expect(equipment.price).toEqual(11350); + expect(equipment.cooldown).toEqual(new Cooldown(2, 2)); + }); + + it("generates SubMunitionMissile based on level", function () { + let template = new SubMunitionMissile(); + + let equipment = template.generate(1); + expect(equipment.requirements).toEqual({ "skill_materials": 1, "skill_photons": 1 }); + expect(equipment.action).toEqual(new FireWeaponAction(equipment, 4, 500, 150, [new DamageEffect(26, 4)])); + expect(equipment.cooldown).toEqual(new Cooldown(1, 0)); + expect(equipment.price).toEqual(163); + + equipment = template.generate(2); + expect(equipment.requirements).toEqual({ "skill_materials": 2, "skill_photons": 1 }); + expect(equipment.action).toEqual(new FireWeaponAction(equipment, 4, 520, 155, [new DamageEffect(28, 5)])); + expect(equipment.cooldown).toEqual(new Cooldown(1, 0)); + expect(equipment.price).toEqual(570); + + equipment = template.generate(3); + expect(equipment.requirements).toEqual({ "skill_materials": 3, "skill_photons": 2 }); + expect(equipment.action).toEqual(new FireWeaponAction(equipment, 4, 544, 161, [new DamageEffect(30, 6)])); + expect(equipment.cooldown).toEqual(new Cooldown(1, 0)); + expect(equipment.price).toEqual(1385); + + equipment = template.generate(10); + expect(equipment.requirements).toEqual({ "skill_materials": 20, "skill_photons": 13 }); + expect(equipment.action).toEqual(new FireWeaponAction(equipment, 4, 824, 231, [new DamageEffect(58, 20)])); + expect(equipment.cooldown).toEqual(new Cooldown(1, 0)); + expect(equipment.price).toEqual(18500); + }); + + it("generates ProkhorovLaser based on level", function () { + let template = new ProkhorovLaser(); + + let equipment = template.generate(1); + expect(equipment.requirements).toEqual({ "skill_photons": 1 }); + expect(equipment.action).toEqual(new FireWeaponAction(equipment, 5, 0, 250, [new DamageEffect(20, 25)])); + expect(equipment.cooldown).toEqual(new Cooldown(1, 1)); + expect(equipment.price).toEqual(152); + + equipment = template.generate(2); + expect(equipment.requirements).toEqual({ "skill_antimatter": 1, "skill_photons": 2 }); + expect(equipment.action).toEqual(new FireWeaponAction(equipment, 5, 0, 260, [new DamageEffect(28, 35)])); + expect(equipment.cooldown).toEqual(new Cooldown(1, 1)); + expect(equipment.price).toEqual(532); + + equipment = template.generate(3); + expect(equipment.requirements).toEqual({ "skill_antimatter": 1, "skill_photons": 3 }); + expect(equipment.action).toEqual(new FireWeaponAction(equipment, 5, 0, 272, [new DamageEffect(37, 47)])); + expect(equipment.cooldown).toEqual(new Cooldown(1, 1)); + expect(equipment.price).toEqual(1292); + + equipment = template.generate(10); + expect(equipment.requirements).toEqual({ "skill_antimatter": 11, "skill_photons": 22 }); + expect(equipment.action).toEqual(new FireWeaponAction(equipment, 5, 0, 412, [new DamageEffect(149, 187)])); + expect(equipment.cooldown).toEqual(new Cooldown(1, 1)); + expect(equipment.price).toEqual(17252); + }); + }); +} diff --git a/src/core/equipments/RawWeapons.ts b/src/core/equipments/RawWeapons.ts new file mode 100644 index 0000000..caa383d --- /dev/null +++ b/src/core/equipments/RawWeapons.ts @@ -0,0 +1,41 @@ +/// + +module TK.SpaceTac.Equipments { + export class GatlingGun extends LootTemplate { + constructor() { + super(SlotType.Weapon, "Gatling Gun", "Mechanical weapon using loads of metal bullets propelled by guided explosions"); + + this.setSkillsRequirements({ "skill_materials": leveled(1, 1.4) }); + this.setCooldown(irepeat(2), irepeat(2)); + this.addFireAction(irepeat(3), leveled(500, 12), irepeat(0), [ + new EffectTemplate(new DamageEffect(), { base: leveled(30), span: leveled(20) }) + ]); + } + } + + export class SubMunitionMissile extends LootTemplate { + constructor() { + super(SlotType.Weapon, "SubMunition Missile", "Explosive missile releasing small shelled payloads, that will in turn explode on impact", 163); + + this.setSkillsRequirements({ "skill_materials": leveled(1, 1.2), "skill_photons": leveled(1, 0.8) }); + this.setCooldown(irepeat(1), irepeat(0)); + this.addFireAction(irepeat(4), leveled(500, 20), leveled(150, 5), [ + new EffectTemplate(new DamageEffect(), { base: leveled(26, 2), span: leveled(4, 1) }) + ]); + } + } + + export class ProkhorovLaser extends LootTemplate { + constructor() { + super(SlotType.Weapon, "Prokhorov Laser", "Powerful mid-range perforating laser, using antimatter to contain the tremendous photonic energy", 152); + + // TODO increased damage to hull + // TODO cone targetting + this.setSkillsRequirements({ "skill_antimatter": leveled(0.3, 0.7), "skill_photons": leveled(1, 1.3) }); + this.setCooldown(irepeat(1), irepeat(1)); + this.addFireAction(irepeat(5), irepeat(0), leveled(250, 10), [ + new EffectTemplate(new DamageEffect(), { base: leveled(20), span: leveled(25) }) + ]); + } + } +} diff --git a/src/core/equipments/SubMunitionMissile.spec.ts b/src/core/equipments/SubMunitionMissile.spec.ts deleted file mode 100644 index d9a847e..0000000 --- a/src/core/equipments/SubMunitionMissile.spec.ts +++ /dev/null @@ -1,105 +0,0 @@ -module TK.SpaceTac.Equipments { - describe("SubMunitionMissile", function () { - it("generates equipment based on level", function () { - let template = new SubMunitionMissile(); - - let equipment = template.generate(1); - expect(equipment.requirements).toEqual({ "skill_materials": 1, "skill_photons": 1 }); - expect(equipment.action).toEqual(new FireWeaponAction(equipment, 4, 500, 150, [new DamageEffect(26, 4)])); - expect(equipment.cooldown).toEqual(new Cooldown(1, 0)); - expect(equipment.price).toEqual(163); - - equipment = template.generate(2); - expect(equipment.requirements).toEqual({ "skill_materials": 2, "skill_photons": 1 }); - expect(equipment.action).toEqual(new FireWeaponAction(equipment, 4, 520, 155, [new DamageEffect(28, 5)])); - expect(equipment.cooldown).toEqual(new Cooldown(1, 0)); - expect(equipment.price).toEqual(570); - - equipment = template.generate(3); - expect(equipment.requirements).toEqual({ "skill_materials": 3, "skill_photons": 2 }); - expect(equipment.action).toEqual(new FireWeaponAction(equipment, 4, 544, 161, [new DamageEffect(30, 6)])); - expect(equipment.cooldown).toEqual(new Cooldown(1, 0)); - expect(equipment.price).toEqual(1385); - - equipment = template.generate(10); - expect(equipment.requirements).toEqual({ "skill_materials": 20, "skill_photons": 13 }); - expect(equipment.action).toEqual(new FireWeaponAction(equipment, 4, 824, 231, [new DamageEffect(58, 20)])); - expect(equipment.cooldown).toEqual(new Cooldown(1, 0)); - expect(equipment.price).toEqual(18500); - }); - - it("hits several targets in circle", function () { - var battle = TestTools.createBattle(1, 2); - - var ship = battle.fleets[0].ships[0]; - ship.setArenaPosition(0, 0); - TestTools.setShipAP(ship, 100); - TestTools.setShipHP(ship, 50, 30); - var enemy1 = battle.fleets[1].ships[0]; - enemy1.setArenaPosition(1, 0); - TestTools.setShipHP(enemy1, 50, 30); - var enemy2 = battle.fleets[1].ships[1]; - enemy2.setArenaPosition(2, 0); - TestTools.setShipHP(enemy2, 50, 30); - - var template = new Equipments.SubMunitionMissile(); - var equipment = template.generate(1); - let action = nn(equipment.action); - action.range = 5; - action.blast = 1.5; - (action.effects[0]).base = 20; - (action.effects[0]).span = 0; - - var checkHP = (h1: number, s1: number, h2: number, s2: number, h3: number, s3: number): void => { - expect(ship.values.hull.get()).toBe(h1); - expect(ship.values.shield.get()).toBe(s1); - expect(enemy1.values.hull.get()).toBe(h2); - expect(enemy1.values.shield.get()).toBe(s2); - expect(enemy2.values.hull.get()).toBe(h3); - expect(enemy2.values.shield.get()).toBe(s3); - }; - checkHP(50, 30, 50, 30, 50, 30); - - battle.log.clear(); - battle.log.addFilter("value"); - - // Fire at a ship - var target = Target.newFromShip(enemy1); - expect(action.checkCannotBeApplied(ship)).toBe(null); - action.apply(ship, target); - checkHP(50, 10, 50, 10, 50, 10); - expect(battle.log.events.length).toBe(5); - expect(battle.log.events[0]).toEqual(new ActionAppliedEvent(ship, action, Target.newFromLocation(1, 0), 4)); - expect(battle.log.events[1]).toEqual(new FireEvent(ship, equipment, Target.newFromLocation(1, 0))); - expect(battle.log.events[2]).toEqual(new DamageEvent(ship, 0, 20)); - expect(battle.log.events[3]).toEqual(new DamageEvent(enemy1, 0, 20)); - expect(battle.log.events[4]).toEqual(new DamageEvent(enemy2, 0, 20)); - - battle.log.clear(); - equipment.cooldown.cool(); - - // Fire in space - target = Target.newFromLocation(2.4, 0); - expect(action.checkCannotBeApplied(ship)).toBe(null); - action.apply(ship, target); - checkHP(50, 10, 40, 0, 40, 0); - expect(battle.log.events.length).toBe(4); - expect(battle.log.events[0]).toEqual(new ActionAppliedEvent(ship, action, target, 4)); - expect(battle.log.events[1]).toEqual(new FireEvent(ship, equipment, target)); - expect(battle.log.events[2]).toEqual(new DamageEvent(enemy1, 10, 10)); - expect(battle.log.events[3]).toEqual(new DamageEvent(enemy2, 10, 10)); - - battle.log.clear(); - equipment.cooldown.cool(); - - // Fire far away - target = Target.newFromLocation(5, 0); - expect(action.checkCannotBeApplied(ship)).toBe(null); - action.apply(ship, target); - checkHP(50, 10, 40, 0, 40, 0); - expect(battle.log.events.length).toBe(2); - expect(battle.log.events[0]).toEqual(new ActionAppliedEvent(ship, action, target, 4)); - expect(battle.log.events[1]).toEqual(new FireEvent(ship, equipment, target)); - }); - }); -} diff --git a/src/core/equipments/SubMunitionMissile.ts b/src/core/equipments/SubMunitionMissile.ts deleted file mode 100644 index fbbb69d..0000000 --- a/src/core/equipments/SubMunitionMissile.ts +++ /dev/null @@ -1,15 +0,0 @@ -/// - -module TK.SpaceTac.Equipments { - export class SubMunitionMissile extends LootTemplate { - constructor() { - super(SlotType.Weapon, "SubMunition Missile", "Explosive missile releasing small shelled payloads, that will in turn explode on impact", 163); - - this.setSkillsRequirements({ "skill_materials": leveled(1, 1.2), "skill_photons": leveled(1, 0.8) }); - this.setCooldown(irepeat(1), irepeat(0)); - this.addFireAction(irepeat(4), leveled(500, 20), leveled(150, 5), [ - new EffectTemplate(new DamageEffect(), { base: leveled(26, 2), span: leveled(4, 1) }) - ]); - } - } -} diff --git a/yarn.lock b/yarn.lock index a10e7f3..1ee9809 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,13 +2,9 @@ # yarn lockfile v1 -"@types/jasmine@^2.5.53": - version "2.5.53" - resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-2.5.53.tgz#4e0cefad09df5ec48c8dd40433512f84b1568d61" - -"@types/phaser@thunderk/phaser#v2.6.2a": - version "2.6.2" - resolved "https://codeload.github.com/thunderk/phaser/tar.gz/a0390d5540e9c080f9c5c48aae94bafaedc85a0e" +"@types/jasmine@^2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-2.6.0.tgz#997b41a27752b4850af2683bc4a8d8222c25bd02" abbrev@1, abbrev@1.0.x: version "1.0.9" @@ -160,21 +156,28 @@ aws4@^1.2.1: version "1.6.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" -babel-polyfill@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.23.0.tgz#8364ca62df8eafb830499f699177466c3b03499d" +babel-polyfill@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153" dependencies: - babel-runtime "^6.22.0" - core-js "^2.4.0" - regenerator-runtime "^0.10.0" + babel-runtime "^6.26.0" + core-js "^2.5.0" + regenerator-runtime "^0.10.5" -babel-runtime@^6.11.6, babel-runtime@^6.22.0: +babel-runtime@^6.11.6: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b" dependencies: core-js "^2.4.0" regenerator-runtime "^0.10.0" +babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + backo2@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" @@ -462,6 +465,10 @@ core-js@^2.2.0, core-js@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e" +core-js@^2.5.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.1.tgz#ae6874dc66937789b80754ff5428df66819ca50b" + core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -1308,21 +1315,17 @@ istanbul@0.4.5, istanbul@^0.4.0: which "^1.1.1" wordwrap "^1.0.0" -jasmine-core@^2.6.3: - version "2.6.4" - resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.6.4.tgz#dec926cd0a9fa287fb6db5c755fa487e74cecac5" +jasmine-core@^2.8.0, jasmine-core@~2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.8.0.tgz#bcc979ae1f9fd05701e45e52e65d3a5d63f1a24e" -jasmine-core@~2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.7.0.tgz#50ff8c4f92d8ef5c0b2c1b846dd263ed85152091" - -jasmine@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-2.7.0.tgz#5cf0bb4e594b4600bb4235560366212ac5aea1b2" +jasmine@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-2.8.0.tgz#6b089c0a11576b1f16df11b80146d91d4e8b8a3e" dependencies: exit "^0.1.2" glob "^7.0.6" - jasmine-core "~2.7.0" + jasmine-core "~2.8.0" js-yaml@3.x: version "3.8.4" @@ -2126,10 +2129,14 @@ redent@^1.0.0: indent-string "^2.1.0" strip-indent "^1.0.1" -regenerator-runtime@^0.10.0: +regenerator-runtime@^0.10.0, regenerator-runtime@^0.10.5: version "0.10.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" +regenerator-runtime@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz#7e54fe5b5ccd5d6624ea6255c3473be090b802e1" + regex-cache@^0.4.2: version "0.4.3" resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145" @@ -2577,9 +2584,9 @@ typedarray@~0.0.5: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" -typescript@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.4.2.tgz#f8395f85d459276067c988aa41837a8f82870844" +typescript@^2.5.3: + version "2.5.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.5.3.tgz#df3dcdc38f3beb800d4bc322646b04a3f6ca7f0d" uglify-js@^2.6: version "2.8.29"