Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Epic merchant #2248

Merged
merged 5 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions resources/text/smallEvents/epicItemShop.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"translations": {
"fr": {
"intro": [
"En pleine progression vers votre destination, une rencontre inattendue survient. Aldéric l'antiquaire émerge de l'horizon, son chariot de trésors à la remorque, prêt à discuter d'une affaire spéciale.",
"Lorsque vous êtes en route, un étrange individu fait son apparition. Aldéric l'antiquaire, marchand ambulant au charme mystérieux, se profile avec une offre captivante.",
"Alors que vous marchez sans hâte vers l'inconnu, une silhouette familière surgit : Aldéric l'antiquaire, le marchand errant, vous tend une proposition intrigante.",
"Alors que votre voyage se déroule sans encombre, un événement singulier survient. Aldéric l'antiquaire, l'artiste des antiquités ambulant, vous convie à un échange mémorable.",
"Dans le cadre de votre voyage, une interruption surprenante survient. C'est Aldéric l'antiquaire, le marchand itinérant, qui vous dévoile un trésor inattendu.",
"Lors d'une brève halte sous un arbre, un personnage mystérieux fait son entrée. C'est Aldéric l'antiquaire, l'errant de l'insolite, prêt à vous immerger dans une proposition des plus alléchantes.",
"Alors que vous avancez à un rythme paisible sur votre chemin, le bruit des roues d'une charrette attire votre attention. Vous apercevez Aldéric l'antiquaire, un homme d'un certain âge vêtu de manière pittoresque, qui parcourt les routes en tant que marchand itinérant. Il vous interpelle avec un sourire bienveillant, vous invitant à explorer sa collection d'objets fascinants.",
"Alors que vous marchez sur un chemin de pierre couvert de poussière, une charrette avec l'inscription \"Aldéric l'antiquaire - marchand d'objets super\" se présente devant vous. Une transaction est bientôt initiée.",
"Tandis que vous marchez tranquillement, un chariot en bois attirant votre curiosité surgit à l'horizon. À son bord se tient Aldéric l'antiquaire, un homme distingué au visage marqué par le temps. Sa charrette est remplie d'antiquités soigneusement disposées, et il se propose de vous montrer ses trésors, tous chargés d'histoires et de valeur.",
"Alors que vous reprenez la route après une courte pause, un individu étonnamment bien vêtu s'approche de vous. Il se présente comme Aldéric l'antiquaire, un marchand ambulant renommé. Sa tenue, mélange d'étoffes anciennes et d'accessoires énigmatiques, reflète son amour pour les objets anciens. Avec un accent teinté d'excitation, il vous détaille l'histoire de ses trouvailles uniques.",
"Alors que vous cheminez en toute tranquillité, une charrette aux allures de trésor ambulant s'immobilise devant vous. Son conducteur, Aldéric l'antiquaire, est un homme à la personnalité chaleureuse, arborant une tenue qui respire le vintage. Il vous convie à explorer sa collection de curiosités, chacune d'entre elles étant assortie d'une histoire qui vous émerveillera.",
"Lors d'une pause sous l'ombre d'un grand arbre, un homme distingué s'approche de vous avec un sourire aimable. Cet homme n'est autre qu'Aldéric l'antiquaire, un marchand de renom. Il porte un costume qui évoque une autre époque, et il vous fait part de son intérêt pour les objets anciens, tous exposés avec soin dans sa charrette.",
"Après de longues heures de marche, un homme d'âge mûr vêtu de vêtements rappelant une époque révolue vous aborde avec courtoisie. Il se présente comme Aldéric l'antiquaire, un connaisseur passionné d'antiquités. Dans sa charrette, vous découvrez une collection d'objets fascinants, et il se fait un plaisir de vous raconter l'histoire de chacun d'eux."
],
"reductionTip": " Il incline légèrement la tête et vous confie en confidence, 'Mais si vous avez le désir de vous aventurer jusqu'à la Route des Merveilles et que vous parvenez à me trouver par là bas, soyez assuré que je vous réserverai une proposition des plus avantageuses.'",
"end": "\n\n{item} | `{price}\uD83D\uDCB0`\n\n**Type :** {type}",
"types": [
"Arme",
"Armure/Bouclier",
"Potion",
"Objet"
]
},
"en": {
"intro": [
"While on your journey to an unknown destination, an unexpected encounter unfolds. Alderic the antiquarian emerges from the horizon, his treasure-laden cart in tow, ready to engage in a special transaction.",
"As you make your way, an intriguing figure appears. Alderic, the enigmatic itinerant merchant, presents you with a captivating proposition.",
"As you leisurely walk into the unknown, a familiar silhouette emerges: Alderic the antiquarian, a wandering merchant, offering you an intriguing proposal.",
"As your journey proceeds smoothly, a singular event takes place. Alderic, the wandering connoisseur of antiquities, invites you to a memorable exchange.",
"During your journey, an unexpected interruption occurs. It's Alderic the itinerant merchant, revealing an unforeseen treasure.",
"During a brief halt under a tree, a mysterious character makes his entrance. It's Alderic the antiquarian, the wanderer of the unusual, ready to immerse you in a most enticing offer.",
"As you advance at a leisurely pace on your path, the sound of cartwheels captures your attention. You spot Alderic the antiquarian, a man of a certain age dressed in a picturesque manner, who roams the roads as a traveling merchant. He beckons you with a benevolent smile, inviting you to explore his collection of captivating objects.",
"While strolling on a dusty, stone-covered path, a cart with the inscription 'Alderic the antiquarian - purveyor of superb objects' appears before you. A transaction is initiated without delay.",
"While you walk serenely, an attractive wooden cart on the horizon piques your curiosity. Aboard it stands Alderic the antiquarian, a distinguished man with a face marked by the passage of time. His cart is filled with carefully arranged antiques, and he offers to reveal his treasures, each laden with stories and value.",
"As you continue your journey after a brief respite, a remarkably well-dressed individual approaches you. He introduces himself as Alderic, the renowned traveling merchant. His attire, a blend of ancient fabrics and enigmatic accessories, reflects his love for ancient objects. With an accent tinged with excitement, he elaborates on the history of his unique finds.",
"While traveling in tranquility, a cart resembling a traveling treasure comes to a halt before you. Its driver, Alderic the antiquarian, is a man with a warm personality, wearing a vintage-inspired outfit. He invites you to explore his collection of curiosities, each accompanied by a story that will captivate you.",
"During a break in the shade of a large tree, a distinguished man approaches you with a friendly smile. This man is none other than Alderic, the renowned antiquarian. He wears a suit reminiscent of a bygone era and shares his passion for antique items, all meticulously displayed in his cart.",
"After hours of walking, a middle-aged man dressed in attire evoking a bygone era approaches you with courtesy. He introduces himself as Alderic, the passionate connoisseur of antiques. In his cart, you discover a collection of fascinating objects, and he takes pleasure in recounting the history of each one."
],
"reductionTip": " He nods slightly and confides in you, 'But if you have the desire to venture to the Wonder Road and manage to find me there, rest assured that I will offer you a most advantageous proposition.'",
"end": "\n\n{item} | `{price}\uD83D\uDCB0`\n\n**Type:** {type}",
"types": [
"Weapon",
"Armor/Shield",
"Potion",
"Item"
]
}
},
"rarity": 1,
"emote": ":star2:"
}
4 changes: 2 additions & 2 deletions resources/text/smallEvents/shop.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"Alors que vous voyagez tranquillement, vous rencontrez {name}. Ce dernier est un marchand ambulant, et vous propose une offre spéciale.",
"Tandis que vous avancez tranquillement sur votre route, vous tombez nez à nez avec {name}, qui vous propose rapidement une offre alléchante.",
"Alors que vous vous apprêtez à vous remettre en marche après une petite pause, un homme se présentant comme \"{name} - marchand ambulant\" vous propose un échange.",
"Au détour d'un rocher, vous tombez nez à nez avec un marchand ambulant nommé {name}, qui semble vendre des choses fortes intéressantes",
"Au détour d'un rocher, vous tombez nez à nez avec un marchand ambulant nommé {name}, qui semble vendre des choses fortes intéressantes.",
"Alors que vous vous baladez tranquillement, une charrette arborant l'enseigne \"{name} - super marchand ambulant d'items\" apparaît devant vous. Une transaction s'amorce immédiatement.",
"À un certain point de votre voyage, un marchand vous interpelle. Il dit s'appeler {name} et avoir des objets pouvant vous aider pendant votre aventure.",
"Après de longues heures de marche, un homme vous aborde. Vous apprenez qu'il se nomme {name} – marchand de première qualité. Il vous montre rapidement un de ses nombreux objets.",
Expand Down Expand Up @@ -64,7 +64,7 @@
"While travelling, you meet {name}. He is an itinerant trader, and claims to offer you only the best of prices.",
"As you walk along an old path, you stumble upon {name}, who quickly makes you an attractive offer.",
"As you are about to start walking again after a short break, a man, introducing himself as \"{name} - itinerant merchant\" proposes a trade.",
"At the turn of a road, you come face to face with an itinerant merchant named {name}, who is seemingly selling very interesting things",
"At the turn of a road, you come face to face with an itinerant merchant named {name}, who is seemingly selling very interesting things.",
"As you are walking along a stone path covered in dust, a cart with the sign \"{name} - super item merchant\" comes in front of you. A transaction is soon initiated.",
"During your adventure, a merchant suddenly calls out to you! He says his name is {name}, and claims to have some items that will help you in the future.",
"After many hours of lonely walking across plains, a man approaches you. You learn that he is called {name} - a first-class merchant. He quickly shows you one of his many items.",
Expand Down
10 changes: 10 additions & 0 deletions src/core/constants/SmallEventConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,4 +236,14 @@ export abstract class SmallEventConstants {
MAX: 250
}
};

