diff --git a/TODO.md b/TODO.md
index f32d1a6..70298d4 100644
--- a/TODO.md
+++ b/TODO.md
@@ -26,7 +26,7 @@ Character sheet
* Highlight allowed destinations during drag-and-drop, with text hints
* When transferring to another ship, if the item can't be equipped (unmatched requirements), the transfer is cancelled instead of trying cargo
* Effective skill is sometimes not updated when upgrading base skill
-* Tooltip to show the sources of attributes
+* Tooltip to show the sources of attributes [WIP]
* Forbid to modify escorted ship
* Add merged cargo display for the whole fleet
diff --git a/src/core/Ship.spec.ts b/src/core/Ship.spec.ts
index 64d2869..eb020a6 100644
--- a/src/core/Ship.spec.ts
+++ b/src/core/Ship.spec.ts
@@ -576,5 +576,25 @@ module TS.SpaceTac.Specs {
new AttributeLimitEffect("precision", 2)
]);
});
+
+ it("gets a textual description of an attribute", function () {
+ let ship = new Ship();
+ expect(ship.getAttributeDescription("skill_photons")).toEqual("Forces of light, and electromagnetic radiation");
+
+ let equipment = new Equipment(SlotType.Engine);
+ equipment.effects = [new AttributeEffect("skill_photons", 4)];
+ equipment.name = "Photonic engine";
+ ship.addSlot(SlotType.Engine).attach(equipment);
+ expect(ship.getAttribute("skill_photons")).toBe(4);
+ expect(ship.getAttributeDescription("skill_photons")).toEqual("Forces of light, and electromagnetic radiation\n\nPhotonic engine Mk1: +4");
+
+ ship.level.forceLevelUp();
+ ship.upgradeSkill("skill_photons");
+ ship.upgradeSkill("skill_photons");
+ expect(ship.getAttributeDescription("skill_photons")).toEqual("Forces of light, and electromagnetic radiation\n\nLevelled up: +2\nPhotonic engine Mk1: +4");
+
+ ship.addStickyEffect(new StickyEffect(new AttributeLimitEffect("skill_photons", 3)));
+ expect(ship.getAttributeDescription("skill_photons")).toEqual("Forces of light, and electromagnetic radiation\n\nLevelled up: +2\nPhotonic engine Mk1: +4\n???: limit to 3");
+ });
});
}
diff --git a/src/core/Ship.ts b/src/core/Ship.ts
index 5f48411..ebc0e93 100644
--- a/src/core/Ship.ts
+++ b/src/core/Ship.ts
@@ -1,55 +1,4 @@
-///
-///
-
module TS.SpaceTac {
-
- /**
- * Set of upgradable skills for a ship
- */
- export class ShipSkills {
- // Skills
- skill_materials = new ShipAttribute("materials skill")
- skill_photons = new ShipAttribute("photons skill")
- skill_antimatter = new ShipAttribute("antimatter skill")
- skill_quantum = new ShipAttribute("quantum skill")
- skill_gravity = new ShipAttribute("gravity skill")
- skill_time = new ShipAttribute("time skill")
- }
-
- /**
- * Set of ShipAttribute for a ship
- */
- export class ShipAttributes extends ShipSkills {
- // Maximal hull value
- hull_capacity = new ShipAttribute("hull capacity")
- // Maximal shield value
- shield_capacity = new ShipAttribute("shield capacity")
- // Maximal power value
- power_capacity = new ShipAttribute("power capacity")
- // Power value recovered each turn
- power_generation = new ShipAttribute("power generation")
- // Ability to move first and fast
- maneuvrability = new ShipAttribute("maneuvrability")
- // Ability to fire far and good
- precision = new ShipAttribute("precision")
- }
-
- /**
- * Set of ShipValue for a ship
- */
- export class ShipValues {
- hull = new ShipValue("hull")
- shield = new ShipValue("shield")
- power = new ShipValue("power")
- }
-
- /**
- * Static attributes and values object for name queries
- */
- export const SHIP_SKILLS = new ShipSkills();
- export const SHIP_ATTRIBUTES = new ShipAttributes();
- export const SHIP_VALUES = new ShipValues();
-
/**
* A single ship in a fleet
*/
@@ -783,5 +732,42 @@ module TS.SpaceTac {
private collectEffects(code: string): BaseEffect[] {
return imaterialize(ifilter(this.ieffects(), effect => effect.code == code));
}
+
+ /**
+ * Get a textual description of an attribute, and the origin of its value
+ */
+ getAttributeDescription(attribute: keyof ShipAttributes): string {
+ let result = this.attributes[attribute].description;
+
+ let diffs: string[] = [];
+ let limits: string[] = [];
+
+ function addEffect(base: string, effect: BaseEffect) {
+ if (effect instanceof AttributeEffect && effect.attrcode == attribute) {
+ diffs.push(`${base}: ${effect.value > 0 ? "+" + effect.value.toString() : effect.value}`);
+ } else if (effect instanceof AttributeLimitEffect && effect.attrcode == attribute) {
+ limits.push(`${base}: limit to ${effect.value}`);
+ }
+ }
+
+ if (attribute in this.skills) {
+ let skill = this.skills[attribute];
+ if (skill.get()) {
+ diffs.push(`Levelled up: +${skill.get()}`);
+ }
+ }
+
+ this.slots.forEach(slot => {
+ if (slot.attached) {
+ let equipment = slot.attached;
+ equipment.effects.forEach(effect => addEffect(equipment.getFullName(), effect));
+ }
+ });
+
+ this.sticky_effects.forEach(effect => addEffect("???", effect.base));
+
+ let sources = diffs.concat(limits).join("\n");
+ return sources ? (result + "\n\n" + sources) : result;
+ }
}
}
diff --git a/src/core/ShipAttribute.ts b/src/core/ShipAttribute.ts
deleted file mode 100644
index f5e241c..0000000
--- a/src/core/ShipAttribute.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-///
-
-module TS.SpaceTac {
- /**
- * A ship attribute is a value computed by a sum of contributions from equipments and sticky effects.
- *
- * A value may be limited by other effects.
- */
- export class ShipAttribute extends ShipValue {
- // Raw contributions value (without limits)
- private raw = 0
-
- // Temporary limits
- private limits: number[] = []
- }
-}
diff --git a/src/core/ShipValue.ts b/src/core/ShipValue.ts
index a01f8b5..d07e2fd 100644
--- a/src/core/ShipValue.ts
+++ b/src/core/ShipValue.ts
@@ -1,4 +1,19 @@
module TS.SpaceTac {
+ const SHIP_VALUES_DESCRIPTIONS: { [name: string]: string } = {
+ "materials skill": "Usage of physical materials such as bullets, shells...",
+ "photons skill": "Forces of light, and electromagnetic radiation",
+ "antimatter skill": "Manipulation of matter and antimatter particles",
+ "quantum skill": "Application of quantum uncertainty principle",
+ "gravity skill": "Interaction with gravitational forces",
+ "time skill": "Control of relativity's time properties",
+ "hull capacity": "Maximal Hull value before the ship risks collapsing",
+ "shield capacity": "Maximal Shield value to protect the hull from damage",
+ "power capacity": "Maximal Power value to use equipment",
+ "power generation": "Power generated at the end of the ship's turn",
+ "maneuvrability": "Ability to move first and fast",
+ "precision": "Ability to target far and good",
+ }
+
/**
* A ship value is a number that may vary and be constrained in a given range.
*/
@@ -18,6 +33,10 @@ module TS.SpaceTac {
this.maximal = maximal;
}
+ get description(): string {
+ return SHIP_VALUES_DESCRIPTIONS[this.name];
+ }
+
/**
* Get the current value
*/
@@ -76,4 +95,64 @@ module TS.SpaceTac {
}
}
}
+
+ /**
+ * A ship attribute is a value computed by a sum of contributions from equipments and sticky effects.
+ *
+ * A value may be limited by other effects.
+ */
+ export class ShipAttribute extends ShipValue {
+ // Raw contributions value (without limits)
+ private raw = 0
+
+ // Temporary limits
+ private limits: number[] = []
+ }
+
+ /**
+ * Set of upgradable skills for a ship
+ */
+ export class ShipSkills {
+ // Skills
+ skill_materials = new ShipAttribute("materials skill")
+ skill_photons = new ShipAttribute("photons skill")
+ skill_antimatter = new ShipAttribute("antimatter skill")
+ skill_quantum = new ShipAttribute("quantum skill")
+ skill_gravity = new ShipAttribute("gravity skill")
+ skill_time = new ShipAttribute("time skill")
+ }
+
+ /**
+ * Set of ShipAttribute for a ship
+ */
+ export class ShipAttributes extends ShipSkills {
+ // Maximal hull value
+ hull_capacity = new ShipAttribute("hull capacity")
+ // Maximal shield value
+ shield_capacity = new ShipAttribute("shield capacity")
+ // Maximal power value
+ power_capacity = new ShipAttribute("power capacity")
+ // Power value recovered each turn
+ power_generation = new ShipAttribute("power generation")
+ // Ability to move first and fast
+ maneuvrability = new ShipAttribute("maneuvrability")
+ // Ability to fire far and good
+ precision = new ShipAttribute("precision")
+ }
+
+ /**
+ * Set of ShipValue for a ship
+ */
+ export class ShipValues {
+ hull = new ShipValue("hull")
+ shield = new ShipValue("shield")
+ power = new ShipValue("power")
+ }
+
+ /**
+ * Static attributes and values object for name queries
+ */
+ export const SHIP_SKILLS = new ShipSkills();
+ export const SHIP_ATTRIBUTES = new ShipAttributes();
+ export const SHIP_VALUES = new ShipValues();
}
diff --git a/src/ui/character/CharacterSheet.ts b/src/ui/character/CharacterSheet.ts
index 77cb77f..9c4bf50 100644
--- a/src/ui/character/CharacterSheet.ts
+++ b/src/ui/character/CharacterSheet.ts
@@ -158,22 +158,30 @@ module TS.SpaceTac.UI {
let attrname = capitalize(SHIP_ATTRIBUTES[attribute].name);
let name = new Phaser.Text(this.game, x - 144, y - 2, attrname,
{ align: "center", font: "20pt Arial", fill: "#c9d8ef", stroke: "#395665", strokeThickness: 1 });
- name.anchor.set(0.5, 0.5);
+ name.anchor.set(0.5);
this.addChild(name);
- let text = new Phaser.Text(this.game, x, y, "",
- { align: "center", font: "bold 18pt Arial", fill: "#FFFFFF" });
- text.anchor.set(0.5, 0.5);
- this.addChild(text);
+ let button_value = new Phaser.Button(this.game, x, y, "common-transparent");
+ button_value.input.useHandCursor = false;
+ button_value.anchor.set(0.5);
+ button_value.width = 58;
+ button_value.height = 42;
+ this.addChild(button_value);
+ this.view.tooltip.bindDynamicText(button_value, () => this.ship.getAttributeDescription(attribute));
- this.attributes[attribute] = text;
+ let value = new Phaser.Text(this.game, x, y, "",
+ { align: "center", font: "bold 18pt Arial", fill: "#FFFFFF" });
+ value.anchor.set(0.5);
+ this.addChild(value);
+
+ this.attributes[attribute] = value;
if (SHIP_SKILLS.hasOwnProperty(attribute)) {
let button = new Phaser.Button(this.game, x + 54, y - 4, "character-skill-upgrade", () => {
this.ship.upgradeSkill(attribute);
this.refresh();
});
- button.anchor.set(0.5, 0.5);
+ button.anchor.set(0.5);
this.ship_upgrades.add(button);
this.view.tooltip.bindStaticText(button, `Spend one point to upgrade ${attrname}`);
diff --git a/src/ui/character/CharacterSlot.ts b/src/ui/character/CharacterSlot.ts
index e51fe79..490d76b 100644
--- a/src/ui/character/CharacterSlot.ts
+++ b/src/ui/character/CharacterSlot.ts
@@ -12,7 +12,8 @@ module TS.SpaceTac.UI {
this.sheet = sheet;
- let sloticon = new Phaser.Button(this.game, 150, 150, `character-slot-${SlotType[slot].toLowerCase()}`);
+ let sloticon = new Phaser.Button(this.game, 150, 150, `character-slots`);
+ sloticon.frame = slot;
sloticon.anchor.set(0.5, 0.5);
this.addChild(sloticon);
sheet.view.tooltip.bindStaticText(sloticon, `${SlotType[slot]} slot`);