antiyoy.js/Warrior.js
2019-04-08 21:54:07 +02:00

247 lines
7.5 KiB
JavaScript

class Warrior extends GameElement {
constructor(x, y, game, civilization, asset) {
super(x, y, game, asset, false);
this.civilization = civilization;
this.isSelected = false;
this.civilization.balance -= this.constructor.initialCosts;
this.setNeedsAction(true);
}
onClick() {
if (this.civilization.player !== player)
return;
this.game.selectCivilization(this.civilization);
if (!this.game.selectedObject && this.needsAction) {
this.isSelected = true;
this.game.selectWarrior(this);
this.game.draggingElement = this.constructor.getDraggingObject(this.game);
}
}
static getDraggingObject(game, className = 'farmer', image = 'knight.svg') {
return super.getDraggingObject(game, className, image);
}
getPossibleTiles(player) {
return this.checkSurroundings(this.x, this.y, player);
}
merge(warrior) {
this.rank += warrior.rank || 1;
this.rank = Math.min(this.rank, 4);
warrior.kill();
this.kill();
const ranks = [Farmer, Hoplite, Servant, Knight];
this.civilization.balance += warrior.constructor.initialCosts + this.constructor.initialCosts;
this.game.addWarrior(this.x, this.y, this.civilization, ranks[this.rank - 1]);
// TODO: Switch image
}
move(x, y) {
if (!this.needsAction)
return false;
if (!this.isPossibleDestination(x, y, this.civilization.player))
return false;
this.game.field[this.x][this.y].object = null;
const tile = this.game.field[x][y];
if (!tile.claimedBy || tile.claimedBy.player === this.civilization.player) { // Friendly territory
if (tile.object instanceof Tree) { // Tree
tile.object.cutDown();
} else if (tile.object instanceof Warrior) { // Obstacle is a friendly warrior
tile.object.merge(this);
this.game.deselectObject();
return true;
}
} else { // Hostile territory
// Check surrounding tiles
if(tile.getAdjacentTiles().find(adjTile => adjTile.claimedBy !== this.civilization &&
!!adjTile.object &&
(adjTile.object instanceof Warrior || adjTile.object instanceof Tower) &&
adjTile.object.rank >= this.rank)) {
return false;
}
if (tile.object instanceof Tree) { // No object/troop on tile
tile.object.cutDown();
} else if (tile.object instanceof Warrior) { // Obstacle is an hostile warrior
if (tile.object.rank < this.rank) { // Hostile warrior/tower is weaker than own troop
tile.object.kill();
}
} else if (tile.object instanceof Building) {
if (tile.object.rank < this.rank) {
tile.object.destroy();
}
}
}
this.x = x;
this.y = y;
this.game.deselectObject();
this.setNeedsAction(false);
const prevCiv = tile.claimedBy;
tile.object = this;
tile.overtake(this.civilization);
if(prevCiv instanceof Civilization && prevCiv !== this.civilization) {
console.log(prevCiv.uuid);
prevCiv.split();
}
this.update();
}
checkSurroundings(x, y, player, step = 0, excluded = []) {
const field = this.game.field;
const possibleSurroundings = [];
const neighbours = field[x][y].getAdjacentTiles().filter(tile => !excluded.includes(tile));
neighbours.forEach(neighbour => {
const {x, y} = neighbour.pos;
if (x < 0 || x >= this.game.fieldSize.x || y < 0 || y >= this.game.fieldSize.y)
return;
if (this.isPossibleTile(x, y)) {
possibleSurroundings.push(field[x][y]);
if (step < 4 && !!field[x][y].claimedBy && field[x][y].claimedBy.player === player)
possibleSurroundings.push(...this.checkSurroundings(x, y, player, ++step, [...excluded, ...neighbours, ...possibleSurroundings]));
}
});
return possibleSurroundings;
}
isPossibleTile(x, y) {
const tile = this.game.field[x][y];
if (!!tile.claimedBy && tile.claimedBy.player === this.civilization.player) { // Friendly territory
if (!tile.object || tile.object instanceof Tree) { // No object/troop on tile
return true;
}
if (tile.object instanceof Warrior) { // Obstacle is a friendly warrior
if (tile.object.rank <= 4 - this.rank) { // Warrior isn't yet on max level
return true;
}
}
// Otherwise there is an unavoidable obstacle
} else { // Hostile territory
if (!tile.object || tile.object instanceof Tree) { // No object/troop on tile
// TODO: Check surrounding tiles
return true;
}
if (tile.object instanceof Warrior || tile.object instanceof Building) { // Obstacle is an hostile warrior
if (tile.object.rank < this.rank) { // Hostile warrior/tower is weaker than own troop
// TODO: Check surrounding tiles
return true;
}
}
// Otherwise there is an unavoidable obstacle
}
return false;
}
isPossibleDestination(x, y, player) {
return this.getPossibleTiles(player).includes(this.game.field[x][y]);
}
kill() {
delete this.game.warriors[this.uuid];
this.element.parentNode.removeChild(this.element);
this.game.field[this.x][this.y].object = null;
// TODO: Show gravestone
}
setNeedsAction(needsAction) {
this.needsAction = needsAction;
if (this.civilization.player === player && needsAction) {
this.element.classList.add('waiting');
} else {
this.element.classList.remove('waiting');
}
}
}
class Farmer extends Warrior {
constructor(x, y, game, civilization) {
super(x, y, game, civilization, 'farmer.svg');
this.rank = 1;
this.costsPerRound = 2;
}
static getDraggingObject(game) {
return super.getDraggingObject(game, 'farmer', 'farmer.svg');
}
static get initialCosts() {
return 10;
}
}
class Hoplite extends Warrior {
constructor(x, y, game, civilization) {
super(x, y, game, civilization, 'hoplite.svg');
this.rank = 2;
this.costsPerRound = 6;
}
static getDraggingObject(game) {
return super.getDraggingObject(game, 'hoplite', 'hoplite.svg');
}
static get initialCosts() {
return 20;
}
}
class Servant extends Warrior {
constructor(x, y, game, civilization) {
super(x, y, game, civilization, '');
this.rank = 3;
this.costsPerRound = 18;
}
static getDraggingObject(game) {
return super.getDraggingObject(game, 'servant', 'servant.svg');
}
static get initialCosts() {
return 30;
}
}
class Knight extends Warrior {
constructor(x, y, game, civilization) {
super(x, y, game, civilization, 'knight.svg');
this.rank = 4;
this.costsPerRound = 36;
}
static getDraggingObject(game) {
return super.getDraggingObject(game, 'knight', 'knight.svg');
}
static get initialCosts() {
return 40;
}
}