247 lines
7.5 KiB
JavaScript
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;
|
|
}
|
|
} |