Add fights

This commit is contained in:
Aslan 2026-01-23 10:35:09 -05:00
parent a14be66890
commit b79e970b07
5 changed files with 323 additions and 0 deletions

View file

@ -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 };