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

Go to PVE Island SE #2318 #2506

Merged
merged 2 commits into from
Jun 7, 2024
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
102 changes: 102 additions & 0 deletions Core/src/core/smallEvents/goToPVEIsland.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import {SmallEventFuncs} from "../../data/SmallEvent";
import Player from "../database/game/models/Player";
import {PlayerMissionsInfos} from "../database/game/models/PlayerMissionsInfo";
import {DraftBotPacket, makePacket} from "../../../../Lib/src/packets/DraftBotPacket";
import {
SmallEventGoToPVEIslandAcceptPacket,
SmallEventGoToPVEIslandNotEnoughGemsPacket, SmallEventGoToPVEIslandRefusePacket
} from "../../../../Lib/src/packets/smallEvents/SmallEventGoToPVEIslandPacket";
import {TravelTime} from "../maps/TravelTime";
import {NumberChangeReason} from "../../../../Lib/src/constants/LogsConstants";
import {Maps} from "../maps/Maps";
import {MapLinkDataController} from "../../data/MapLink";
import {Settings} from "../database/game/models/Setting";
import {PVEConstants} from "../../../../Lib/src/constants/PVEConstants";
import {MissionsController} from "../missions/MissionsController";
import {PlayerSmallEvents} from "../database/game/models/PlayerSmallEvent";
import {LogsReadRequests} from "../database/logs/LogsReadRequests";
import {EndCallback, ReactionCollectorInstance} from "../utils/ReactionsCollector";
import {BlockingUtils} from "../utils/BlockingUtils";
import {BlockingConstants} from "../../../../Lib/src/constants/BlockingConstants";
import { ReactionCollectorGoToPVEIsland } from "../../../../Lib/src/packets/interaction/ReactionCollectorGoToPVEIsland";
import {ReactionCollectorAcceptReaction} from "../../../../Lib/src/packets/interaction/ReactionCollectorPacket";

async function startBoatTravel(player: Player, price: number, anotherMemberOnBoat: Player | null, startTravelTimestamp: number, response: DraftBotPacket[]): Promise<boolean> {
const missionInfo = await PlayerMissionsInfos.getOfPlayer(player.id);
if (missionInfo.gems < price) {
response.push(makePacket(SmallEventGoToPVEIslandNotEnoughGemsPacket, {}));
return false;
}

await TravelTime.removeEffect(player, NumberChangeReason.SMALL_EVENT);
await Maps.startTravel(
player,
await MapLinkDataController.instance.getById(await Settings.PVE_ISLAND.getValue()),
anotherMemberOnBoat ? anotherMemberOnBoat.startTravelDate.valueOf() : startTravelTimestamp
);
await missionInfo.addGems(-price, player.keycloakId, NumberChangeReason.SMALL_EVENT);
await missionInfo.save();
if (price === PVEConstants.TRAVEL_COST[PVEConstants.TRAVEL_COST.length - 1]) {
await MissionsController.update(player, response, {
missionId: "wealthyPayForPVEIsland"
});
}

response.push(makePacket(SmallEventGoToPVEIslandAcceptPacket, { alone: !anotherMemberOnBoat }));
return true;
}

