homicide is now real
This commit is contained in:
parent
50321d04b2
commit
47da949b6d
@ -1,8 +1,14 @@
|
||||
import { Message, TextChannel } from "discord.js";
|
||||
import { Character, CHARACTERS, PotencyStatus, Target } from "./characters";
|
||||
import { Message, TextBasedChannel } from "discord.js";
|
||||
import { Character, CHARACTERS, Effect, PotencyStatus, Target } from "./characters";
|
||||
import { Player } from "./models/player";
|
||||
import { Unit } from "./models/unit";
|
||||
|
||||
export enum BattleState {
|
||||
Ongoing,
|
||||
Team1Win,
|
||||
Team2Win
|
||||
}
|
||||
|
||||
interface StatusEffects {
|
||||
poison: number
|
||||
regeneration: number
|
||||
@ -15,6 +21,7 @@ interface PotencyEffects {
|
||||
resistanceChange: PotencyStatus[]
|
||||
accuracyChange: PotencyStatus[]
|
||||
speedChange: PotencyStatus[]
|
||||
damageChange: PotencyStatus[]
|
||||
}
|
||||
|
||||
class BattleUnit {
|
||||
@ -41,13 +48,14 @@ class BattleUnit {
|
||||
potencyEffects: PotencyEffects = {
|
||||
resistanceChange: [],
|
||||
accuracyChange: [],
|
||||
speedChange: []
|
||||
speedChange: [],
|
||||
damageChange: []
|
||||
}
|
||||
active = true
|
||||
}
|
||||
|
||||
export class Battle {
|
||||
constructor (channel: TextChannel, player1: Player, player2: Player, team1: [Unit, Unit, Unit], team2: [Unit, Unit, Unit]) {
|
||||
constructor (channel: TextBasedChannel, player1: Player, player2: Player, team1: [Unit, Unit, Unit], team2: [Unit, Unit, Unit]) {
|
||||
this.channel = channel;
|
||||
this.player1 = player1;
|
||||
this.player2 = player2;
|
||||
@ -56,9 +64,15 @@ export class Battle {
|
||||
this.units = this.team1.concat(this.team2) as [BattleUnit, BattleUnit, BattleUnit, BattleUnit, BattleUnit, BattleUnit];
|
||||
}
|
||||
|
||||
simulateRound () {
|
||||
simulateRound (): BattleState {
|
||||
this.log = '';
|
||||
this.tickStatuses(this.units);
|
||||
this.checkAlive(this.units);
|
||||
this.useSkills(this.units);
|
||||
|
||||
if (!this.team1.filter(e => {return e.active})[0]) return BattleState.Team2Win;
|
||||
else if (!this.team2.filter(e => {return e.active})[0]) return BattleState.Team1Win;
|
||||
else return BattleState.Ongoing;
|
||||
}
|
||||
|
||||
tickStatuses (units: BattleUnit[]) {
|
||||
@ -94,7 +108,7 @@ export class Battle {
|
||||
for (let i = 0; i < units.length; i++) {
|
||||
const rolls = []
|
||||
let modifiedSpeed = units[i].speed
|
||||
for (const change of units[i].potencyEffects.accuracyChange) {
|
||||
for (const change of units[i].potencyEffects.speedChange) {
|
||||
modifiedSpeed -= change.potency;
|
||||
}
|
||||
for (let o = 0; o < modifiedSpeed; o++) {
|
||||
@ -106,8 +120,12 @@ export class Battle {
|
||||
|
||||
order.sort((a, b) => {return b[1] - a[1]});
|
||||
|
||||
console.debug(order);
|
||||
|
||||
for (const initiative of order) {
|
||||
const unit = units[initiative[1]];
|
||||
const unit = units[initiative[0]];
|
||||
if (!unit.active) continue;
|
||||
|
||||
const skill = unit.character.skills[Math.floor(Math.random()*unit.character.skills.length)];
|
||||
const team = initiative[0] < 3 ? 1 : 2
|
||||
const target = team === 1 ? this.team2[Math.floor(Math.random()*this.team2.length)] : this.team1[Math.floor(Math.random()*this.team1.length)];
|
||||
@ -121,35 +139,52 @@ export class Battle {
|
||||
for (const effect of skill.effects) {
|
||||
switch (effect.target){
|
||||
case Target.Self:
|
||||
this.runEffect([unit]);
|
||||
this.runEffect(effect, unit, [unit]);
|
||||
break;
|
||||
case Target.Team:
|
||||
this.runEffect(team === 1 ? this.team1 : this.team2);
|
||||
this.runEffect(effect, unit, team === 1 ? this.team1 : this.team2);
|
||||
break;
|
||||
case Target.OneTeammate:
|
||||
this.runEffect([allyTarget]);
|
||||
this.runEffect(effect, unit, [allyTarget]);
|
||||
break;
|
||||
case Target.OneOpponent:
|
||||
this.runEffect([target]);
|
||||
this.runEffect(effect, unit, [target]);
|
||||
break;
|
||||
case Target.AllOpponents:
|
||||
this.runEffect(team === 1 ? this.team2 : this.team1);
|
||||
this.runEffect(effect, unit, team === 1 ? this.team2 : this.team1);
|
||||
break;
|
||||
case Target.TrueRandomOpponent:
|
||||
this.runEffect([team === 1 ? this.team2[Math.floor(Math.random()*this.team2.length)] : this.team1[Math.floor(Math.random()*this.team1.length)]]);
|
||||
this.runEffect(effect, unit, [team === 1 ? this.team2[Math.floor(Math.random()*this.team2.length)] : this.team1[Math.floor(Math.random()*this.team1.length)]]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.checkAlive(this.units);
|
||||
}
|
||||
}
|
||||
|
||||
runEffect (effect: Effect, self: BattleUnit, targets: BattleUnit[]) {
|
||||
if (effect.damage) {
|
||||
for (const target of targets) {
|
||||
let damage = effect.damage;
|
||||
for (const statChange of self.potencyEffects.damageChange) {
|
||||
Math.round(damage *= 1+(statChange.potency/100));
|
||||
}
|
||||
for (const statChange of target.potencyEffects.resistanceChange) {
|
||||
Math.round(damage *= 1-(statChange.potency/100));
|
||||
}
|
||||
|
||||
this.appendLog(`${target.character.nameShort} took ${damage} damage!`);
|
||||
target.health -= damage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
runEffect (targets: BattleUnit[]) {
|
||||
|
||||
}
|
||||
|
||||
checkAlive (units: BattleUnit[]) {
|
||||
for (const unit of units) {
|
||||
if (unit.health <= 0) unit.active = false;
|
||||
if (!unit.active) continue;
|
||||
console.debug(unit.health);
|
||||
if (unit.health > 0) continue;
|
||||
unit.active = false;
|
||||
this.appendLog(`${unit.character.nameShort} has been defeated!`);
|
||||
}
|
||||
}
|
||||
@ -157,13 +192,14 @@ export class Battle {
|
||||
appendLog (str: string) {
|
||||
if (this.log) this.log += '\n';
|
||||
this.log += str;
|
||||
console.debug(str);
|
||||
return this.log;
|
||||
}
|
||||
|
||||
message?: Message
|
||||
log = ""
|
||||
|
||||
channel: TextChannel
|
||||
channel: TextBasedChannel
|
||||
player1: Player
|
||||
player2: Player
|
||||
team1: [BattleUnit, BattleUnit, BattleUnit]
|
||||
|
@ -34,16 +34,17 @@ const Effect = z.object({
|
||||
resistanceChange: z.optional(PotencyStatus),
|
||||
accuracyChange: z.optional(PotencyStatus),
|
||||
speedChange: z.optional(PotencyStatus),
|
||||
damageChange: z.optional(PotencyStatus),
|
||||
function: z.optional(z.string())
|
||||
}).strict();
|
||||
type Effect = z.infer<typeof Effect>;
|
||||
export type Effect = z.infer<typeof Effect>;
|
||||
|
||||
const Skill = z.object({
|
||||
name: z.string(),
|
||||
accuracy: z.optional(z.number().int()),
|
||||
effects: z.array(Effect)
|
||||
}).strict();
|
||||
type Skill = z.infer<typeof Skill>;
|
||||
export type Skill = z.infer<typeof Skill>;
|
||||
|
||||
const Character = z.object({
|
||||
id: z.number().int(),
|
||||
|
39
src/slash/battletest.ts
Normal file
39
src/slash/battletest.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { ApplicationCommandOptionData, ApplicationCommandOptionType, CommandInteraction } from "discord.js"
|
||||
import { Battle, BattleState } from "../battle"
|
||||
import { CBClient } from "../cbclient"
|
||||
import { CHARACTERS } from "../characters"
|
||||
import { Player } from "../models/player"
|
||||
import { Unit } from "../models/unit"
|
||||
import { createArgumentsObject, SlashCommand } from "./slash"
|
||||
|
||||
export class BattleTestCommand implements SlashCommand {
|
||||
name = 'battletest'
|
||||
description = 'shhh'
|
||||
permission = []
|
||||
ownerOnly = false
|
||||
guildOnly = false
|
||||
guildID = "739645806100873328" //for testing
|
||||
args: ApplicationCommandOptionData[] = []
|
||||
|
||||
async execute(int: CommandInteraction) {
|
||||
const client = int.client as CBClient;
|
||||
const you = await client.findOrCreatePlayer(int.user.id);
|
||||
const units = (await Unit.findAll());
|
||||
const battle = new Battle(int.channel!, you, you, units.slice(0, 3) as [Unit, Unit, Unit], units.slice(3, 6) as [Unit, Unit, Unit]);
|
||||
|
||||
await int.reply({
|
||||
content: 'gottem'
|
||||
});
|
||||
let state: BattleState = BattleState.Ongoing;
|
||||
while (state === BattleState.Ongoing) {
|
||||
state = battle.simulateRound();
|
||||
await int.channel?.send(battle.log);
|
||||
}
|
||||
switch (state) {
|
||||
case BattleState.Team1Win:
|
||||
return await int.channel?.send('gamer 1 wins');
|
||||
case BattleState.Team2Win:
|
||||
return await int.channel?.send('gamer 2 wins');
|
||||
}
|
||||
}
|
||||
};
|
@ -1,3 +1,4 @@
|
||||
import { BattleTestCommand } from "./battletest";
|
||||
import { InitCommand } from "./init";
|
||||
import { RandomCaseCommand } from "./randomcase";
|
||||
import { RollCommand } from "./roll";
|
||||
@ -6,5 +7,6 @@ import { SlashCommand } from "./slash";
|
||||
export const SlashCommandList: SlashCommand[] = [
|
||||
new RandomCaseCommand(),
|
||||
new InitCommand(),
|
||||
new RollCommand()
|
||||
new RollCommand(),
|
||||
new BattleTestCommand()
|
||||
];
|
Loading…
Reference in New Issue
Block a user