Skip to content

Commit

Permalink
Rework the auto complete and fix the set knockback for all characters
Browse files Browse the repository at this point in the history
  • Loading branch information
bartdebever committed Jul 3, 2024
1 parent ff5ae61 commit c0d44b4
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 36 deletions.
7 changes: 1 addition & 6 deletions src/commands/character-command.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { injectable } from 'inversify';
import { Command } from './command';
import { SlashCommandBuilder, CommandInteraction, CacheType } from 'discord.js';
import { charactersChoices } from './utils/character-options';
import { Search } from '../data/search';
import { CharacterEmbedCreator } from '../embeds/character-embed-creator';

Expand All @@ -17,11 +16,7 @@ export class CharacterCommand implements Command {
.setName('character')
.setDescription('Get the information about a specific character.')
.addStringOption((option) =>
option
.setName('character')
.setDescription('The character to look for')
.setRequired(true)
.addChoices(...charactersChoices)
option.setName('character').setDescription('The character to look for').setRequired(true).setAutocomplete(true)
);
return [builder];
}
Expand Down
4 changes: 3 additions & 1 deletion src/commands/frame-data-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ export class FrameDataCommand implements Command {
.addStringOption((option) =>
option.setName('character').setDescription('The character to get the move for').setRequired(true).setAutocomplete(true)
)
.addStringOption((option) => option.setName('move').setDescription('The move to look for').setRequired(true));
.addStringOption((option) =>
option.setName('move').setDescription('The move to look for').setRequired(true).setAutocomplete(true)
);
return [builder];
}
async handleCommand(interaction: CommandInteraction<CacheType>): Promise<void> {
Expand Down
16 changes: 5 additions & 11 deletions src/commands/knockback-command.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { SlashCommandBuilder, CommandInteraction, CacheType, InteractionResponse } from 'discord.js';
import { Command } from './command';
import { charactersChoices } from './utils/character-options';
import { inject, injectable } from 'inversify';
import { Logger } from 'winston';
import { Symbols } from '../config/symbols';
Expand All @@ -26,18 +25,13 @@ export abstract class KnockbackCommand implements Command {
.setName(name)
.setDescription('Get the crouch cancel info for a move')
.addStringOption((option) =>
option
.setName('character')
.setDescription('The character executing the move')
.setRequired(true)
.addChoices(...charactersChoices)
option.setName('character').setDescription('The character executing the move').setRequired(true).setAutocomplete(true)
)
.addStringOption((option) => option.setName('move').setDescription('The move to look for').setRequired(true))
.addStringOption((option) =>
option
.setName('target')
.setDescription('The character being attacked')
.addChoices(...charactersChoices)
option.setName('move').setDescription('The move to look for').setRequired(true).setAutocomplete(true)
)
.addStringOption((option) =>
option.setName('target').setDescription('The character being attacked').setAutocomplete(true)
);
return builder;
});
Expand Down
4 changes: 4 additions & 0 deletions src/data/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ export class Search {
foundMoves.push({ move: move, distance: distance });
}

console.log(foundMoves);

foundMoves.sort(this.sortDistanceResults);