static EPIC_ITEM_SHOP = {
MIN_RARITY: ItemConstants.RARITY.EPIC,
MAX_RARITY: ItemConstants.RARITY.LEGENDARY,
GREAT_DEAL_PROBABILITY: 0.1,
GREAT_DEAL_MULTIPLAYER: 3.5,
BASE_MULTIPLIER: 5.5,
ROAD_OF_WONDERS_MULTIPLIER: 1.5,
REDUCTION_TIP_PROBABILITY: 0.2 // 20% chance to have a reduction tip
};
}
86 changes: 86 additions & 0 deletions src/core/smallEvents/epicItemShopSmallEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import {SmallEvent} from "./SmallEvent";
import {CommandInteraction} from "discord.js";
import {DraftBotEmbed} from "../messages/DraftBotEmbed";
import {format} from "../utils/StringFormatter";
import {generateRandomItem, getItemValue} from "../utils/ItemUtils";
import {Constants} from "../Constants";
import {BlockingUtils} from "../utils/BlockingUtils";
import {RandomUtils} from "../utils/RandomUtils";
import {Translations} from "../Translations";
import {DraftBotValidateReactionMessage} from "../messages/DraftBotValidateReactionMessage";
import {BlockingConstants} from "../constants/BlockingConstants";
import Player from "../database/game/models/Player";
import {SmallEventConstants} from "../constants/SmallEventConstants";
import {Maps} from "../maps/Maps";
import {callbackShopSmallEvent} from "../utils/SmallEventUtils";
import {ItemConstants} from "../constants/ItemConstants";
import {MapConstants} from "../constants/MapConstants";


