1+ from typing import Callable
2+
13from discord import Embed , Interaction , app_commands
24from discord .ext .commands import GroupCog
35from humanize import intcomma
46from tabulate import WIDE_CHARS_MODE , tabulate
57
68from bot .main import ActBot
79from bot .ui import EmbedX
8- from db .item import Item
10+ from db .actor import Actor
11+ from db .item import ITEMS , Item , ItemStack , ItemType
12+ from utils .misc import numsign
913
1014
1115def add_preview_notice (embed : Embed ):
@@ -27,107 +31,139 @@ def add_preview_notice(embed: Embed):
2731class InventoryCog (
2832 GroupCog , group_name = "items" , description = "Allows players to use items."
2933):
30- ITEMS : list [Item ]
3134 BUYABLE_ITEMS : list [Item ]
3235
3336 def __init__ (self , bot : ActBot ):
3437 self .bot = bot
35- self .ITEMS = list ( bot . get_db (). find ( Item ))
36- self .BUYABLE_ITEMS = [ item for item in self .ITEMS if item . is_buyable == True ]
37- self .buy .autocomplete ("item_id" )(self .item_autocomplete )
38- self .view .autocomplete ("item_id" )(self .item_autocomplete )
38+ self .BUYABLE_ITEMS = [ item for item in ITEMS if item . is_buyable == True ]
39+ self .buy . autocomplete ( "item_id" )( self .buyable_items_autocomplete )
40+ self .store .autocomplete ("item_id" )(self .buyable_items_autocomplete )
41+ self .equip .autocomplete ("item_id" )(self .actor_equippable_items_autocomplete )
3942
4043 # ----------------------------------------------------------------------------------------------------
4144
4245 @app_commands .guild_only ()
4346 @app_commands .command (description = "View your items or another member's items" )
4447 async def bag (self , interaction : Interaction ):
45- await interaction .response .send_message (
46- embed = EmbedX .info (
47- emoji = "🎒" ,
48- title = "Inventory" ,
49- description = "🐵 Abducted Monkey **x 3**" ,
48+ embed = EmbedX .info (emoji = "🎒" , title = "Inventory" )
49+ actor = self .bot .get_db (interaction .guild ).find_one (
50+ Actor , Actor .id == interaction .user .id
51+ ) or self .bot .create_actor (interaction .user )
52+
53+ item_stacks = actor .item_stacks
54+ if item_stacks :
55+ midpoint = len (item_stacks ) // 2
56+ item_stack_row : Callable [[ItemStack ], str ] = lambda item_stack : (
57+ f"{ item_stack .item .emoji } **{ item_stack .item .name } `{ item_stack .quantity } `**"
5058 )
51- )
59+ first_column = [
60+ item_stack_row (item_stack ) for item_stack in item_stacks [:midpoint ]
61+ ]
62+ second_column = [
63+ item_stack_row (item_stack ) for item_stack in item_stacks [midpoint :]
64+ ]
65+ embed .add_field (name = "" , value = "\n " .join (first_column ), inline = True )
66+ embed .add_field (name = "" , value = "\n " .join (second_column ), inline = True )
67+ else :
68+ embed .add_field (name = "" , value = "_No items_" )
69+
70+ equipped_items = actor .equipped_items
71+ embed .add_field (name = "Equipment" , value = "" , inline = False )
72+ if equipped_items :
73+ midpoint = len (item_stacks ) // 2
74+ equipped_item_row : Callable [[Item ], str ] = lambda item : (
75+ f"{ item .alt_emoji } **{ item .name } **"
76+ )
77+ first_column = [
78+ equipped_item_row (item ) for item in equipped_items [:midpoint ]
79+ ]
80+ second_column = [
81+ equipped_item_row (item ) for item in equipped_items [midpoint :]
82+ ]
83+ embed .add_field (name = "" , value = "\n " .join (first_column ), inline = True )
84+ embed .add_field (name = "" , value = "\n " .join (second_column ), inline = True )
85+ else :
86+ embed .add_field (name = "" , value = "_No items_" )
5287
53- @app_commands .guild_only ()
54- @app_commands .command (description = "View purchasable items" )
55- async def store (self , interaction : Interaction ):
56- # store_items = [
57- # f"{item.emoji} **{item.name}** : 💰 **{item.price}** Gold"
58- # for item in self.BUYABLE_ITEMS
59- # ]
60- embed = EmbedX .info (emoji = "🏬" , title = "Store" )
61- items_column = []
62- prices_column = []
63-
64- for item in self .BUYABLE_ITEMS :
65- items_column .append (f"{ item .emoji } **{ item .name } **" )
66- prices_column .append (f"**`💰{ intcomma (item .price )} `**" )
67- embed .add_field (name = "Item" , value = "\n " .join (items_column ))
68- embed .add_field (name = "Price" , value = "\n " .join (prices_column ))
69- url = "https://cdn.discordapp.com/attachments/1349262615431483473/1349272946555748372/store.png?ex=67d27fda&is=67d12e5a&hm=29365e671148a9996341f92b1d34a1f7004e642478e1b6249f0d13b5d7a8c051&"
70- # embed.set_image(url=url)
71- embed .set_thumbnail (url = url )
72- embed .add_field (
73- name = "Command" ,
74- value = f"👁 `/{ self .view .qualified_name } `\n "
75- f"💳 `/{ self .buy .qualified_name } `" ,
76- inline = False ,
77- )
7888 await interaction .response .send_message (embed = embed )
7989
8090 @app_commands .guild_only ()
81- @app_commands .command (description = "View an item information " )
91+ @app_commands .command (description = "View purchasable items " )
8292 @app_commands .rename (item_id = "item" )
8393 @app_commands .describe (item_id = "Choose item you wish to view" )
84- async def view (self , interaction : Interaction , item_id : str ):
85- item = next ((item for item in self .BUYABLE_ITEMS if item .id == item_id ), None )
86- if not item :
87- await interaction .response .send_message (
88- embed = EmbedX .error (f"Invalid **item** input: `{ item_id } `\n " ),
89- ephemeral = True ,
90- )
91- return
92- embed = EmbedX .info (
93- emoji = item .emoji ,
94- title = item .name ,
95- description = item .description ,
96- )
97- embed .add_field (name = "Price" , value = f"💰 **{ intcomma (item .price )} **" )
98- if item .health_bonus :
99- embed .add_field (
100- name = "Health" ,
101- value = f":heart: +**{ intcomma (item .health_bonus )} **" ,
102- )
103- if item .energy_bonus :
104- embed .add_field (
105- name = "Energy" ,
106- value = f"⚡ +**{ intcomma (item .energy_bonus )} **" ,
107- )
108- if item .max_health_bonus :
109- embed .add_field (
110- name = "Max Health" ,
111- value = f":heart: +**{ intcomma (item .max_health_bonus )} **" ,
112- )
113- if item .max_energy_bonus :
114- embed .add_field (
115- name = "Max Energy" ,
116- value = f"⚡ +**{ intcomma (item .max_energy_bonus )} **" ,
94+ async def store (self , interaction : Interaction , item_id : str = "" ):
95+ if item_id :
96+ item = next (
97+ (item for item in self .BUYABLE_ITEMS if item .id == item_id ), None
11798 )
118- if item .attack_bonus :
119- embed .add_field (
120- name = "Attack" ,
121- value = f":crossed_swords: +**{ intcomma (item .attack_bonus )} **" ,
99+ if not item :
100+ await interaction .response .send_message (
101+ embed = EmbedX .error (f"Invalid **item** input: `{ item_id } `\n " ),
102+ ephemeral = True ,
103+ )
104+ return
105+ embed = EmbedX .info (
106+ emoji = item .alt_emoji ,
107+ title = item .name ,
108+ description = item .description ,
122109 )
123- if item .defense_bonus :
110+ embed .add_field (name = "Price" , value = f"💰 **{ intcomma (item .price )} **" )
111+ if item .health_bonus :
112+ embed .add_field (
113+ name = "Health" ,
114+ value = f":heart: **{ numsign (intcomma (item .health_bonus ))} **" ,
115+ )
116+ if item .energy_bonus :
117+ embed .add_field (
118+ name = "Energy" ,
119+ value = f"⚡ **{ numsign (intcomma (item .energy_bonus ))} **" ,
120+ )
121+ if item .max_health_bonus :
122+ embed .add_field (
123+ name = "Max Health" ,
124+ value = f":heart: **{ numsign (intcomma (item .max_health_bonus ))} **" ,
125+ )
126+ if item .max_energy_bonus :
127+ embed .add_field (
128+ name = "Max Energy" ,
129+ value = f"⚡ **{ numsign (intcomma (item .max_energy_bonus ))} **" ,
130+ )
131+ if item .attack_bonus :
132+ embed .add_field (
133+ name = "Attack" ,
134+ value = f":crossed_swords: **{ numsign (intcomma (item .attack_bonus ))} **" ,
135+ )
136+ if item .defense_bonus :
137+ embed .add_field (
138+ name = "Defense" ,
139+ value = f"🛡 **{ numsign (intcomma (item .defense_bonus ))} **" ,
140+ )
141+ if item .speed_bonus :
142+ embed .add_field (
143+ name = "Speed" , value = f"🥾 **{ numsign (intcomma (item .speed_bonus ))} **"
144+ )
145+ embed .set_thumbnail (url = item .icon_url )
146+ await interaction .response .send_message (embed = embed )
147+ else :
148+ embed = EmbedX .info (emoji = "🏬" , title = "Store" )
149+ items = self .BUYABLE_ITEMS
150+ if items :
151+ midpoint = len (items ) // 2
152+ row : Callable [[Item ], str ] = (
153+ lambda item : f"{ item .emoji or item .alt_emoji } **{ item .name } `💰{ intcomma (item .price )} `**"
154+ )
155+ first_column = [row (item ) for item in items [:midpoint ]]
156+ second_column = [row (item ) for item in items [midpoint :]]
157+ embed .add_field (name = "" , value = "\n " .join (first_column ))
158+ embed .add_field (name = "" , value = "\n " .join (second_column ))
159+ else :
160+ embed .add_field (name = "" , value = "_No items_" )
124161 embed .add_field (
125- name = "Defense" , value = f"🛡 +**{ intcomma (item .defense_bonus )} **"
162+ name = "Buy" ,
163+ value = f"🛒 `/{ self .buy .qualified_name } `" ,
164+ inline = False ,
126165 )
127- if item .speed_bonus :
128- embed .add_field (name = "Speed" , value = f"🥾 +**{ intcomma (item .speed_bonus )} **" )
129- embed .set_thumbnail (url = item .icon_url )
130- await interaction .response .send_message (embed = embed )
166+ await interaction .response .send_message (embed = embed )
131167
132168 @app_commands .guild_only ()
133169 @app_commands .guild_only ()
@@ -150,11 +186,11 @@ async def buy(self, interaction: Interaction, item_id: str, quantity: int = 1):
150186 embed = EmbedX .success (
151187 emoji = "🛒" ,
152188 title = "Purchase" ,
153- description = f"{ member .mention } purchased **{ quantity } ** x { item .emoji } **{ item .name } ** for 💰 **{ total_price } **." ,
189+ description = f"{ member .mention } purchased **{ quantity } ** x { item .alt_emoji } **{ item .name } ** for 💰 **{ total_price } **." ,
154190 )
155191 embed .set_author (name = member .display_name , icon_url = member .display_avatar )
156192 embed .set_thumbnail (url = item .icon_url )
157- await interaction .response .send_message (embed = embed )
193+ await interaction .response .send_message (embed = add_preview_notice ( embed ) )
158194
159195 @app_commands .guild_only ()
160196 @app_commands .command (description = "Equip an equippable item" )
@@ -184,12 +220,12 @@ async def use(self, interaction: Interaction, item: str):
184220
185221 # ----------------------------------------------------------------------------------------------------
186222
187- async def item_autocomplete (
223+ async def buyable_items_autocomplete (
188224 self , interaction : Interaction , current : str
189225 ) -> list [app_commands .Choice [str ]]:
190226 return [
191227 app_commands .Choice (
192- name = f"{ item .emoji } { item .name } ― 💰{ intcomma (item .price )} " ,
228+ name = f"{ item .alt_emoji } { item .name } ― 💰{ intcomma (item .price )} " ,
193229 value = item .id ,
194230 )
195231 for item in [
@@ -198,3 +234,22 @@ async def item_autocomplete(
198234 if current .lower () in item .name .lower ()
199235 ][:25 ]
200236 ]
237+
238+ async def actor_equippable_items_autocomplete (
239+ self , interaction : Interaction , current : str
240+ ) -> list [app_commands .Choice [str ]]:
241+ actor = self .bot .get_db (interaction .guild ).find_one (
242+ Actor , Actor .id == interaction .user .id
243+ ) or self .bot .create_actor (interaction .user )
244+ return [
245+ app_commands .Choice (
246+ name = f"{ item .alt_emoji } { item .name } " ,
247+ value = item .id ,
248+ )
249+ for item in [
250+ item_stack .item
251+ for item_stack in actor .item_stacks
252+ if item_stack .item .type == ItemType .EQUIPPABLE
253+ and current .lower () in item_stack .item .name .lower ()
254+ ][:25 ]
255+ ]
0 commit comments