brick-dungeon: core mechanics
This commit is contained in:
parent
0bb010190d
commit
5e4af4d923
|
|
@ -4,7 +4,10 @@ export const nextFrame = async (): Promise<number> => new Promise((resolve) => r
|
||||||
export const randInt = (min: number, max: number) => Math.round(min + (max - min - 1) * Math.random());
|
export const randInt = (min: number, max: number) => Math.round(min + (max - min - 1) * Math.random());
|
||||||
export const randBool = () => Math.random() < 0.5;
|
export const randBool = () => Math.random() < 0.5;
|
||||||
export const choice = (array: any[]) => array[randInt(0, array.length)];
|
export const choice = (array: any[]) => array[randInt(0, array.length)];
|
||||||
export const weightedChoice = <T>(options: [T, number][]): T => {
|
export const weightedChoice = <T extends string | number>(options: [T, number][] | Partial<Record<T, number>>): T | null => {
|
||||||
|
if (!Array.isArray(options)) {
|
||||||
|
options = Object.entries(options) as [T, number][];
|
||||||
|
}
|
||||||
const sum = options.reduce((acc, o) => acc + o[1], 0);
|
const sum = options.reduce((acc, o) => acc + o[1], 0);
|
||||||
|
|
||||||
const rnd = Math.random() * sum;
|
const rnd = Math.random() * sum;
|
||||||
|
|
@ -17,7 +20,7 @@ export const weightedChoice = <T>(options: [T, number][]): T => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return options[0][0];
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const range = (size: number | string) => Object.keys((new Array(+size)).fill(0)).map(k => +k);
|
export const range = (size: number | string) => Object.keys((new Array(+size)).fill(0)).map(k => +k);
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 198 B After Width: | Height: | Size: 198 B |
|
|
@ -5,18 +5,21 @@ const emptySprite: BrickDisplayImage = { image: [], width: 0, height: 0 };
|
||||||
export interface Item {
|
export interface Item {
|
||||||
sprite: BrickDisplayImage;
|
sprite: BrickDisplayImage;
|
||||||
damage: number;
|
damage: number;
|
||||||
heal?: number;
|
|
||||||
accuracy: number;
|
accuracy: number;
|
||||||
|
heal?: number;
|
||||||
|
instantUse?: boolean;
|
||||||
|
consumable?: boolean;
|
||||||
ranged: boolean;
|
ranged: boolean;
|
||||||
consumable: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Monster {
|
export interface Monster {
|
||||||
sprite: BrickDisplayImage;
|
sprite: BrickDisplayImage;
|
||||||
damage: number;
|
damage: number;
|
||||||
|
accuracy: number;
|
||||||
health: number;
|
health: number;
|
||||||
|
maxHealth: number;
|
||||||
ranged: boolean;
|
ranged: boolean;
|
||||||
lootTable: Record<string, number>; // <itemId, probability of drop>
|
lootTable: Partial<Record<Items, number>>; // <itemId, probability of drop>
|
||||||
secondLootChance: number;
|
secondLootChance: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -48,28 +51,24 @@ export const ITEMS: Item[] = [
|
||||||
damage: 1,
|
damage: 1,
|
||||||
accuracy: 1,
|
accuracy: 1,
|
||||||
ranged: false,
|
ranged: false,
|
||||||
consumable: false,
|
|
||||||
},
|
},
|
||||||
{ // SWORD
|
{ // SWORD
|
||||||
sprite: emptySprite,
|
sprite: emptySprite,
|
||||||
accuracy: 1,
|
accuracy: 1,
|
||||||
damage: 5,
|
damage: 5,
|
||||||
ranged: false,
|
ranged: false,
|
||||||
consumable: false,
|
|
||||||
},
|
},
|
||||||
{ // BIG_SWORD
|
{ // BIG_SWORD
|
||||||
sprite: emptySprite,
|
sprite: emptySprite,
|
||||||
accuracy: 0.9,
|
accuracy: 0.9,
|
||||||
damage: 10,
|
damage: 10,
|
||||||
ranged: false,
|
ranged: false,
|
||||||
consumable: false,
|
|
||||||
},
|
},
|
||||||
{ // BOW
|
{ // BOW
|
||||||
sprite: emptySprite,
|
sprite: emptySprite,
|
||||||
accuracy: 0.7,
|
accuracy: 0.7,
|
||||||
damage: 5,
|
damage: 5,
|
||||||
ranged: true,
|
ranged: true,
|
||||||
consumable: false,
|
|
||||||
},
|
},
|
||||||
{ // GRENADE
|
{ // GRENADE
|
||||||
sprite: emptySprite,
|
sprite: emptySprite,
|
||||||
|
|
@ -92,14 +91,16 @@ export const ITEMS: Item[] = [
|
||||||
damage: 0,
|
damage: 0,
|
||||||
heal: 5,
|
heal: 5,
|
||||||
ranged: false,
|
ranged: false,
|
||||||
consumable: true,
|
instantUse: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
export const MONSTERS: Monster[] = [
|
export const MONSTERS: Monster[] = [
|
||||||
{ // SMALL_SLIME
|
{ // SMALL_SLIME
|
||||||
sprite: emptySprite,
|
sprite: emptySprite,
|
||||||
health: 1,
|
health: 1,
|
||||||
|
maxHealth: 1,
|
||||||
damage: 1,
|
damage: 1,
|
||||||
|
accuracy: 0.5,
|
||||||
lootTable: {
|
lootTable: {
|
||||||
[Items.HEAL]: 0.5,
|
[Items.HEAL]: 0.5,
|
||||||
[Items.SWORD]: 0.3,
|
[Items.SWORD]: 0.3,
|
||||||
|
|
@ -112,7 +113,9 @@ export const MONSTERS: Monster[] = [
|
||||||
{ // SMALL_DEMON
|
{ // SMALL_DEMON
|
||||||
sprite: emptySprite,
|
sprite: emptySprite,
|
||||||
health: 2,
|
health: 2,
|
||||||
|
maxHealth: 2,
|
||||||
damage: 1,
|
damage: 1,
|
||||||
|
accuracy: 0.7,
|
||||||
lootTable: {
|
lootTable: {
|
||||||
[Items.HEAL]: 0.5,
|
[Items.HEAL]: 0.5,
|
||||||
[Items.SWORD]: 0.3,
|
[Items.SWORD]: 0.3,
|
||||||
|
|
@ -126,7 +129,9 @@ export const MONSTERS: Monster[] = [
|
||||||
{ // SNAKE
|
{ // SNAKE
|
||||||
sprite: emptySprite,
|
sprite: emptySprite,
|
||||||
health: 3,
|
health: 3,
|
||||||
|
maxHealth: 3,
|
||||||
damage: 2,
|
damage: 2,
|
||||||
|
accuracy: 0.8,
|
||||||
lootTable: {
|
lootTable: {
|
||||||
[Items.HEAL]: 0.5,
|
[Items.HEAL]: 0.5,
|
||||||
[Items.POTION]: 0.3,
|
[Items.POTION]: 0.3,
|
||||||
|
|
@ -139,13 +144,15 @@ export const MONSTERS: Monster[] = [
|
||||||
{ // SMALL_ELEMENTAL
|
{ // SMALL_ELEMENTAL
|
||||||
sprite: emptySprite,
|
sprite: emptySprite,
|
||||||
health: 4,
|
health: 4,
|
||||||
|
maxHealth: 4,
|
||||||
damage: 2,
|
damage: 2,
|
||||||
|
accuracy: 0.5,
|
||||||
lootTable: {
|
lootTable: {
|
||||||
[Items.HEAL]: 0.5,
|
[Items.HEAL]: 0.5,
|
||||||
[Items.BOW]: 0.3,
|
[Items.BOW]: 0.3,
|
||||||
[Items.GRENADE]: 0.1,
|
[Items.GRENADE]: 0.1,
|
||||||
},
|
},
|
||||||
ranged: false,
|
ranged: true,
|
||||||
secondLootChance: 0,
|
secondLootChance: 0,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@ import { isPressed, updateKeys } from "@common/input";
|
||||||
|
|
||||||
import backgroundImage from './assets/background.png';
|
import backgroundImage from './assets/background.png';
|
||||||
import spritesheetImage from './assets/spritesheet.png';
|
import spritesheetImage from './assets/spritesheet.png';
|
||||||
import { ITEMS, Items, MONSTERS, loadData, type Item } from "./data";
|
import { ITEMS, Items, MONSTERS, loadData, type Item, type Monster } from "./data";
|
||||||
|
import { delay, randBool, weightedChoice } from "@common/utils";
|
||||||
|
|
||||||
let display: BrickDisplay;
|
let display: BrickDisplay;
|
||||||
let background: BrickDisplayImage;
|
let background: BrickDisplayImage;
|
||||||
|
|
@ -13,21 +14,31 @@ const playerY = 2;
|
||||||
|
|
||||||
let y = 0;
|
let y = 0;
|
||||||
let targetY = 0;
|
let targetY = 0;
|
||||||
|
let playerHealth = 10;
|
||||||
|
let playerBlink = 0;
|
||||||
|
|
||||||
let playerTurn = true;
|
let playerTurn = true;
|
||||||
let lootToConfirm: Items | null = null;
|
let lootToConfirm: Items | null = null;
|
||||||
|
let lootBlink = false;
|
||||||
|
|
||||||
let selectedSlot = 0;
|
let selectedSlot = 0;
|
||||||
let inventory: Items[] = [Items.STICK, Items.BOW];
|
let inventory: Items[] = [Items.STICK];
|
||||||
|
|
||||||
let monsterAlive = true;
|
let monsterAlive = true;
|
||||||
let monster = -1;
|
let currentMonster = -1;
|
||||||
let monsterY = 12;
|
let monsterY = 12;
|
||||||
let monsterTargetY = 12;
|
let monsterTargetY = 12;
|
||||||
|
let monsterBlink = 0;
|
||||||
|
|
||||||
let bulletY = -1;
|
let bulletY = -1;
|
||||||
let bulletBlink = false;
|
let bulletBlink = false;
|
||||||
let bulletTargetY = -1;
|
let bulletTargetY = -1;
|
||||||
|
|
||||||
|
let lootY = -1;
|
||||||
|
let lootItem: Items | null = null;
|
||||||
|
let secondLootY = -1;
|
||||||
|
let secondLootItem: Items | null = null;
|
||||||
|
|
||||||
let frames = 0;
|
let frames = 0;
|
||||||
let prevFrameTime: number = 0;
|
let prevFrameTime: number = 0;
|
||||||
async function loop(time: number) {
|
async function loop(time: number) {
|
||||||
|
|
@ -35,8 +46,22 @@ async function loop(time: number) {
|
||||||
const dt = time - prevFrameTime;
|
const dt = time - prevFrameTime;
|
||||||
prevFrameTime = time;
|
prevFrameTime = time;
|
||||||
|
|
||||||
|
if (frames % 8 == 0) {
|
||||||
|
lootBlink = !lootBlink;
|
||||||
|
}
|
||||||
|
|
||||||
|
let lootConfirmed = false;
|
||||||
const item = ITEMS[inventory[selectedSlot]];
|
const item = ITEMS[inventory[selectedSlot]];
|
||||||
if (bulletTargetY !== bulletY) {
|
const monster = MONSTERS[currentMonster];
|
||||||
|
if (playerBlink) {
|
||||||
|
if (frames % 4 == 0) {
|
||||||
|
playerBlink--;
|
||||||
|
}
|
||||||
|
} else if (monsterBlink) {
|
||||||
|
if (frames % 4 == 0) {
|
||||||
|
monsterBlink--;
|
||||||
|
}
|
||||||
|
} else if (bulletTargetY !== bulletY) {
|
||||||
console.log('Bullet animation');
|
console.log('Bullet animation');
|
||||||
if (frames % 2 == 0) {
|
if (frames % 2 == 0) {
|
||||||
bulletY += Math.sign(bulletTargetY - bulletY);
|
bulletY += Math.sign(bulletTargetY - bulletY);
|
||||||
|
|
@ -52,18 +77,25 @@ async function loop(time: number) {
|
||||||
if (frames % 3 == 0) {
|
if (frames % 3 == 0) {
|
||||||
y += Math.sign(targetY - y);
|
y += Math.sign(targetY - y);
|
||||||
}
|
}
|
||||||
} else if (playerTurn) {
|
} else if (playerTurn && playerHealth > 0) {
|
||||||
// console.log('Player turn');
|
lootToConfirm = null;
|
||||||
if (isPressed('ArrowLeft')) {
|
if (y === lootY) {
|
||||||
|
lootToConfirm = lootItem;
|
||||||
|
playerTurn = false;
|
||||||
|
} else if (y === secondLootY) {
|
||||||
|
lootToConfirm = secondLootItem;
|
||||||
|
playerTurn = false;
|
||||||
|
} else if (isPressed('ArrowLeft')) {
|
||||||
selectedSlot = (selectedSlot + inventory.length - 1) % inventory.length;
|
selectedSlot = (selectedSlot + inventory.length - 1) % inventory.length;
|
||||||
} else if (isPressed('ArrowRight')) {
|
} else if (isPressed('ArrowRight')) {
|
||||||
selectedSlot = (selectedSlot + 1) % inventory.length;
|
selectedSlot = (selectedSlot + 1) % inventory.length;
|
||||||
}
|
} else if (isPressed('ArrowUp') && (!monsterAlive || y < monsterY - 5)) {
|
||||||
if (isPressed('ArrowUp') && (!monsterAlive || y < monsterY - 5)) {
|
|
||||||
targetY = y + 4;
|
targetY = y + 4;
|
||||||
playerTurn = false;
|
playerTurn = false;
|
||||||
}
|
} else if (isPressed('ArrowDown')) {
|
||||||
if (isPressed('Space') && (monsterAlive && (y >= monsterY - 5 || item.ranged))) {
|
targetY = y - 4;
|
||||||
|
playerTurn = false;
|
||||||
|
} else if (isPressed('Space') && (monsterAlive && (y >= monsterY - 5 || item.ranged || item.heal))) {
|
||||||
if (item.consumable) {
|
if (item.consumable) {
|
||||||
inventory.splice(selectedSlot, 1);
|
inventory.splice(selectedSlot, 1);
|
||||||
selectedSlot = (selectedSlot + inventory.length - 1) % inventory.length;
|
selectedSlot = (selectedSlot + inventory.length - 1) % inventory.length;
|
||||||
|
|
@ -71,49 +103,142 @@ async function loop(time: number) {
|
||||||
if (item.ranged) {
|
if (item.ranged) {
|
||||||
console.log('Ranged attack')
|
console.log('Ranged attack')
|
||||||
bulletY = y + playerY + playerSprite.height;
|
bulletY = y + playerY + playerSprite.height;
|
||||||
bulletTargetY = monsterY + MONSTERS[monster].sprite.height;
|
bulletTargetY = monsterY + monster.sprite.height;
|
||||||
|
} else if (item.heal) {
|
||||||
|
console.log('Heal' + item.heal);
|
||||||
|
playerHealth += item.heal;
|
||||||
|
playerTurn = false;
|
||||||
} else {
|
} else {
|
||||||
console.log('Melee attack');
|
console.log('Melee attack');
|
||||||
damageMonster(item);
|
damageMonster(item);
|
||||||
}
|
|
||||||
playerTurn = false;
|
playerTurn = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if (lootToConfirm) {
|
} else if (lootToConfirm) {
|
||||||
console.log('lootConfirm');
|
console.log('Loot confirm');
|
||||||
// TODO
|
|
||||||
|
if (isPressed('Space')) {
|
||||||
|
const i = ITEMS[lootToConfirm];
|
||||||
|
if (i.instantUse && i.heal) {
|
||||||
|
playerHealth += i.heal;
|
||||||
|
} else {
|
||||||
|
inventory.push(lootToConfirm);
|
||||||
|
}
|
||||||
|
|
||||||
|
lootConfirmed = true;
|
||||||
|
} else if (isPressed('ArrowUp')) {
|
||||||
|
targetY = y + 4;
|
||||||
|
playerTurn = true;
|
||||||
|
} else if (isPressed('ArrowDown')) {
|
||||||
|
targetY = y - 4;
|
||||||
|
playerTurn = true;
|
||||||
|
}
|
||||||
} else if (monsterAlive) { // Monster turn
|
} else if (monsterAlive) { // Monster turn
|
||||||
console.log('Monster turn');
|
console.log('Monster turn');
|
||||||
// TODO
|
if (monster.health <= 0) {
|
||||||
|
if (monsterBlink === 0) { // wait blink animation finish
|
||||||
|
monsterAlive = false;
|
||||||
|
|
||||||
|
const lootTable = { ...monster.lootTable };
|
||||||
|
for (const item of inventory) {
|
||||||
|
lootTable[item] = 0;
|
||||||
|
}
|
||||||
|
const drop = weightedChoice(lootTable);
|
||||||
|
lootY = monsterY - 1;
|
||||||
|
lootItem = drop;
|
||||||
|
|
||||||
|
if (drop != null) {
|
||||||
|
lootTable[drop] = 0;
|
||||||
|
const rnd = Math.random();
|
||||||
|
if (rnd < monster.secondLootChance) {
|
||||||
|
secondLootY = monsterY + 7;
|
||||||
|
secondLootItem = weightedChoice(lootTable);
|
||||||
|
}
|
||||||
|
}
|
||||||
playerTurn = true;
|
playerTurn = true;
|
||||||
|
}
|
||||||
|
} else if (monster.ranged) {
|
||||||
|
const retreat = randBool();
|
||||||
|
if (retreat) {
|
||||||
|
monsterTargetY = monsterY + 4;
|
||||||
|
playerTurn = true;
|
||||||
|
} else {
|
||||||
|
bulletY = monsterY + monster.sprite.height;
|
||||||
|
bulletTargetY = y + playerY + playerSprite.height;
|
||||||
|
}
|
||||||
|
} else if (y < monsterY - 5) {
|
||||||
|
monsterTargetY = monsterY - 4;
|
||||||
|
playerTurn = true;
|
||||||
|
} else {
|
||||||
|
damagePlayer(monster);
|
||||||
|
playerTurn = true;
|
||||||
|
}
|
||||||
} else { // return control to player
|
} else { // return control to player
|
||||||
playerTurn = true;
|
playerTurn = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (y === targetY && (lootItem || secondLootItem) && lootY < y - 10) {
|
||||||
|
lootConfirmed = true;
|
||||||
|
}
|
||||||
|
if (lootConfirmed) {
|
||||||
|
lootY = -1;
|
||||||
|
secondLootY = -1;
|
||||||
|
lootItem = null;
|
||||||
|
secondLootItem = null;
|
||||||
|
spawnNextMonster();
|
||||||
|
playerTurn = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (bulletY > 0 && bulletTargetY === bulletY) {
|
if (bulletY > 0 && bulletTargetY === bulletY) {
|
||||||
bulletTargetY = bulletY = -1;
|
bulletTargetY = bulletY = -1;
|
||||||
bulletBlink = false;
|
bulletBlink = false;
|
||||||
|
if (playerTurn) {
|
||||||
damageMonster(item);
|
damageMonster(item);
|
||||||
|
playerTurn = false;
|
||||||
|
} else {
|
||||||
|
damagePlayer(monster);
|
||||||
|
playerTurn = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
display.clear();
|
display.clear();
|
||||||
display.clear(true);
|
display.clear(true);
|
||||||
|
|
||||||
display.speed = item.damage;
|
display.speed = item.damage;
|
||||||
|
display.score = playerHealth;
|
||||||
|
display.gameOver = playerHealth === 0;
|
||||||
|
|
||||||
const bgY = y % display.height;
|
const bgY = y % display.height;
|
||||||
display.drawImage(background, 0, bgY);
|
display.drawImage(background, 0, bgY);
|
||||||
display.drawImage(background, 0, bgY - display.height);
|
display.drawImage(background, 0, bgY - display.height);
|
||||||
|
|
||||||
|
if (playerBlink % 2 == 0) {
|
||||||
display.drawImage(playerSprite, 3, display.height - playerSprite.height - playerY);
|
display.drawImage(playerSprite, 3, display.height - playerSprite.height - playerY);
|
||||||
if (monsterAlive && MONSTERS[monster]) {
|
}
|
||||||
display.drawImage(MONSTERS[monster].sprite, 3, display.height + (y - monsterY) - MONSTERS[monster].sprite.height - playerY);
|
|
||||||
|
if (monsterAlive && monsterBlink % 2 == 0 && monster) {
|
||||||
|
display.drawImage(monster.sprite, 3, display.height + (y - monsterY) - monster.sprite.height - playerY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lootItem && lootItem !== lootToConfirm) {
|
||||||
|
display.drawImage(ITEMS[lootItem].sprite, 3, display.height + (y - lootY) - ITEMS[lootItem].sprite.height - playerY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (secondLootItem && secondLootItem !== lootToConfirm) {
|
||||||
|
display.drawImage(ITEMS[secondLootItem].sprite, 3, display.height + (y - secondLootY) - ITEMS[secondLootItem].sprite.height - playerY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bulletY > 0) {
|
if (bulletY > 0) {
|
||||||
display.setPixel(display.width >> 1, display.height + (y - bulletY), bulletBlink);
|
display.setPixel(display.width >> 1, display.height + (y - bulletY), bulletBlink);
|
||||||
}
|
}
|
||||||
|
|
||||||
display.drawImage(ITEMS[inventory[selectedSlot]].sprite, 0, 0, true);
|
if (lootToConfirm) {
|
||||||
|
if (lootBlink) {
|
||||||
|
display.drawImage(ITEMS[lootToConfirm].sprite, 0, 0, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
display.drawImage(item.sprite, 0, 0, true);
|
||||||
|
}
|
||||||
|
|
||||||
display.update();
|
display.update();
|
||||||
|
|
||||||
|
|
@ -122,22 +247,34 @@ async function loop(time: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function spawnNextMonster() {
|
function spawnNextMonster() {
|
||||||
monster++;
|
currentMonster++;
|
||||||
monsterAlive = MONSTERS[monster] != null;
|
monsterAlive = MONSTERS[currentMonster] != null;
|
||||||
monsterTargetY = monsterY = y + 13;
|
if (monsterAlive) {
|
||||||
|
MONSTERS[currentMonster].health = MONSTERS[currentMonster].maxHealth;
|
||||||
|
}
|
||||||
|
monsterY = y + 20;
|
||||||
|
monsterTargetY = y + 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
function damageMonster(item: Item) {
|
function damageMonster(item: Item) {
|
||||||
const rnd = Math.random();
|
const rnd = Math.random();
|
||||||
console.log(`Attack for ${item.damage}, success: ${rnd.toFixed(1)} < ${item.accuracy}`)
|
console.log(`Attack for ${item.damage}, success: ${rnd.toFixed(1)} < ${item.accuracy}`);
|
||||||
if (monsterAlive && rnd < item.accuracy) {
|
if (monsterAlive && rnd < item.accuracy) {
|
||||||
MONSTERS[monster].health -= item.damage;
|
MONSTERS[currentMonster].health -= item.damage;
|
||||||
console.log(`Monster HP: ${MONSTERS[monster].health}`);
|
monsterBlink = 10;
|
||||||
if (MONSTERS[monster].health <= 0) {
|
console.log(`Monster HP: ${MONSTERS[currentMonster].health}`);
|
||||||
monsterAlive = false;
|
}
|
||||||
// TODO spawn loot
|
}
|
||||||
|
|
||||||
spawnNextMonster();
|
function damagePlayer(monster: Monster) {
|
||||||
|
const rnd = Math.random();
|
||||||
|
console.log(`Monster attack for ${monster.damage}, success: ${rnd.toFixed(1)} < ${monster.accuracy}`);
|
||||||
|
|
||||||
|
if (rnd < monster.accuracy) {
|
||||||
|
playerHealth -= monster.damage;
|
||||||
|
playerBlink = 10;
|
||||||
|
if (playerHealth <= 0) {
|
||||||
|
playerHealth = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue