homicide is now real
This commit is contained in:
parent
50321d04b2
commit
47da949b6d
@ -1,8 +1,14 @@
|
|||||||
import { Message, TextChannel } from "discord.js";
|
import { Message, TextBasedChannel } from "discord.js";
|
||||||
import { Character, CHARACTERS, PotencyStatus, Target } from "./characters";
|
import { Character, CHARACTERS, Effect, PotencyStatus, Target } from "./characters";
|
||||||
import { Player } from "./models/player";
|
import { Player } from "./models/player";
|
||||||
import { Unit } from "./models/unit";
|
import { Unit } from "./models/unit";
|
||||||
|
|
||||||
|
export enum BattleState {
|
||||||
|
Ongoing,
|
||||||
|
Team1Win,
|
||||||
|
Team2Win
|
||||||
|
}
|
||||||
|
|
||||||
interface StatusEffects {
|
interface StatusEffects {
|
||||||
poison: number
|
poison: number
|
||||||
regeneration: number
|
regeneration: number
|
||||||
@ -15,6 +21,7 @@ interface PotencyEffects {
|
|||||||
resistanceChange: PotencyStatus[]
|
resistanceChange: PotencyStatus[]
|
||||||
accuracyChange: PotencyStatus[]
|
accuracyChange: PotencyStatus[]
|
||||||
speedChange: PotencyStatus[]
|
speedChange: PotencyStatus[]
|
||||||
|
damageChange: PotencyStatus[]
|
||||||
}
|
}
|
||||||
|
|
||||||
class BattleUnit {
|
class BattleUnit {
|
||||||
@ -41,13 +48,14 @@ class BattleUnit {
|
|||||||
potencyEffects: PotencyEffects = {
|
potencyEffects: PotencyEffects = {
|
||||||
resistanceChange: [],
|
resistanceChange: [],
|
||||||
accuracyChange: [],
|
accuracyChange: [],
|
||||||
speedChange: []
|
speedChange: [],
|
||||||
|
damageChange: []
|
||||||
}
|
}
|
||||||
active = true
|
active = true
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Battle {
|
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.channel = channel;
|
||||||
this.player1 = player1;
|
this.player1 = player1;
|
||||||
this.player2 = player2;
|
this.player2 = player2;
|
||||||
@ -56,9 +64,15 @@ export class Battle {
|
|||||||
this.units = this.team1.concat(this.team2) as [BattleUnit, BattleUnit, BattleUnit, BattleUnit, BattleUnit, BattleUnit];
|
this.units = this.team1.concat(this.team2) as [BattleUnit, BattleUnit, BattleUnit, BattleUnit, BattleUnit, BattleUnit];
|
||||||
}
|
}
|
||||||
|
|
||||||
simulateRound () {
|
simulateRound (): BattleState {
|
||||||
|
this.log = '';
|
||||||
this.tickStatuses(this.units);
|
this.tickStatuses(this.units);
|
||||||
this.checkAlive(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[]) {
|
tickStatuses (units: BattleUnit[]) {
|
||||||
@ -94,7 +108,7 @@ export class Battle {
|
|||||||
for (let i = 0; i < units.length; i++) {
|
for (let i = 0; i < units.length; i++) {
|
||||||
const rolls = []
|
const rolls = []
|
||||||
let modifiedSpeed = units[i].speed
|
let modifiedSpeed = units[i].speed
|
||||||
for (const change of units[i].potencyEffects.accuracyChange) {
|
for (const change of units[i].potencyEffects.speedChange) {
|
||||||
modifiedSpeed -= change.potency;
|
modifiedSpeed -= change.potency;
|
||||||
}
|
}
|
||||||
for (let o = 0; o < modifiedSpeed; o++) {
|
for (let o = 0; o < modifiedSpeed; o++) {
|
||||||
@ -106,8 +120,12 @@ export class Battle {
|
|||||||
|
|
||||||
order.sort((a, b) => {return b[1] - a[1]});
|
order.sort((a, b) => {return b[1] - a[1]});
|
||||||
|
|
||||||
|
console.debug(order);
|
||||||
|
|
||||||
for (const initiative of 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 skill = unit.character.skills[Math.floor(Math.random()*unit.character.skills.length)];
|
||||||
const team = initiative[0] < 3 ? 1 : 2
|
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)];
|
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) {
|
for (const effect of skill.effects) {
|
||||||
switch (effect.target){
|
switch (effect.target){
|
||||||
case Target.Self:
|
case Target.Self:
|
||||||
this.runEffect([unit]);
|
this.runEffect(effect, unit, [unit]);
|
||||||
break;
|
break;
|
||||||
case Target.Team:
|
case Target.Team:
|
||||||
this.runEffect(team === 1 ? this.team1 : this.team2);
|
this.runEffect(effect, unit, team === 1 ? this.team1 : this.team2);
|
||||||
break;
|
break;
|
||||||
case Target.OneTeammate:
|
case Target.OneTeammate:
|
||||||
this.runEffect([allyTarget]);
|
this.runEffect(effect, unit, [allyTarget]);
|
||||||
break;
|
break;
|
||||||
case Target.OneOpponent:
|
case Target.OneOpponent:
|
||||||
this.runEffect([target]);
|
this.runEffect(effect, unit, [target]);
|
||||||
break;
|
break;
|
||||||
case Target.AllOpponents:
|
case Target.AllOpponents:
|
||||||
this.runEffect(team === 1 ? this.team2 : this.team1);
|
this.runEffect(effect, unit, team === 1 ? this.team2 : this.team1);
|
||||||
break;
|
break;
|
||||||
case Target.TrueRandomOpponent:
|
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;
|
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[]) {
|
checkAlive (units: BattleUnit[]) {
|
||||||
for (const unit of units) {
|
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!`);
|
this.appendLog(`${unit.character.nameShort} has been defeated!`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,13 +192,14 @@ export class Battle {
|
|||||||
appendLog (str: string) {
|
appendLog (str: string) {
|
||||||
if (this.log) this.log += '\n';
|
if (this.log) this.log += '\n';
|
||||||
this.log += str;
|
this.log += str;
|
||||||
|
console.debug(str);
|
||||||
return this.log;
|
return this.log;
|
||||||
}
|
}
|
||||||
|
|
||||||
message?: Message
|
message?: Message
|
||||||
log = ""
|
log = ""
|
||||||
|
|
||||||
channel: TextChannel
|
channel: TextBasedChannel
|
||||||
player1: Player
|
player1: Player
|
||||||
player2: Player
|
player2: Player
|
||||||
team1: [BattleUnit, BattleUnit, BattleUnit]
|
team1: [BattleUnit, BattleUnit, BattleUnit]
|
||||||
|
@ -34,16 +34,17 @@ const Effect = z.object({
|
|||||||
resistanceChange: z.optional(PotencyStatus),
|
resistanceChange: z.optional(PotencyStatus),
|
||||||
accuracyChange: z.optional(PotencyStatus),
|
accuracyChange: z.optional(PotencyStatus),
|
||||||
speedChange: z.optional(PotencyStatus),
|
speedChange: z.optional(PotencyStatus),
|
||||||
|
damageChange: z.optional(PotencyStatus),
|
||||||
function: z.optional(z.string())
|
function: z.optional(z.string())
|
||||||
}).strict();
|
}).strict();
|
||||||
type Effect = z.infer<typeof Effect>;
|
export type Effect = z.infer<typeof Effect>;
|
||||||
|
|
||||||
const Skill = z.object({
|
const Skill = z.object({
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
accuracy: z.optional(z.number().int()),
|
accuracy: z.optional(z.number().int()),
|
||||||
effects: z.array(Effect)
|
effects: z.array(Effect)
|
||||||
}).strict();
|
}).strict();
|
||||||
type Skill = z.infer<typeof Skill>;
|
export type Skill = z.infer<typeof Skill>;
|
||||||
|
|
||||||
const Character = z.object({
|
const Character = z.object({
|
||||||
id: z.number().int(),
|
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 { InitCommand } from "./init";
|
||||||
import { RandomCaseCommand } from "./randomcase";
|
import { RandomCaseCommand } from "./randomcase";
|
||||||
import { RollCommand } from "./roll";
|
import { RollCommand } from "./roll";
|
||||||
@ -6,5 +7,6 @@ import { SlashCommand } from "./slash";
|
|||||||
export const SlashCommandList: SlashCommand[] = [
|
export const SlashCommandList: SlashCommand[] = [
|
||||||
new RandomCaseCommand(),
|
new RandomCaseCommand(),
|
||||||
new InitCommand(),
|
new InitCommand(),
|
||||||
new RollCommand()
|
new RollCommand(),
|
||||||
|
new BattleTestCommand()
|
||||||
];
|
];
|
Loading…
Reference in New Issue
Block a user