/**
* Make all the calculations to generate the multiplier to use for the price of the item
* @param player
*/
async function generateMultiplier(player: Player): Promise<number> {
const destination = await player.getDestination();
const origin = await player.getPreviousMap();
let multiplier = RandomUtils.draftbotRandom.bool(SmallEventConstants.EPIC_ITEM_SHOP.GREAT_DEAL_PROBABILITY) ?
SmallEventConstants.EPIC_ITEM_SHOP.GREAT_DEAL_MULTIPLAYER : SmallEventConstants.EPIC_ITEM_SHOP.BASE_MULTIPLIER;
if (destination.id === MapConstants.LOCATIONS_IDS.ROAD_OF_WONDERS || origin.id === MapConstants.LOCATIONS_IDS.ROAD_OF_WONDERS) {
multiplier = SmallEventConstants.EPIC_ITEM_SHOP.ROAD_OF_WONDERS_MULTIPLIER;
}
return multiplier;
}

export const smallEvent: SmallEvent = {
/**
* Check if small event can be executed
*/
canBeExecuted(player: Player): Promise<boolean> {
return Promise.resolve(Maps.isOnContinent(player));
},

/**
* Find a merchant who sells you a random item at a cheap price (or is it)
* @param interaction
* @param language
* @param player
* @param seEmbed
*/
async executeSmallEvent(interaction: CommandInteraction, language: string, player: Player, seEmbed: DraftBotEmbed): Promise<void> {
const randomItem = await generateRandomItem(
RandomUtils.draftbotRandom.pick(
Object.values(ItemConstants.CATEGORIES).filter((category) => category !== ItemConstants.CATEGORIES.POTION)
),
SmallEventConstants.EPIC_ITEM_SHOP.MIN_RARITY,
SmallEventConstants.EPIC_ITEM_SHOP.MAX_RARITY
);

const multiplier = await generateMultiplier(player);
const price = Math.round(getItemValue(randomItem) * multiplier);

const translationShop = Translations.getModule("smallEvents.epicItemShop", language);
const endCallback = callbackShopSmallEvent(player, price, interaction, language, Translations.getModule("commands.shop", language), randomItem);
const reductionTip = RandomUtils.draftbotRandom.bool(SmallEventConstants.EPIC_ITEM_SHOP.REDUCTION_TIP_PROBABILITY) && multiplier > SmallEventConstants.EPIC_ITEM_SHOP.ROAD_OF_WONDERS_MULTIPLIER
? translationShop.get("reductionTip")
: "";
await new DraftBotValidateReactionMessage(
interaction.user,
endCallback
)
.setAuthor({
name: seEmbed.data.author.name,
iconURL: interaction.user.displayAvatarURL()
})
.setDescription(seEmbed.data.description
+ format(
translationShop.getRandom("intro")
+ reductionTip
+ translationShop.get("end"), {
item: randomItem.toString(language, null),
price,
type: `${Constants.REACTIONS.ITEM_CATEGORIES[randomItem.getCategory()]} ${translationShop.get(`types.${randomItem.getCategory()}`)}`
}))
.editReply(interaction, (collector) => BlockingUtils.blockPlayerWithCollector(player.discordUserId, BlockingConstants.REASONS.MERCHANT, collector));
}
};
52 changes: 3 additions & 49 deletions src/core/smallEvents/shopSmallEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,64 +2,18 @@ import {SmallEvent} from "./SmallEvent";
import {CommandInteraction} from "discord.js";
import {DraftBotEmbed} from "../messages/DraftBotEmbed";
import {format} from "../utils/StringFormatter";
import {generateRandomItem, getItemValue, giveItemToPlayer} from "../utils/ItemUtils";
import {generateRandomItem, getItemValue} from "../utils/ItemUtils";
import {Constants} from "../Constants";
import {BlockingUtils} from "../utils/BlockingUtils";
import {RandomUtils} from "../utils/RandomUtils";
import {TranslationModule, Translations} from "../Translations";
import {Translations} from "../Translations";
import {DraftBotValidateReactionMessage} from "../messages/DraftBotValidateReactionMessage";
import {sendErrorMessage} from "../utils/ErrorUtils";
import {GenericItemModel} from "../database/game/models/GenericItemModel";
import {BlockingConstants} from "../constants/BlockingConstants";
import {NumberChangeReason} from "../constants/LogsConstants";
import Player from "../database/game/models/Player";
import {InventorySlots} from "../database/game/models/InventorySlot";
import {SmallEventConstants} from "../constants/SmallEventConstants";
import {ItemConstants} from "../constants/ItemConstants";
import {Maps} from "../maps/Maps";

