Skip to content

Commit

Permalink
Add 'Quip' Verb for Quipped crew.
Browse files Browse the repository at this point in the history
  • Loading branch information
Nathaniel Moschkin committed Nov 1, 2023
1 parent 5353e81 commit 8d6342b
Show file tree
Hide file tree
Showing 9 changed files with 360 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/commands/cheapestfffe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ async function asyncHandler(
}
}).sort((a: any, b: any) => {
let r = 0;
if (!r) r = (b.rarity/b.max_rarity) - (a.rarity/a.max_rarity);
//if (!r) r = (b.rarity/b.max_rarity) - (a.rarity/a.max_rarity);
if (!r) r = a.requiredChronCost - b.requiredChronCost;
return r;
});
Expand Down
2 changes: 2 additions & 0 deletions src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { ProfileCommand } from './profile';
import { CrewNeedCommand } from './crewneed';
import { OffersCommand } from './offers';
import { CheapestFFFECommand } from './cheapestfffe';
import { QuipmentCommand } from './quip';

export let Commands: Definitions.Command[] = [
AssociateCommand,
Expand All @@ -32,4 +33,5 @@ export let Commands: Definitions.Command[] = [
SearchCommand,
StatsCommand,
VoyTimeCommand,
QuipmentCommand
];
217 changes: 217 additions & 0 deletions src/commands/quip.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
import { Message, EmbedBuilder, ApplicationCommandOptionType } from 'discord.js';
import yargs from 'yargs';

import { DCData } from '../data/DCData';
import { formatSources, formatRecipe, appelate, getItemBonuses } from '../utils/items';
import { colorFromRarity, formatCollectionName, formatCurrentStatLine, formatSkillsStatsWithEmotes, formatStatLine } from '../utils/crew';
import { getEmoteOrString, sendAndCache } from '../utils/discord';
import CONFIG from '../utils/config';
import { applyCrewBuffs, loadFullProfile, loadProfile, toTimestamp, userFromMessage } from '../utils/profile';
import { getNeededItems } from '../utils/equipment';
import { PlayerCrew } from '../datacore/player';
import { EquipmentItem } from '../datacore/equipment';
import { rarityLabels } from '../datacore/game-elements';

function bonusName(bonus: string) {
let cfg = CONFIG.STATS_CONFIG[Number.parseInt(bonus)];
if (cfg) {
return `${CONFIG.SKILLS[cfg.skill as Definitions.SkillName]} ${cfg.stat}`;
} else {
return `*unknown (${bonus})*`;
}
}

async function asyncHandler(
message: Message,
crewman?: string
) {
// This is just to break up the flow and make sure any exceptions end up in the .catch, not thrown during yargs command execution
await new Promise<void>(resolve => setImmediate(() => resolve()));

let user = await userFromMessage(message);
let settings = user?.profiles[0] ? await loadProfile(user.profiles[0].dbid) : null;
let profile = user?.profiles[0] ? loadFullProfile(user.profiles[0].dbid) : null;
if (!user || !profile) {
sendAndCache(message, "Sorry, I couldn't find an associated profile for your user.")
return;
}
if (crewman?.length) {
crewman = crewman.toLowerCase().trim();
}

let botCrew = DCData.getBotCrew();
let quipment = DCData.getItems().filter((item: Definitions.Item) => item.type === 15 || item.type === 14);

let profileCrew = profile.player.character.crew;
let profileItems = profile.player.character.items;
let quippedCrew = profileCrew.filter((c: PlayerCrew) => {
if (!!c.kwipment?.length) {
if (crewman?.length) {
let bcrew = botCrew.find(f => f.symbol===c.symbol);
if (!bcrew) return false;
if (!bcrew?.name.toLowerCase().trim().includes(crewman)) return false;
}
c.kwipment_items = (c.kwipment.map(kw => quipment.find(q => q.kwipment_id?.toString() === kw[1].toString()))?.filter(chk => !!chk) ?? []) as Definitions.Item[];
return true;
}
else {
return false;
}
})
.map((crew: PlayerCrew) => {
let matched = botCrew.find((crew) => {
return crew.symbol === crew.symbol
}) as Definitions.BotCrew;
crew = JSON.parse(JSON.stringify(crew));
crew.name = matched?.name ?? crew.name;
crew.bigbook_tier = matched?.bigbook_tier;
crew.date_added = new Date(crew.date_added);
if (settings) crew.base_skills = applyCrewBuffs(crew.base_skills, settings.buffConfig);
return crew;
})
.sort((a: PlayerCrew, b: PlayerCrew) => {
let r = 0;
if (!r) r = (b.kwipment_items?.length ?? 0) - (a.kwipment_items?.length ?? 0);
if (!r) r = (b.max_rarity - a.max_rarity);
if (!r) r = (a.bigbook_tier - b.bigbook_tier);
if (!r) r = a.symbol.localeCompare(b.symbol);
return r;
});
if (!quippedCrew?.length) {
if (crewman){
sendAndCache(message, `Couldn't find any quipped crew in your profile that matches '${crewman}'. If you think this is a mistake, please update your profile, and try again.`)
return;
}
else {
sendAndCache(message, "Couldn't find any quipped crew in your profile. If you think this is a mistake, please update your profile, and try again.")
return;
}
}
const embeds = [] as EmbedBuilder[];
quippedCrew.slice(0, 5).forEach((can: PlayerCrew) => {
const matched = botCrew.find((crew) => {
return crew.symbol === can.symbol
}) as Definitions.BotCrew;

if (!matched) {
return;
}

let embed = new EmbedBuilder()
.setTitle(`${matched.name}`)
.setDescription(`Current Quipment`)
.setThumbnail(`${CONFIG.ASSETS_URL}${matched.imageUrlPortrait}`)
.setColor(colorFromRarity(matched.max_rarity))
.addFields(
// {
// name: 'Rarity',
// value: '⭐'.repeat(can.rarity) + '🌑'.repeat(matched.max_rarity - can.rarity),
// inline: false
// },
{
name: `Immortalized Stats`,
value: formatCurrentStatLine(message, { ... matched, ...can }),
inline: false
},
{
name: `Quipped Stats`,
value: formatSkillsStatsWithEmotes(message, can.skills),
inline: false
}
)

if (can.kwipment_items?.length) {
if (!!crewman) {
embeds.push(embed);
for (let quip of can.kwipment_items) {
let b = getItemBonuses(quip as EquipmentItem).bonuses as Definitions.Skills;

embed = new EmbedBuilder()
.setTitle(`${quip.name}`)
.setDescription(quip.flavor)
.setThumbnail(`${CONFIG.ASSETS_URL}${quip.imageUrl}`)
.setColor(colorFromRarity(quip.rarity))

embed = embed.addFields( {
name: `Buffs`,
value: formatSkillsStatsWithEmotes(message, b),
inline: false
},
{
name: "Rarity",
value: ((quip.rarity ? '⭐'.repeat(quip.rarity ?? 0) : '')),
inline: true
},
{
name: "Duration",
value: `${quip.duration} h`,
inline: true
},
{
name: "Equippable By",
value: `${rarityLabels[(quip.max_rarity_requirement ?? 1) - 1]} crew`,
inline: true
});
if (quip.traits_requirement?.length) {
embed = embed.addFields({
name: 'Required Traits',
value: `${quip.traits_requirement?.map(t => appelate(t)).join(` ${quip.traits_requirement_operator} `)}`,
inline: false
});
}
embeds.push(embed);
}
}
else {
for (let quip of can.kwipment_items) {
let b = getItemBonuses(quip as EquipmentItem).bonuses as Definitions.Skills;

embed = embed.addFields({
name: quip.name,
value: ((quip.rarity ? '⭐'.repeat(quip.rarity ?? 0) : '')) + formatSkillsStatsWithEmotes(message, b) + `\nDuration: ${quip.duration} h` +
((!!quip.traits_requirement?.length) ? `\nTraits: ${quip.traits_requirement?.map(t => appelate(t)).join(` ${quip.traits_requirement_operator} `)}` : '') +
`\nEquippable by ${rarityLabels[(quip.max_rarity_requirement ?? 1) - 1]} crew`

})
}
embeds.push(embed);
}
}


});

sendAndCache(message,
`Currently quipped crew in **${user.profiles[0].captainName}**'s roster (last updated ${toTimestamp(profile.lastModified ?? user.profiles[0].lastUpdate)})`,
{ embeds }
);

}

class Quipment implements Definitions.Command {
name = 'quip';
command = 'quip [crew]';
aliases = [];
describe = 'Shows currently quipped crew';
options = [{
name: 'crew',
type: ApplicationCommandOptionType.String,
description: 'show quipment stats for the specified crew',
required: false
}]

builder(yp: yargs.Argv): yargs.Argv {
return yp.option('crew', {
alias: 'c',
desc: 'show quipment stats for the specified crew'
});
}

handler(args: yargs.Arguments) {
let message = <Message>args.message;
let crew = args.crew as string;
args.promisedResult = asyncHandler(message, crew);
}
}

export let QuipmentCommand = new Quipment();
22 changes: 16 additions & 6 deletions src/datacore/equipment.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
import { Icon } from "./game-elements"
import { PlayerCrew, PlayerEquipmentItem } from "./player"

export interface EquipmentCommon extends PlayerEquipmentItem {

export interface EquipmentCommon extends PlayerEquipmentItem, Definitions.Item {
archetype_id: number;
symbol: string
type: number
name: string
flavor: string
//flavorContext?: JSX.Element;
rarity: number
short_name?: string
imageUrl: string
bonuses?: EquipmentBonuses
bonuses: EquipmentBonuses
quantity?: number;
needed?: number;
factionOnly?: boolean;
factionOnly: boolean;
demandCrew?: string[];

duration?: number;
max_rarity_requirement?: number;
traits_requirement_operator?: string; // "and" | "or" | "not" | "xor";
traits_requirement?: string[];
kwipment?: boolean;
kwipment_id?: number | string;
}

export interface EquipmentItem extends EquipmentCommon {
Expand All @@ -24,13 +34,13 @@ export interface EquipmentItem extends EquipmentCommon {
rarity: number
short_name?: string
imageUrl: string
bonuses?: EquipmentBonuses
bonuses: EquipmentBonuses
quantity?: number;
needed?: number;
factionOnly?: boolean;
factionOnly: boolean;

item_sources: EquipmentItemSource[]
recipe?: EquipmentRecipe
recipe: EquipmentRecipe

empty?: boolean;
isReward?: boolean;
Expand Down
5 changes: 3 additions & 2 deletions src/datacore/player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -451,8 +451,9 @@ export interface Player {
*/
equipment: number[][] | number[]

kwipment: number[][]
kwipment_expiration: number[]
kwipment: number[][];
kwipment_expiration: number[];
kwipment_items?: Definitions.Item[];
q_bits: number

icon: Icon
Expand Down
2 changes: 1 addition & 1 deletion src/utils/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default class CONFIG {
medicine_skill: 'Medicine'
};

static readonly STATS_CONFIG: { [index: number]: any } = {
static readonly STATS_CONFIG: { [index: number]: { symbol: string, skill: string, stat: string } } = {
2: { symbol: 'engineering_skill_core', skill: 'engineering_skill', stat: 'Core Skill' },
3: { symbol: 'engineering_skill_range_min', skill: 'engineering_skill', stat: 'Skill Proficiency Min' },
4: { symbol: 'engineering_skill_range_max', skill: 'engineering_skill', stat: 'Skill Proficiency Max' },
Expand Down
Loading

0 comments on commit 8d6342b

Please sign in to comment.