character sheet: Added tooltips for attributes with description and sources (WIP)
This commit is contained in:
parent
1c45602586
commit
b8bfbb8063
2
TODO.md
2
TODO.md
|
@ -26,7 +26,7 @@ Character sheet
|
||||||
* Highlight allowed destinations during drag-and-drop, with text hints
|
* 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
|
* 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
|
* 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
|
* Forbid to modify escorted ship
|
||||||
* Add merged cargo display for the whole fleet
|
* Add merged cargo display for the whole fleet
|
||||||
|
|
||||||
|
|
|
@ -576,5 +576,25 @@ module TS.SpaceTac.Specs {
|
||||||
new AttributeLimitEffect("precision", 2)
|
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");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,55 +1,4 @@
|
||||||
/// <reference path="ShipAttribute.ts"/>
|
|
||||||
/// <reference path="ShipValue.ts"/>
|
|
||||||
|
|
||||||
module TS.SpaceTac {
|
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
|
* A single ship in a fleet
|
||||||
*/
|
*/
|
||||||
|
@ -783,5 +732,42 @@ module TS.SpaceTac {
|
||||||
private collectEffects(code: string): BaseEffect[] {
|
private collectEffects(code: string): BaseEffect[] {
|
||||||
return imaterialize(ifilter(this.ieffects(), effect => effect.code == code));
|
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[<keyof ShipSkills>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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
/// <reference path="ShipValue.ts"/>
|
|
||||||
|
|
||||||
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[] = []
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,19 @@
|
||||||
module TS.SpaceTac {
|
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.
|
* 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;
|
this.maximal = maximal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get description(): string {
|
||||||
|
return SHIP_VALUES_DESCRIPTIONS[this.name];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current value
|
* 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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,22 +158,30 @@ module TS.SpaceTac.UI {
|
||||||
let attrname = capitalize(SHIP_ATTRIBUTES[attribute].name);
|
let attrname = capitalize(SHIP_ATTRIBUTES[attribute].name);
|
||||||
let name = new Phaser.Text(this.game, x - 144, y - 2, attrname,
|
let name = new Phaser.Text(this.game, x - 144, y - 2, attrname,
|
||||||
{ align: "center", font: "20pt Arial", fill: "#c9d8ef", stroke: "#395665", strokeThickness: 1 });
|
{ 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);
|
this.addChild(name);
|
||||||
|
|
||||||
let text = new Phaser.Text(this.game, x, y, "",
|
let button_value = new Phaser.Button(this.game, x, y, "common-transparent");
|
||||||
{ align: "center", font: "bold 18pt Arial", fill: "#FFFFFF" });
|
button_value.input.useHandCursor = false;
|
||||||
text.anchor.set(0.5, 0.5);
|
button_value.anchor.set(0.5);
|
||||||
this.addChild(text);
|
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)) {
|
if (SHIP_SKILLS.hasOwnProperty(attribute)) {
|
||||||
let button = new Phaser.Button(this.game, x + 54, y - 4, "character-skill-upgrade", () => {
|
let button = new Phaser.Button(this.game, x + 54, y - 4, "character-skill-upgrade", () => {
|
||||||
this.ship.upgradeSkill(<keyof ShipSkills>attribute);
|
this.ship.upgradeSkill(<keyof ShipSkills>attribute);
|
||||||
this.refresh();
|
this.refresh();
|
||||||
});
|
});
|
||||||
button.anchor.set(0.5, 0.5);
|
button.anchor.set(0.5);
|
||||||
this.ship_upgrades.add(button);
|
this.ship_upgrades.add(button);
|
||||||
|
|
||||||
this.view.tooltip.bindStaticText(button, `Spend one point to upgrade ${attrname}`);
|
this.view.tooltip.bindStaticText(button, `Spend one point to upgrade ${attrname}`);
|
||||||
|
|
|
@ -12,7 +12,8 @@ module TS.SpaceTac.UI {
|
||||||
|
|
||||||
this.sheet = sheet;
|
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);
|
sloticon.anchor.set(0.5, 0.5);
|
||||||
this.addChild(sloticon);
|
this.addChild(sloticon);
|
||||||
sheet.view.tooltip.bindStaticText(sloticon, `${SlotType[slot]} slot`);
|
sheet.view.tooltip.bindStaticText(sloticon, `${SlotType[slot]} slot`);
|
||||||
|
|
Loading…
Reference in a new issue