Reference Source Test

WTF-Adventure/server/data/combat/skeletonking.js

import _ from 'underscore';
import Combat from '../../js/game/entity/character/combat/combat';
import Utils from '../../js/util/utils';

/**
 * First of its kind, the Skeleton King will spawn 4 minions.
 * Two sorcerers on (x + 1, y + 1) & (x - 1, y + 1)
 *
 * And two death knights on (x + 1, y - 1) & (x - 1, y - 1)
 */
export default class SkeletonKing extends Combat {
  constructor(character) {
    super(character);

    this.character = Object.assign(character, {
      spawnDistance: 10,
    });
    this.lastSpawn = 0;
    this.minions = [];

    character.onDeath(() => {
      this.reset();
    });
  }

  reset() {
    this.lastSpawn = 0;

    const listCopy = this.minions.slice();

    for (let i = 0; i < listCopy.length; i += 1) {
      this.world.kill(listCopy[i]);
    }
  }

  hit(character, target, hitInfo) {
    if (this.isAttacked()) {
      this.beginMinionAttack();
    }

    if (this.canSpawn()) {
      this.spawnMinions();
    }

    super.hit(character, target, hitInfo);
  }

  spawnMinions() {
    const x = this.character.x;
    const y = this.character.y;

    this.lastSpawn = new Date().getTime();

    if (!this.colliding(x + 2, y - 2)) {
      this.minions.push(this.world.spawnMob(17, x + 2, y + 2));
    }

    if (!this.colliding(x - 2, y - 2)) {
      this.minions.push(this.world.spawnMob(17, x - 2, y + 2));
    }

    if (!this.colliding(x + 1, y + 1)) {
      this.minions.push(this.world.spawnMob(11, x + 1, y - 1));
    }

    if (!this.colliding(x - 1, y + 1)) {
      this.minions.push(this.world.spawnMob(11, x - 1, y - 1));
    }

    _.each(this.minions, (minion) => {
      minion.onDeath(() => {
        if (this.isLast()) {
          this.lastSpawn = new Date().getTime();
        }

        this.minions.splice(this.minions.indexOf(minion), 1);
      });

      if (this.isAttacked()) {
        this.beginMinionAttack();
      }
    });
  }

  beginMinionAttack() {
    if (!this.hasMinions()) {
      return;
    }

    _.each(this.minions, (minion) => {
      const randomTarget = this.getRandomTarget();

      if (!minion.hasTarget() && randomTarget) {
        minion.combat.begin(randomTarget);
      }
    });
  }

  getRandomTarget() {
    if (this.isAttacked()) {
      const keys = Object.keys(this.attackers);
      const randomAttacker = this.attackers[keys[Utils.randomInt(0, keys.length)]];

      if (randomAttacker) {
        return randomAttacker;
      }
    }

    if (this.character.hasTarget()) {
      return this.character.target;
    }

    return null;
  }

  hasMinions() {
    return this.minions.length > 0;
  }

  isLast() {
    return this.minions.length === 1;
  }

  canSpawn() {
    return (
      new Date().getTime() - this.lastSpawn > 25000
      && !this.hasMinions()
      && this.isAttacked()
    );
  }
}