1
0
Fork 0
spacetac/src/ui/character/CharacterSheet.ts

418 lines
15 KiB
TypeScript

module TK.SpaceTac.UI {
export enum CharacterSheetMode {
CREATION,
EDITION,
DISPLAY
}
/**
* Character sheet, displaying ship characteristics
*/
export class CharacterSheet {
// Global sheet mode
mode: CharacterSheetMode
// Parent view
view: BaseView
// UI components builder
container: UIContainer
builder: UIBuilder
// Close/validate button
close_button: UIButton
// X positions
xshown = 0
xhidden = -2000
// Groups
group_level: UIContainer
group_portraits: UIContainer
group_attributes: UIContainer
group_actions: UIContainer
group_upgrades: UIContainer
// Currently displayed fleet
fleet?: Fleet
// Currently displayed ship
ship?: Ship
// Variable data
personality?: CharacterPersonality
image_portrait: UIImage
text_model: UIText
text_description: UIText
text_name?: UIText
text_level: UIText
text_upgrade_points: UIText
valuebar_experience: ValueBar
constructor(view: BaseView, mode: CharacterSheetMode, onclose?: Function) {
this.view = view;
this.mode = mode;
let builder = new UIBuilder(view);
this.container = builder.container("character-sheet");
builder = builder.in(this.container);
let bg = builder.image("character-sheet");
bg.setInteractive();
this.builder = builder.styled({ color: "#dce9f9", size: 16, shadow: true });
if (!onclose) {
onclose = () => this.hide();
}
this.xhidden = -this.view.getWidth();
this.container.x = this.xhidden;
this.image_portrait = this.builder.image("common-transparent", 435, 271, true);
this.builder.image("character-entry", 24, 740);
this.group_portraits = this.builder.container("portraits", 90, 755);
let model_bg = this.builder.image("character-ship-model", 434, 500, true);
this.text_model = this.builder.in(model_bg).text("", 0, 0, { size: 28 });
let description_bg = this.builder.image("character-ship-description", 434, 654, true);
this.text_description = this.builder.in(description_bg).text("", 0, 0, { color: "#a0afc3", width: 510 });
this.group_attributes = this.builder.container("attributes", 28, 28);
this.group_actions = this.builder.container("actions", 698, 28);
this.group_level = this.builder.container("level");
let points_bg = this.builder.in(this.group_level).image("character-level-upgrades", 582, 986);
this.builder.in(points_bg, builder => {
builder.text("Upgrade points", 46, 10, { center: false, vcenter: false });
builder.image("character-upgrade-point", 147, 59, true);
});
this.text_upgrade_points = this.builder.in(points_bg).text("", 106, 60, { size: 28 });
let level_bg = this.builder.in(this.group_level).image("character-level-display", 434, 1032, true);
this.text_level = this.builder.in(level_bg).text("", 0, 4, { size: 28 });
this.valuebar_experience = this.builder.in(level_bg).valuebar("character-level-experience", -level_bg.width * 0.5, -level_bg.height * 0.5);
this.group_upgrades = this.builder.container("upgrades");
if (this.mode == CharacterSheetMode.CREATION) {
this.builder.in(this.builder.image("character-section-title", 180, 30, false)).text("Ship", 80, 45, { color: "#dce9f9", size: 32 });
this.personality = new CharacterPersonality(this.builder, 950, 30);
this.close_button = this.builder.button("character-validate-creation", 140, 930, onclose,
"Validate the team, and start the campaign", undefined, {
hover_bottom: true,
text: "Validate team",
text_x: 295,
text_y: 57,
text_style: { size: 32, color: "#fff3df" }
}
);
this.builder.in(this.builder.image("character-creation-help", 970, 680), builder => {
builder.text("Compose your initial team by choosing a model for each ship, and customize the name and personality of the Artificial Intelligence pilot",
405, 150, { color: "#a3bbd9", size: 22, width: 500 });
});
this.builder.button("character-model-prev", 216, 500, () => this.changeModel(-1), "Select previous model", undefined, { center: true });
this.builder.button("character-model-next", 654, 500, () => this.changeModel(1), "Select next model", undefined, { center: true });
this.group_level.visible = false;
this.group_upgrades.visible = false;
} else {
this.text_name = this.builder.in(this.builder.image("character-name-display", 434, 940, true)).text("", 0, 0, { size: 28 });
this.close_button = this.builder.button("character-close-button", 1837, 0, onclose, "Close the character sheet");
}
this.refreshUpgrades();
this.refreshAttributes();
this.refreshActions();
}
/**
* Move the sheet to a specific layer
*/
moveToLayer(layer: UIContainer): void {
layer.add(this.container);
}
/**
* Check if the sheet should be interactive
*/
isInteractive(): boolean {
return this.ship ? (this.mode != CharacterSheetMode.DISPLAY && !this.ship.critical) : false;
}
/**
* Change the ship model
*/
changeModel(offset: number): void {
if (this.mode == CharacterSheetMode.CREATION && this.ship) {
let models = ShipModel.getDefaultCollection();
let idx = models.map(model => model.code).indexOf(this.ship.model.code) + offset;
if (idx < 0) {
idx = models.length - 1;
} else if (idx >= models.length) {
idx = 0;
}
this.ship.setModel(models[idx]);
this.refresh();
}
}
/**
* Refresh the ship information display
*/
private refreshShipInfo(): void {
if (this.ship) {
let ship = this.ship;
this.builder.change(this.image_portrait, `ship-${ship.model.code}-portrait`);
if (this.text_name) {
this.text_name.setText(ship.name || "");
}
if (this.personality) {
this.personality.displayShip(ship);
}
this.text_model.setText(ship.model.name);
this.text_level.setText(`Level ${ship.level.get()}`);
this.text_description.setText(ship.model.getDescription());
this.text_upgrade_points.setText(`${ship.getAvailableUpgradePoints()}`);
this.valuebar_experience.setValue(ship.level.getExperience(), ship.level.getNextGoal());
}
}
/**
* Refresh the upgrades display
*/
private refreshUpgrades(): void {
let builder = this.builder.in(this.group_upgrades);
builder.clear();
if (!this.ship || this.mode == CharacterSheetMode.CREATION) {
return;
}
let ship = this.ship;
let initial = builder.image("character-initial", 970, 30);
// Base equipment (level 1)
builder.styled({ center: false, vcenter: false }).in(initial, builder => {
builder.text("Base equipment", 32, 8, { color: "#e2e9d1" });
builder.in(builder.container("attributes"), builder => {
let effects = cfilter(ship.model.getEffects(1, []), AttributeEffect);
effects.forEach(effect => {
let button = builder.button(`attribute-${effect.attrcode}`, 0, 8, undefined,
`${capitalize(SHIP_VALUES_NAMES[effect.attrcode])} - ${SHIP_VALUES_DESCRIPTIONS[effect.attrcode]}`);
builder.in(button, builder => {
builder.text(`${effect.value}`, 56, 8, { size: 22 });
});
});
builder.distribute("x", 236, 870);
});
builder.in(builder.container("actions"), builder => {
let actions = ship.model.getActions(1, []);
actions.forEach(action => {
let button = builder.button("common-transparent", 0, 66, undefined, action.getEffectsDescription());
builder.in(button, builder => {
let icon = builder.image(`action-${action.code}`);
icon.setScale(0.1875);
if (actions.length < 5) {
builder.text(`${action.name}`, 56, 12, { size: 16 });
}
});
});
builder.distribute("x", 28, 888);
});
});
// Level number
range(10).forEach(i => {
builder.text(`${i + 1}`, 920, i == 0 ? 92 : (110 + i * 100), {
center: true,
vcenter: true,
size: 28,
color: ship.level.get() >= (i + 1) ? "#dce9f9" : "#293038"
});
});
// Level upgrades
range(9).forEach(i => {
builder.image("character-level-separator", 844, 154 + i * 100);
let level = i + 2;
let upgrades = ship.model.getLevelUpgrades(level);
upgrades.forEach((upgrade, j) => {
let onchange = (selected: boolean) => {
this.refreshShipInfo(); // TODO Only upgrade points
this.refreshActions();
this.refreshAttributes();
};
new CharacterUpgrade(ship, upgrade, level).draw(builder, 970 + j * 315, 170 + i * 100,
this.isInteractive() ? onchange : undefined);
});
});
}
/**
* Refresh the attributes display
*/
private refreshAttributes(): void {
let builder = this.builder.in(this.group_attributes);
builder.clear();
builder.image("character-ship-column-left", 0, 0);
builder.text("Attributes", 74, 20, { color: "#a3bbd9" });
if (this.ship) {
let ship = this.ship;
builder.in(builder.container("items"), builder => {
keys(SHIP_ATTRIBUTES).forEach(attribute => {
let button = builder.button(`attribute-${attribute}`, 24, 0, undefined,
ship.getAttributeDescription(attribute));
builder.in(button).text(`${ship.getAttribute(attribute)}`, 78, 27, { size: 22 });
});
builder.distribute("y", 40, 688);
});
}
}
/**
* Refresh the actions display
*/
private refreshActions(): void {
let builder = this.builder.in(this.group_actions);
builder.clear();
builder.image("character-ship-column-right", 0, 0);
builder.text("Actions", 74, 20, { color: "#a3bbd9" });
if (this.ship) {
let ship = this.ship;
builder.in(builder.container("items"), builder => {
let actions = ship.actions.listAll().filter(action => !(action instanceof EndTurnAction));
actions.forEach(action => {
let button = builder.button(`action-${action.code}`, 24, 0, undefined, filler => ActionTooltip.fill(filler, ship, action));
button.setScale(0.375);
});
builder.distribute("y", 40, 688);
});
}
}
/**
* Refresh the fleet display
*/
private refreshFleet(): void {
destroyChildren(this.group_portraits);
if (this.fleet) {
let builder = this.builder.in(this.group_portraits);
this.fleet.ships.forEach((ship, idx) => {
let button: UIButton;
button = new CharacterPortrait(ship).draw(builder, 64 + idx * 140, 64, () => {
if (button) {
button.toggle(true, UIButtonUnicity.EXCLUSIVE_MIN);
this.ship = ship;
this.refreshShipInfo();
this.refreshActions();
this.refreshAttributes();
this.refreshUpgrades();
}
});
if (ship == this.ship) {
button.toggle(true);
}
});
}
}
/**
* Check if the sheet is shown
*/
isOpened(): boolean {
return this.container.x != this.xhidden;
}
/**
* Show the sheet for a given ship
*/
show(ship: Ship, animate = true, sound = true) {
this.ship = ship;
this.fleet = ship.fleet;
this.refreshShipInfo();
this.refreshUpgrades();
this.refreshAttributes();
this.refreshActions();
if (ship.fleet !== this.fleet || ship.fleet.ships.length != this.group_portraits.length) {
this.refreshFleet();
}
if (sound) {
this.view.audio.playOnce("ui-dialog-open");
}
if (animate) {
this.view.tweens.add({
targets: this.container,
x: this.xshown,
duration: 400,
easing: 'Circ.easeInOut'
});
} else {
this.container.x = this.xshown;
}
}
/**
* Hide the sheet
*/
hide(animate = true) {
this.view.audio.playOnce("ui-dialog-close");
if (animate) {
this.view.tweens.add({
targets: this.container,
x: this.xhidden,
duration: 400,
ease: 'Circ.easeInOut'
});
} else {
this.container.x = this.xhidden;
}
}
/**
* Refresh the sheet display
*/
refresh() {
if (this.ship) {
this.refreshShipInfo();
this.refreshUpgrades();
this.refreshAttributes();
this.refreshActions();
this.refreshFleet();
}
}
}
}