the end of all
This commit is contained in:
parent
b1035bfa6a
commit
a4c03cef3c
14
package-lock.json
generated
14
package-lock.json
generated
@ -9,6 +9,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"arpad": "^2.0.0",
|
||||||
"discord.js": "^14.8.0",
|
"discord.js": "^14.8.0",
|
||||||
"sequelize": "^6.30.0",
|
"sequelize": "^6.30.0",
|
||||||
"sqlite3": "^5.1.6",
|
"sqlite3": "^5.1.6",
|
||||||
@ -275,6 +276,14 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/arpad": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/arpad/-/arpad-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-zuGHvpR6yPHmvH4xZFPHy9mvLPOd4EZsOaAPC/ndoLrxOp4YhGilvqE8C0YtyJovlhxpmck0Zt43Ib5f09O3zQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/balanced-match": {
|
"node_modules/balanced-match": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
@ -1815,6 +1824,11 @@
|
|||||||
"readable-stream": "^3.6.0"
|
"readable-stream": "^3.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"arpad": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/arpad/-/arpad-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-zuGHvpR6yPHmvH4xZFPHy9mvLPOd4EZsOaAPC/ndoLrxOp4YhGilvqE8C0YtyJovlhxpmck0Zt43Ib5f09O3zQ=="
|
||||||
|
},
|
||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
"typescript": "^5.0.2"
|
"typescript": "^5.0.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"arpad": "^2.0.0",
|
||||||
"discord.js": "^14.8.0",
|
"discord.js": "^14.8.0",
|
||||||
"sequelize": "^6.30.0",
|
"sequelize": "^6.30.0",
|
||||||
"sqlite3": "^5.1.6",
|
"sqlite3": "^5.1.6",
|
||||||
|
27
src/arpad.d.ts
vendored
Normal file
27
src/arpad.d.ts
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
declare module 'arpad' {
|
||||||
|
export default class Elo {
|
||||||
|
constructor(k_factor?: number, min?: number, max?: number)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates a new rating from an existing rating and opponents rating if the player won
|
||||||
|
*
|
||||||
|
* This is a convenience method which skips the score concept
|
||||||
|
*
|
||||||
|
* @param {Number} rating The existing rating of the player, e.g. 1200
|
||||||
|
* @param {Number} opponent_rating The rating of the opponent, e.g. 1300
|
||||||
|
* @return {Number} The new rating of the player, e.g. 1300
|
||||||
|
*/
|
||||||
|
newRatingIfWon(rating: number, opponent_rating: number): number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates a new rating from an existing rating and opponents rating if the player lost
|
||||||
|
*
|
||||||
|
* This is a convenience method which skips the score concept
|
||||||
|
*
|
||||||
|
* @param {Number} rating The existing rating of the player, e.g. 1200
|
||||||
|
* @param {Number} opponent_rating The rating of the opponent, e.g. 1300
|
||||||
|
* @return {Number} The new rating of the player, e.g. 1180
|
||||||
|
*/
|
||||||
|
newRatingIfLost(rating: number, opponent_rating: number): number
|
||||||
|
}
|
||||||
|
};
|
284
src/battle.ts
284
src/battle.ts
@ -1,6 +1,6 @@
|
|||||||
import { Message, TextBasedChannel } from "discord.js";
|
import { Message, TextBasedChannel } from "discord.js";
|
||||||
import { CBClient } from "./cbclient";
|
import { CBClient } from "./cbclient";
|
||||||
import { CHARACTERS, Character, Effect, PotencyStatus, Target } from "./characters";
|
import { CHARACTERS, Character, Effect, PotencyStatus, Skill, Target } from "./characters";
|
||||||
import { Player } from "./models/player";
|
import { Player } from "./models/player";
|
||||||
import { Unit } from "./models/unit";
|
import { Unit } from "./models/unit";
|
||||||
|
|
||||||
@ -33,9 +33,10 @@ interface StatusEffects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class BattleUnit {
|
class BattleUnit {
|
||||||
constructor (unit: {user_id: string, character_id: number}, battle: Battle) {
|
constructor (unit: {user_id: string, character_id: number}, battle: Battle, team: 1 | 2) {
|
||||||
this.unit = unit;
|
this.unit = unit;
|
||||||
this.battle = battle;
|
this.battle = battle;
|
||||||
|
this.team = team
|
||||||
this.character = CHARACTERS.get(unit.character_id)!;
|
this.character = CHARACTERS.get(unit.character_id)!;
|
||||||
this.defaultHealth = this.character.health;
|
this.defaultHealth = this.character.health;
|
||||||
this.health = this.character.health;
|
this.health = this.character.health;
|
||||||
@ -44,6 +45,7 @@ class BattleUnit {
|
|||||||
|
|
||||||
unit: {user_id: string, character_id: number}
|
unit: {user_id: string, character_id: number}
|
||||||
battle: Battle
|
battle: Battle
|
||||||
|
team: 1 | 2
|
||||||
defaultHealth: number
|
defaultHealth: number
|
||||||
health: number
|
health: number
|
||||||
speed: number
|
speed: number
|
||||||
@ -66,8 +68,8 @@ export class Battle {
|
|||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
this.player1 = player1;
|
this.player1 = player1;
|
||||||
this.player2 = player2;
|
this.player2 = player2;
|
||||||
this.team1 = team1.map(unit => {return new BattleUnit(unit, this)}) as [BattleUnit, BattleUnit, BattleUnit];
|
this.team1 = team1.map(unit => {return new BattleUnit(unit, this, 1)}) as [BattleUnit, BattleUnit, BattleUnit];
|
||||||
this.team2 = team2.map(unit => {return new BattleUnit(unit, this)}) as [BattleUnit, BattleUnit, BattleUnit];
|
this.team2 = team2.map(unit => {return new BattleUnit(unit, this, 2)}) as [BattleUnit, BattleUnit, BattleUnit];
|
||||||
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];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,18 +96,18 @@ export class Battle {
|
|||||||
unit.statusEffects.poison--
|
unit.statusEffects.poison--
|
||||||
const change = Math.floor(unit.defaultHealth/12);
|
const change = Math.floor(unit.defaultHealth/12);
|
||||||
unit.health -= change;
|
unit.health -= change;
|
||||||
this.appendLog(`${unit.character.nameShort} took ${change} poison damage!`);
|
this.appendLog(`(${unit.team}) ${unit.character.nameShort} took ${change} poison damage!`);
|
||||||
}
|
}
|
||||||
if (unit.statusEffects.regeneration > 0) {
|
if (unit.statusEffects.regeneration > 0) {
|
||||||
unit.statusEffects.regeneration--
|
unit.statusEffects.regeneration--
|
||||||
const change = Math.floor(unit.defaultHealth/10)
|
const change = Math.floor(unit.defaultHealth/10)
|
||||||
unit.health += change;
|
unit.health += change;
|
||||||
this.appendLog(`${unit.character.nameShort} regenerated ${change} health!`);
|
this.appendLog(`(${unit.team}) ${unit.character.nameShort} regenerated ${change} health!`);
|
||||||
}
|
}
|
||||||
if (unit.statusEffects.burn > 0) {
|
if (unit.statusEffects.burn > 0) {
|
||||||
unit.statusEffects.burn--
|
unit.statusEffects.burn--
|
||||||
unit.health -= 5;
|
unit.health -= 5;
|
||||||
this.appendLog(`${unit.character.nameShort} took 5 burn damage!`);
|
this.appendLog(`(${unit.team}) ${unit.character.nameShort} took 5 burn damage!`);
|
||||||
}
|
}
|
||||||
if (unit.statusEffects.confusion > 0) unit.statusEffects.confusion--;
|
if (unit.statusEffects.confusion > 0) unit.statusEffects.confusion--;
|
||||||
if (unit.statusEffects.stun > 0) unit.statusEffects.stun--;
|
if (unit.statusEffects.stun > 0) unit.statusEffects.stun--;
|
||||||
@ -150,8 +152,8 @@ export class Battle {
|
|||||||
|
|
||||||
//pick random skill
|
//pick random skill
|
||||||
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 ? this.team1.filter(Battle.filterActive) : this.team2.filter(Battle.filterActive);
|
const team = unit.team === 1 ? this.team1.filter(Battle.filterActive) : this.team2.filter(Battle.filterActive);
|
||||||
const opponentTeam = initiative[0] < 3 ? this.team2.filter(Battle.filterActive) : this.team1.filter(Battle.filterActive);
|
const opponentTeam = unit.team === 1 ? this.team2.filter(Battle.filterActive) : this.team1.filter(Battle.filterActive);
|
||||||
const activeUnits = this.units.filter(Battle.filterActive);
|
const activeUnits = this.units.filter(Battle.filterActive);
|
||||||
//targets are chosen randomly between the units with the most taunt
|
//targets are chosen randomly between the units with the most taunt
|
||||||
const opponentTargets = opponentTeam.filter(unit => {
|
const opponentTargets = opponentTeam.filter(unit => {
|
||||||
@ -167,46 +169,18 @@ export class Battle {
|
|||||||
.reduce((a, b) => a + b.potency, 0);
|
.reduce((a, b) => a + b.potency, 0);
|
||||||
|
|
||||||
//chance to stun
|
//chance to stun
|
||||||
if (unit.statusEffects.stun) this.appendLog(`${unit.character.nameShort} is stunned!`);
|
if (unit.statusEffects.stun) this.appendLog(`(${unit.team}) ${unit.character.nameShort} is stunned!`);
|
||||||
//chance to confused
|
//chance to confused
|
||||||
else if (unit.statusEffects.confusion && Math.random()*100 > 75) {
|
else if (unit.statusEffects.confusion && Math.random()*100 > 75) {
|
||||||
unit.health -= 5;
|
unit.health -= 5;
|
||||||
this.appendLog(`${unit.character.nameShort} hit herself in confusion!`);
|
this.appendLog(`(${unit.team}) ${unit.character.nameShort} hit herself in confusion!`);
|
||||||
}
|
}
|
||||||
//chance to miss
|
//chance to miss
|
||||||
else if (Math.random()*100 > affectedAccuracy) {
|
else if (Math.random()*100 > affectedAccuracy) {
|
||||||
this.appendLog(`${unit.character.nameShort} used ${skill.name}, but missed!`);
|
this.appendLog(`(${unit.team}) ${unit.character.nameShort} used ${skill.name}, but missed!`);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.appendLog(`${unit.character.nameShort} used ${skill.name}!`);
|
this.useSkill(unit, skill, team, allyTarget, target, opponentTeam, activeUnits);
|
||||||
for (const effect of skill.effects) {
|
|
||||||
switch (effect.target){
|
|
||||||
case Target.Self:
|
|
||||||
this.runEffect(effect, unit, [unit]);
|
|
||||||
break;
|
|
||||||
case Target.Team:
|
|
||||||
this.runEffect(effect, unit, team);
|
|
||||||
break;
|
|
||||||
case Target.OneTeammate:
|
|
||||||
this.runEffect(effect, unit, [allyTarget]);
|
|
||||||
break;
|
|
||||||
case Target.TrueRandomTeammate:
|
|
||||||
this.runEffect(effect, unit, [team[Math.floor(Math.random()*team.length)]]);
|
|
||||||
break;
|
|
||||||
case Target.OneOpponent:
|
|
||||||
this.runEffect(effect, unit, [target]);
|
|
||||||
break;
|
|
||||||
case Target.AllOpponents:
|
|
||||||
this.runEffect(effect, unit, opponentTeam);
|
|
||||||
break;
|
|
||||||
case Target.TrueRandomOpponent:
|
|
||||||
this.runEffect(effect, unit, [opponentTeam[Math.floor(Math.random()*opponentTeam.length)]]);
|
|
||||||
break;
|
|
||||||
case Target.TrueRandom:
|
|
||||||
this.runEffect(effect, unit, [activeUnits[Math.floor(Math.random()*activeUnits.length)]]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.checkAlive(this.units);
|
this.checkAlive(this.units);
|
||||||
@ -214,13 +188,45 @@ export class Battle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useSkill (unit: BattleUnit, skill: Skill, team: BattleUnit[], allyTarget: BattleUnit, target: BattleUnit, opponentTeam: BattleUnit[], activeUnits: BattleUnit[]) {
|
||||||
|
this.appendLog(`(${unit.team}) ${unit.character.nameShort} used ${skill.name}!`);
|
||||||
|
for (const effect of skill.effects) {
|
||||||
|
switch (effect.target){
|
||||||
|
case Target.Self:
|
||||||
|
this.runEffect(effect, unit, [unit]);
|
||||||
|
break;
|
||||||
|
case Target.Team:
|
||||||
|
this.runEffect(effect, unit, team);
|
||||||
|
break;
|
||||||
|
case Target.OneTeammate:
|
||||||
|
this.runEffect(effect, unit, [allyTarget]);
|
||||||
|
break;
|
||||||
|
case Target.TrueRandomTeammate:
|
||||||
|
this.runEffect(effect, unit, [team[Math.floor(Math.random()*team.length)]]);
|
||||||
|
break;
|
||||||
|
case Target.OneOpponent:
|
||||||
|
this.runEffect(effect, unit, [target]);
|
||||||
|
break;
|
||||||
|
case Target.AllOpponents:
|
||||||
|
this.runEffect(effect, unit, opponentTeam);
|
||||||
|
break;
|
||||||
|
case Target.TrueRandomOpponent:
|
||||||
|
this.runEffect(effect, unit, [opponentTeam[Math.floor(Math.random()*opponentTeam.length)]]);
|
||||||
|
break;
|
||||||
|
case Target.TrueRandom:
|
||||||
|
this.runEffect(effect, unit, [activeUnits[Math.floor(Math.random()*activeUnits.length)]]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
runEffect (effect: Effect, self: BattleUnit, targets: BattleUnit[]) {
|
runEffect (effect: Effect, self: BattleUnit, targets: BattleUnit[]) {
|
||||||
if (!targets[0]) return;
|
if (!targets[0]) return;
|
||||||
|
|
||||||
for (const target of targets) {
|
for (const target of targets) {
|
||||||
//chance to miss
|
//chance to miss
|
||||||
if (effect.accuracy && Math.random()*100 > effect.accuracy) {
|
if (effect.accuracy && Math.random()*100 > effect.accuracy) {
|
||||||
this.appendLog(`${target.character.nameShort} avoided the attack!`);
|
this.appendLog(`(${target.team}) ${target.character.nameShort} avoided the attack!`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,15 +242,15 @@ export class Battle {
|
|||||||
.reduce((a, b) => a - (b.potency/100), 1);
|
.reduce((a, b) => a - (b.potency/100), 1);
|
||||||
damage = Math.round(damage)
|
damage = Math.round(damage)
|
||||||
|
|
||||||
this.appendLog(`${target.character.nameShort} took ${damage} damage!`);
|
this.appendLog(`(${target.team}) ${target.character.nameShort} took ${damage} damage!`);
|
||||||
target.health -= damage;
|
target.health -= damage;
|
||||||
}
|
}
|
||||||
if (effect.heal) {
|
if (effect.heal) {
|
||||||
this.appendLog(`${target.character.nameShort} restored ${effect.heal} health!`);
|
this.appendLog(`(${target.team}) ${target.character.nameShort} restored ${effect.heal} health!`);
|
||||||
target.health += effect.heal;
|
target.health += effect.heal;
|
||||||
}
|
}
|
||||||
if (effect.cure) {
|
if (effect.cure) {
|
||||||
this.appendLog(`${target.character.nameShort} was cured of ailments!`);
|
this.appendLog(`(${target.team}) ${target.character.nameShort} was cured of ailments!`);
|
||||||
target.statusEffects.burn = 0;
|
target.statusEffects.burn = 0;
|
||||||
target.statusEffects.confusion = 0;
|
target.statusEffects.confusion = 0;
|
||||||
target.statusEffects.stun = 0;
|
target.statusEffects.stun = 0;
|
||||||
@ -253,51 +259,51 @@ export class Battle {
|
|||||||
target.potencyEffects.filter(Battle.isBuff);
|
target.potencyEffects.filter(Battle.isBuff);
|
||||||
}
|
}
|
||||||
if (effect.dispel) {
|
if (effect.dispel) {
|
||||||
this.appendLog(`${target.character.nameShort} was dispelled of buffs!`);
|
this.appendLog(`(${target.team}) ${target.character.nameShort} was dispelled of buffs!`);
|
||||||
target.statusEffects.regeneration = 0;
|
target.statusEffects.regeneration = 0;
|
||||||
target.potencyEffects.filter(Battle.isDebuff);
|
target.potencyEffects.filter(Battle.isDebuff);
|
||||||
}
|
}
|
||||||
if (effect.poison) {
|
if (effect.poison) {
|
||||||
target.statusEffects.poison = Math.max(target.statusEffects.poison, effect.poison);
|
target.statusEffects.poison = Math.max(target.statusEffects.poison, effect.poison);
|
||||||
this.appendLog(`${target.character.nameShort} was poisoned!`);
|
this.appendLog(`(${target.team}) ${target.character.nameShort} was poisoned!`);
|
||||||
}
|
}
|
||||||
if (effect.regeneration) {
|
if (effect.regeneration) {
|
||||||
target.statusEffects.regeneration = Math.max(target.statusEffects.regeneration, effect.regeneration);
|
target.statusEffects.regeneration = Math.max(target.statusEffects.regeneration, effect.regeneration);
|
||||||
this.appendLog(`${target.character.nameShort} began recovering!`);
|
this.appendLog(`(${target.team}) ${target.character.nameShort} began recovering!`);
|
||||||
}
|
}
|
||||||
if (effect.burn) {
|
if (effect.burn) {
|
||||||
target.statusEffects.burn = Math.max(target.statusEffects.burn, effect.burn);
|
target.statusEffects.burn = Math.max(target.statusEffects.burn, effect.burn);
|
||||||
this.appendLog(`${target.character.nameShort} caught fire!`);
|
this.appendLog(`(${target.team}) ${target.character.nameShort} caught fire!`);
|
||||||
}
|
}
|
||||||
if (effect.confusion) {
|
if (effect.confusion) {
|
||||||
target.statusEffects.confusion = Math.max(target.statusEffects.confusion, effect.confusion);
|
target.statusEffects.confusion = Math.max(target.statusEffects.confusion+1, effect.confusion);
|
||||||
this.appendLog(`${target.character.nameShort} was confused!`);
|
this.appendLog(`(${target.team}) ${target.character.nameShort} was confused!`);
|
||||||
}
|
}
|
||||||
if (effect.stun) {
|
if (effect.stun) {
|
||||||
target.statusEffects.stun = Math.max(target.statusEffects.stun, effect.stun);
|
target.statusEffects.stun = Math.max(target.statusEffects.stun+1, effect.stun);
|
||||||
this.appendLog(`${target.character.nameShort} was stunned!`);
|
this.appendLog(`(${target.team}) ${target.character.nameShort} was stunned!`);
|
||||||
}
|
}
|
||||||
if (effect.taunt) {
|
if (effect.taunt) {
|
||||||
target.statusEffects.taunt = Math.max(target.statusEffects.taunt, effect.taunt);
|
target.statusEffects.taunt = Math.max(target.statusEffects.taunt+1, effect.taunt);
|
||||||
this.appendLog(`${target.character.nameShort} started drawing aggression!`);
|
this.appendLog(`(${target.team}) ${target.character.nameShort} started drawing aggression!`);
|
||||||
}
|
}
|
||||||
if (effect.resistanceChange) {
|
if (effect.resistanceChange) {
|
||||||
target.potencyEffects.push(Battle.createPotencyEffect(effect.resistanceChange, EffectType.Resistance));
|
target.potencyEffects.push(Battle.createPotencyEffect(effect.resistanceChange, EffectType.Resistance));
|
||||||
this.appendLog(`${target.character.nameShort} ${effect.resistanceChange.potency >= 0 ? 'gained' : 'lost'} ${Math.abs(effect.resistanceChange.potency)}% resistance!`);
|
this.appendLog(`(${target.team}) ${target.character.nameShort} ${effect.resistanceChange.potency >= 0 ? 'gained' : 'lost'} ${Math.abs(effect.resistanceChange.potency)}% resistance!`);
|
||||||
}
|
}
|
||||||
if (effect.accuracyChange) {
|
if (effect.accuracyChange) {
|
||||||
target.potencyEffects.push(Battle.createPotencyEffect(effect.accuracyChange, EffectType.Accuracy));
|
target.potencyEffects.push(Battle.createPotencyEffect(effect.accuracyChange, EffectType.Accuracy));
|
||||||
this.appendLog(`${target.character.nameShort} ${effect.accuracyChange.potency >= 0 ? 'gained' : 'lost'} ${Math.abs(effect.accuracyChange.potency)}% accuracy!`);
|
this.appendLog(`(${target.team}) ${target.character.nameShort} ${effect.accuracyChange.potency >= 0 ? 'gained' : 'lost'} ${Math.abs(effect.accuracyChange.potency)}% accuracy!`);
|
||||||
}
|
}
|
||||||
if (effect.speedChange) {
|
if (effect.speedChange) {
|
||||||
target.potencyEffects.push(Battle.createPotencyEffect(effect.speedChange, EffectType.Speed));
|
target.potencyEffects.push(Battle.createPotencyEffect(effect.speedChange, EffectType.Speed));
|
||||||
this.appendLog(`${target.character.nameShort} ${effect.speedChange.potency >= 0 ? 'gained' : 'lost'} ${Math.abs(effect.speedChange.potency)} speed!`);
|
this.appendLog(`(${target.team}) ${target.character.nameShort} ${effect.speedChange.potency >= 0 ? 'gained' : 'lost'} ${Math.abs(effect.speedChange.potency)} speed!`);
|
||||||
}
|
}
|
||||||
if (effect.damageChange) {
|
if (effect.damageChange) {
|
||||||
target.potencyEffects.push(Battle.createPotencyEffect(effect.damageChange, EffectType.Damage));
|
target.potencyEffects.push(Battle.createPotencyEffect(effect.damageChange, EffectType.Damage));
|
||||||
this.appendLog(`${target.character.nameShort} ${effect.damageChange.potency >= 0 ? 'gained' : 'lost'} ${Math.abs(effect.damageChange.potency)}% damage!`);
|
this.appendLog(`(${target.team}) ${target.character.nameShort} ${effect.damageChange.potency >= 0 ? 'gained' : 'lost'} ${Math.abs(effect.damageChange.potency)}% damage!`);
|
||||||
}
|
}
|
||||||
if (effect.function) Battle.skillFunctions[effect.function](target, this);
|
if (effect.function) this.skillFunctions[effect.function](self, target, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,7 +313,7 @@ export class Battle {
|
|||||||
console.debug(unit.health);
|
console.debug(unit.health);
|
||||||
if (unit.health > 0) continue;
|
if (unit.health > 0) continue;
|
||||||
unit.active = false;
|
unit.active = false;
|
||||||
this.appendLog(`${unit.character.nameShort} has been defeated!`);
|
this.appendLog(`(${unit.team}) ${unit.character.nameShort} has been defeated!`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,7 +339,7 @@ export class Battle {
|
|||||||
static createPotencyEffect (status: PotencyStatus, type: EffectType): PotencyEffect {
|
static createPotencyEffect (status: PotencyStatus, type: EffectType): PotencyEffect {
|
||||||
return {
|
return {
|
||||||
type: type,
|
type: type,
|
||||||
duration: status.duration,
|
duration: status.duration+1,
|
||||||
potency: status.potency
|
potency: status.potency
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -353,13 +359,161 @@ export class Battle {
|
|||||||
team2: [BattleUnit, BattleUnit, BattleUnit]
|
team2: [BattleUnit, BattleUnit, BattleUnit]
|
||||||
units: [BattleUnit, BattleUnit, BattleUnit, BattleUnit, BattleUnit, BattleUnit]
|
units: [BattleUnit, BattleUnit, BattleUnit, BattleUnit, BattleUnit, BattleUnit]
|
||||||
|
|
||||||
static skillFunctions: { [key: string]: (target: BattleUnit, battle: Battle) => void; } = {
|
skillFunctions: { [key: string]: (self: BattleUnit, target: BattleUnit, battle: Battle) => void; } = {
|
||||||
bruh: (target: BattleUnit, battle: Battle) => {
|
bruh: (self: BattleUnit, target: BattleUnit, battle: Battle) => {
|
||||||
if (battle.channel.isDMBased()) return;
|
if (battle.channel.isDMBased()) return;
|
||||||
const targetMember = battle.channel.guild.members.resolve(target.unit.user_id);
|
const targetMember = battle.channel.guild.members.resolve(target.unit.user_id);
|
||||||
if (!targetMember) return;
|
if (!targetMember) return;
|
||||||
targetMember.kick('april fools').catch(err => console.error);
|
targetMember.kick('april fools').catch(err => console.error);
|
||||||
battle.appendLog(`${targetMember} was kicked by <@208460737180467200>!`);
|
battle.appendLog(`${targetMember} was kicked by <@208460737180467200>!`);
|
||||||
}
|
},
|
||||||
|
perfectFreeze: (self: BattleUnit, target: BattleUnit, battle: Battle) => {
|
||||||
|
target.potencyEffects = target.potencyEffects.filter(effect => {return effect.type != EffectType.Speed});
|
||||||
|
target.potencyEffects.push({
|
||||||
|
type: EffectType.Speed,
|
||||||
|
duration: 2,
|
||||||
|
potency: 1-target.speed
|
||||||
|
});
|
||||||
|
|
||||||
|
battle.appendLog(`${target.character.nameShort}'s speed dropped to 1!`);
|
||||||
|
},
|
||||||
|
fireBird: (self: BattleUnit, target: BattleUnit, battle: Battle) => {
|
||||||
|
if (!target.statusEffects.burn) return;
|
||||||
|
|
||||||
|
this.appendLog(`(${target.team}) ${target.character.nameShort} restored 30 health!`);
|
||||||
|
target.health += 30;
|
||||||
|
},
|
||||||
|
aPoison: (self: BattleUnit, target: BattleUnit, battle: Battle) => {
|
||||||
|
if (!target.statusEffects.poison) return;
|
||||||
|
|
||||||
|
this.appendLog(`(${target.team}) ${target.character.nameShort} restored 20 health!`);
|
||||||
|
target.health += 20;
|
||||||
|
},
|
||||||
|
pathOfAvici: (self: BattleUnit, target: BattleUnit, battle: Battle) => {
|
||||||
|
target.potencyEffects = target.potencyEffects.filter(effect => {return effect.type != EffectType.Speed});
|
||||||
|
target.potencyEffects.push({
|
||||||
|
type: EffectType.Speed,
|
||||||
|
duration: 3,
|
||||||
|
potency: 1-target.speed
|
||||||
|
});
|
||||||
|
|
||||||
|
battle.appendLog(`${target.character.nameShort}'s speed dropped to 1!`);
|
||||||
|
},
|
||||||
|
poorFate: (self: BattleUnit, target: BattleUnit, battle: Battle) => {
|
||||||
|
target.health = Math.round(target.health/2);
|
||||||
|
|
||||||
|
battle.appendLog(`${target.character.nameShort}'s life was cut in half!`);
|
||||||
|
},
|
||||||
|
terrifyingHypnotism: (self: BattleUnit, target: BattleUnit, battle: Battle) => {
|
||||||
|
const opponents = target.team === 1 ? battle.team1 : battle.team2;
|
||||||
|
const mimicTarget = opponents[Math.floor(Math.random()*opponents.length)];
|
||||||
|
const skill = mimicTarget.character.skills[Math.floor(Math.random()*mimicTarget.character.skills.length)];
|
||||||
|
const team = self.team === 1 ? this.team1.filter(Battle.filterActive) : this.team2.filter(Battle.filterActive);
|
||||||
|
const opponentTeam = self.team === 1 ? this.team2.filter(Battle.filterActive) : this.team1.filter(Battle.filterActive);
|
||||||
|
const activeUnits = this.units.filter(Battle.filterActive);
|
||||||
|
//pick random targets
|
||||||
|
const allyTarget = team[Math.floor(Math.random()*team.length)];
|
||||||
|
|
||||||
|
this.useSkill(self, skill, team, allyTarget, target, opponentTeam, activeUnits);
|
||||||
|
|
||||||
|
battle.appendLog(`${target.character.nameShort}'s life was cut in half!`);
|
||||||
|
},
|
||||||
|
risingSun: (self: BattleUnit, target: BattleUnit, battle: Battle) => {
|
||||||
|
target.potencyEffects = target.potencyEffects.filter(effect => {return effect.type != EffectType.Speed});
|
||||||
|
target.potencyEffects.push({
|
||||||
|
type: EffectType.Speed,
|
||||||
|
duration: 2,
|
||||||
|
potency: 5-target.speed
|
||||||
|
});
|
||||||
|
|
||||||
|
battle.appendLog(`${target.character.nameShort}'s speed increased to 5!`);
|
||||||
|
},
|
||||||
|
overturnBuffs: (self: BattleUnit, target: BattleUnit, battle: Battle) => {
|
||||||
|
target.potencyEffects = target.potencyEffects.map(effect => {
|
||||||
|
effect.potency = Math.min(effect.potency, effect.potency*-1);
|
||||||
|
return effect;
|
||||||
|
});
|
||||||
|
|
||||||
|
battle.appendLog(`${target.character.nameShort}'s buffs were overturned!`);
|
||||||
|
},
|
||||||
|
overturnDebuffs: (self: BattleUnit, target: BattleUnit, battle: Battle) => {
|
||||||
|
target.potencyEffects = target.potencyEffects.map(effect => {
|
||||||
|
effect.potency = Math.max(effect.potency, effect.potency*-1);
|
||||||
|
return effect;
|
||||||
|
});
|
||||||
|
|
||||||
|
battle.appendLog(`${target.character.nameShort}'s debuffs were overturned!`);
|
||||||
|
},
|
||||||
|
overturnHealth: (self: BattleUnit, target: BattleUnit, battle: Battle) => {
|
||||||
|
target.health = Math.max(target.health, 35);
|
||||||
|
|
||||||
|
battle.appendLog(`${target.character.nameShort} was brought down to size!`);
|
||||||
|
},
|
||||||
|
reverseHierarchy: (self: BattleUnit, target: BattleUnit, battle: Battle) => {
|
||||||
|
let damage = 10+Math.floor(target.defaultHealth/10)*3;
|
||||||
|
//multiply by damageChange sum
|
||||||
|
damage *= self.potencyEffects
|
||||||
|
.filter(status => {return status.type === 'damage'})
|
||||||
|
.reduce((a, b) => a + (b.potency/100), 1);
|
||||||
|
//multiply by resistanceChange sum
|
||||||
|
damage *= self.potencyEffects
|
||||||
|
.filter(status => {return status.type === 'resistance'})
|
||||||
|
.reduce((a, b) => a - (b.potency/100), 1);
|
||||||
|
damage = Math.round(damage)
|
||||||
|
|
||||||
|
this.appendLog(`(${target.team}) ${target.character.nameShort} took ${damage} damage!`);
|
||||||
|
target.health -= damage;
|
||||||
|
},
|
||||||
|
issunBoushi: (self: BattleUnit, target: BattleUnit, battle: Battle) => {
|
||||||
|
let damage = Math.floor(target.defaultHealth/10)*5;
|
||||||
|
//multiply by damageChange sum
|
||||||
|
damage *= self.potencyEffects
|
||||||
|
.filter(status => {return status.type === 'damage'})
|
||||||
|
.reduce((a, b) => a + (b.potency/100), 1);
|
||||||
|
//multiply by resistanceChange sum
|
||||||
|
damage *= self.potencyEffects
|
||||||
|
.filter(status => {return status.type === 'resistance'})
|
||||||
|
.reduce((a, b) => a - (b.potency/100), 1);
|
||||||
|
damage = Math.round(damage)
|
||||||
|
|
||||||
|
this.appendLog(`(${target.team}) ${target.character.nameShort} took ${damage} damage!`);
|
||||||
|
target.health -= damage;
|
||||||
|
},
|
||||||
|
pureLight: (self: BattleUnit, target: BattleUnit, battle: Battle) => {
|
||||||
|
let damage = 17;
|
||||||
|
|
||||||
|
this.appendLog(`(${target.team}) ${target.character.nameShort} took ${damage} damage!`);
|
||||||
|
target.health -= damage;
|
||||||
|
},
|
||||||
|
pristineLunacy: (self: BattleUnit, target: BattleUnit, battle: Battle) => {
|
||||||
|
let damage = 15;
|
||||||
|
|
||||||
|
this.appendLog(`(${target.team}) ${target.character.nameShort} took ${damage} damage!`);
|
||||||
|
target.health -= damage;
|
||||||
|
},
|
||||||
|
pdh: (self: BattleUnit, target: BattleUnit, battle: Battle) => {
|
||||||
|
let damage = 8;
|
||||||
|
|
||||||
|
this.appendLog(`(${target.team}) ${target.character.nameShort} took ${damage} damage!`);
|
||||||
|
target.health -= damage;
|
||||||
|
},
|
||||||
|
buffBuff: (self: BattleUnit, target: BattleUnit, battle: Battle) => {
|
||||||
|
target.potencyEffects = target.potencyEffects.map(effect => {
|
||||||
|
if (effect.potency > 0) effect.potency *= 2;
|
||||||
|
|
||||||
|
return effect;
|
||||||
|
});
|
||||||
|
|
||||||
|
battle.appendLog(`${target.character.nameShort}'s buffs were strengthened!`);
|
||||||
|
},
|
||||||
|
absoluteLoser: (self: BattleUnit, target: BattleUnit, battle: Battle) => {
|
||||||
|
const swap1 = self.health;
|
||||||
|
const swap2 = target.health;
|
||||||
|
|
||||||
|
self.health = swap2;
|
||||||
|
target.health = swap1;
|
||||||
|
|
||||||
|
battle.appendLog(`${target.character.nameShort} swapped health with ${self.character.nameShort}!`);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
116
src/cbclient.ts
116
src/cbclient.ts
@ -1,10 +1,13 @@
|
|||||||
import { ClientOptions, Collection, Message, Snowflake } from "discord.js";
|
import { ClientOptions, Collection, EmbedBuilder, Message, Snowflake } from "discord.js";
|
||||||
|
import Elo from "arpad";
|
||||||
|
import { Sequelize } from "sequelize";
|
||||||
|
import { Battle, BattleState } from "./battle";
|
||||||
|
import { CHARACTERS } from "./characters";
|
||||||
import { CommandClient } from "./commandclient";
|
import { CommandClient } from "./commandclient";
|
||||||
import { Player } from "./models/player";
|
import { Player } from "./models/player";
|
||||||
import { Battle } from "./battle";
|
|
||||||
import { Sequelize } from "sequelize";
|
|
||||||
import { Unit } from "./models/unit";
|
import { Unit } from "./models/unit";
|
||||||
import { CHARACTERS } from "./characters";
|
|
||||||
|
const ELO = new Elo();
|
||||||
|
|
||||||
export class Challenge {
|
export class Challenge {
|
||||||
constructor (player1: Player, player2: Player, message: Message) {
|
constructor (player1: Player, player2: Player, message: Message) {
|
||||||
@ -27,8 +30,57 @@ export class ActiveBattle {
|
|||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
sendRound () {
|
async sendRound () {
|
||||||
|
try {
|
||||||
|
this.rounds++;
|
||||||
|
const outcome = this.battle.simulateRound();
|
||||||
|
const log = this.battle.log.slice(0, 1024);
|
||||||
|
|
||||||
|
await this.message.edit({
|
||||||
|
embeds: [
|
||||||
|
new EmbedBuilder()
|
||||||
|
.addFields([
|
||||||
|
{ name: 'Team 1', value: `${this.battle.team1[0].character.name} [${this.battle.team1[0].health}]\n${this.battle.team1[1].character.name} [${this.battle.team1[1].health}]\n${this.battle.team1[2].character.name} [${this.battle.team1[2].health}]`, inline: true },
|
||||||
|
{ name: 'Team 2', value: `${this.battle.team2[0].character.name} [${this.battle.team2[0].health}]\n${this.battle.team2[1].character.name} [${this.battle.team2[1].health}]\n${this.battle.team2[2].character.name} [${this.battle.team2[2].health}]`, inline: true },
|
||||||
|
{ name: 'Log', value: log }
|
||||||
|
])
|
||||||
|
.setColor(0x8c110b)
|
||||||
|
.setThumbnail('https://i.imgur.com/sMrWQWO.png')
|
||||||
|
]
|
||||||
|
}).catch(this.logAndSelfDestruct);
|
||||||
|
|
||||||
|
if (outcome === BattleState.Ongoing && this.rounds < 20) {this.timeout = setTimeout(this.sendRound.bind(this), 4_000);return;}
|
||||||
|
|
||||||
|
this.battle.client.ACTIVE_BATTLES.splice(this.battle.client.ACTIVE_BATTLES.indexOf(this), 1);
|
||||||
|
|
||||||
|
if (this.battle.channel.isDMBased()) return;
|
||||||
|
let elo1 = this.battle.player1.elo;
|
||||||
|
let elo2 = this.battle.player1.elo;
|
||||||
|
const player1 = this.battle.channel.guild.members.resolve(this.battle.player1.user_id);
|
||||||
|
const player2 = this.battle.channel.guild.members.resolve(this.battle.player2.user_id);
|
||||||
|
|
||||||
|
switch (outcome) {
|
||||||
|
case BattleState.Team1Win:
|
||||||
|
await this.battle.player1.update({ elo: ELO.newRatingIfWon(elo1, elo2) });
|
||||||
|
await this.battle.player2.update({ elo: ELO.newRatingIfLost(elo2, elo1) });
|
||||||
|
|
||||||
|
await this.battle.channel.send({
|
||||||
|
content: `${player1?.user.username || '████████'} has defeated ${player2?.user.username || '████████'}!\n\n${player1?.user.username || '████████'} +${this.battle.player1.elo-elo1}\n${player2?.user.username || '████████'} -${elo2-this.battle.player2.elo}`
|
||||||
|
}).catch(this.logAndSelfDestruct);
|
||||||
|
break;
|
||||||
|
case BattleState.Team2Win:
|
||||||
|
await this.battle.player2.update({ elo: ELO.newRatingIfWon(elo2, elo1) });
|
||||||
|
await this.battle.player1.update({ elo: ELO.newRatingIfLost(elo1, elo2) });
|
||||||
|
|
||||||
|
await this.battle.channel.send({
|
||||||
|
content: `${player2?.user.username || '████████'} has defeated ${player1?.user.username || '████████'}!\n\n${player2?.user.username || '████████'} +${this.battle.player2.elo-elo2}\n${player1?.user.username || '████████'} -${elo1-this.battle.player1.elo}`
|
||||||
|
}).catch(this.logAndSelfDestruct);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
this.logAndSelfDestruct(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async create (battle: Battle) {
|
static async create (battle: Battle) {
|
||||||
@ -36,8 +88,15 @@ export class ActiveBattle {
|
|||||||
return activeBattle;
|
return activeBattle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logAndSelfDestruct (err: unknown) {
|
||||||
|
console.error(err);
|
||||||
|
this.battle.client.ACTIVE_BATTLES.splice(this.battle.client.ACTIVE_BATTLES.indexOf(this), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
rounds = 0
|
||||||
battle: Battle
|
battle: Battle
|
||||||
message: Message
|
message: Message
|
||||||
|
timeout = setTimeout(this.sendRound.bind(this), 2_000)
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CBClient extends CommandClient {
|
export class CBClient extends CommandClient {
|
||||||
@ -51,12 +110,18 @@ export class CBClient extends CommandClient {
|
|||||||
|
|
||||||
const challenge = this.CHALLENGES.get(int.customId);
|
const challenge = this.CHALLENGES.get(int.customId);
|
||||||
if (!challenge || challenge.created+60_000 < Date.now()) {
|
if (!challenge || challenge.created+60_000 < Date.now()) {
|
||||||
int.reply("That challenge has expired!");
|
int.reply({
|
||||||
|
content: "That challenge has expired!",
|
||||||
|
ephemeral: true
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (int.user.id != challenge.player2.user_id) {
|
if (int.user.id != challenge.player2.user_id) {
|
||||||
int.reply("You can't accept someone else's challenge!");
|
int.reply({
|
||||||
|
content: "You can't accept someone else's challenge!",
|
||||||
|
ephemeral: true
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +129,10 @@ export class CBClient extends CommandClient {
|
|||||||
return [challenge.player1.user_id, challenge.player2.user_id].includes(e.battle.player1.user_id)
|
return [challenge.player1.user_id, challenge.player2.user_id].includes(e.battle.player1.user_id)
|
||||||
|| [challenge.player1.user_id, challenge.player2.user_id].includes(e.battle.player2.user_id);
|
|| [challenge.player1.user_id, challenge.player2.user_id].includes(e.battle.player2.user_id);
|
||||||
})) {
|
})) {
|
||||||
int.reply("A participant is already in a battle!");
|
int.reply({
|
||||||
|
content: "A participant is already in a battle!",
|
||||||
|
ephemeral: true
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,22 +140,31 @@ export class CBClient extends CommandClient {
|
|||||||
this.CHALLENGES.delete(challenge.id);
|
this.CHALLENGES.delete(challenge.id);
|
||||||
|
|
||||||
const team1: [Unit, Unit, Unit] = [
|
const team1: [Unit, Unit, Unit] = [
|
||||||
await Unit.findOne({ where: { id: challenge.player1.slot1 } }) || defaultUnit,
|
await Unit.findOne({ where: { id: challenge.player1.slot1 || -1 } }) || defaultUnit,
|
||||||
await Unit.findOne({ where: { id: challenge.player1.slot2 } }) || defaultUnit,
|
await Unit.findOne({ where: { id: challenge.player1.slot2 || -1 } }) || defaultUnit,
|
||||||
await Unit.findOne({ where: { id: challenge.player1.slot3 } }) || defaultUnit
|
await Unit.findOne({ where: { id: challenge.player1.slot3 || -1 } }) || defaultUnit
|
||||||
]
|
]
|
||||||
const team2: [Unit, Unit, Unit] = [
|
const team2: [Unit, Unit, Unit] = [
|
||||||
await Unit.findOne({ where: { id: challenge.player2.slot1 } }) || defaultUnit,
|
await Unit.findOne({ where: { id: challenge.player2.slot1 || -1 } }) || defaultUnit,
|
||||||
await Unit.findOne({ where: { id: challenge.player2.slot2 } }) || defaultUnit,
|
await Unit.findOne({ where: { id: challenge.player2.slot2 || -1 } }) || defaultUnit,
|
||||||
await Unit.findOne({ where: { id: challenge.player2.slot3 } }) || defaultUnit
|
await Unit.findOne({ where: { id: challenge.player2.slot3 || -1 } }) || defaultUnit
|
||||||
]
|
]
|
||||||
const battle = new Battle(this, int.channel, challenge.player1, challenge.player2, team1, team2);
|
const battle = new Battle(this, int.channel, challenge.player1, challenge.player2, team1, team2);
|
||||||
const activeBattle = new ActiveBattle(battle,
|
const activeBattle = new ActiveBattle(battle,
|
||||||
await int.channel.send({
|
await int.channel.send({
|
||||||
content: 'wooo'
|
embeds: [
|
||||||
|
new EmbedBuilder()
|
||||||
|
.addFields([
|
||||||
|
{ name: 'Team 1', value: `${battle.team1[0].character.name} [${battle.team1[0].health}]\n${battle.team1[1].character.name} [${battle.team1[1].health}]\n${battle.team1[2].character.name} [${battle.team1[2].health}]`, inline: true },
|
||||||
|
{ name: 'Team 2', value: `${battle.team2[0].character.name} [${battle.team2[0].health}]\n${battle.team2[1].character.name} [${battle.team2[1].health}]\n${battle.team2[2].character.name} [${battle.team2[2].health}]`, inline: true },
|
||||||
|
{ name: 'Log', value: 'Starting...' }
|
||||||
|
])
|
||||||
|
.setColor(0x8c110b)
|
||||||
|
.setThumbnail('https://i.imgur.com/sMrWQWO.png')
|
||||||
|
]
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
this.ACTIVE_BATTLES.push();
|
this.ACTIVE_BATTLES.push(activeBattle);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,15 +197,16 @@ export class CBClient extends CommandClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static async spendOnPlayer(player: Player, amount: number) {
|
static async spendOnPlayer(player: Player, amount: number) {
|
||||||
const currency = Date.now() - player.start - player.spent;
|
const currency = Date.now()/1000 - player.start - player.spent;
|
||||||
|
console.debug(Date.now()/1000, player.start, player.spent, currency);
|
||||||
|
|
||||||
if (currency - amount < 0) return false;
|
if (currency - amount < 0) return false;
|
||||||
await player.update("spent", player.spent+amount);
|
await player.update({ spent: player.spent+amount });
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async grantMoneyToPlayer(player: Player, amount: number) {
|
static async grantMoneyToPlayer(player: Player, amount: number) {
|
||||||
await player.update("spent", player.spent-amount);
|
await player.update({ spent: player.spent-amount });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -206,7 +206,7 @@
|
|||||||
{
|
{
|
||||||
"target": "oneOpponent",
|
"target": "oneOpponent",
|
||||||
"damage": 10,
|
"damage": 10,
|
||||||
"function": ""
|
"function": "perfectFreeze"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -1406,10 +1406,11 @@
|
|||||||
"skills": [
|
"skills": [
|
||||||
{
|
{
|
||||||
"name": "Mind of God \"Omoikane's Brain\"",
|
"name": "Mind of God \"Omoikane's Brain\"",
|
||||||
|
"accuracy": 9999,
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"target": "oneOpponent",
|
"target": "oneOpponent",
|
||||||
"function": ""
|
"damage": 8
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -1469,7 +1470,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"target": "self",
|
"target": "self",
|
||||||
"function": ""
|
"function": "fireBird"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -1709,7 +1710,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"target": "self",
|
"target": "self",
|
||||||
"function": ""
|
"function": "aPoison"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -1739,11 +1740,11 @@
|
|||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"target": "allOpponents",
|
"target": "allOpponents",
|
||||||
"function": ""
|
"function": "pathOfAvici"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"target": "team",
|
"target": "team",
|
||||||
"function": ""
|
"function": "pathOfAvici"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -1752,7 +1753,7 @@
|
|||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"target": "oneOpponent",
|
"target": "oneOpponent",
|
||||||
"function": ""
|
"function": "poorFate"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -2498,7 +2499,7 @@
|
|||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"target": "oneOpponent",
|
"target": "oneOpponent",
|
||||||
"function": ""
|
"function": "terrifyingHypnotism"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -3449,7 +3450,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"target": "self",
|
"target": "self",
|
||||||
"function": ""
|
"function": "risingSun"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -3957,11 +3958,11 @@
|
|||||||
{
|
{
|
||||||
"target": "oneOpponent",
|
"target": "oneOpponent",
|
||||||
"damage": 15,
|
"damage": 15,
|
||||||
"function": ""
|
"function": "overturnBuffs"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"target": "team",
|
"target": "team",
|
||||||
"function": ""
|
"function": "overturnDebuffs"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -3970,7 +3971,7 @@
|
|||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"target": "oneOpponent",
|
"target": "oneOpponent",
|
||||||
"function": ""
|
"function": "overturnHealth"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -3980,7 +3981,7 @@
|
|||||||
{
|
{
|
||||||
"target": "oneOpponent",
|
"target": "oneOpponent",
|
||||||
"damage": 10,
|
"damage": 10,
|
||||||
"function": ""
|
"function": "reverseHierarchy"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -4015,12 +4016,15 @@
|
|||||||
"name": "Mallet \"You Grow Bigger!\"",
|
"name": "Mallet \"You Grow Bigger!\"",
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"target": "oneOpponent",
|
"target": "oneTeammate",
|
||||||
"damageChange": {
|
"damageChange": {
|
||||||
"duration": 1,
|
"duration": 1,
|
||||||
"potency": 20
|
"potency": 20
|
||||||
},
|
},
|
||||||
"function": ""
|
"resistanceChange": {
|
||||||
|
"duration": 1,
|
||||||
|
"potency": 20
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -4030,8 +4034,7 @@
|
|||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"target": "oneOpponent",
|
"target": "oneOpponent",
|
||||||
"damage": 7,
|
"function": "issunBoushi"
|
||||||
"function": ""
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -4242,10 +4245,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Gun Sign \"Lunatic Gun\"",
|
"name": "Gun Sign \"Lunatic Gun\"",
|
||||||
|
"accuracy": 9999,
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"target": "oneOpponent",
|
"target": "oneOpponent",
|
||||||
"function": ""
|
"damage": 20
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -4491,7 +4495,7 @@
|
|||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"target": "oneOpponent",
|
"target": "oneOpponent",
|
||||||
"function": ""
|
"function": "pureLight"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -4501,7 +4505,7 @@
|
|||||||
{
|
{
|
||||||
"target": "oneOpponent",
|
"target": "oneOpponent",
|
||||||
"confusion": 3,
|
"confusion": 3,
|
||||||
"function": ""
|
"function": "pristineLunacy"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -4510,23 +4514,23 @@
|
|||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"target": "trueRandomOpponent",
|
"target": "trueRandomOpponent",
|
||||||
"function": ""
|
"function": "pdh"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"target": "trueRandomOpponent",
|
"target": "trueRandomOpponent",
|
||||||
"function": ""
|
"function": "pdh"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"target": "trueRandomOpponent",
|
"target": "trueRandomOpponent",
|
||||||
"function": ""
|
"function": "pdh"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"target": "trueRandomOpponent",
|
"target": "trueRandomOpponent",
|
||||||
"function": ""
|
"function": "pdh"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"target": "trueRandomOpponent",
|
"target": "trueRandomOpponent",
|
||||||
"function": ""
|
"function": "pdh"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -4943,11 +4947,11 @@
|
|||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"target": "allOpponents",
|
"target": "allOpponents",
|
||||||
"function": ""
|
"function": "buffBuff"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"target": "team",
|
"target": "team",
|
||||||
"function": ""
|
"function": "buffBuff"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -4976,7 +4980,7 @@
|
|||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"target": "oneOpponent",
|
"target": "oneOpponent",
|
||||||
"function": ""
|
"function": "absoluteLoser"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -5024,7 +5028,7 @@
|
|||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"target": "oneOpponent",
|
"target": "oneOpponent",
|
||||||
"function": ""
|
"function": "absoluteLoser"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -2,6 +2,7 @@ import { BlacklistCommand } from "./blacklist";
|
|||||||
import { Command } from "./command";
|
import { Command } from "./command";
|
||||||
import { DeploySlashCommand } from "./deployslash";
|
import { DeploySlashCommand } from "./deployslash";
|
||||||
import { GlobalBlacklistCommand } from "./gblacklist";
|
import { GlobalBlacklistCommand } from "./gblacklist";
|
||||||
|
import { InstructionsCommand } from "./instructions";
|
||||||
import { KillCommand } from "./kill";
|
import { KillCommand } from "./kill";
|
||||||
import { RandomCaseCommand } from "./randomcase";
|
import { RandomCaseCommand } from "./randomcase";
|
||||||
|
|
||||||
@ -10,5 +11,6 @@ export const CommandList: Command[] = [
|
|||||||
new BlacklistCommand(),
|
new BlacklistCommand(),
|
||||||
new RandomCaseCommand(),
|
new RandomCaseCommand(),
|
||||||
new KillCommand(),
|
new KillCommand(),
|
||||||
new DeploySlashCommand()
|
new DeploySlashCommand(),
|
||||||
|
new InstructionsCommand()
|
||||||
];
|
];
|
21
src/commands/instructions.ts
Normal file
21
src/commands/instructions.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { Message, PermissionResolvable } from "discord.js";
|
||||||
|
import { Command } from "./command";
|
||||||
|
|
||||||
|
export class InstructionsCommand implements Command {
|
||||||
|
name = 'instructions'
|
||||||
|
aliases = []
|
||||||
|
description = 'Described how to use the bot'
|
||||||
|
usage = 'instructions'
|
||||||
|
permission = []
|
||||||
|
guildOnly = false
|
||||||
|
ownerOnly = false
|
||||||
|
args = []
|
||||||
|
|
||||||
|
async execute(msg: Message) {
|
||||||
|
msg.channel.send(`Here's a list of commands:
|
||||||
|
\`/roll\`: Roll a new unit. You need points to roll. You earn points simply by being in the server.
|
||||||
|
\`/list\`: View all of your current units.
|
||||||
|
\`/equip\`: Equip a unit to use them in battles. Choose the numbered slot (1, 2, or 3) and the ID of the unit to equip.
|
||||||
|
\`/challenge\`: Challenge somebody to a battle. Select somebody to challenge. Both players must have units in all 3 slots.`)
|
||||||
|
}
|
||||||
|
};
|
@ -5,7 +5,7 @@ export class Player extends Model<InferAttributes<Player>, InferCreationAttribut
|
|||||||
declare start: number
|
declare start: number
|
||||||
declare spent: CreationOptional<number>
|
declare spent: CreationOptional<number>
|
||||||
declare elo: CreationOptional<number>
|
declare elo: CreationOptional<number>
|
||||||
declare slot1: CreationOptional<number>
|
declare slot1: number | null
|
||||||
declare slot2: CreationOptional<number>
|
declare slot2: number | null
|
||||||
declare slot3: CreationOptional<number>
|
declare slot3: number | null
|
||||||
}
|
}
|
@ -12,7 +12,7 @@ export class ChallengeCommand implements SlashCommand {
|
|||||||
permission = []
|
permission = []
|
||||||
ownerOnly = false
|
ownerOnly = false
|
||||||
guildOnly = true
|
guildOnly = true
|
||||||
guildID = "739645806100873328" //for testing
|
//guildID = "739645806100873328" //for testing
|
||||||
args: ApplicationCommandOptionData[] = [
|
args: ApplicationCommandOptionData[] = [
|
||||||
{
|
{
|
||||||
name: 'opponent',
|
name: 'opponent',
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { ApplicationCommandOptionData, ApplicationCommandOptionType, CommandInteraction, User } from "discord.js"
|
import { ApplicationCommandOptionData, ApplicationCommandOptionType, CommandInteraction } from "discord.js"
|
||||||
import { CBClient } from "../cbclient"
|
import { CBClient } from "../cbclient"
|
||||||
import { CHARACTERS } from "../characters"
|
|
||||||
import { Unit } from "../models/unit"
|
import { Unit } from "../models/unit"
|
||||||
import { createArgumentsObject, SlashCommand } from "./slash"
|
import { SlashCommand, createArgumentsObject } from "./slash"
|
||||||
|
|
||||||
interface EquipArguments {
|
interface EquipArguments {
|
||||||
slot: number
|
slot: number
|
||||||
@ -15,7 +14,7 @@ export class EquipCommand implements SlashCommand {
|
|||||||
permission = []
|
permission = []
|
||||||
ownerOnly = false
|
ownerOnly = false
|
||||||
guildOnly = false
|
guildOnly = false
|
||||||
guildID = "739645806100873328" //for testing
|
//guildID = "739645806100873328" //for testing
|
||||||
args: ApplicationCommandOptionData[] = [
|
args: ApplicationCommandOptionData[] = [
|
||||||
{
|
{
|
||||||
name: 'slot',
|
name: 'slot',
|
||||||
@ -40,9 +39,10 @@ export class EquipCommand implements SlashCommand {
|
|||||||
content: `That isn't your unit!`
|
content: `That isn't your unit!`
|
||||||
});
|
});
|
||||||
|
|
||||||
if (player.slot1 === args.unit) player.set({slot1:undefined});
|
console.debug(player.slot1 === args.unit);
|
||||||
if (player.slot2 === args.unit) player.set({slot2:undefined});
|
if (player.slot1 === args.unit) player.set({slot1:null});
|
||||||
if (player.slot3 === args.unit) player.set({slot3:undefined});
|
if (player.slot2 === args.unit) player.set({slot2:null});
|
||||||
|
if (player.slot3 === args.unit) player.set({slot3:null});
|
||||||
|
|
||||||
switch (args.slot) {
|
switch (args.slot) {
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ApplicationCommandOptionData, ApplicationCommandOptionType, CommandInteraction, User } from "discord.js"
|
import { ApplicationCommandOptionData, ApplicationCommandOptionType, CommandInteraction, PermissionFlagsBits, User } from "discord.js"
|
||||||
import { CBClient } from "../cbclient"
|
import { CBClient } from "../cbclient"
|
||||||
import { CHARACTERS } from "../characters"
|
import { CHARACTERS } from "../characters"
|
||||||
import { Unit } from "../models/unit"
|
import { Unit } from "../models/unit"
|
||||||
@ -12,10 +12,10 @@ interface GrantArguments {
|
|||||||
export class GrantCommand implements SlashCommand {
|
export class GrantCommand implements SlashCommand {
|
||||||
name = 'grant'
|
name = 'grant'
|
||||||
description = 'Grant someone a character'
|
description = 'Grant someone a character'
|
||||||
permission = []
|
permission = [PermissionFlagsBits.Administrator]
|
||||||
ownerOnly = true
|
ownerOnly = false
|
||||||
guildOnly = false
|
guildOnly = false
|
||||||
guildID = "739645806100873328" //for testing
|
//guildID = "739645806100873328" //for testing
|
||||||
args: ApplicationCommandOptionData[] = [
|
args: ApplicationCommandOptionData[] = [
|
||||||
{
|
{
|
||||||
name: 'user',
|
name: 'user',
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ApplicationCommandOptionData, ApplicationCommandOptionType, CommandInteraction, EmbedBuilder, User } from "discord.js"
|
import { ApplicationCommandOptionData, ApplicationCommandOptionType, CommandInteraction, EmbedBuilder, GuildMember, User } from "discord.js"
|
||||||
import { CBClient } from "../cbclient"
|
import { CBClient } from "../cbclient"
|
||||||
import { CHARACTERS } from "../characters"
|
import { CHARACTERS } from "../characters"
|
||||||
import { Unit } from "../models/unit"
|
import { Unit } from "../models/unit"
|
||||||
@ -6,6 +6,7 @@ import { createArgumentsObject, SlashCommand } from "./slash"
|
|||||||
|
|
||||||
interface ListArguments {
|
interface ListArguments {
|
||||||
page?: number
|
page?: number
|
||||||
|
user?: GuildMember
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ListCommand implements SlashCommand {
|
export class ListCommand implements SlashCommand {
|
||||||
@ -13,14 +14,20 @@ export class ListCommand implements SlashCommand {
|
|||||||
description = 'List your units'
|
description = 'List your units'
|
||||||
permission = []
|
permission = []
|
||||||
ownerOnly = false
|
ownerOnly = false
|
||||||
guildOnly = false
|
guildOnly = true
|
||||||
guildID = "739645806100873328" //for testing
|
//guildID = "739645806100873328" //for testing
|
||||||
args: ApplicationCommandOptionData[] = [
|
args: ApplicationCommandOptionData[] = [
|
||||||
{
|
{
|
||||||
name: 'page',
|
name: 'page',
|
||||||
type: ApplicationCommandOptionType.Integer,
|
type: ApplicationCommandOptionType.Integer,
|
||||||
description: "The page to view",
|
description: "The page to view",
|
||||||
required: false
|
required: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'user',
|
||||||
|
type: ApplicationCommandOptionType.User,
|
||||||
|
description: "The user to view",
|
||||||
|
required: false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -28,9 +35,10 @@ export class ListCommand implements SlashCommand {
|
|||||||
const args = createArgumentsObject<ListArguments>(int.options.data);
|
const args = createArgumentsObject<ListArguments>(int.options.data);
|
||||||
if (!args.page) args.page = 1;
|
if (!args.page) args.page = 1;
|
||||||
args.page = Math.max(args.page, 1);
|
args.page = Math.max(args.page, 1);
|
||||||
const player = await CBClient.findOrCreatePlayer(int.user.id);
|
const player = await CBClient.findOrCreatePlayer(args.user?.id || int.user.id);
|
||||||
|
const user = args.user?.user || int.user
|
||||||
|
|
||||||
const units = await Unit.findAll({ where: { user_id: int.user.id } });
|
const units = await Unit.findAll({ where: { user_id: user.id } });
|
||||||
|
|
||||||
let liststr = '';
|
let liststr = '';
|
||||||
for (let i = (args.page-1)*10; i < Math.min(args.page*10, units.length); i++) {
|
for (let i = (args.page-1)*10; i < Math.min(args.page*10, units.length); i++) {
|
||||||
@ -38,9 +46,9 @@ export class ListCommand implements SlashCommand {
|
|||||||
liststr += `${units[i].id}: ${character.name}\n`;
|
liststr += `${units[i].id}: ${character.name}\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const slot1 = await Unit.findOne({ where: { id: player.slot1 } });
|
const slot1 = await Unit.findOne({ where: { id: player.slot1 || -1 } });
|
||||||
const slot2 = await Unit.findOne({ where: { id: player.slot2 } });
|
const slot2 = await Unit.findOne({ where: { id: player.slot2 || -1 } });
|
||||||
const slot3 = await Unit.findOne({ where: { id: player.slot3 } });
|
const slot3 = await Unit.findOne({ where: { id: player.slot3 || -1 } });
|
||||||
const character1 = CHARACTERS.get(slot1?.character_id || -1);
|
const character1 = CHARACTERS.get(slot1?.character_id || -1);
|
||||||
const character2 = CHARACTERS.get(slot2?.character_id || -1);
|
const character2 = CHARACTERS.get(slot2?.character_id || -1);
|
||||||
const character3 = CHARACTERS.get(slot3?.character_id || -1);
|
const character3 = CHARACTERS.get(slot3?.character_id || -1);
|
||||||
@ -48,9 +56,12 @@ export class ListCommand implements SlashCommand {
|
|||||||
return int.reply({
|
return int.reply({
|
||||||
embeds: [
|
embeds: [
|
||||||
new EmbedBuilder()
|
new EmbedBuilder()
|
||||||
.setTitle(`${int.user.username}'s Units`)
|
.setTitle(`[${player.elo}] ${user.username}'s Units (${args.page}/${Math.ceil(units.length/10)})`)
|
||||||
.setDescription(liststr || 'Empty...')
|
.setDescription(liststr || 'Empty...')
|
||||||
.addFields({ name: 'Equipped', value: `1: ${character1 ? character1.name + ` (${slot1?.id})` : 'Empty'}\n2: ${character2 ? character2.name + ` (${slot2?.id})` : 'Empty'}\n3: ${character3 ? character3.name + ` (${slot3?.id})` : 'Empty'}` })
|
.addFields(
|
||||||
|
{ name: 'Equipped', value: `1: ${character1 ? character1.name + ` (${slot1?.id})` : 'Empty'}\n2: ${character2 ? character2.name + ` (${slot2?.id})` : 'Empty'}\n3: ${character3 ? character3.name + ` (${slot3?.id})` : 'Empty'}` },
|
||||||
|
{ name: `${Math.round((Date.now()/1000)-player.start-player.spent)} points`, value: `${Math.round((Date.now()/1000)-player.start-player.spent) > 3600 ? 'You can roll!' : 'Keep saving...'}` }
|
||||||
|
)
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -6,17 +6,17 @@ import { createArgumentsObject, SlashCommand } from "./slash"
|
|||||||
|
|
||||||
export class RollCommand implements SlashCommand {
|
export class RollCommand implements SlashCommand {
|
||||||
name = 'roll'
|
name = 'roll'
|
||||||
description = 'Pull a random character'
|
description = 'Pull a random character for 3600 points'
|
||||||
permission = []
|
permission = []
|
||||||
ownerOnly = false
|
ownerOnly = false
|
||||||
guildOnly = false
|
guildOnly = false
|
||||||
guildID = "739645806100873328" //for testing
|
//guildID = "739645806100873328" //for testing
|
||||||
args: ApplicationCommandOptionData[] = []
|
args: ApplicationCommandOptionData[] = []
|
||||||
|
|
||||||
async execute(int: CommandInteraction) {
|
async execute(int: CommandInteraction) {
|
||||||
const player = await CBClient.findOrCreatePlayer(int.user.id);
|
const player = await CBClient.findOrCreatePlayer(int.user.id);
|
||||||
|
|
||||||
if (!(await CBClient.spendOnPlayer(player, 3600_000))) return int.reply({
|
if (!(await CBClient.spendOnPlayer(player, 3600))) return int.reply({
|
||||||
content: "You don't have the money!",
|
content: "You don't have the money!",
|
||||||
ephemeral: true
|
ephemeral: true
|
||||||
});
|
});
|
||||||
@ -30,7 +30,7 @@ export class RollCommand implements SlashCommand {
|
|||||||
return int.reply({
|
return int.reply({
|
||||||
embeds: [
|
embeds: [
|
||||||
new EmbedBuilder()
|
new EmbedBuilder()
|
||||||
.setTitle(`You got **${character.name}**!`)
|
.setTitle(`${int.user.username}, you got **${character.name}**!`)
|
||||||
.setImage(character.img)
|
.setImage(character.img)
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user