export const smallEventFuncs: SmallEventFuncs = {
async canBeExecuted(player: Player): Promise<boolean> {
return player.level >= PVEConstants.MIN_LEVEL &&
Maps.isNearWater(player) &&
player.hasEnoughEnergyToJoinTheIsland() &&
await PlayerSmallEvents.playerSmallEventCount(player.id, "goToPVEIsland") === 0 &&
await LogsReadRequests.getCountPVEIslandThisWeek(player.keycloakId, player.guildId) < PVEConstants.TRAVEL_COST.length;
},

async executeSmallEvent(context, response, player): Promise<void> {
const price = await player.getTravelCostThisWeek();
const anotherMemberOnBoat = await Maps.getGuildMembersOnBoat(player);
const travelTimestamp = Date.now();

const collector = new ReactionCollectorGoToPVEIsland(
price,
player.getCumulativeFightPoint(),
player.getMaxCumulativeFightPoint()
);

const endCallback: EndCallback = async (collector: ReactionCollectorInstance, response: DraftBotPacket[]): Promise<void> => {
const reaction = collector.getFirstReaction();

if (reaction && reaction.reaction.type === ReactionCollectorAcceptReaction.name) {
const isGoneOnIsland = await startBoatTravel(player, price, anotherMemberOnBoat[0], travelTimestamp, response);
if (isGoneOnIsland) {
await MissionsController.update(player, response, {
missionId: "joinPVEIsland",
set: true
});
}
}
else {
response.push(makePacket(SmallEventGoToPVEIslandRefusePacket, {}));
}

BlockingUtils.unblockPlayer(player.id, BlockingConstants.REASONS.PVE_ISLAND);
};

const packet = new ReactionCollectorInstance(
collector,
context,
{
allowedPlayerKeycloakIds: [player.keycloakId],
reactionLimit: 1
},
endCallback
)
.block(player.id, BlockingConstants.REASONS.PVE_ISLAND)
.build();

response.push(packet);
}
};
5 changes: 3 additions & 2 deletions Core/src/core/utils/ItemUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ import {ItemAcceptPacket} from "../../../../Lib/src/packets/notifications/ItemAc
import {ItemFoundPacket} from "../../../../Lib/src/packets/notifications/ItemFoundPacket";
import {ReactionCollectorItemChoice, ReactionCollectorItemChoiceItemReaction} from "../../../../Lib/src/packets/interaction/ReactionCollectorItemChoice";
import {EndCallback, ReactionCollectorInstance} from "./ReactionsCollector";
import {ReactionCollectorItemAccept, ReactionCollectorItemAcceptAcceptReaction} from "../../../../Lib/src/packets/interaction/ReactionCollectorItemAccept";
import {ReactionCollectorItemAccept} from "../../../../Lib/src/packets/interaction/ReactionCollectorItemAccept";
import {ReactionCollectorAcceptReaction} from "../../../../Lib/src/packets/interaction/ReactionCollectorPacket";