/**
* Get the callback of the shop small event
* @param player
* @param price
* @param interaction
* @param language
* @param translationShop
* @param randomItem
*/
function callbackShopSmallEvent(
player: Player,
price: number,
interaction: CommandInteraction,
language: string,
translationShop: TranslationModule,
randomItem: GenericItemModel): (msg: DraftBotValidateReactionMessage) => Promise<void> {
return async (msg: DraftBotValidateReactionMessage): Promise<void> => {
BlockingUtils.unblockPlayer(player.discordUserId, BlockingConstants.REASONS.MERCHANT);
if (msg.isValidated()) {
if (player.money < price) {
await sendErrorMessage(interaction.user, interaction, language,
translationShop.format("error.cannotBuy", {
missingMoney: price - player.money
})
);
return;
}
await giveItemToPlayer(player, randomItem, language, interaction.user, interaction.channel, await InventorySlots.getOfPlayer(player.id), SmallEventConstants.SHOP.RESALE_MULTIPLIER, 1);
await player.spendMoney({
amount: price,
channel: interaction.channel,
language,
reason: NumberChangeReason.SMALL_EVENT
});
await player.save();
return;
}
await sendErrorMessage(interaction.user, interaction, language,
Translations.getModule("commands.shop", language).get("error.canceledPurchase"), true
);
};
}
import {callbackShopSmallEvent} from "../utils/SmallEventUtils";