if (foundMoves.length === 0) {
return new SearchResult(SearchResultType.MoveNotFound, foundAlias.record.character);
}
Expand Down
59 changes: 46 additions & 13 deletions src/embeds/knockback-embed-creator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export abstract class KnockbackEmbedCreator extends BaseEmbedCreator {
const characterEmote = CharacterEmoji.getEmoteId(character.normalizedName);
const targetEmote = CharacterEmoji.getEmoteId(target.normalizedName);
embedBuilder.setTitle(`${characterEmote} ${character.name} - ${move.name} vs ${target.name} ${targetEmote} `);
for (const hitbox of move.hitboxes) {
for (const hitbox of move.hitboxes.sort(this.orderHitboxes)) {
if (hitbox.angle > 179 && hitbox.angle != 361) {
hitboxMap.set(hitbox.name, `Can not be ${this.shortTerm} due to angle being higher than 179 (${hitbox.angle})`);
} else if (hitbox.angle === 0) {
Expand All @@ -65,8 +65,7 @@ export abstract class KnockbackEmbedCreator extends BaseEmbedCreator {
private createForAll(character: Character, move: Move, embedBuilder: EmbedBuilder, dataLoader: Loader): EmbedBuilder[] {
const characterEmote = CharacterEmoji.getEmoteId(character.normalizedName);
embedBuilder.setTitle(`${characterEmote} ${character.name} - ${move.name}`);

for (const hitbox of move.hitboxes) {
for (const hitbox of move.hitboxes.sort(this.orderHitboxes)) {
if (hitbox.angle > 179 && hitbox.angle != 361) {
embedBuilder.addFields({
name: hitbox.name,
Expand All @@ -76,17 +75,8 @@ export abstract class KnockbackEmbedCreator extends BaseEmbedCreator {
} else if (hitbox.angle === 0) {
embedBuilder.addFields({ name: hitbox.name, value: `Can not be ${this.shortTerm} due to angle being 0` });
continue;
} else if (hitbox.setKnockback && hitbox.setKnockback < this.knockbackTarget) {
embedBuilder.addFields({
name: hitbox.name,
value: `Can not break ${this.longTerm} due to the hitbox having low set knockback`,
});
continue;
} else if (hitbox.setKnockback) {
embedBuilder.addFields({
name: hitbox.name,
value: `Can not be ${this.shortTerm} due to the hitbox having high set knockback`,
});
this.addSetKnockbackField(embedBuilder, hitbox, dataLoader);
continue;
}

Expand Down Expand Up @@ -141,4 +131,47 @@ export abstract class KnockbackEmbedCreator extends BaseEmbedCreator {
private orderCharacters(characterOne: Character, characterTwo: Character): number {
return characterOne.name.localeCompare(characterTwo.name);
}

private orderHitboxes(hitboxOne: Hitbox, hitboxTwo: Hitbox): number {
return hitboxOne.name.localeCompare(hitboxTwo.name, undefined, { numeric: true, sensitivity: 'base' });
}

private addSetKnockbackField(embedBuilder: EmbedBuilder, hitbox: Hitbox, dataLoader: Loader): void {
const succeedsArray: Character[][] = [[], []];
for (const character of dataLoader.data
.filter((character) => character.characterStatistics.weight > 0)
.sort(this.orderCharacters)) {
if (!CrouchCancelCalculator.meetsKnockbackTarget(hitbox, character, this.knockbackTarget)) {
succeedsArray[0].push(character);
} else {
succeedsArray[1].push(character);
}
}

if (succeedsArray[0].length == 0) {
embedBuilder.addFields({
name: hitbox.name,
value: `Can never be ${this.shortTerm} by all characters.`,
});
return;
} else if (succeedsArray[1].length == 0) {
embedBuilder.addFields({
name: hitbox.name,
value: `Can always be ${this.shortTerm} by all characters.`,
});
return;
}

const canText =
`**Can always be ${this.shortTerm} by:**\n` +
succeedsArray[0].map((character) => CharacterEmoji.getEmoteId(character.normalizedName)).join(' ');
const canNotText =
`**Can never be ${this.shortTerm} by:**\n` +
succeedsArray[1].map((character) => CharacterEmoji.getEmoteId(character.normalizedName)).join(' ');

embedBuilder.addFields({
name: hitbox.name,
value: canText + '\n' + canNotText,
});
}
}
63 changes: 58 additions & 5 deletions src/interactions/auto-complete-interaction-handler.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,80 @@
import { inject, injectable } from 'inversify';
import { BaseInteractionHandler } from './base-interaction-handler';
import { AutocompleteInteraction, Client } from 'discord.js';
import { ApplicationCommandOptionChoiceData, AutocompleteInteraction, Client } from 'discord.js';
import { Logger } from 'winston';
import { Symbols } from '../config/symbols';
import { FailureStore } from '../data/failure-store';
import { Search } from '../data/search';
import { Loader } from '../data/loader';
import { SearchResultType } from '../models/search/search-result-type';
import { Move } from '../models/move';
import { ReadableStreamDefaultController } from 'stream/web';

@injectable()
export class AutoCompleteInteractionHandler extends BaseInteractionHandler {
constructor(
search: Search,
@inject(Symbols.Logger) logger: Logger,
failureStore: FailureStore,
@inject(Symbols.Client) private client: Client
@inject(Symbols.Client) private client: Client,
private loader: Loader
) {
super(search, logger, failureStore);
}

async handle(autoCompleteInteraction: AutocompleteInteraction): Promise<void> {
const focusedValue = autoCompleteInteraction.options.getFocused();
const characters = this.search.searchForCharacter(focusedValue.split(' '));
await autoCompleteInteraction.respond(
const focusedValue = autoCompleteInteraction.options.getFocused(true);
if (focusedValue.name === 'move') {
await this.handleMoveInteraction(autoCompleteInteraction);
return;
}

await this.handleCharacterInteraction(autoCompleteInteraction);
}

private async handleMoveInteraction(autoCompleteInteraction: AutocompleteInteraction): Promise<void> {
const focusedValue = autoCompleteInteraction.options.getFocused(true);
const characterText = autoCompleteInteraction.options.getString('character', true);
const result = this.search.search(characterText + ' ' + focusedValue.value);

if (result.type === SearchResultType.Move) {
let moves: Move[];
if (result.possibleMoves && result.possibleMoves.length > 0) {
moves = result.possibleMoves;
} else {
moves = [result.move];
}
await this.respond(
autoCompleteInteraction,
moves.map((move) => ({
name: move.name,
value: move.normalizedName,
}))
);

return;
}

await this.respond(autoCompleteInteraction, []);
}

private async handleCharacterInteraction(autoCompleteInteraction: AutocompleteInteraction): Promise<void> {
const focusedValue = autoCompleteInteraction.options.getFocused(true);
const characters = this.search.searchForCharacter(focusedValue.value.split(' '));
await this.respond(
autoCompleteInteraction,
characters.map((character) => ({ name: character.name, value: character.normalizedName }))
);
}

private async respond(
autoCompleteInteraction: AutocompleteInteraction,
options: ApplicationCommandOptionChoiceData<string>[]
): Promise<void> {
if (options.length > 25) {
options = options.slice(0, 25);
}

await autoCompleteInteraction.respond(options);
}
}

0 comments on commit c0d44b4

Please sign in to comment.