/* global ml */
/* eslint-disable max-len,curly,complexity,prefer-template, no-warning-comments */
/** @module Monster */
import ItemBackend from './item.mjs';
import MonsterCommon from "../../Frontend/game/common/monster.mjs";
import MonsterModel from "../models/monster";
import sql from "../sequelize";
// a list of all dead monsters (improves the performance of save)
let deadMonsterIds = [];
export default class Monster extends MonsterCommon {
constructor(...args) {
super(...args);
this.placeInRandomRoom();
this.targetx = -1;
this.targety = -1;
}
/**
* Puts
* monster in half of all "rooms".
* @param {Floor} floor The floor to add monsters to
*/
generateMonsters(floor) {
for(let i = 0; i < this.map.rooms.length * this.monsterRatio; i++) {
floor.monsters[i] = new Monster('sir spoopy', 100, 10, this, i, 1);
}
}
static async load(floor) {
let monsterModel = new MonsterModel(sql);
let rawMonsters = await monsterModel.findAll({
where: {
floorId: floor.id
}
});
floor.monsters = [];
rawMonsters.forEach((raw, i) => {
let monster = new Monster(raw.name, raw.hp, 10, floor, i, raw.type);
monster.setCoodinates(raw.x, raw.y);
floor.monsters.push(monster);
});
}
/**
* Saves monsters to the database.
* @param {boolean} create Create new monster rows (first save only)
*/
static async saveAll(floor, create) {
let monsterModel = new MonsterModel(sql);
let monsters = []; // collect monsters for bulkCreate
// create or update the data
let save = (data) => {
if(create) {
monsters.push(data);
} else {
return monsterModel.update(data, {
where: {
id: data.id
}
});
}
return undefined; // make eslint happy
};
for(let i = 0; i < floor.monsters.length; i++) {
let monster = floor.monsters[i];
await save({
id: `${monster.floor.id}-${monster.id}`,
floorId: monster.floor.id,
x: monster.x,
y: monster.y,
hp: monster.hp,
type: monster.type,
name: monster.name
});
}
// use bulk create
if(create) {
await monsterModel.bulkCreate(monsters);
}
// delete dead monsters
await monsterModel.destroy({
where: {
id: deadMonsterIds
}
});
}
/**
* Given a min and a max integer, returns a random number between the two (*inclusive)
* @param min
* @param max
*/
getRandomNumber(min, max) {
return Math.floor(Math.random() * max) + min;
}
/**
* Select only the propertys we need for sending monsters to the client
*/
toJSON() {
return {
id: this.id,
targetx: this.targetx,
targety: this.targety,
hp: this.hp,
type: this.type,
x: this.x,
y: this.y,
name: this.name
};
}
/**
* ~WIP drop items down the road
*
* Monster dies.
*/
die() {
ml.logger.verbose(`Monster ${this.id} died`, ml.tags.monster);
if(this.type === "boss") {
ItemBackend.spawnKey(this.floor, Math.round(this.x), Math.round(this.y));
} else if(Math.floor(Math.random() * 5) === 0) {
ItemBackend.spawnRandomItem(this.floor, Math.round(this.x), Math.round(this.y));
}
this.x = -1; // (-1, -1) coordinate tells us that the monster is dead
this.y = -1;
this.alive = false;
// remove from the monsters array
let thisIdx = this.floor.monsters.indexOf(this);
this.floor.monsters.splice(thisIdx, 1);
// add to the list of monsters for save to delete
deadMonsterIds.push(`${this.floor.id}-${this.id}`);
}
}