Add fights
This commit is contained in:
parent
a14be66890
commit
b79e970b07
5 changed files with 323 additions and 0 deletions
|
|
@ -0,0 +1,160 @@
|
|||
import type { MatrixClient } from "matrix-js-sdk";
|
||||
import type {
|
||||
Attack,
|
||||
IEntity,
|
||||
INPC,
|
||||
IPlayer,
|
||||
TFullNPC,
|
||||
} from "./structures/entities.js";
|
||||
import { locationFarlands } from "./structures/locations.js";
|
||||
import { getAttack, getMaxHealth, getNpcData, isPlayer } from "./entity.js";
|
||||
import { sleep } from "matrix-js-sdk/lib/utils.js";
|
||||
|
||||
const fightEntity = async (
|
||||
client: MatrixClient,
|
||||
roomId: string,
|
||||
attacker: IPlayer | TFullNPC,
|
||||
defender: IPlayer | TFullNPC,
|
||||
) => {
|
||||
let attackerAttacks: Attack[] = [];
|
||||
let attackerDamage = 0;
|
||||
let attackerDefense = 0;
|
||||
attacker.inventory.items.forEach((item) => {
|
||||
item.attacks.forEach((attack) => {
|
||||
attackerAttacks.push(attack);
|
||||
});
|
||||
item.stats.forEach((stat) => {
|
||||
attackerDamage += stat.damage;
|
||||
attackerDefense += stat.defense;
|
||||
});
|
||||
});
|
||||
attackerDamage *= 1 + attacker.strength / 10;
|
||||
attackerDefense *= 1 + attacker.strength / 10;
|
||||
|
||||
let defenderAttacks: Attack[] = [];
|
||||
let defenderDamage = 0;
|
||||
let defenderDefense = 0;
|
||||
defender.inventory.items.forEach((item) => {
|
||||
item.attacks.forEach((attack) => {
|
||||
defenderAttacks.push(attack);
|
||||
});
|
||||
item.stats.forEach((stat) => {
|
||||
defenderDamage += stat.damage;
|
||||
defenderDefense += stat.defense;
|
||||
});
|
||||
});
|
||||
defenderDamage *= 1 + defender.strength / 10;
|
||||
defenderDefense *= 1 + defender.strength / 10;
|
||||
|
||||
let winner: IPlayer | TFullNPC | undefined = undefined;
|
||||
let loser: IPlayer | TFullNPC | undefined = undefined;
|
||||
|
||||
while (true) {
|
||||
await sleep(5000);
|
||||
|
||||
const attackerWon = fightRound(
|
||||
client,
|
||||
roomId,
|
||||
attackerAttacks,
|
||||
attackerDamage,
|
||||
defender,
|
||||
defenderDefense,
|
||||
);
|
||||
|
||||
if (attackerWon) {
|
||||
winner = attacker;
|
||||
loser = defender;
|
||||
break;
|
||||
}
|
||||
|
||||
const defenderWon = fightRound(
|
||||
client,
|
||||
roomId,
|
||||
defenderAttacks,
|
||||
defenderDamage,
|
||||
attacker,
|
||||
attackerDefense,
|
||||
);
|
||||
|
||||
if (defenderWon) {
|
||||
winner = defender;
|
||||
loser = attacker;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
client.sendTextMessage(
|
||||
roomId,
|
||||
`${attacker.name} has won the fight against ${defender.name}!`,
|
||||
);
|
||||
|
||||
if (isPlayer(loser)) {
|
||||
respawnPlayer(client, roomId, loser as IPlayer);
|
||||
} else {
|
||||
const npcData = getNpcData((loser as INPC).id);
|
||||
npcData.dead = true;
|
||||
}
|
||||
};
|
||||
|
||||
const fightRound = (
|
||||
client: MatrixClient,
|
||||
roomId: string,
|
||||
attackerAttacks: Attack[],
|
||||
attackerDamage: number,
|
||||
defender: IPlayer | TFullNPC,
|
||||
defenderDefense: number,
|
||||
): boolean => {
|
||||
const attackerAttack =
|
||||
attackerAttacks[Math.floor(Math.random() * attackerAttacks.length)];
|
||||
|
||||
if (!attackerAttack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const attackerAttackInfo = getAttack(attackerAttack);
|
||||
|
||||
const attackerAttackDamage =
|
||||
attackerDamage *
|
||||
attackerAttackInfo.damageMultiplier *
|
||||
(0.5 + Math.random() * 0.5);
|
||||
|
||||
defender.health -= attackerAttackDamage;
|
||||
|
||||
if (defender.health <= 0) {
|
||||
const msg = getRandomAttackMessage(
|
||||
defender.health <= -getMaxHealth(defender)
|
||||
? attackerAttackInfo.messagesOverpower
|
||||
: attackerAttackInfo.messagesDead,
|
||||
);
|
||||
client.sendTextMessage(roomId, msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const msg = getRandomAttackMessage(attackerAttackInfo.messages);
|
||||
client.sendTextMessage(roomId, msg);
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const respawnPlayer = (
|
||||
client: MatrixClient,
|
||||
roomId: string,
|
||||
player: IPlayer,
|
||||
) => {
|
||||
const defaultRespawn = locationFarlands;
|
||||
|
||||
player.location = defaultRespawn.id;
|
||||
player.health = getMaxHealth(player);
|
||||
|
||||
client.sendTextMessage(
|
||||
roomId,
|
||||
`${player.name} has been respawned in ${defaultRespawn.name}`,
|
||||
);
|
||||
};
|
||||
|
||||
const getRandomAttackMessage = (messages: string[]): string => {
|
||||
return messages[Math.floor(Math.random() * messages.length)] ?? "";
|
||||
};
|
||||
|
||||
export { fightEntity, fightRound, respawnPlayer, getRandomAttackMessage };
|
||||
Loading…
Add table
Add a link
Reference in a new issue