/**
* Get the value of an item
Expand Down Expand Up @@ -325,7 +326,7 @@ export const giveItemToPlayer = async function(

const endCallback: EndCallback = async (collector: ReactionCollectorInstance, response: DraftBotPacket[]): Promise<void> => {
const reaction = collector.getFirstReaction();
const isValidated = reaction && reaction.reaction instanceof ReactionCollectorItemAcceptAcceptReaction;
const isValidated = reaction && reaction.reaction.type === ReactionCollectorAcceptReaction.name;
player = await Players.getById(player.id);
BlockingUtils.unblockPlayer(player.id, BlockingConstants.REASONS.ACCEPT_ITEM);
await sellOrKeepItem(
Expand Down
9 changes: 8 additions & 1 deletion Discord/src/messages/DraftbotSmallEventEmbed.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import {DraftBotEmbed} from "./DraftBotEmbed";
import {DraftBotIcons} from "../../../Lib/src/DraftBotIcons";
import i18n from "../translations/i18n";
import {Language} from "../../../Lib/src/Language";
import {User} from "discord.js";

export class DraftbotSmallEventEmbed extends DraftBotEmbed {
constructor(smallEventId: keyof typeof DraftBotIcons.small_events, description: string) {
constructor(smallEventId: keyof typeof DraftBotIcons.small_events, description: string, user: User, language: Language) {
super();
this.setAuthor({
name: i18n.t("commands:report.journal", { lng: language, pseudo: user.displayName }),
iconURL: user.displayAvatarURL()
});
this.setDescription(`${DraftBotIcons.small_events[smallEventId]} ${description}`);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {ReactionCollectorCreationPacket} from "../../../../Lib/src/packets/inter
import { ReactionCollectorBigEventData} from "../../../../Lib/src/packets/interaction/ReactionCollectorBigEvent";
import {chooseDestinationCollector, createBigEventCollector} from "../../commands/player/ReportCommand";
import {ReactionCollectorChooseDestinationData} from "../../../../Lib/src/packets/interaction/ReactionCollectorChooseDestination";
import {ReactionCollectorGoToPVEIslandData} from "../../../../Lib/src/packets/interaction/ReactionCollectorGoToPVEIsland";
import {goToPVEIslandCollector} from "../../smallEvents/goToPVEIsland";

export default class ReactionCollectorHandler {
@packetHandler(ReactionCollectorCreationPacket)
Expand All @@ -16,6 +18,9 @@ export default class ReactionCollectorHandler {
case ReactionCollectorChooseDestinationData.name:
await chooseDestinationCollector(packet, context);
break;
case ReactionCollectorGoToPVEIslandData.name:
await goToPVEIslandCollector(packet, context);
break;
default:
throw `Unknown collector with data: ${packet.data.type}`; // Todo error embed
}
Expand Down
69 changes: 63 additions & 6 deletions Discord/src/packetHandlers/handlers/SmallEventsHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,14 @@ import {SmallEventBigBadKind} from "../../../../Lib/src/enums/SmallEventBigBadKi
import i18n from "../../translations/i18n";
import {DraftBotIcons} from "../../../../Lib/src/DraftBotIcons";
import {SmallEventBoatAdvicePacket} from "../../../../Lib/src/packets/smallEvents/SmallEventBoatAdvicePacket";
import {
SmallEventGoToPVEIslandAcceptPacket, SmallEventGoToPVEIslandNotEnoughGemsPacket,
SmallEventGoToPVEIslandRefusePacket
} from "../../../../Lib/src/packets/smallEvents/SmallEventGoToPVEIslandPacket";
import {KeycloakUtils} from "../../../../Lib/src/keycloak/KeycloakUtils";
import {keycloakConfig} from "../../bot/DraftBotShard";

function getRandomIntro(language: Language): string {
export function getRandomSmallEventIntro(language: Language): string {
return StringUtils.getRandomTranslation("smallEvents:intro", language);
}

Expand All @@ -21,8 +27,9 @@ export default class SmallEventsHandler {
async smallEventAdvanceTime(socket: WebSocket, packet: SmallEventAdvanceTimePacket, context: PacketContext): Promise<void> {
const interaction = DiscordCache.getInteraction(context.discord!.interaction);
if (interaction) {
const description = getRandomIntro(interaction.userLanguage) + StringUtils.getRandomTranslation("smallEvents:advanceTime.stories", interaction.userLanguage, { time: packet.amount });
await interaction.editReply({ embeds: [new DraftbotSmallEventEmbed("advanceTime", description)]});
const description = getRandomSmallEventIntro(interaction.userLanguage)
+ StringUtils.getRandomTranslation("smallEvents:advanceTime.stories", interaction.userLanguage, { time: packet.amount });
await interaction.editReply({ embeds: [new DraftbotSmallEventEmbed("advanceTime", description, interaction.user, interaction.userLanguage)]});
}
}

Expand All @@ -45,8 +52,8 @@ export default class SmallEventsHandler {
story = "";
}

const description = getRandomIntro(interaction.userLanguage) + story;
await interaction.editReply({embeds: [new DraftbotSmallEventEmbed("bigBad", description)]});
const description = getRandomSmallEventIntro(interaction.userLanguage) + story;
await interaction.editReply({embeds: [new DraftbotSmallEventEmbed("bigBad", description, interaction.user, interaction.userLanguage)]});
}
}

Expand All @@ -59,7 +66,57 @@ export default class SmallEventsHandler {
interaction.userLanguage,
{ advice: StringUtils.getRandomTranslation("smallEvents:boatAdvice.advices", interaction.userLanguage) }
);
await interaction.editReply({ embeds: [new DraftbotSmallEventEmbed("boatAdvice", description)]});
await interaction.editReply({ embeds: [new DraftbotSmallEventEmbed("boatAdvice", description, interaction.user, interaction.userLanguage)]});
}
}

@packetHandler(SmallEventGoToPVEIslandAcceptPacket)
async smallEventGoToPVEIslandAccept(socket: WebSocket, packet: SmallEventGoToPVEIslandAcceptPacket, context: PacketContext): Promise<void> {
const user = (await KeycloakUtils.getUserByKeycloakId(keycloakConfig, context.keycloakId!))!;
const interaction = DiscordCache.getButtonInteraction(context.discord!.buttonInteraction!);
if (interaction) {
await interaction.editReply({ embeds: [
new DraftbotSmallEventEmbed(
"goToPVEIsland",
i18n.t(
packet.alone
? "smallEvents:goToPVEIsland.endStoryAccept"
: "smallEvents:goToPVEIsland.endStoryAcceptWithMember",
{ lng: user.attributes.language[0] }
),
interaction.user,
user.attributes.language[0]
)]});
}
}

@packetHandler(SmallEventGoToPVEIslandRefusePacket)
async smallEventGoToPVEIslandRefuse(socket: WebSocket, packet: SmallEventGoToPVEIslandRefusePacket, context: PacketContext): Promise<void> {
const user = (await KeycloakUtils.getUserByKeycloakId(keycloakConfig, context.keycloakId!))!;
const interaction = DiscordCache.getButtonInteraction(context.discord!.buttonInteraction!);
if (interaction) {
await interaction.editReply({ embeds: [
new DraftbotSmallEventEmbed(
"goToPVEIsland",
i18n.t("smallEvents:goToPVEIsland.endStoryRefuse", { lng: user.attributes.language[0] }),
interaction.user,
user.attributes.language[0]
)]});
}
}

@packetHandler(SmallEventGoToPVEIslandNotEnoughGemsPacket)
async smallEventGoToPVEIslandNotEnoughGems(socket: WebSocket, packet: SmallEventGoToPVEIslandNotEnoughGemsPacket, context: PacketContext): Promise<void> {
const user = (await KeycloakUtils.getUserByKeycloakId(keycloakConfig, context.keycloakId!))!;
const interaction = DiscordCache.getButtonInteraction(context.discord!.buttonInteraction!);
if (interaction) {
await interaction.editReply({ embeds: [
new DraftbotSmallEventEmbed(
"goToPVEIsland",
i18n.t("smallEvents:goToPVEIsland.notEnoughGems", { lng: user.attributes.language[0] }),
interaction.user,
user.attributes.language[0]
)]});
}
}
}
38 changes: 38 additions & 0 deletions Discord/src/smallEvents/goToPVEIsland.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {ReactionCollectorCreationPacket} from "../../../Lib/src/packets/interaction/ReactionCollectorPacket";
import {PacketContext} from "../../../Lib/src/packets/DraftBotPacket";
import {DiscordCache} from "../bot/DiscordCache";
import { ReactionCollectorGoToPVEIslandData } from "../../../Lib/src/packets/interaction/ReactionCollectorGoToPVEIsland";
import i18n from "../translations/i18n";
import {DraftbotSmallEventEmbed} from "../messages/DraftbotSmallEventEmbed";
import {getRandomSmallEventIntro} from "../packetHandlers/handlers/SmallEventsHandler";
import {StringUtils} from "../utils/StringUtils";
import {DiscordCollectorUtils} from "../utils/DiscordCollectorUtils";

export async function goToPVEIslandCollector(packet: ReactionCollectorCreationPacket, context: PacketContext): Promise<void> {
const interaction = DiscordCache.getInteraction(context.discord!.interaction)!;
const data = packet.data.data as ReactionCollectorGoToPVEIslandData;

const embed = new DraftbotSmallEventEmbed(
"goToPVEIsland",
getRandomSmallEventIntro(interaction.userLanguage)
+ StringUtils.getRandomTranslation(
"smallEvents:goToPVEIsland.stories",
interaction.userLanguage,
{
priceText: data.price === 0
? i18n.t("smallEvents:goToPVEIsland.priceFree", { lng: interaction.userLanguage })
: i18n.t("smallEvents:goToPVEIsland.priceMoney", { lng: interaction.userLanguage, price: data.price })
}
)
+ "\n\n"
+ i18n.t("smallEvents:goToPVEIsland.confirm", {
lng: interaction.userLanguage,
fightPoints: data.energy.current,
fightPointsMax: data.energy.max
}),
interaction.user,
interaction.userLanguage
);

await DiscordCollectorUtils.createAcceptRefuseCollector(interaction, embed, packet, context);
}
Loading
Loading