export const smallEvent: SmallEvent = {
/**
Expand Down
55 changes: 55 additions & 0 deletions src/core/utils/SmallEventUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import Player from "../database/game/models/Player";
import {CommandInteraction} from "discord.js";
import {TranslationModule, Translations} from "../Translations";
import {GenericItemModel} from "../database/game/models/GenericItemModel";
import {DraftBotValidateReactionMessage} from "../messages/DraftBotValidateReactionMessage";
import {BlockingUtils} from "./BlockingUtils";
import {BlockingConstants} from "../constants/BlockingConstants";
import {sendErrorMessage} from "./ErrorUtils";
import {giveItemToPlayer} from "./ItemUtils";
import {NumberChangeReason} from "../constants/LogsConstants";
import {InventorySlots} from "../database/game/models/InventorySlot";
import {SmallEventConstants} from "../constants/SmallEventConstants";

/**
* Get the callback of the shop small event
* @param player
* @param price
* @param interaction
* @param language
* @param translationShop
* @param randomItem
*/
export function callbackShopSmallEvent(
player: Player,
price: number,
interaction: CommandInteraction,
language: string,
translationShop: TranslationModule,
randomItem: GenericItemModel): (msg: DraftBotValidateReactionMessage) => Promise<void> {
return async (msg: DraftBotValidateReactionMessage): Promise<void> => {
BlockingUtils.unblockPlayer(player.discordUserId, BlockingConstants.REASONS.MERCHANT);
if (msg.isValidated()) {
if (player.money < price) {
await sendErrorMessage(interaction.user, interaction, language,
translationShop.format("error.cannotBuy", {
missingMoney: price - player.money
})
);
return;
}
await giveItemToPlayer(player, randomItem, language, interaction.user, interaction.channel, await InventorySlots.getOfPlayer(player.id), SmallEventConstants.SHOP.RESALE_MULTIPLIER, 1);
await player.spendMoney({
amount: price,
channel: interaction.channel,
language,
reason: NumberChangeReason.SMALL_EVENT
});
await player.save();
return;
}
await sendErrorMessage(interaction.user, interaction, language,
Translations.getModule("commands.shop", language).get("error.canceledPurchase"), true
);
};
}