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

174 lines
6.4 KiB
TypeScript

module TS.SpaceTac.UI {
/**
* Interface for any graphical area that may contain or receive an equipment
*/
export interface CharacterEquipmentContainer {
/**
* Check if a point in the character sheet is inside the container
*/
isInside(x: number, y: number): boolean
/**
* Get a centric anchor point and scaling to snap the equipment
*/
getEquipmentAnchor(): { x: number, y: number, scale: number, alpha: number }
/**
* Get a vertical offset to position the price tag
*/
getPriceOffset(): number
/**
* Add an equipment to the container
*/
addEquipment(equipment: CharacterEquipment, source: CharacterEquipmentContainer | null, test: boolean): boolean
/**
* Remove an equipment from the container
*/
removeEquipment(equipment: CharacterEquipment, destination: CharacterEquipmentContainer | null, test: boolean): boolean
}
/**
* Display a ship equipment, either attached to a slot, in cargo, or being dragged down
*/
export class CharacterEquipment extends Phaser.Button {
sheet: CharacterSheet
item: Equipment
container: CharacterEquipmentContainer
price: number
constructor(sheet: CharacterSheet, equipment: Equipment, container: CharacterEquipmentContainer) {
let icon = sheet.view.getImageInfo(`equipment-${equipment.code}`);
super(sheet.game, 0, 0, icon.key, undefined, undefined, icon.frame, icon.frame);
this.sheet = sheet;
this.item = equipment;
this.container = container;
this.price = 0;
this.anchor.set(0.5, 0.5);
this.setupDragDrop(sheet);
this.snapToContainer();
sheet.view.tooltip.bind(this, filler => this.fillTooltip(filler));
}
jasmineToString() {
return this.item.jasmineToString();
}
/**
* Find the container under a specific screen location
*/
findContainerAt(x: number, y: number): CharacterEquipmentContainer | null {
return ifirst(this.sheet.iEquipmentContainers(), container => container.isInside(x, y));
}
/**
* Display a price tag
*/
setPrice(price: number) {
if (!price || this.price) {
return;
}
this.price = price;
let tag = new Phaser.Image(this.game, 0, 0, "character-price-tag");
let yoffset = this.container.getPriceOffset();
tag.position.set(0, -yoffset * 2 + tag.height);
tag.anchor.set(0.5, 0.5);
tag.scale.set(2, 2);
tag.alpha = 0.85;
this.addChild(tag);
let text = new Phaser.Text(this.game, -10, 4, price.toString(), { align: "center", font: "18pt Arial", fill: "#FFFFCC" });
text.anchor.set(0.5, 0.5);
tag.addChild(text);
}
/**
* Snap in place to its current container
*/
snapToContainer() {
let info = this.container.getEquipmentAnchor();
this.position.set(info.x, info.y);
this.scale.set(0.5 * info.scale, 0.5 * info.scale);
this.alpha = info.alpha;
}
/**
* Enable dragging to another slot
*/
setupDragDrop(sheet: CharacterSheet) {
this.inputEnabled = true;
if (this.container.removeEquipment(this, null, true)) {
this.input.enableDrag(false, true);
}
this.events.onDragStart.add(() => {
this.sheet.view.audio.playOnce("ui-drag");
this.scale.set(0.5, 0.5);
this.alpha = 0.8;
});
this.events.onDragStop.add(() => {
this.sheet.view.audio.playOnce("ui-drop");
let destination = this.findContainerAt(this.x, this.y);
if (destination && destination != this.container) {
if (this.applyDragDrop(this.container, destination, false)) {
this.container = destination;
this.snapToContainer();
sheet.refresh(); // TODO Only if required (destination is "virtual")
} else {
this.snapToContainer();
}
} else {
this.snapToContainer();
}
});
}
/**
* Apply drag and drop between two containers
*
* Return true if something changed (or would change, if test=true).
*/
applyDragDrop(source: CharacterEquipmentContainer, destination: CharacterEquipmentContainer, test: boolean): boolean {
let possible = source.removeEquipment(this, destination, true) && destination.addEquipment(this, source, true);
if (test) {
return possible;
} else if (possible) {
if (source.removeEquipment(this, destination, false)) {
if (destination.addEquipment(this, source, false)) {
return true;
} else {
console.error("Destination container refused to accept equipment", this, source, destination);
// Go back to source
if (source.addEquipment(this, null, false)) {
return false;
} else {
console.error("Equipment lost in bad exchange !", this, source, destination);
return true;
}
}
} else {
console.error("Source container refused to give away equipment", this, source, destination);
return false;
}
} else {
return false;
}
}
/**
* Fill a tooltip with equipment data
*/
fillTooltip(filler: TooltipFiller): boolean {
let title = this.item.getFullName();
if (this.item.slot_type !== null) {
title += ` (${SlotType[this.item.slot_type]})`;
}
filler.addText(0, 0, title, "#cccccc", 20, false, true);
filler.addText(0, 40, this.item.getFullDescription(), "#cccccc", 18, false, false, 700);
return true;
}
}
}