1
0
Fork 0

Improved character sheet tooltips

This commit is contained in:
Michaël Lemaire 2018-03-06 15:39:48 +01:00
parent 41f9b1ad6f
commit 69a65b0735
28 changed files with 795 additions and 662 deletions

File diff suppressed because it is too large Load diff

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 95 KiB

@ -1 +1 @@
Subproject commit 2882c791e8af845517fd030c6e789296d347213d
Subproject commit 0fcd953719ed8dbaab92cfaf525a2e34078b069a

View file

@ -15,7 +15,7 @@ module TK.SpaceTac {
var fleet = new Fleet(player);
var ship_generator = new ShipGenerator(this.random);
let models = this.random.sample(BaseModel.getDefaultCollection(), ship_count);
let models = this.random.sample(ShipModel.getDefaultCollection(), ship_count);
range(ship_count).forEach(i => {
var ship = ship_generator.generate(level, models[i] || null, upgrade);

View file

@ -5,7 +5,7 @@ module TK.SpaceTac.Specs {
check.equals(ship.getName(false), "Ship");
check.equals(ship.getName(true), "Level 1 Ship");
ship.model = new BaseModel("test", "Hauler");
ship.model = new ShipModel("test", "Hauler");
check.equals(ship.getName(false), "Hauler");
check.equals(ship.getName(true), "Level 1 Hauler");
@ -35,7 +35,7 @@ module TK.SpaceTac.Specs {
});
test.case("applies permanent effects of ship model on attributes", check => {
let model = new BaseModel();
let model = new ShipModel();
let ship = new Ship(null, null, model);
check.patch(model, "getEffects", () => [
@ -151,17 +151,19 @@ module TK.SpaceTac.Specs {
let ship = new Ship();
check.equals(ship.getAttributeDescription("maneuvrability"), "Ability to move first, fast and to evade weapons");
check.patch(ship.model, "getEffects", () => [new AttributeEffect("maneuvrability", 4)]);
ship.updateAttributes();
check.equals(ship.getAttribute("maneuvrability"), 4);
check.equals(ship.getAttributeDescription("maneuvrability"), "Ability to move first, fast and to evade weapons\n\nLevel 1 Ship: +4");
check.patch(ship, "getUpgrades", () => [
{ code: "Base", effects: [new AttributeEffect("maneuvrability", 3)] },
{ code: "Up1", effects: [new AttributeEffect("precision", 1)] },
{ code: "Up2", effects: [new AttributeEffect("precision", 1), new AttributeEffect("maneuvrability", 1)] }
]);
check.equals(ship.getAttributeDescription("maneuvrability"), "Ability to move first, fast and to evade weapons\n\nBase: +3\nUp2: +1");
ship.active_effects.add(new StickyEffect(new AttributeLimitEffect("maneuvrability", 3)));
check.equals(ship.getAttributeDescription("maneuvrability"), "Ability to move first, fast and to evade weapons\n\nLevel 1 Ship: +4\nSticky effect: limit to 3");
check.equals(ship.getAttributeDescription("maneuvrability"), "Ability to move first, fast and to evade weapons\n\nBase: +3\nUp2: +1\nSticky effect: limit to 3");
ship.active_effects.remove(ship.active_effects.list()[0]);
ship.active_effects.add(new AttributeEffect("maneuvrability", -1));
check.equals(ship.getAttributeDescription("maneuvrability"), "Ability to move first, fast and to evade weapons\n\nLevel 1 Ship: +4\nActive effect: -1");
check.equals(ship.getAttributeDescription("maneuvrability"), "Ability to move first, fast and to evade weapons\n\nBase: +3\nUp2: +1\nActive effect: -1");
});
test.case("produces death diffs", check => {

View file

@ -6,7 +6,7 @@ module TK.SpaceTac {
*/
export class Ship extends RObject {
// Ship model
model: BaseModel
model: ShipModel
// Fleet this ship is a member of
fleet: Fleet
@ -52,7 +52,7 @@ module TK.SpaceTac {
play_priority = 0
// Create a new ship inside a fleet
constructor(fleet: Fleet | null = null, name: string | null = null, model = new BaseModel()) {
constructor(fleet: Fleet | null = null, name: string | null = null, model = new ShipModel()) {
super();
this.fleet = fleet || new Fleet();
@ -139,14 +139,14 @@ module TK.SpaceTac {
/**
* Get the list of activated upgrades
*/
getUpgrades(): ModelUpgrade[] {
getUpgrades(): ShipUpgrade[] {
return this.model.getActivatedUpgrades(this.level.get(), this.level.getUpgrades());
}
/**
* Toggle an upgrade
*/
activateUpgrade(upgrade: ModelUpgrade, on: boolean): void {
activateUpgrade(upgrade: ShipUpgrade, on: boolean): void {
if (on && (upgrade.cost || 0) > this.getAvailableUpgradePoints()) {
return;
}
@ -402,8 +402,10 @@ module TK.SpaceTac {
}
}
this.getModelEffects().forEach(effect => {
addEffect(`Level ${this.level.get()} ${this.model.name}`, effect);
this.getUpgrades().forEach(upgrade => {
if (upgrade.effects) {
upgrade.effects.forEach(effect => addEffect(upgrade.code, effect));
}
});
this.active_effects.list().forEach(effect => {

View file

@ -2,7 +2,7 @@ module TK.SpaceTac.Specs {
testing("ShipGenerator", test => {
test.case("can use ship model", check => {
var gen = new ShipGenerator();
var model = new BaseModel("test", "Test");
var model = new ShipModel("test", "Test");
var ship = gen.generate(3, model, false);
check.same(ship.model, model);
check.same(ship.level.get(), 3);

View file

@ -15,10 +15,10 @@ module TK.SpaceTac {
*
* If *upgrade* is true, random levelling options will be chosen
*/
generate(level: number, model: BaseModel | null = null, upgrade = true): Ship {
generate(level: number, model: ShipModel | null = null, upgrade = true): Ship {
if (!model) {
// Get a random model
model = BaseModel.getRandomModel(level, this.random);
model = ShipModel.getRandomModel(level, this.random);
}
let result = new Ship(null, null, model);

View file

@ -94,7 +94,7 @@ module TK.SpaceTac {
*
* This does not check the upgrade points needed
*/
activateUpgrade(upgrade: ModelUpgrade, active: boolean): void {
activateUpgrade(upgrade: ShipUpgrade, active: boolean): void {
if (active) {
add(this.upgrades, upgrade.code);
} else {
@ -105,7 +105,7 @@ module TK.SpaceTac {
/**
* Check if an upgrade is active
*/
hasUpgrade(upgrade: ModelUpgrade): boolean {
hasUpgrade(upgrade: ShipUpgrade): boolean {
return contains(this.upgrades, upgrade.code);
}
}

View file

@ -58,7 +58,7 @@ module TK.SpaceTac {
* Set a ship attributes (by changing its model)
*/
static setShipModel(ship: Ship, hull: number, shield = 0, power = 0, level = 1, actions: BaseAction[] = [], effects: BaseEffect[] = []) {
let model = new BaseModel();
let model = new ShipModel();
ship.level.forceLevel(level);
ship.model = model;

View file

@ -4,7 +4,7 @@ module TK.SpaceTac.Specs {
let actions = new ActionList();
check.equals(actions.listAll(), [EndTurnAction.SINGLETON]);
let model = new BaseModel();
let model = new ShipModel();
let ship = new Ship(null, null, model);
actions.updateFromShip(ship);
check.equals(actions.listAll(), [EndTurnAction.SINGLETON]);
@ -17,8 +17,8 @@ module TK.SpaceTac.Specs {
check.equals(actions.listAll(), [action1, action2, EndTurnAction.SINGLETON]);
check.called(mock, [[3, []]]);
let up1: ModelUpgrade = { code: "up1" };
let up2: ModelUpgrade = { code: "up2" };
let up1: ShipUpgrade = { code: "up1" };
let up2: ShipUpgrade = { code: "up2" };
check.patch(model, "getLevelUpgrades", () => [up1, up2]);
ship.level.activateUpgrade(up1, true);
actions.updateFromShip(ship);

View file

@ -1,7 +1,7 @@
/// <reference path="BaseModel.ts" />
/// <reference path="ShipModel.ts" />
module TK.SpaceTac {
export class ModelAvenger extends BaseModel {
export class ModelAvenger extends ShipModel {
constructor() {
super("avenger", "Avenger");
}
@ -10,7 +10,7 @@ module TK.SpaceTac {
return "A heavy ship, dedicated to firing high precision charged shots across great distances.";
}
getLevelUpgrades(level: number): ModelUpgrade[] {
getLevelUpgrades(level: number): ShipUpgrade[] {
let engine = new MoveAction("Engine", {
distance_per_power: 50,
safety_distance: 250,
@ -35,19 +35,10 @@ module TK.SpaceTac {
}, "submunitionmissile");
long_range_missile.configureCooldown(1, 2);
let shield_booster = new TriggerAction("Shield Booster", {
effects: [
new StickyEffect(new AttributeEffect("shield_capacity", 50), 2),
new ValueEffect("shield", 70),
],
power: 2
}, "forcefield");
shield_booster.configureCooldown(1, 4);
if (level == 1) {
return [
{
code: "Base Attributes",
code: "Avenger Base",
effects: [
new AttributeEffect("precision", 8),
new AttributeEffect("maneuvrability", 0),
@ -73,28 +64,41 @@ module TK.SpaceTac {
return [
{
code: "Laser Targetting",
description: "Improved targetting, using fine-grained laser sensors",
cost: 1,
effects: [new AttributeEffect("precision", 2)]
effects: [new AttributeEffect("precision", 2)],
},
{
code: "Basic Countermeasures",
description: "Chaffs and lures to divert enemy fire",
cost: 1,
effects: [new AttributeEffect("maneuvrability", 2)]
effects: [new AttributeEffect("maneuvrability", 2)],
},
{
code: "Targetting Assist",
description: "Share your targetting subnetwork with nearby ships",
cost: 3,
actions: [new ToggleAction("Targetting Assist", {
power: 3,
radius: 300,
effects: [new AttributeEffect("precision", 2)]
}, "precisionboost")]
}, "precisionboost")],
},
];
} else if (level == 3) {
let shield_booster = new TriggerAction("Shield Booster", {
effects: [
new StickyEffect(new AttributeEffect("shield_capacity", 50), 2),
new ValueEffect("shield", 70),
],
power: 2
}, "forcefield");
shield_booster.configureCooldown(1, 4);
return [
{
code: "Gyroscopic Stabilizers",
description: "Heavy mercury gyroscopes, used to stabilize the whole ship while firing",
cost: 1,
effects: [
new AttributeEffect("precision", 3),
@ -103,11 +107,13 @@ module TK.SpaceTac {
},
{
code: "Shield Booster",
description: "Temporary power surge directed toward the shield mainframe, to boost its output",
cost: 3,
actions: [shield_booster]
},
{
code: "Hard Coated Hull",
description: "Improved metal coating of outer hull layers, making them more damage resistant",
cost: 2,
effects: [new AttributeEffect("hull_capacity", 10)]
},

View file

@ -1,7 +1,7 @@
/// <reference path="BaseModel.ts" />
/// <reference path="ShipModel.ts" />
module TK.SpaceTac {
export class ModelBreeze extends BaseModel {
export class ModelBreeze extends ShipModel {
constructor() {
super("breeze", "Breeze");
}
@ -10,7 +10,7 @@ module TK.SpaceTac {
return "A swift piece of maneuvrability, able to go deep behind enemy lines, and come back without a scratch.";
}
getLevelUpgrades(level: number): ModelUpgrade[] {
getLevelUpgrades(level: number): ShipUpgrade[] {
if (level == 1) {
let engine = new MoveAction("Engine", {
distance_per_power: 300,
@ -36,7 +36,7 @@ module TK.SpaceTac {
return [
{
code: "Base Attributes",
code: "Breeze Base",
effects: [
new AttributeEffect("precision", 3),
new AttributeEffect("maneuvrability", 12),

View file

@ -1,7 +1,7 @@
/// <reference path="BaseModel.ts" />
/// <reference path="ShipModel.ts" />
module TK.SpaceTac {
export class ModelCommodore extends BaseModel {
export class ModelCommodore extends ShipModel {
constructor() {
super("commodore", "Commodore");
}
@ -10,7 +10,7 @@ module TK.SpaceTac {
return "A devil whirlwind, very dangerous to surround.";
}
getLevelUpgrades(level: number): ModelUpgrade[] {
getLevelUpgrades(level: number): ShipUpgrade[] {
if (level == 1) {
let engine = new MoveAction("Engine", {
distance_per_power: 150,
@ -33,7 +33,7 @@ module TK.SpaceTac {
return [
{
code: "Base Attributes",
code: "Commodore Base",
effects: [
new AttributeEffect("precision", 5),
new AttributeEffect("maneuvrability", 6),

View file

@ -1,7 +1,7 @@
/// <reference path="BaseModel.ts" />
/// <reference path="ShipModel.ts" />
module TK.SpaceTac {
export class ModelCreeper extends BaseModel {
export class ModelCreeper extends ShipModel {
constructor() {
super("creeper", "Creeper");
}
@ -10,7 +10,7 @@ module TK.SpaceTac {
return "A fast ship, with low firepower but extensive support modules.";
}
getLevelUpgrades(level: number): ModelUpgrade[] {
getLevelUpgrades(level: number): ShipUpgrade[] {
if (level == 1) {
let engine = new MoveAction("Engine", {
distance_per_power: 220,
@ -40,7 +40,7 @@ module TK.SpaceTac {
return [
{
code: "Base Attributes",
code: "Creeper Base",
effects: [
new AttributeEffect("precision", 3),
new AttributeEffect("maneuvrability", 12),

View file

@ -1,7 +1,7 @@
/// <reference path="BaseModel.ts" />
/// <reference path="ShipModel.ts" />
module TK.SpaceTac {
export class ModelFalcon extends BaseModel {
export class ModelFalcon extends ShipModel {
constructor() {
super("falcon", "Falcon");
}
@ -10,7 +10,7 @@ module TK.SpaceTac {
return "A ship with an efficient targetting system, allowing to hit multiple foes.";
}
getLevelUpgrades(level: number): ModelUpgrade[] {
getLevelUpgrades(level: number): ShipUpgrade[] {
if (level == 1) {
let engine = new MoveAction("Engine", {
distance_per_power: 130,
@ -32,7 +32,7 @@ module TK.SpaceTac {
return [
{
code: "Base Attributes",
code: "Falcon Base",
effects: [
new AttributeEffect("precision", 8),
new AttributeEffect("maneuvrability", 4),

View file

@ -1,7 +1,7 @@
/// <reference path="BaseModel.ts" />
/// <reference path="ShipModel.ts" />
module TK.SpaceTac {
export class ModelFlea extends BaseModel {
export class ModelFlea extends ShipModel {
constructor() {
super("flea", "Flea");
}
@ -10,7 +10,7 @@ module TK.SpaceTac {
return "An agile but weak ship, specialized in disruptive technologies.";
}
getLevelUpgrades(level: number): ModelUpgrade[] {
getLevelUpgrades(level: number): ShipUpgrade[] {
if (level == 1) {
let engine = new MoveAction("Engine", {
distance_per_power: 400,
@ -32,7 +32,7 @@ module TK.SpaceTac {
return [
{
code: "Base Attributes",
code: "Flea Base",
effects: [
new AttributeEffect("precision", 0),
new AttributeEffect("maneuvrability", 15),

View file

@ -1,7 +1,7 @@
/// <reference path="BaseModel.ts" />
/// <reference path="ShipModel.ts" />
module TK.SpaceTac {
export class ModelJumper extends BaseModel {
export class ModelJumper extends ShipModel {
constructor() {
super("jumper", "Jumper");
}
@ -10,7 +10,7 @@ module TK.SpaceTac {
return "A mid-range action ship, with support abilities.";
}
getLevelUpgrades(level: number): ModelUpgrade[] {
getLevelUpgrades(level: number): ShipUpgrade[] {
if (level == 1) {
let engine = new MoveAction("Engine", {
distance_per_power: 200,
@ -38,7 +38,7 @@ module TK.SpaceTac {
return [
{
code: "Base Attributes",
code: "Jumper Base",
effects: [
new AttributeEffect("precision", 9),
new AttributeEffect("maneuvrability", 3),

View file

@ -1,7 +1,7 @@
/// <reference path="BaseModel.ts" />
/// <reference path="ShipModel.ts" />
module TK.SpaceTac {
export class ModelRhino extends BaseModel {
export class ModelRhino extends ShipModel {
constructor() {
super("rhino", "Rhino");
}
@ -10,7 +10,7 @@ module TK.SpaceTac {
return "A sturdy ship, able to sustain massive damage.";
}
getLevelUpgrades(level: number): ModelUpgrade[] {
getLevelUpgrades(level: number): ShipUpgrade[] {
if (level == 1) {
let engine = new MoveAction("Engine", {
distance_per_power: 140,
@ -32,7 +32,7 @@ module TK.SpaceTac {
return [
{
code: "Base Attributes",
code: "Rhino Base",
effects: [
new AttributeEffect("precision", 4),
new AttributeEffect("maneuvrability", 3),

View file

@ -1,7 +1,7 @@
/// <reference path="BaseModel.ts" />
/// <reference path="ShipModel.ts" />
module TK.SpaceTac {
export class ModelTomahawk extends BaseModel {
export class ModelTomahawk extends ShipModel {
constructor() {
super("tomahawk", "Tomahawk");
}
@ -10,7 +10,7 @@ module TK.SpaceTac {
return "A ship compensating its somewhat weak equipments with high power and usability.";
}
getLevelUpgrades(level: number): ModelUpgrade[] {
getLevelUpgrades(level: number): ShipUpgrade[] {
if (level == 1) {
let engine = new MoveAction("Engine", {
distance_per_power: 160,
@ -49,7 +49,7 @@ module TK.SpaceTac {
return [
{
code: "Base Attributes",
code: "Tomahawk Base",
effects: [
new AttributeEffect("precision", 8),
new AttributeEffect("maneuvrability", 3),

View file

@ -1,7 +1,7 @@
/// <reference path="BaseModel.ts" />
/// <reference path="ShipModel.ts" />
module TK.SpaceTac {
export class ModelTrapper extends BaseModel {
export class ModelTrapper extends ShipModel {
constructor() {
super("trapper", "Trapper");
}
@ -10,7 +10,7 @@ module TK.SpaceTac {
return "A mostly defensive ship, used to protect allies from enemy fire.";
}
getLevelUpgrades(level: number): ModelUpgrade[] {
getLevelUpgrades(level: number): ShipUpgrade[] {
if (level == 1) {
let engine = new MoveAction("Engine", {
distance_per_power: 220,
@ -38,7 +38,7 @@ module TK.SpaceTac {
return [
{
code: "Base Attributes",
code: "Trapper Base",
effects: [
new AttributeEffect("precision", 3),
new AttributeEffect("maneuvrability", 2),

View file

@ -1,7 +1,7 @@
/// <reference path="BaseModel.ts" />
/// <reference path="ShipModel.ts" />
module TK.SpaceTac {
export class ModelXander extends BaseModel {
export class ModelXander extends ShipModel {
constructor() {
super("xander", "Xander");
}
@ -10,7 +10,7 @@ module TK.SpaceTac {
return "A ship with impressive survival capabilities.";
}
getLevelUpgrades(level: number): ModelUpgrade[] {
getLevelUpgrades(level: number): ShipUpgrade[] {
if (level == 1) {
let engine = new MoveAction("Engine", {
distance_per_power: 150,
@ -37,7 +37,7 @@ module TK.SpaceTac {
return [
{
code: "Base Attributes",
code: "Xander Base",
effects: [
new AttributeEffect("precision", 8),
new AttributeEffect("maneuvrability", 5),

View file

@ -1,25 +1,25 @@
module TK.SpaceTac.Specs {
testing("BaseModel", test => {
testing("ShipModel", test => {
test.case("picks random models from default collection", check => {
check.patch(console, "error", null);
check.patch(BaseModel, "getDefaultCollection", iterator([
[new BaseModel("a")],
check.patch(ShipModel, "getDefaultCollection", iterator([
[new ShipModel("a")],
[],
[new BaseModel("a"), new BaseModel("b")],
[new BaseModel("a")],
[new ShipModel("a"), new ShipModel("b")],
[new ShipModel("a")],
[],
]));
check.equals(BaseModel.getRandomModel(), new BaseModel("a"), "pick from a one-item list");
check.equals(BaseModel.getRandomModel(), new BaseModel(), "pick from an empty list");
check.equals(ShipModel.getRandomModel(), new ShipModel("a"), "pick from a one-item list");
check.equals(ShipModel.getRandomModel(), new ShipModel(), "pick from an empty list");
check.equals(sorted(BaseModel.getRandomModels(2), (a, b) => cmp(a.code, b.code)), [new BaseModel("a"), new BaseModel("b")], "sample from good-sized list");
check.equals(BaseModel.getRandomModels(2), [new BaseModel("a"), new BaseModel("a")], "sample from too small list");
check.equals(BaseModel.getRandomModels(2), [new BaseModel(), new BaseModel()], "sample from empty list");
check.equals(sorted(ShipModel.getRandomModels(2), (a, b) => cmp(a.code, b.code)), [new ShipModel("a"), new ShipModel("b")], "sample from good-sized list");
check.equals(ShipModel.getRandomModels(2), [new ShipModel("a"), new ShipModel("a")], "sample from too small list");
check.equals(ShipModel.getRandomModels(2), [new ShipModel(), new ShipModel()], "sample from empty list");
});
test.case("makes upgrades available by level", check => {
let model = new BaseModel();
let model = new ShipModel();
function verify(desc: string, level: number, specific: string[], available: string[], activated: string[], chosen: string[] = []) {
check.in(`${desc} level ${level}`, check => {
@ -31,7 +31,7 @@ module TK.SpaceTac.Specs {
verify("initial", 1, [], [], []);
check.patch(model, "getLevelUpgrades", (level: number): ModelUpgrade[] => {
check.patch(model, "getLevelUpgrades", (level: number): ShipUpgrade[] => {
if (level == 1) {
return [
{ code: "l1" },

View file

@ -4,11 +4,13 @@ module TK.SpaceTac {
*
* Upgrades allow for customizing a model, and are unlocked at given levels
*/
export type ModelUpgrade = {
export type ShipUpgrade = {
// Displayable upgrade name, should be unique on the model
code: string
// Upgrade points cost (may be used to balance upgrades)
cost?: number
// Textual description of the upgrade
description?: string
// Optional list of upgrade codes that must be activated for this one to be available
depends?: string[]
// Optional list of upgrade codes that this upgrade will fully replace
@ -26,7 +28,7 @@ module TK.SpaceTac {
*
* A model defines the ship's design, actions, permanent effects, and levelling options.
*/
export class BaseModel {
export class ShipModel {
constructor(
// Code to identify the model
readonly code = "default",
@ -52,7 +54,7 @@ module TK.SpaceTac {
/**
* Get basic level upgrades
*/
protected getStandardUpgrades(level: number): ModelUpgrade[] {
protected getStandardUpgrades(level: number): ShipUpgrade[] {
return [
{ code: `Hull upgrade Lv${level - 1}`, effects: [new AttributeEffect("hull_capacity", 5)], cost: 2 },
{ code: `Shield upgrade Lv${level - 1}`, effects: [new AttributeEffect("shield_capacity", 5)], cost: 2 },
@ -63,15 +65,15 @@ module TK.SpaceTac {
/**
* Get the list of upgrades unlocked at a given level
*/
getLevelUpgrades(level: number): ModelUpgrade[] {
getLevelUpgrades(level: number): ShipUpgrade[] {
return [];
}
/**
* Get the list of upgrades activated, given a ship level and an upgrade set
*/
getActivatedUpgrades(level: number, upgrade_codes: string[]): ModelUpgrade[] {
let result: ModelUpgrade[] = [];
getActivatedUpgrades(level: number, upgrade_codes: string[]): ShipUpgrade[] {
let result: ShipUpgrade[] = [];
range(level).forEach(i => {
let upgrades = this.getLevelUpgrades(i + 1);
@ -95,7 +97,7 @@ module TK.SpaceTac {
*
* This does not filter the upgrades on dependencies
*/
getAvailableUpgrades(level: number): ModelUpgrade[] {
getAvailableUpgrades(level: number): ShipUpgrade[] {
return flatten(range(level).map(i => this.getLevelUpgrades(i + 1)));
}
@ -120,14 +122,14 @@ module TK.SpaceTac {
*
* This scans the current namespace for model classes starting with 'Model'.
*/
static getDefaultCollection(): BaseModel[] {
let result: BaseModel[] = [];
static getDefaultCollection(): ShipModel[] {
let result: ShipModel[] = [];
let namespace: any = TK.SpaceTac;
for (let class_name in namespace) {
if (class_name && class_name.indexOf("Model") == 0) {
let model_class = namespace[class_name];
if (model_class.prototype instanceof BaseModel) {
if (model_class.prototype instanceof ShipModel) {
let model = new model_class();
result.push(model);
}
@ -140,15 +142,15 @@ module TK.SpaceTac {
/**
* Pick a random model in the default collection
*/
static getRandomModel(level?: number, random = RandomGenerator.global): BaseModel {
let collection = BaseModel.getDefaultCollection();
static getRandomModel(level?: number, random = RandomGenerator.global): ShipModel {
let collection = ShipModel.getDefaultCollection();
if (level) {
collection = collection.filter(model => model.isAvailable(level));
}
if (collection.length == 0) {
console.error("Couldn't pick a random ship model");
return new BaseModel();
return new ShipModel();
} else {
return random.choice(collection);
}
@ -159,17 +161,17 @@ module TK.SpaceTac {
*
* At first it tries to pick unique models, then fill with duplicates
*/
static getRandomModels(count: number, level?: number, random = RandomGenerator.global): BaseModel[] {
let collection = BaseModel.getDefaultCollection();
static getRandomModels(count: number, level?: number, random = RandomGenerator.global): ShipModel[] {
let collection = ShipModel.getDefaultCollection();
if (level) {
collection = collection.filter(model => model.isAvailable(level));
}
if (collection.length == 0) {
console.error("Couldn't pick a random model");
return range(count).map(() => new BaseModel());
return range(count).map(() => new ShipModel());
} else {
let result: BaseModel[] = [];
let result: ShipModel[] = [];
while (count > 0) {
let picked = random.sample(collection, Math.min(count, collection.length));
result = result.concat(picked);

View file

@ -7,7 +7,7 @@ module TK.SpaceTac.UI.Specs {
let ship = testgame.view.battle.play_order[2];
TestTools.setShipModel(ship, 58, 140, 12);
ship.name = "Fury";
ship.model = new BaseModel("fake", "Fury");
ship.model = new ShipModel("fake", "Fury");
check.patch(ship.model, "getDescription", () => "Super ship model !");
TestTools.addWeapon(ship, 50);
TestTools.setAttribute(ship, "precision", 7);

View file

@ -0,0 +1,75 @@
/// <reference path="../TestGame.ts"/>
module TK.SpaceTac.UI.Specs {
testing("CharacterUpgrade", test => {
let testgame = setupSingleView(test, () => [new BaseView(), []]);
test.acase("fills tooltip content", async check => {
let ship = new Ship();
let upgrade: ShipUpgrade = {
code: "Test Upgrade",
description: "A super ship upgrade",
effects: [
new AttributeEffect("hull_capacity", 10),
new AttributeEffect("shield_capacity", 5),
]
};
let display = new CharacterUpgrade(ship, upgrade, 3);
let tooltip = new TooltipContainer(testgame.view);
let builder = new TooltipBuilder(tooltip);
display.fillTooltip(builder);
check.equals(cfilter(tooltip.content.children, Phaser.Text).map(child => child.text), [
"Test Upgrade",
"Permanent effects:",
"• hull capacity +10",
"• shield capacity +5",
"A super ship upgrade",
]);
upgrade.effects = [];
upgrade.actions = [new TriggerAction("Test action", {
range: 50,
effects: [new DamageEffect(10)]
})];
builder.clear();
display.fillTooltip(builder);
check.equals(cfilter(tooltip.content.children, Phaser.Text).map(child => child.text), [
"Test Upgrade",
"Fire (power 1, range 50km):",
"• do 10 damage on target",
"A super ship upgrade",
]);
})
test.acase("gets an appropriate icon", async check => {
let ship = new Ship();
let upgrade: ShipUpgrade = {
code: "Test Upgrade",
effects: [
new AttributeEffect("hull_capacity", 10),
new AttributeEffect("shield_capacity", 5),
]
};
let display = new CharacterUpgrade(ship, upgrade, 3);
check.equals(display.getIcon(), "attribute-hull_capacity");
upgrade.effects = [];
upgrade.actions = [new BaseAction("Test Action")];
check.equals(display.getIcon(), "action-testaction");
upgrade.actions = [];
check.equals(display.getIcon(), "translucent");
upgrade.effects = [new DamageEffect(10)];
check.equals(display.getIcon(), "translucent");
upgrade.effects = [
new DamageEffect(10),
new AttributeMultiplyEffect("precision", 2)
];
check.equals(display.getIcon(), "attribute-precision");
})
})
}

View file

@ -5,7 +5,7 @@ module TK.SpaceTac.UI {
export class CharacterUpgrade {
constructor(
readonly ship: Ship,
readonly upgrade: ModelUpgrade,
readonly upgrade: ShipUpgrade,
readonly level: number
) {
}
@ -28,7 +28,7 @@ module TK.SpaceTac.UI {
if (enabled) {
builder.text(this.upgrade.code, 166, 40, { size: 16, color: "#e7ebf0", width: 210 });
let icon = builder.image(this.getIcon(this.upgrade), 40, 40, true);
let icon = builder.image(this.getIcon(), 40, 40, true);
if (icon.width && icon.width > 64) {
icon.scale.set(64 / icon.width);
}
@ -60,32 +60,43 @@ module TK.SpaceTac.UI {
/**
* Fill the tooltip for this upgrade
*/
private fillTooltip(builder: TooltipBuilder): boolean {
fillTooltip(builder: TooltipBuilder): boolean {
builder.text(this.upgrade.code, 0, 0, { size: 20 });
let y = 30;
let y = 42;
if (this.upgrade.effects) {
if (bool(this.upgrade.effects)) {
builder.text("Permanent effects:", 0, y);
y += 30;
this.upgrade.effects.forEach(effect => {
builder.text(effect.getDescription(), 0, y);
builder.text(`${effect.getDescription()}`, 0, y);
y += 30;
});
}
if (this.upgrade.actions) {
if (bool(this.upgrade.actions)) {
this.upgrade.actions.forEach(action => {
builder.text(action.getEffectsDescription(), 0, y);
y += 60;
action.getEffectsDescription().split('\n').forEach(line => {
builder.text(line, 0, y);
y += 30;
})
});
}
if (bool(this.upgrade.description)) {
y += 10;
builder.text(this.upgrade.description, 0, y, { size: 14, color: "#999999", width: 540 });
}
return true;
}
/**
* Get an icon code for an upgrade
*/
private getIcon(upgrade: ModelUpgrade): string {
getIcon(): string {
let upgrade = this.upgrade;
if (upgrade.actions && upgrade.actions.length) {
return `action-${upgrade.actions[0].code}`;
} else if (upgrade.effects && upgrade.effects.length) {

View file

@ -12,7 +12,7 @@ module TK.SpaceTac.UI {
create() {
super.create();
let models = BaseModel.getRandomModels(2);
let models = ShipModel.getRandomModels(2);
this.built_fleet = new Fleet();
this.built_fleet.addShip(new Ship(null, MissionGenerator.generateCharacterName(), models[0]));

View file

@ -4,7 +4,7 @@ module TK.SpaceTac.UI {
export type TooltipFiller = string | ((filler: TooltipBuilder) => string) | ((filler: TooltipBuilder) => boolean);
class TooltipContainer extends Phaser.Group {
export class TooltipContainer extends Phaser.Group {
view: BaseView
background: Phaser.Graphics
content: Phaser.Group