|
- let itemGenerator = require('../items/generator');
-
- let abs = Math.abs.bind(Math);
- let rnd = Math.random.bind(Math);
- let max = Math.max.bind(Math);
-
- module.exports = {
- type: 'mob',
-
- target: null,
-
- physics: null,
-
- originX: 0,
- originY: 0,
-
- walkDistance: 1,
- maxChaseDistance: 25,
- goHome: false,
-
- init: function (blueprint) {
- this.physics = this.obj.instance.physics;
-
- this.originX = this.obj.x;
- this.originY = this.obj.y;
- },
-
- update: function () {
- let obj = this.obj;
-
- let target = null;
- if (obj.aggro)
- target = obj.aggro.getHighest();
-
- //Have we reached home?
- if (this.goHome) {
- let distanceFromHome = Math.max(Math.abs(this.originX - obj.x), Math.abs(this.originY - obj.y));
- if (distanceFromHome < this.walkDistance)
- this.goHome = false;
- }
-
- //Are we too far from home?
- if ((!this.goHome) && (!obj.follower) && (target)) {
- if (!this.canChase(target)) {
- obj.clearQueue();
- obj.aggro.unAggro(target);
- target = obj.aggro.getHighest();
- }
- }
-
- if (!this.goHome) {
- //Are we in fight mode?
- if ((target) && (target !== obj) && ((!obj.follower) || (obj.follower.master !== target))) {
- this.fight(target);
- return;
- }
- //Is fight mode over?
- else if ((!target) && (this.target)) {
- this.target = null;
- obj.clearQueue();
- this.goHome = true;
- }
- }
-
- //If we're already going somewhere, don't calculate a new path
- if (obj.actionQueue.length > 0)
- return;
-
- //Unless we're going home, don't always move
- if ((!this.goHome) && (rnd() < 0.85))
- return;
-
- //don't move around if we're not allowed to, unless we're going home
- let walkDistance = this.walkDistance;
- if ((!this.goHome) && (walkDistance <= 0))
- return;
-
- let toX = this.originX + ~~(rnd() * (walkDistance * 2)) - walkDistance;
- let toY = this.originY + ~~(rnd() * (walkDistance * 2)) - walkDistance;
-
- if (!this.physics.isCellOpen(toX, toY))
- return;
-
- let path = this.physics.getPath({
- x: obj.x,
- y: obj.y
- }, {
- x: toX,
- y: toY
- }, false);
-
- let pLen = path.length;
- for (let i = 0; i < pLen; i++) {
- let p = path[i];
-
- obj.queue({
- action: 'move',
- data: {
- x: p.x,
- y: p.y
- }
- });
- }
-
- //We use goHometo force followers to follow us around but they should never stay in that state
- // since it messes with combat
- if (obj.follower)
- this.goHome = false;
- },
- fight: function (target) {
- if (this.target !== target) {
- this.obj.clearQueue();
- this.target = target;
- }
- //If the target is true, it means we can't reach the target and should wait for a new one
- if (this.target === true)
- return;
-
- let obj = this.obj;
- let x = obj.x;
- let y = obj.y;
-
- let tx = ~~target.x;
- let ty = ~~target.y;
-
- let distance = max(abs(x - tx), abs(y - ty));
- let furthestRange = obj.spellbook.getFurthestRange();
- let doesCollide = null;
- let hasLos = null;
-
- if (distance <= furthestRange) {
- doesCollide = this.physics.mobsCollide(x, y, obj);
- if (!doesCollide) {
- hasLos = this.physics.hasLos(x, y, tx, ty);
- if (hasLos) {
- if (((obj.follower) && (obj.follower.master.player)) || (rnd() < 0.65)) {
- let spell = obj.spellbook.getRandomSpell(target);
- let success = obj.spellbook.cast({
- spell: spell,
- target: target
- });
- //null means we don't have LoS
- if (success !== null)
- return;
- hasLos = false;
- } else
- return;
- }
- }
- }
-
- let targetPos = this.physics.getClosestPos(x, y, tx, ty, target);
- if (!targetPos) {
- //Find a new target
- obj.aggro.ignore(target);
- //TODO: Don't skip a turn
- return;
- }
- let newDistance = max(abs(targetPos.x - tx), abs(targetPos.y - ty));
-
- if ((newDistance >= distance) && (newDistance > furthestRange)) {
- if (hasLos === null)
- hasLos = this.physics.hasLos(x, y, tx, ty);
- if (hasLos) {
- if (doesCollide === null)
- doesCollide = this.physics.mobsCollide(x, y, obj);
- if (!doesCollide) {
- obj.aggro.ignore(target);
- return;
- }
- } else {
- if (doesCollide === null)
- doesCollide = this.physics.mobsCollide(x, y, obj);
- if (!doesCollide) {
- obj.aggro.ignore(target);
- return;
- }
- }
- }
-
- let path = this.physics.getPath({
- x: x,
- y: y
- }, {
- x: targetPos.x,
- y: targetPos.y
- });
- if (path.length === 0) {
- obj.aggro.ignore(target);
- //TODO: Don't skip a turn
- return;
- }
-
- let p = path[0];
- obj.queue({
- action: 'move',
- data: {
- x: p.x,
- y: p.y
- }
- });
- },
-
- canChase: function (obj) {
- let distanceFromHome = Math.max(Math.abs(this.originX - obj.x), Math.abs(this.originY - obj.y));
- return ((!this.goHome) && (distanceFromHome <= this.maxChaseDistance));
- }
- };
|