def embed(state: LeaderSkillViewState): lls = state.l_mon.leader_skill rls = state.r_mon.leader_skill return EmbedView(embed_main=EmbedMain( title=ls_multiplier_text(lls, rls), description=Box( BoldText( MonsterHeader.name(state.l_mon, link=True, show_jp=True)), Text(lls.desc if lls else 'None'), BoldText( MonsterHeader.name(state.r_mon, link=True, show_jp=True)), Text(rls.desc if rls else 'None')), color=state.color), embed_footer=embed_footer_with_state(state))
def embed(cls, state: IdViewState): m = state.monster fields = [ EmbedField( '/'.join(['{}'.format(t.name) for t in m.types]), Box(IdView.all_awakenings_row(m, state.transform_base), IdView.killers_row(m, state.transform_base))), EmbedField( 'Inheritable' if m.is_inheritable else 'Not inheritable', IdView.misc_info(m, state.true_evo_type_raw, state.acquire_raw, state.base_rarity), inline=True), EmbedField(IdView.stats_header(m).to_markdown(), IdView.stats(m), inline=True), EmbedField( IdView.active_skill_header(m, state.transform_base).to_markdown(), Text(m.active_skill.desc if m.active_skill else 'None')), EmbedField( IdView.leader_skill_header(m).to_markdown(), Text(m.leader_skill.desc if m.leader_skill else 'None')), evos_embed_field(state) ] return EmbedView(EmbedMain(color=state.color, title=MonsterHeader.long_maybe_tsubaki( m, state.alt_monsters[0].monster.monster_id == cls.TSUBAKI).to_markdown(), url=puzzledragonx(m)), embed_thumbnail=EmbedThumbnail(MonsterImage.icon(m)), embed_footer=embed_footer_with_state(state), embed_fields=fields)
def invalid_monster_text(query: str, monster: "MonsterModel", append_text: str, link: bool = False): monster_name = MonsterHeader.short_with_emoji(monster, link=link).to_markdown() return f'Your query `{query}` found {monster_name}{append_text}.'
def embed(m: "MonsterModel", color): return EmbedView(EmbedMain( color=color, title=MonsterHeader.long_v2(m).to_markdown(), description=LinksView.linksbox(m), url=puzzledragonx(m)), embed_thumbnail=EmbedThumbnail(MonsterImage.icon(m)))
def embed(state: PicViewState): url = MonsterImage.picture(state.monster) animated = state.monster.has_animation fields = [ EmbedField( 'Extra Links', Box( Box(Text('Animation:'), LinkedText('(MP4)', MonsterImage.video(state.monster)), Text('|'), LinkedText('(GIF)', MonsterImage.gif(state.monster)), delimiter=' ') if animated else None, Box(Text('Orb Skin:'), LinkedText('Regular', MonsterImage.orb_skin(state.monster)), Text('|'), LinkedText( 'Color Blind', MonsterImage.orb_skin_colorblind(state.monster)), delimiter=' ') if state.monster.orb_skin_id else None, )) ] return EmbedView( EmbedMain(color=state.color, title=MonsterHeader.long_v2(state.monster).to_markdown(), url=puzzledragonx(state.monster)), embed_footer=pad_info_footer_with_state(state), embed_fields=fields, embed_body_image=EmbedBodyImage(url), )
def embed(state: MaterialsViewState): # m: "MonsterModel", color, mats, usedin, gemid, gemusedin, skillups, skillup_evo_count, link return EmbedView( EmbedMain(color=state.color, title=MonsterHeader.long_v2(state.monster).to_markdown(), url=puzzledragonx(state.monster)), embed_thumbnail=EmbedThumbnail(MonsterImage.icon(state.monster)), embed_footer=pad_info_footer_with_state(state), embed_fields=[ f for f in [ mat_use_field(state.mats, "Evo materials") if state.mats or not (state.monster.is_stackable or state.gem_override) else None, mat_use_field(state.usedin, "Material for", 10 ) if state.usedin else None, mat_use_field( state.gemusedin, "Evo gem ({}) is mat for". format(state.gemid), 10 if state.gem_override else 5 ) if state.gemusedin else None, skillup_field(state.skillups, state. skillup_evo_count, state.link) if not (state.monster.is_stackable or state.gem_override ) else None ] if f is not None ])
def _monster_list(monsters): if not len(monsters): return [] return [ MonsterHeader.short_with_emoji(mon, link=True, prefix=char_to_emoji(i)) for i, mon in enumerate(monsters) ]
def _monster_list(monsters): if not len(monsters): return [] return [ MonsterHeader.short_with_emoji(mon, link=True) for mon in sorted(monsters, key=lambda x: int(x.monster_id)) ]
def embed(cls, state: EvosViewState): fields = [ EmbedField( ("{} evolution" if len(state.alt_versions) == 1 else "{} evolutions").format(len(state.alt_versions)), Box(*EvosView._evo_lines(state.alt_versions, state.monster))) ] if state.gem_versions: fields.append( EmbedField( ("{} evolve gem" if len(state.gem_versions) == 1 else "{} evolve gems").format(len(state.gem_versions)), Box(*EvosView._evo_lines(state.gem_versions, state.monster)))) return EmbedView(EmbedMain(color=state.color, title=MonsterHeader.long_maybe_tsubaki( state.monster, state.alt_monsters[0].monster.monster_id == cls.TSUBAKI).to_markdown(), url=puzzledragonx(state.monster)), embed_thumbnail=EmbedThumbnail( MonsterImage.icon(state.monster)), embed_footer=embed_footer_with_state(state), embed_fields=fields)
def _pantheon_lines(monsters, base_monster): if not len(monsters): return [] return [ MonsterHeader.short_with_emoji(mon, link=mon.monster_id != base_monster.monster_id) for mon in sorted(monsters, key=lambda x: int(x.monster_id)) ]
def _evo_lines(monsters, current_monster): if not len(monsters): return [] return [ MonsterHeader.short_with_emoji(ae, link=ae.monster_id != current_monster.monster_id) for ae in sorted(monsters, key=lambda x: int(x.monster_id)) ]
def embed(cls, state: TransformInfoViewState): base_mon = state.base_mon transformed_mon = state.transformed_mon lsmultiplier = state.query_settings.lsmultiplier fields = [ EmbedField( '/'.join(['{}'.format(t.name) for t in transformed_mon.types]), Box( Box(get_emoji(cls.up_emoji_name), cls.normal_awakenings_row(transformed_mon) if len(transformed_mon.awakenings) != 0 else Box( Text('No Awakenings')), delimiter=' '), TransformInfoView.base_info(base_mon), cls.killers_row(base_mon, base_mon)), ), EmbedField(BoldText(transformat('Card info')), TransformInfoView.card_info(base_mon, transformed_mon, state.acquire_raw), inline=True), EmbedField(BoldText('Stats -> ' + transformat('Transform')), TransformInfoView.stats(base_mon, transformed_mon), inline=True), EmbedField( transformat( TransformInfoView.transform_active_header( transformed_mon).to_markdown()), Box( Text( cls.active_skill_text(transformed_mon.active_skill, state.awoken_skill_map)), TransformInfoView.base_active_header( base_mon).to_markdown(), Text( cls.active_skill_text(base_mon.active_skill, state.awoken_skill_map)))), EmbedField( transformat( TransformInfoView.leader_header(transformed_mon, False, lsmultiplier, base_mon).to_markdown()), Box( Text(transformed_mon.leader_skill.desc if transformed_mon. leader_skill else 'None'), TransformInfoView.leader_header(base_mon, True, lsmultiplier, base_mon).to_markdown(), Text(base_mon.leader_skill.desc if base_mon. leader_skill else 'None'))) ] return EmbedView(EmbedMain(color=state.color, title=MonsterHeader.fmt_id_header( transformed_mon, False, state.is_jp_buffed).to_markdown(), url=puzzledragonx(transformed_mon)), embed_thumbnail=EmbedThumbnail( MonsterImage.icon(transformed_mon)), embed_footer=embed_footer_with_state(state), embed_fields=fields)
def mat_use_field(mons, title, max_mons=MAX_MONS_TO_SHOW): text = None if len(mons) == 0: text = "None" elif len(mons) > max_mons: text = f"({len(mons) - max_mons} more monster{'s' if len(mons) - max_mons > 1 else ''})" return EmbedField( title, Box(*(MonsterHeader.short_with_emoji(em) for em in mons[:max_mons]), text))
def _monster_list(monsters, current_index): if not len(monsters): return [] return [ MonsterHeader.short_with_emoji(mon, link=SeriesScrollView._is_linked( i, current_index), prefix=char_to_emoji(str(i))) for i, mon in enumerate(monsters) ]
def embed(state: PantheonViewState): fields = [ EmbedField( 'Pantheon: {}'.format(state.series_name), Box(*[ MonsterHeader.short_with_emoji(m) for m in sorted(state.pantheon_list, key=lambda x: x.monster_no_na) ])) ] return EmbedView( EmbedMain(color=state.color, title=MonsterHeader.long_v2(state.monster).to_markdown(), url=puzzledragonx(state.monster)), embed_footer=pad_info_footer_with_state(state), embed_fields=fields, embed_thumbnail=EmbedThumbnail(MonsterImage.icon(state.monster)), )
def embed(state: LeaderSkillSingleViewState): ls = state.mon.leader_skill return EmbedView( embed_main=EmbedMain( title=createSingleMultiplierText(ls), description=Box( BoldText(MonsterHeader.name(state.mon, link=True, show_jp=True)), Text(ls.desc if ls else 'None')), color=state.color), embed_footer=embed_footer_with_state(state))
def monster_list(cls, monsters: List["MonsterModel"], current_monster_id: int): if not len(monsters): return [] return [ MonsterHeader.short_with_emoji(mon, link=True, prefix=cls.get_emoji( i, current_monster_id)) for i, mon in enumerate(monsters) ]
def embed(state, props: IdTracebackViewProps): return EmbedView( EmbedMain( color=state.color, title=MonsterHeader.fmt_id_header(props.monster, use_emoji=True), description=get_description(props.score) ), embed_fields=[ EmbedField('Matched Name Tokens', Box(props.name_tokens)), EmbedField('Matched Modifier Tokens', Box(props.modifier_tokens)), EmbedField('Equally-scoring matches', Box(props.lower_priority_monsters)), ], embed_footer=embed_footer_with_state(state), )
def embed(state: TransformInfoViewState): base_mon = state.base_mon transformed_mon = state.transformed_mon fields = [ EmbedField( '/'.join(['{}'.format(t.name) for t in transformed_mon.types]), Box( Box(TRANSFORM_EMOJI, IdView.normal_awakenings_row(transformed_mon) if len(transformed_mon.awakenings) != 0 else Box( Text('No Awakenings')), delimiter=' '), base_info(base_mon), IdView.killers_row(base_mon, base_mon)), ), EmbedField(BoldText(transformat('Card info')), card_info(base_mon, transformed_mon, state.acquire_raw), inline=True), EmbedField(BoldText('Stats -> ' + transformat('Transform')), stats(base_mon, transformed_mon), inline=True), EmbedField( transformat( transform_active_header(transformed_mon).to_markdown()), Box( Text(transformed_mon.active_skill.desc if transformed_mon. active_skill else 'None'), base_active_header(base_mon).to_markdown(), Text(base_mon.active_skill.desc if base_mon. active_skill else 'None'))), EmbedField( transformat( leader_header(transformed_mon, False).to_markdown()), Box( Text(transformed_mon.leader_skill.desc if transformed_mon. leader_skill else 'None'), leader_header(base_mon, True).to_markdown(), Text(base_mon.leader_skill.desc if base_mon. leader_skill else 'None'))) ] return EmbedView(EmbedMain( color=state.color, title=MonsterHeader.long_v2(transformed_mon).to_markdown(), url=puzzledragonx(transformed_mon)), embed_thumbnail=EmbedThumbnail( MonsterImage.icon(transformed_mon)), embed_footer=embed_footer_with_state(state), embed_fields=fields)
def embed(cls, state: OtherInfoViewState): m: "MonsterModel" = state.monster return EmbedView( EmbedMain( color=state.color, title=MonsterHeader.fmt_id_header( state.monster, state.alt_monsters[0].monster.monster_id == cls.TSUBAKI, state.is_jp_buffed).to_markdown(), url=puzzledragonx(m)), embed_footer=embed_footer_with_state(state), embed_fields=[ EmbedField( "Stats at +297:", Box( # need to put these on the same line to get around discord's insane # whitespace margins around code blocks Text(statsbox(m, plus=297) + 'Stats at +0:'), Text(statsbox(m, plus=0)), LabeledText("JP Name", m.name_ja), LinksView.linksbox(m), LabeledText("JP Added", str(m.reg_date)) if m.reg_date else None, LabeledText("Series", m.series.name_en), Box(LabeledText("Sell MP", '{:,}'.format(m.sell_mp)), LabeledText("Buy MP", '{:,}'.format(m.buy_mp)) if m.buy_mp else None, delimiter=' '), Box( LabeledText("Sell Gold", '{:,}'.format(m.sell_gold))), Box(LabeledText( "XP to Max", '{:.1f}'.format(m.exp / 1000000).rstrip('0').rstrip('.') + 'M' if m.exp >= 1000000 else '{:,}'.format(m.exp)), LabeledText("Max Level", str(m.level)), delimiter=' '), Box(LabeledText("Weighted Stats", str(m.stats()[3])), Text('LB {} (+{}%)'.format( m.stats(lv=110)[3], m.limit_mult)) if m.limit_mult > 0 else None, delimiter=' | '), LabeledText("Fodder EXP", '{:,}'.format(m.fodder_exp)), Box(LabeledText("Rarity", str(m.rarity)), LabeledText("Cost", str(m.cost)), delimiter=' '))), cls.evos_embed_field(state) ])
def embed(state, props: AwakeningHelpViewProps): monster = props.monster fields = [ EmbedField('Normal Awakenings', get_normal_awakenings(monster)), EmbedField('Super Awakenings', get_super_awakenings(monster)) ] return EmbedView( EmbedMain(color=state.color, description='This monster has no awakenings.' if not monster.awakenings else ''), embed_author=EmbedAuthor( MonsterHeader.long_v2(monster).to_markdown(), puzzledragonx(monster), MonsterImage.icon(monster)), embed_footer=embed_footer_with_state(state), embed_fields=fields)
def embed(state: IdViewState): m = state.monster fields = [ EmbedField( '/'.join(['{}'.format(t.name) for t in m.types]), Box( IdView.all_awakenings_row(m), IdView.killers_row(m, state.transform_base) ) ), EmbedField( 'Inheritable' if m.is_inheritable else 'Not inheritable', IdView.misc_info(m, state.true_evo_type_raw, state.acquire_raw, state.base_rarity), inline=True ), EmbedField( IdView.stats_header(m).to_markdown(), IdView.stats(m), inline=True ), EmbedField( IdView.active_skill_header(m).to_markdown(), Text(m.active_skill.desc if m.active_skill else 'None') ), EmbedField( IdView.leader_skill_header(m).to_markdown(), Text(m.leader_skill.desc if m.leader_skill else 'None') ), EmbedField( "Alternate Evos", HighlightableLinks( links=[LinkedText(str(m.monster_no_na), puzzledragonx(m)) for m in state.alt_monsters], highlighted=next(i for i, mon in enumerate(state.alt_monsters) if m.monster_id == mon.monster_id) ) ) ] return EmbedView( EmbedMain( color=state.color, title=MonsterHeader.long_v2(m).to_markdown(), url=puzzledragonx(m)), embed_thumbnail=EmbedThumbnail(MonsterImage.icon(m)), embed_footer=pad_info_footer_with_state(state), embed_fields=fields)
def embed(cls, state: PantheonViewState): fields = [EmbedField( 'Pantheon: {}'.format(state.series_name), Box(*_pantheon_lines(state.pantheon_list, state.base_monster)) ), evos_embed_field(state)] return EmbedView( EmbedMain( color=state.color, title=MonsterHeader.long_maybe_tsubaki(state.monster, state.alt_monsters[0].monster.monster_id == cls.TSUBAKI ).to_markdown(), url=puzzledragonx(state.monster)), embed_footer=embed_footer_with_state(state), embed_fields=fields, embed_thumbnail=EmbedThumbnail(MonsterImage.icon(state.monster)), )
def skillup_field(mons, sec, link): text = None text2 = None if len(mons) == 0: text = "None" if sec: text2 = Box( f"({max(len(mons) - MAX_MONS_TO_SHOW, 0) + sec} ", LinkedText(f"more monster{'s' if max(len(mons) - MAX_MONS_TO_SHOW, 0) + sec > 1 else ''}", link), f", incl. {sec} alt evo{'s' if sec > 1 else ''})", delimiter="") elif len(mons) > MAX_MONS_TO_SHOW: text2 = f"({len(mons) - MAX_MONS_TO_SHOW} more monsters)" return EmbedField( "Skillups", Box(*(MonsterHeader.short_with_emoji(em) for em in mons[:MAX_MONS_TO_SHOW]), text, text2))
def embed(cls, state: OtherInfoViewState): m: "MonsterModel" = state.monster return EmbedView( EmbedMain(color=state.color, title=MonsterHeader.long_maybe_tsubaki( state.monster, state.alt_monsters[0].monster.monster_id == cls.TSUBAKI).to_markdown(), url=puzzledragonx(m)), embed_footer=embed_footer_with_state(state), embed_fields=[ EmbedField( "Stats at +297:", Box( Text(statsbox(m)), LabeledText("JP Name", m.name_ja), LinksView.linksbox(m), LabeledText("History", m.history_us) if m.history_us else None, LabeledText("Series", m.series.name_en), Box(LabeledText("Sell MP", '{:,}'.format(m.sell_mp)), LabeledText("Buy MP", '{:,}'.format(m.buy_mp)) if m.buy_mp else None, delimiter=' '), Box(LabeledText( "XP to Max", '{:.1f}'.format(m.exp / 1000000).rstrip('0').rstrip('.') + 'M' if m.exp >= 1000000 else '{:,}'.format(m.exp)), LabeledText("Max Level", str(m.level)), delimiter=' '), Box(LabeledText("Weighted Stats", str(m.stats()[3])), Text('LB {} (+{}%)'.format( m.stats(lv=110)[3], m.limit_mult)) if m.limit_mult > 0 else None, delimiter=' | '), LabeledText("Fodder EXP", '{:,}'.format(m.fodder_exp)), Box(LabeledText("Rarity", str(m.rarity)), LabeledText("Cost", str(m.cost)), delimiter=' '))), evos_embed_field(state) ])
def embed(state: TransformInfoViewState): base_mon = state.base_mon transformed_mon = state.transformed_mon fields = [ EmbedField( '/'.join(['{}'.format(t.name) for t in transformed_mon.types]), Box( IdView.normal_awakenings_row(transformed_mon) if len(transformed_mon.awakenings) != 0 else Box( Text('No Awakenings')), base_info(base_mon)), ), EmbedField('Card info', IdView.misc_info(transformed_mon, state.true_evo_type_raw, state.acquire_raw, state.base_rarity), inline=True), EmbedField(IdView.stats_header(transformed_mon).to_markdown(), IdView.stats(transformed_mon), inline=True), EmbedField( IdView.active_skill_header(transformed_mon).to_markdown() + base_skill(base_mon), Text(transformed_mon.active_skill.desc if transformed_mon. active_skill else 'None')), EmbedField( IdView.leader_skill_header(transformed_mon).to_markdown(), Text(transformed_mon.leader_skill.desc if transformed_mon. leader_skill else 'None')) ] return EmbedView(EmbedMain( color=state.color, title=MonsterHeader.long_v2(transformed_mon).to_markdown(), url=puzzledragonx(transformed_mon)), embed_thumbnail=EmbedThumbnail( MonsterImage.icon(transformed_mon)), embed_footer=pad_info_footer_with_state(state), embed_fields=fields)
def embed(cls, state: IdViewState): m = state.monster fields = [ EmbedField( '/'.join(['{}'.format(t.name) for t in m.types]), Box(IdView.all_awakenings_row(m, state.transform_base), cls.killers_row(m, state.transform_base))), EmbedField( 'Inheritable' if m.is_inheritable else 'Not inheritable', IdView.misc_info(m, state.true_evo_type_raw, state.acquire_raw, state.base_rarity), inline=True), EmbedField(IdView.stats_header(m, state.previous_evolutions, state.query_settings).to_markdown(), IdView.stats(m, state.previous_evolutions, state.query_settings), inline=True), EmbedField( cls.active_skill_header( m, state.previous_transforms).to_markdown(), Text( cls.active_skill_text(m.active_skill, state.awoken_skill_map))), EmbedField( cls.leader_skill_header(m, state.query_settings.lsmultiplier, state.transform_base).to_markdown(), Text(m.leader_skill.desc if m.leader_skill else 'None')), cls.evos_embed_field(state) ] return EmbedView(EmbedMain( color=state.color, title=MonsterHeader.fmt_id_header( m, state.alt_monsters[0].monster.monster_id == cls.TSUBAKI, state.is_jp_buffed).to_markdown(), url=puzzledragonx(m)), embed_thumbnail=EmbedThumbnail(MonsterImage.icon(m)), embed_footer=embed_footer_with_state(state), embed_fields=fields)
def embed(cls, state: PicViewState): url = MonsterImage.picture(state.monster) animated = state.monster.has_animation fields = [ EmbedField( 'Extra Links', Box( Box(Text('Animation:'), LinkedText('(MP4)', MonsterImage.video(state.monster)), Text('|'), LinkedText('(GIF)', MonsterImage.gif(state.monster)), delimiter=' ') if animated else None, Box(Text('Orb Skin:'), LinkedText('Regular', MonsterImage.orb_skin(state.monster)), Text('|'), LinkedText( 'Color Blind', MonsterImage.orb_skin_colorblind(state.monster)), delimiter=' ') if state.monster.orb_skin_id else None, )), cls.evos_embed_field(state) ] return EmbedView( EmbedMain( color=state.color, title=MonsterHeader.fmt_id_header( state.monster, state.alt_monsters[0].monster.monster_id == cls.TSUBAKI, state.is_jp_buffed).to_markdown(), url=puzzledragonx(state.monster)), embed_footer=embed_footer_with_state(state), embed_fields=fields, embed_body_image=EmbedBodyImage(url), )
def embed(cls, state: ButtonInfoViewState): is_coop = state.display_options.players == ButtonInfoOptions.coop is_desktop = state.display_options.device == ButtonInfoOptions.desktop max_110 = state.display_options.max_level == ButtonInfoOptions.limit_break monster = state.monster info = state.info fields = [ EmbedField( # this block does not change if the lv110/lv120 toggle is clicked ButtonInfoView.get_max_level_text(monster, True), Box( Text('Without Latents'), # avoid whitespace after code block Box( get_stat_block(info.coop if is_coop else info.solo), Text('With Latents (Atk+)'), delimiter='' ), get_stat_block(info.coop_latent if is_coop else info.solo_latent) ), inline=True ), EmbedField( 'Lv. 120', Box( Text('Without Latents'), # avoid whitespace after code block Box( get_stat_block(info.coop_slb if is_coop else info.solo_slb), Text('With Latents (Atk++)'), delimiter='' ), get_stat_block(info.coop_slb_latent if is_coop else info.solo_slb_latent) ), inline=True ) if monster.limit_mult != 0 else None, EmbedField( ButtonInfoView.get_common_buttons_title_text(monster, max_110), Box( Text('*Inherits are assumed to be the max possible level (up to 110) and +297.*'), # janky, but python gives DeprecationWarnings when using \* in a regular string Text(r'*\* = on-color stat bonus applied*'), Text('Card Button Damage'), # done this way to not have the whitespace after code block Box( BlockText(info.get_card_btn_str(is_coop, max_110)), Text('Team Button Contribution'), delimiter='' ), BlockText(info.get_team_btn_str(is_coop, max_110)) ) ) if is_desktop else None, EmbedField( ButtonInfoView.get_common_buttons_title_text(monster, max_110), Box( Text('*Inherits are assumed to be the max possible level (up to 110) and +297.*'), # janky, but python gives DeprecationWarnings when using \* in a regular string Text(r'*\* = on-color stat bonus applied*') ) ) if not is_desktop else None, EmbedField( 'Card Button Damage', BlockText(get_mobile_btn_str(info.get_card_btn_str(is_coop, max_110))), inline=True ) if not is_desktop else None, EmbedField( 'Team Button Contribution', BlockText(get_mobile_btn_str(info.get_team_btn_str(is_coop, max_110))), inline=True ) if not is_desktop else None, cls.evos_embed_field(state) ] return EmbedView( EmbedMain( color=state.color, description='(Co-op mode)' if is_coop else '(Singleplayer mode)' ), embed_author=EmbedAuthor( MonsterHeader.long_v2(monster).to_markdown(), puzzledragonx(monster), MonsterImage.icon(monster) ), embed_footer=embed_footer_with_state(state), embed_fields=fields )
def embed(state, props: ExperienceCurveViewProps): regular = get_normal_exp_difference(props.monster, props.low, props.high, props.offset) lb = get_lb_exp_difference(props.monster, props.low, props.high, props.offset) slb = get_slb_exp_difference(props.monster, props.low, props.high, props.offset) is_light = props.monster.full_damage_attr.value == 3 return EmbedView( EmbedMain( color=state.color, title=MonsterHeader.fmt_id_header(props.monster, use_emoji=True), url=puzzledragonx(props.monster), description=Text(f'lv{props.low} -> lv{props.high} (' + (trunc_humanize(props.monster.exp_curve) if props.monster.exp_curve else "no") + f' curve)'), ), embed_thumbnail=EmbedThumbnail(MonsterImage.icon(props.monster)), embed_fields=[ EmbedField(title='Exact', body=Box( LabeledText("Reg", humanize_number(regular)), LabeledText("LB", humanize_number(lb)), LabeledText("SLB", humanize_number(slb)), LabeledText("Net", humanize_number(regular + lb + slb))), inline=True), EmbedField(title='Approx', body=Box( LabeledText("Reg", trunc_humanize(regular)), LabeledText("LB", trunc_humanize(lb)), LabeledText("SLB", trunc_humanize(slb)), LabeledText("Net", trunc_humanize(regular + lb + slb))), inline=True), EmbedField( title='Resources', body=Box( LabeledText( "Globes " + emoji_cache.get_emoji( f'orb_{props.monster.full_damage_attr.name.lower()}' ), str( get_total_needed( props.monster, props.low, props.high, props.offset, ceil(1.5 * GLOBE_EXP[ props.monster.full_damage_attr.value]), is_light))), LabeledText( "TA2", str( get_total_needed(props.monster, props.low, props.high, props.offset, TA2_EXP, is_light))), LabeledText( "TA3", str( get_total_needed(props.monster, props.low, props.high, props.offset, TA3_EXP, is_light))), ), inline=True) ], embed_footer=embed_footer_with_state(state))