@@ -2,9 +2,10 @@ import type { BotContext } from "@/context.js";
22
33import * as time from "@/utils/time.js" ;
44import * as lootService from "@/service/loot.js" ;
5- import { LootAttributeKindId , LootKindId } from "@/service/lootData.js" ;
5+ import { LootAttributeKindId , LootKindId , resolveLootTemplate } from "@/service/lootData.js" ;
66import log from "@log" ;
77import { randomEntry } from "@/service/random.js" ;
8+ import { Snowflake , userMention } from "discord.js" ;
89
910export async function degradeItems ( _context : BotContext ) {
1011 log . info ( "Degrading loot items" ) ;
@@ -81,3 +82,70 @@ export async function exposeWithRadiation(context: BotContext) {
8182 ] ,
8283 } ) ;
8384}
85+
86+ export async function runHalfLife ( context : BotContext ) {
87+ log . info ( "Running half life" ) ;
88+
89+ const allWaste = await lootService . getLootsByKindId ( LootKindId . RADIOACTIVE_WASTE ) ;
90+
91+ // See: https://github.com/NullDev/CSZ-Bot/issues/470
92+ // We don't do /2 straigt away, so we can roll this out more slowly initially. We can increase this to 2 once we got this number down in general
93+ // Also, consider aligning this with the drop rate of radioactive waste, so we have that balanced
94+ const targetWasteCount = Math . ceil ( allWaste . length / 1.1 ) ;
95+
96+ if ( targetWasteCount >= allWaste . length ) {
97+ return ;
98+ }
99+
100+ const wasteToRemove = allWaste . sort ( ( a , b ) => Math . random ( ) ) . slice ( targetWasteCount ) ;
101+ if ( wasteToRemove . length === 0 ) {
102+ return ;
103+ }
104+
105+ const leadTemplate = resolveLootTemplate ( LootKindId . BLEI ) ;
106+ if ( ! leadTemplate ) {
107+ log . error ( "Could not resolve loot template for lead." ) ;
108+ return ;
109+ }
110+
111+ const replacedStats = new Map < Snowflake , number > ( ) ;
112+
113+ for ( const l of wasteToRemove ) {
114+ const replaced = await lootService . replaceLoot (
115+ l . id ,
116+ {
117+ displayName : leadTemplate . displayName ,
118+ description : leadTemplate . infoDescription ?? leadTemplate . dropDescription ,
119+ lootKindId : leadTemplate . id ,
120+ usedImage : leadTemplate . asset ,
121+ winnerId : l . winnerId ,
122+ claimedAt : l . claimedAt ,
123+ guildId : l . guildId ,
124+ channelId : l . channelId ,
125+ messageId : l . messageId ,
126+ origin : "replacement" ,
127+ } ,
128+ true ,
129+ ) ;
130+
131+ replacedStats . set ( replaced . winnerId , replacedStats . getOrInsert ( replaced . winnerId , 0 ) + 1 ) ;
132+ }
133+
134+ const listFormatter = new Intl . ListFormat ( "de" , {
135+ style : "short" ,
136+ type : "conjunction" ,
137+ } ) ;
138+
139+ const decayStats = replacedStats
140+ . entries ( )
141+ . toArray ( )
142+ . map ( ( [ user , count ] ) => `${ count } x von <@${ user } >` ) ;
143+
144+ await context . textChannels . hauptchat . send ( {
145+ embeds : [
146+ {
147+ description : `:radioactive: Der Müll ${ decayStats . length === 1 ? "eines Users" : "einiger User" } ist zu einem Stück Blei zerfallen: ${ listFormatter . format ( decayStats ) } . :radioactive:` ,
148+ } ,
149+ ] ,
150+ } ) ;
151+ }
0 commit comments