Example #1
0
def toMode(argument):
    argument = argument.lower()
    if argument in ["legend", "legendary"]:
        return "legendary"
    elif argument in ["camp", "campaign"]:
        return "campaign"
    raise custom_exceptions.DataNotFound("Mode", argument.title())
 def __init__(self, world, parent=None, **attributes):
   if not (1 <= world <= 7):
     raise custom_exceptions.DataNotFound("World", world)
   super().__init__(parent, **attributes)
   if self.parent is None:
     self.parent = HeroRootMessage(**attributes)
   self.world = world
   self.child_emojis = [self.context.bot.get_emoji(self.context.guild, key) for key in world_hero[world]]
 def __init__(self, level, mode, parent=None, **attributes):
     super().__init__(parent, **attributes)
     self.level = level
     self.mode = mode
     self.state = 0
     self.achieve = False
     dbrow = attributes.pop("dbrow", None)
     self.link = attributes.pop("link", None)
     self.task = attributes.pop("task", None)
     if not dbrow:
         dbrow = self.context.bot.db[self.context.guild.id].select(
             "wave", [level, mode])
         if not dbrow:
             raise custom_exceptions.DataNotFound(
                 "Level Waves", f"{level} {mode}" if mode else level)
         else:
             dbrow = list(dbrow.values())
     if self.task is None or self.link is None:
         level_general = self.context.bot.db[self.context.guild.id].select(
             "levels", level)
         if not level_general:
             raise custom_exceptions.DataNotFound("Level", level)
         else:
             self.task = level_general["task"]
             self.link = level_general["link"]
     if self.parent is None:
         self.parent = LevelIndividualMessage(level, **attributes)
     # check the level's wave data to decide its child emojis
     self.level_info = {
         "level": dbrow[0],
         "mode": dbrow[1],
         "initial_gold": dbrow[2],
         "max_life": dbrow[3],
         "enemy_waves": json.loads(dbrow[4])
     }
     for wave in self.level_info["enemy_waves"]:
         wave["achievements"] = parse_wave_achievements(wave["enemies"])
     if len(
             self.level_info["enemy_waves"]
     ) > 1:  # only need to show more info when there are more than 1 waves
         self.child_emojis += [
             text_emojis["info"], "🏆"
         ] + num_emojis[1:len(self.level_info["enemy_waves"]) + 1]
     else:
         self.child_emojis = ["🏆"]
Example #4
0
 def __init__(self, world, parent=None, **attributes):
     if not (1 <= world <= 7):
         raise custom_exceptions.DataNotFound("World", world)
     super().__init__(parent, **attributes)
     if self.parent is None:
         self.parent = TowerRootMessage(**attributes)
     db = self.context.bot.db[self.context.guild.id]
     self.towers = db.query(
         f'SELECT tower, description1, description2 FROM tower WHERE world="{world}"'
     )
     self.world = world
     self.child_emojis = num_emojis[1:len(self.towers) + 1]
 def __init__(self, level, parent=None, **attributes):
     super().__init__(parent, **attributes)
     self.level = level
     self.dbrow = attributes.pop("dbrow", None)
     db = self.context.bot.db[self.context.guild.id]
     if not self.dbrow:
         self.dbrow = db.select("levels", level)
         if not self.dbrow:
             raise custom_exceptions.DataNotFound("Level", level)
         else:
             self.dbrow = list(self.dbrow.values())
     world = self.dbrow[1]
     if level.startswith("S"):
         self.footer = "Shattered Realms"
         w = "S"
     elif level.startswith("A"):
         self.footer = "Arcade"
         w = "A"
     elif level.startswith("Connie"):
         self.footer = "Connie Story"
         w = "Connie"
     elif level.startswith("C"):
         self.footer = f"World {world} Challenge"
         w = "C"
     elif level.startswith("E"):
         self.footer = f"World {world} Endless"
         w = "E"
     else:
         self.footer = f"World {world}"
         w = world
     if self.parent is None:
         self.parent = LevelWorldMessage(w, **attributes)
     # check the level's wave data to decide its child emojis
     wave_info = db.query(f'SELECT * FROM wave WHERE level="{level}"')
     self.wave_info = None
     self.legendary_info = None
     if wave_info:
         for row in wave_info:
             if row[1].lower() == "legendary":
                 self.legendary_info = row
             elif row[1].lower() in ["", "campaign"]:
                 self.wave_info = row
     if self.wave_info:
         self.child_emojis.append("👽")
     if self.legendary_info:
         self.child_emojis.append("🏆")
Example #6
0
def toLevelWorld(argument):
    world = argument.lower()
    if world.startswith("world"):
        return int(world[5:].strip())
    elif world.startswith("w"):
        return int(world[1:].strip())
    elif world in ["s", "sr", "shattered realms", "shatteredrealms"]:
        return "S"
    elif world in ["a", "arcade", "arcades"]:
        return "A"
    elif world in ["e", "endless"]:
        return "E"
    elif world in ["c", "challenge", "challenges"]:
        return "C"
    elif world in ["connie", "connie story", "conniestrory"]:
        return "Connie"
    raise custom_exceptions.DataNotFound("World", argument.title())
 def __init__(self, levels, name, parent=None, **attributes):
     super().__init__(parent, **attributes)
     if self.parent is None:
         self.parent = LevelRootMessage(None, **attributes)
     self.name = name
     db = self.context.bot.db[self.context.guild.id]
     level_list = ", ".join([f'"{level}"' for level in levels])
     self.level_info = db.query(
         f"SELECT * FROM levels where level in ({level_list})")
     self.level_info.sort(key=lambda level: levels.index(level[0]))
     if not self.level_info:
         raise custom_exceptions.DataNotFound("Levels", level_list)
     if len(self.level_info) > len(num_emojis) - 1:
         raise ValueError("Too many levels")
     elif len(self.level_info) == len(num_emojis) - 1:
         self.child_emojis = num_emojis[1:]
     else:
         self.child_emojis = num_emojis[1:len(self.level_info) + 1]
Example #8
0
 def __init__(self, world, tower, parent=None, **attributes):
     super().__init__(parent, **attributes)
     if self.parent is None:
         self.parent = TowerWorldMessage(world, None, **attributes)
     self.info_type = TowerIndividualMessage.InfoType.basic
     self.towerInfo = attributes.pop("towerInfo", None)
     if self.towerInfo is None:  # no result passed in attributes, then go for a new db query
         db = self.context.bot.db[self.context.guild.id]
         result = db.query(
             f'SELECT basic, starUpgrade, lvUpgrade, leftBranchName, leftBranch, rightBranchName, rightBranch, reinforcement, buff, url '
             f'FROM tower JOIN buff ON tower.type=buff.unit AND tower.world=buff.world WHERE tower.tower="{tower}" and tower.world={world}'
         )
         if len(result) == 0:
             raise custom_exceptions.DataNotFound(f"W{world} Tower",
                                                  string.capwords(tower))
         self.towerInfo = result[0]
     self.towerInfo = list(self.towerInfo)
     self.tower = tower
     self.world = world
     coin_emoji = self.context.bot.get_emoji(self.context.guild, "coin")
     star_emoji = self.context.bot.get_emoji(self.context.guild, "star")
     if star_emoji is not None:
         self.towerInfo[1] = self.towerInfo[1].replace("⭐", f"{star_emoji}")
     else:
         star_emoji = item_emojis["star"]
     if coin_emoji is not None:
         self.towerInfo[2] = self.towerInfo[2].replace("💰", f"{coin_emoji}")
         self.towerInfo[4] = self.towerInfo[4].replace("💰", f"{coin_emoji}")
         self.towerInfo[6] = self.towerInfo[6].replace("💰", f"{coin_emoji}")
         self.towerInfo[7] = self.towerInfo[7].replace("💰", f"{coin_emoji}")
     self.child_emojis = [
         text_emojis["info"], star_emoji, text_emojis["up"],
         letter_emojis["L"], letter_emojis["R"]
     ]
     self.emoji_descriptions = [
         "Basic Info", "Star Upgrade", "Level Upgrade", "Left Branch",
         "Right Branch"
     ]
 def __init__(self, achievement, num, parent=None, **attributes):
     super().__init__(parent, **attributes)
     world = attributes.pop("world", None)
     mode = attributes.pop("mode", None)
     sort_by_absolute = attributes.pop("sort_by_absolute", False)
     # use the world and mode arguments to limit the search
     where_clause = []
     select_clause = self.general_columns + achievements
     # the time required for entering and exiting the level
     self.tlevel = self.context.bot.get_setting(self.context.guild,
                                                "LEVEL_EXTRA_TIME")
     # the time required for calling a wave
     self.twave = self.context.bot.get_setting(self.context.guild,
                                               "WAVE_EXTRA_TIME")
     limit = 10
     if world:
         where_clause.append(f"world={world}")
     if mode:
         where_clause.append(f'mode="{mode}"')
     # check the achievemnt argument to get the sorting method
     achievement_parse = achievement.replace('_', ' ').title()
     time_string = f"time/2.0+{self.tlevel}+wave*{self.twave}"
     time_calculation = lambda row: row[4] / 2.0 + self.tlevel + row[
         6] * self.twave
     if achievement == "fast":
         self.goal = "levels with the shortest completion time"
         self.info = ["TIME"]
         self.info_fun = lambda row: [f"{row[-1]:.0f}"]
         select_clause.append(f"MIN({time_string}) AS criteria")
         sort_method = "criteria ASC"
     elif achievement in tower_achievements:
         self.goal = f"levels with the highest gold rewards to help tower achievements"
         self.info = ["GOLD", "TIME", "GPS"]
         self.info_fun = lambda row: [
             row[5], f"{time_calculation(row):.0f}", f"{row[-1]:.2f}"
         ]
         criteria_str = f"CAST(gold AS FLOAT)/({time_string})"
         if sort_by_absolute == False:
             select_clause.append(f"MAX({criteria_str}) AS criteria")
             sort_method = "criteria DESC"
         else:
             select_clause.append(f"MAX(gold-time/100.0)")
             select_clause.append(f"({criteria_str}) AS criteria")
             sort_method = "gold DESC"
     else:
         if achievement in ["villager", "bandit"]:
             target = f"**{achievement_parse}s**"
             farm = "NUM"
         else:
             target = f"**{achievement_parse}** Enemies"
             farm = "KILL"
         ind = select_clause.index(
             achievement)  # index of achievement in results
         where_clause.append(f"{achievement}>0")
         if num:
             self.goal = f"levels that quickly farm **{num}** {target}"
             self.info = [f"{farm}", "TIME", "RUN", "SUM_T"]
             self.info_fun = lambda row: [
                 row[ind], f"{time_calculation(row):.0f}",
                 int(-(-num // row[ind])), f"{row[-1]:.0f}"
             ]
             num = float(num)
             criteria_str = f"({time_string})*(CAST (({num}/{achievement}) AS INT)+(({num}/{achievement})>CAST (({num}/{achievement}) AS INT)))"
             select_clause.append(f"MIN({criteria_str}) AS criteria")
             sort_method = "criteria ASC"
         else:
             self.goal = f"levels that quickly farm {target}"
             self.info = [f"{farm}", "TIME", "KPS"]
             self.info_fun = lambda row: [
                 row[ind], f"{time_calculation(row):.0f}", f"{row[-1]:.2f}"
             ]
             criteria_str = f"CAST({achievement} AS FLOAT)/({time_string})"
             if not sort_by_absolute == True:
                 select_clause.append(f"MAX({criteria_str}) AS criteria")
                 sort_method = "criteria DESC"
             else:
                 select_clause[ind] = f"MAX({achievement})"
                 select_clause.append(f"({criteria_str}) AS criteria")
                 sort_method = f"{achievement} DESC"
     where_clause = " AND ".join(where_clause) if where_clause else "TRUE"
     select_clause = ", ".join(select_clause)
     self.result = self.context.bot.db[self.context.guild.id].query(
         f"SELECT {select_clause} FROM achievement NATURAL JOIN levels WHERE ({where_clause}) GROUP BY level, mode ORDER BY {sort_method}, LENGTH(level), level LIMIT {limit}"
     )
     if not self.result:
         condition = []
         if world:
             condition.append(f"W{world}")
         if mode:
             condition.append(f"{mode.title()} mode")
         raise custom_exceptions.DataNotFound(
             "Achievement", f"{achievement_parse} in {' '.join(condition)}"
             if condition else achievement_parse)
     self.update_state(0)
Example #10
0
 async def _buff(self, context, *, name=None):
     if name is None:
         await context.send_help("buff")
         return
     name = name.lower()
     if name in ["haste"]:
         name = "haste"
         description = "Increase the speed of a unit by some percentage value."
         stack = "Most of the hastes from different sources stack with each other, except:\n1) Haste x1.5 from towers, but theoretically we cannot use towers from different worlds at the same time so not a problem\n2) Haste x1.5 from enemies, this usually is not a problem either\nAnd it's also worth mentioning that the haste x1.5 from enemies' aura stacks with haste x1.5 from tower's aura."
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/2/27/Haste.jpg/revision/latest?cb=20200822214559"
     elif name in ["slow"]:
         name = "slow"
         description = "Decrease the speed of a unit by some percentage value."
         stack = "There are 5 kinds of slows and they stack with each other.\n1) The most common slow by 50% with a clock on top\n2) Slow by 25% from Sethos' R6 sandstorm\n3) Move speed x0.4 from Smoulder's r4 aura\n4) Slow from Shamiko\n4) Slow by 60% from Elara's rifts' explosion (explosion only, slow from her active and aura of rifts is 50%)"
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/5/54/Slow.jpg/revision/latest?cb=20200822214559"
     elif name in ["cold"]:
         name = "cold"
         description = "Decrease the move speed by 50% and the animation speed by 25%. The slow on animation speed may stop some heroes from casting special spells."
         stack = "The speed reduction stacks with slow buffs."
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/7/70/Cold.jpg/revision/latest?cb=20200822214558"
     elif name in ["decrepit", "decrepify"]:
         name = "decrepit"
         description = "Decrease the speed and reduce the armor of a unit. This includes a decrepit from Yan (speed x0.35, armor -0.25) and a stronger version from W4 Small Golem (speed x0.25, armor -0.5)."
         stack = "The speed reduction stacks with slow buff and the armor reduction stacks with armor buff."
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/e/e6/Decrepify.jpg/revision/latest?cb=20200822214559"
     elif name in ["poison", "venom"]:
         name = "poison"
         description = "Ignores the shield points and deals damage (usually magical or true damage) over time. This includes a normal poison which deals `(3+0.05 ND) TD` every 0.42s and others from heroes."
         stack = "There are several different poison buffs with different damage multipliers, and they stack with each other. For example venom from Sethos stacks with posion from Mabyn."
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/8/87/Poison.jpg/revision/latest?cb=20200822214559"
     elif name in ["burn", "burning"]:
         name = "burn"
         description = "Deals `(2+0.05 ND) PD` every 0.4s."
         stack = "There is only one kind of burn buff so they cannot stack even they are from different sources."
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/8/8c/Burn.jpg/revision/latest?cb=20200822214559"
     elif name in ["bleed", "bleeding"]:
         name = "bleed"
         description = "Deals `(2+0.05 ND) PD` every 0.33s while moving."
         stack = "There is only one kind of bleed buff so they cannot stack even they are from different sources."
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/7/72/Bleed.jpg/revision/latest?cb=20200822215031"
     elif name in ["shield", "armor"]:
         name = "shield"
         description = "Gives some max shield points and increase the armor of a unit."
         stack = "Shield buffs from different sources stack with each other, but because they only gives max shield points, the shield points won't be restored if the unit loses some shield in battle."
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/4/43/Shield.jpg/revision/latest?cb=20200822214557"
     elif name in ["armor break", "break armor"]:
         name = "armor break"
         description = "Reduce the armor of a unit. Could be a percentage reduce (e.g. x0.5) or a value reduce (e.g. -0.2)."
         stack = "The armor breaks with different values can stack with each other. For example, a unit can receive x0.5 and x0.7 armor break and totally the armor will be x0.35."
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/0/02/Armor_break.jpg/revision/latest?cb=20200822214559"
     elif name in ["terror", "terrify"]:
         name = "terror"
         description = "Makes a unit to move backward, but the unit is still able to attack."
         stack = "Terror from Shamiko/Elara/Mabyn are literally different, but they may interfere each other due to some bug."
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/4/48/Terror.jpg/revision/latest?cb=20200822214558"
     elif name in ["blind"]:
         name = "blind"
         description = "Increase the miss chance of a unit by 50%."
         stack = "All blinds buffs are the same and cannot stack."
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/7/7b/Blind.jpg/revision/latest?cb=20200822214559"
     elif name in ["curse", "silence"]:
         name = "curse/silence"
         description = "Stops a unit from attacking or casting, also stops the cooldowns. This buff is either from W2 Heretic or W4 Pyromancer Tower."
         stack = ""
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/9/97/Curse.jpg/revision/latest?cb=20200822214558"
     elif name in [
             "stun", "freeze", "shock", "cocoon", "paralysis", "bind"
     ]:
         name = "stun/freeze/shock/..."
         description = "Stuns a unit so it cannot do anything."
         stack = "Buffs with different names can stack with each other, but with the same name a buff will only replace an older one."
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/a/a7/Stun.jpg/revision/latest?cb=20200822214559"
     elif name in ["cloak"]:
         name = "cloak"
         description = "Make a unit invisible to most of the ranged attacks, but it may be damaged from AOE effect, and cloaked enemies can be revealed by melee engagement."
         stack = ""
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/5/56/Cloak.jpg/revision/latest?cb=20200822214559"
     elif name in ["spirit", "spirit curse"]:
         name = "spirit curse"
         description = "Reduce the damage by 25% and deals `(5+0.05 ND) TD` every 0.42s."
         stack = "This cursed poison can stack with other poisons."
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/8/85/Spirit_curse.jpg/revision/latest?cb=20200822214559"
     elif name in ["polymorph", "poly", "polymorphism"]:
         name = "polymorph"
         description = "Reduce the HP to 1/4, move speed to 1/2, remove all armor, and silence the unit."
         stack = ""
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/e/e0/Polymorph.jpg/revision/latest?cb=20200901022035"
     elif name in ["charm"]:
         name = "charm"
         description = "Make the enemy fight for you. Your units can benifit from aura of the enemy. Some charmed enemies don't engage in melee, including W3 Mummy, W4 Magic Book & Cloud Sunfish, W6 Origami Crane & Harpy."
         stack = ""
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/d/de/Charm.jpg/revision/latest?cb=20200901023011"
     elif name in ["ground", "grounded"]:
         name = "grounded"
         description = "Ground the flying enemies making them stoppable by ground troops."
         stack = ""
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/d/da/Grounded.jpg/revision/latest?cb=20211007161430"
     elif name in ["slime", "slime cover"]:
         name = "slime cover"
         description = "Slime cover buffs ground slime enemies: HP x2, damage x1.5; It debuffs your allies: move speed x0.6, damage x0.8. It can be cleansed by Voltari Perch right branch upgrade."
         stack = ""
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/4/46/Slime_covered.jpg/revision/latest?cb=20211007161428"
     else:
         raise custom_exceptions.DataNotFound("Buff", string.capwords(name))
     embed = discord.Embed(title=f"**{string.capwords(name)}**",
                           timestamp=context.message.created_at)
     if description:
         embed.add_field(name="Effects:", value=description, inline=False)
     if stack:
         embed.add_field(name="Stack information:",
                         value=stack,
                         inline=False)
     embed.set_footer(text="BUFF/DEBUFF")
     if url:
         embed.set_thumbnail(url=url)
     await context.send(embed=embed)
Example #11
0
 async def _item(self, context, *, name=None):
     if name is None:
         await context.send_help("item")
         return
     name = name.lower()
     if name in ["armageddon"]:
         name = "armageddon"
         cooldown = 20
         description = "Deals `600 TD + 50% hp` damage to 20 non-boss enemies, and `10% hp` damage to all bosses."
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/b/b5/Armageddon_Consumable.png/revision/latest?cb=20200822204546"
     elif name in ["fire potion", "fire", "bomb"]:
         name = "fire potion"
         cooldown = 10
         description = "Deals `400 TD` to enemies in AOE range 2."
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/9/92/Bomb_Consumable.png/revision/latest?cb=20200822204547"
     elif name in ["freeze potion", "freeze"]:
         name = "freeze potion"
         cooldown = 60
         description = "Freeze all enemies for 5s."
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/4/40/Freeze_Consumable.png/revision/latest?cb=20200822204547"
     elif name in ["freeze potion lv2", "freeze lv2", "freeze2"]:
         name = "freeze potion lv2"
         cooldown = 60
         description = "Freeze all enemies for 7.5s."
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/4/40/Freeze_Consumable.png/revision/latest?cb=20200822204547"
     elif name in ["gold boost", "gold"]:
         name = "gold boost"
         cooldown = 30
         description = "Instantly grants 500 coins."
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/0/0c/Coin_Consumable.png/revision/latest?cb=20200822204547"
     elif name in ["healing potion", "heal potion", "healing", "heal"]:
         name = "healing potion"
         cooldown = 5
         description = "Revives dead heroes, and in 15s heals allies in AOE range 3 `150 HP`."
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/2/2a/Revive_Consumable.png/revision/latest?cb=20200822204547"
     elif name in ["meteor"]:
         name = "meteor"
         cooldown = 30
         description = (
             f"Instantly kills all non-boss enemies in AOE range 4, deals `9% hp` damage to bosses, and summons 2 lava golems.\n"
             f"After that, drops 5 more small meteors to random enemies with AOE range 1 and same damage effect.\n"
             f"Lava golems has 400 hp, and deals `42 TD + 10% hp` damage on a non-boss enemy, or `1% hp` damage on a boss every 1s."
         )
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/1/18/Inferno_Consumable.png/revision/latest?cb=20200822204547"
     elif name in ["summon potion", "summon"]:
         name = "summon potion"
         cooldown = 5
         description = "Summons a lava golem with 200 hp, dealing `42 TD + 10% hp` damage on a non-boss enemy, or `1.25% hp` damage on a boss every 1s."
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/3/3d/Summon_Consumable.png/revision/latest?cb=20200822204547"
     elif name in ["substitute"]:
         name = "Substitute"
         cooldown = 5
         description = "Summons a substitute with 200 hp, 100% physical and magical armor, 100% dodge, immue to debuffs. It blocks 6 enemies (except bosses) with 3 engage range. \n- Each time it takes a hit, it receives `1 TD` (totally takes 200 hits).\n- Its HP can be boosted by Hogan's R6 skill"
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/2/27/Substitute_Consumable.png/revision/latest?cb=20211005051014"
     elif name in ["swift soda", "swift", "soda"]:
         name = "swift soda"
         cooldown = 20
         description = "Resets all heroes' actives cooldown, and haste their speed x2 and boost their damage x1.1 for 30s."
         url = "https://static.wikia.nocookie.net/realm-defense-hero-legends-td/images/7/7c/SwiftSoda_Consumable.png/revision/latest?cb=20211005051012"
     else:
         raise custom_exceptions.DataNotFound("Item", string.capwords(name))
     embed = discord.Embed(title=f"**{string.capwords(name)}**",
                           timestamp=context.message.created_at,
                           description=f"Cooldown: {cooldown}s")
     embed.add_field(name="Effects:", value=description, inline=False)
     if url:
         embed.set_footer(text="ITEM", icon_url=url)
     else:
         embed.set_footer(text="ITEM")
     await context.send(embed=embed)
Example #12
0
    async def enemy(self,
                    context,
                    world: typing.Optional[toWorld],
                    *,
                    enemy=None):
        # check world argument
        if world is not None and (world <= 0 or world >= 8):
            raise custom_exceptions.DataNotFound("World", world)
        searchLimit = self.get_search_limit(context.guild)
        where_clause = []
        if enemy:
            enemy = enemy.lower()
            if enemy in ["bird", "birds", "fly", "air",
                         "flying"]:  # aliases for "flying"
                where_clause.append(f'remark="flying"')
            elif enemy in ["boss"]:
                where_clause.append(f'remark="boss"')
            else:
                where_clause.append(f'enemy LIKE "%{enemy}%"')
        if world:
            where_clause.append(f'enemy.world={world}')
        where_clause = " AND ".join(where_clause) if where_clause else True
        result = self.bot.db[context.guild.id].query(
            f"SELECT enemy, enemy.world, type, hp, physicalArmor, magicalArmor, moveSpeed, castSpeed, normalDamage, specialDamage, dodge, abilities, remark, buff, url "
            f"FROM enemy JOIN buff ON buff.unit='enemy' AND enemy.world=buff.world WHERE {where_clause} LIMIT {searchLimit}"
        )

        if len(result) == 0:
            raise custom_exceptions.DataNotFound(
                f"W{world} Enemy" if world is not None else "Enemy",
                string.capwords(enemy))
        elif len(result) == searchLimit:  # too many results
            prefix = self.bot.get_guild_prefix(
                context.guild) if context.guild else context.prefix
            await context.send(
                f"There are more than {searchLimit-1} enemies that match your input name, "
                f"please input a more accurate name to narrow down the search: `{prefix}{context.command.qualified_name} {context.command.signature}`"
            )
            return

        timeout = self.get_active_time(context.guild) * 60

        def getInteractiveMessage(ind):
            return InteractiveEndMessage(embed=self.get_enemy_embed(
                context, result[ind]),
                                         context=context,
                                         timeout=timeout)

        if len(result) > 1:
            prefix = self.bot.get_guild_prefix(
                context.guild) if context.guild else context.prefix
            enemies = [
                f"`{prefix}enemy w{result[i][1]} {result[i][0]}`"
                for i in range(len(result))
            ]
            content = f"There are {len(result)} results that match your keyword, please make a choice by reacting:"
            guide = InteractiveSelectionMessage(selections=enemies,
                                                transfer=getInteractiveMessage,
                                                description=content,
                                                context=context,
                                                timeout=timeout)
            await guide.start()
        else:
            embed = self.get_enemy_embed(context, result[0])
            await context.send(embed=embed)
Example #13
0
def find_achievement(name):
    name = name.lower()
    close_word = find_closest(name, list(achievement_synonyms))
    if close_word:
        return achievement_synonyms[close_word]
    raise custom_exceptions.DataNotFound("Achievement", name.title())
Example #14
0
    async def _achieve(self,
                       context,
                       world: typing.Optional[toWorld],
                       mode: typing.Optional[toMode],
                       achievement: find_achievement = "fast",
                       num: typing.Optional[int] = None,
                       sort_by_absolute: typing.Optional[bool] = None):
        # check world argument
        if world is not None and (world <= 0 or world >= 8):
            raise custom_exceptions.DataNotFound("World", world)
        if world == 7 and achievement == "slime":  # extra parsing for w7 slime
            achievement = "w7_slime"
        timeout = self.bot.get_setting(context.guild, "ACTIVE_TIME") * 60
        if achievement in tappables:
            where_clause = [f'tappable LIKE "%{achievement}%"']
            if world:
                where_clause.append(f"world={world}")
            where_clause = " AND ".join(
                where_clause) if where_clause else "TRUE"
            limit = self.bot.get_setting(context.guild, "SEARCH_LIMIT") - 1
            result = self.bot.db[context.guild.id].query(
                f"SELECT * FROM levels WHERE ({where_clause}) LIMIT {limit}")
            if len(result) == 0:
                raise custom_exceptions.DataNotFound(
                    "Achievement",
                    f"{achievement} in W{world}" if world else achievement)

            timeout = self.bot.get_setting(context.guild, "ACTIVE_TIME") * 60

            def getInteractiveMessage(ind):
                row = result[0]
                return level_guide.LevelIndividualMessage(row[0],
                                                          context=context,
                                                          timeout=timeout,
                                                          dbrow=row)

            if len(result) > 1:
                levels = [
                    f"`W{result[i][1]} lv.{result[i][0]:<5} {result[i][2]}`"
                    for i in range(len(result))
                ]
                content = f"You can complete the mission **{achievement.title()}** in below levels, react to see the details of a level:"
                guide = InteractiveSelectionMessage(
                    selections=levels,
                    transfer=getInteractiveMessage,
                    description=content,
                    colour=discord.Colour.green(),
                    context=context,
                    timeout=timeout)
                await guide.start()
            else:
                guide = getInteractiveMessage(0)
                await guide.start()
        else:
            guide = level_guide.LevelAchievementMessage(
                achievement,
                num,
                context=context,
                timeout=timeout,
                world=world,
                mode=mode,
                sort_by_absolute=sort_by_absolute)
            await guide.start()
 def __init__(self, world, parent=None, **attributes):
     if world not in [1, 2, 3, 4, 5, 6, 7, "S", "A", "E", "C", "Connie"]:
         raise custom_exceptions.DataNotFound("World", world)
     super().__init__(parent, **attributes)
     self.world = world
     if self.parent is None:
         self.parent = LevelRootMessage(**attributes)
     if world in [1, 2]:
         self.world_text = f"World {world}"
         self.child_emojis = num_emojis[1:3]
         self.categories = [
             f"Level {world*20-19}-{world*20-10}",
             f"Level {world*20-9:>2}-{world*20}"
         ]
         self.lists = [[
             f"{i}" for i in range(world * 20 - 19, world * 20 - 10 + 1)
         ], [f"{i}" for i in range(world * 20 - 9, world * 20 + 1)]]
     elif world in [3, 4, 5, 6]:
         self.world_text = f"World {world}"
         self.child_emojis = num_emojis[1:5]
         self.categories = [
             f"Level {world*40-79}-{world*40-70}",
             f"Level {world*40-69}-{world*40-60}",
             f"Level {world*40-59}-{world*40-50}",
             f"Level {world*40-49}-{world*40-40}"
         ]
         self.lists = [
             [f"{i}" for i in range(world * 40 - 79, world * 40 - 70 + 1)],
             [f"{i}" for i in range(world * 40 - 69, world * 40 - 60 + 1)],
             [f"{i}" for i in range(world * 40 - 59, world * 40 - 50 + 1)],
             [f"{i}" for i in range(world * 40 - 49, world * 40 - 40 + 1)]
         ]
     elif world in [7]:
         self.world_text = f"World {world}"
         self.child_emojis = num_emojis[1:2]
         self.categories = [f"Level {world*40-79}-{world*40-70}"]
         self.lists = [[
             f"{i}" for i in range(world * 40 - 79, world * 40 - 70 + 1)
         ]]
     elif world in ["S"]:
         self.world_text = f"Shattered Realms"
         self.child_emojis = num_emojis[1:9]
         self.categories = [
             f"Level  1-5  Piece of Pridefall",
             f"Level  6-10 Frozen Fragment", f"Level 11-15 Sunken Sands",
             f"Level 16-20 Fallen Corruption", f"Level 21-25 Shifted Sands",
             f"Level 26-30 Tundra Plateau", f"Level 31-35 Simmering Sands",
             f"Level 36-40 Desolate Drifts"
         ]
         self.lists = [[f"S{i}" for i in range(1, 6)],
                       [f"S{i}" for i in range(6, 11)],
                       [f"S{i}" for i in range(11, 16)],
                       [f"S{i}" for i in range(16, 21)],
                       [f"S{i}" for i in range(21, 26)],
                       [f"S{i}" for i in range(26, 31)],
                       [f"S{i}" for i in range(31, 36)],
                       [f"S{i}" for i in range(36, 41)]]
     elif world in ["A"]:
         self.world_text = f"Arcade"
         self.child_emojis = num_emojis[1:6]
         self.categories = [
             f"A1 Potions vs Slimes", f"A2 Present Plunder",
             f"A3 Secret Weapon", f"A4 Siberian Match",
             f"A5 Defense of Athena"
         ]
         self.lists = [[f"A1-{i}" for i in range(1, 4)],
                       [f"A2-{i}" for i in range(1, 4)],
                       [f"A3-{i}" for i in range(1, 4)],
                       [f"A4-{i}" for i in range(1, 4)],
                       [f"A5-{i}" for i in range(1, 4)]]
     elif world in ["E"]:
         self.world_text = f"Endless"
         self.child_emojis = num_emojis[1:6]
         self.categories = [f"World {i} Endless" for i in range(1, 6)]
         self.levels = [f"E{i}" for i in range(1, 6)]
     elif world in ["C"]:
         self.world_text = f"Challenge"
         self.child_emojis = [num_emojis[i] for i in [1, 2, 3, 6]]
         self.categories = [f"World {i} Challenge" for i in [1, 2, 3, 6]]
         self.lists = [[f"C1-{i}" for i in range(1, 6)],
                       [f"C2-{i}" for i in range(1, 11)],
                       [f"C3-{i}" for i in range(1, 11)],
                       [f"C6-{i}" for i in range(1, 11)]]
     elif world in ["Connie"]:
         self.world_text = f"Connie Story"
         self.child_emojis = num_emojis[1:8]
         self.categories = [f"Chapter {i}" for i in range(1, 8)]
         self.levels = [f"Connie{i}" for i in range(1, 8)]
    def __init__(self, achieves, nums, parent=None, **attributes):
        super().__init__(parent, **attributes)
        self.achieves = achieves
        self.nums = nums
        self.attributes = attributes.copy()
        self.achieves_ind = [
            achievements.index(achievement) for achievement in achieves
        ]
        world = attributes.pop("world", None)
        mode = attributes.pop("mode", None)
        sort_by_absolute = attributes.pop("sort_by_absolute", False)
        self.candidates = attributes.pop("candidates", None)
        self.tlevel = self.context.bot.get_setting(self.context.guild,
                                                   "LEVEL_EXTRA_TIME")
        self.twave = self.context.bot.get_setting(self.context.guild,
                                                  "WAVE_EXTRA_TIME")
        if self.candidates is None:
            # use the world and mode arguments to limit the search
            where_clause = [
                " OR ".join([f"{achievement}>0" for achievement in achieves])
            ]
            select_clause = self.general_columns + achievements + [
                f"time/2.0+{self.tlevel}+wave*{self.twave} AS tvalid"
            ]
            if world:
                where_clause.append(f"world={world}")
            if mode:
                where_clause.append(f'mode="{mode}"')
            select_clause = ", ".join(select_clause)
            where_clause = f"({') AND ('.join(where_clause)})"
            self.candidates = self.context.bot.db[self.context.guild.id].query(
                f"SELECT {select_clause} FROM achievement NATURAL JOIN levels WHERE {where_clause}"
            )
        if not self.candidates:
            condition = []
            if world:
                condition.append(f"W{world}")
            if mode:
                condition.append(f"{mode.title()} mode")
            achieves_parse = ', '.join([
                achievement.replace('_', ' ').title()
                for achievement in achieves
            ])
            raise custom_exceptions.DataNotFound(
                "Achievement", f"{achieves_parse} in {' '.join(condition)}"
                if condition else achieves_parse)

        # optimize process
        constraint_coeffs = []
        for i in range(len(achieves)):
            constraint_coeffs.append([])
        lower_bounds = nums
        cost_coeffs = []
        for i, row in enumerate(self.candidates):
            _, time, row_achieves = self.row_split(row)
            counts = self.get_target_achieves(row_achieves)
            for j, count in enumerate(counts):
                constraint_coeffs[j].append(count)
            cost_coeffs.append(
                time if not sort_by_absolute else 10000 + time
            )  # give a small weight on time so that level with less time will be more likely to be selected
        self.minimum_sol = find_minimal_cost(constraint_coeffs, lower_bounds,
                                             cost_coeffs)
        self.minimum_sol.sort(reverse=True, key=lambda sol: sol[1])
        self.update_state(0)
Example #17
0
    async def tower(self,
                    context,
                    world: typing.Optional[toWorld],
                    *,
                    tower=None):
        # check world argument
        if world is not None and (world <= 0 or world >= 8):
            raise custom_exceptions.DataNotFound("World", world)
        if tower is None:
            await context.invoke(self.bot.get_command("guide tower"), world)
            return
        tower = tower.lower()
        searchLimit = self.get_search_limit(context.guild)
        if world is None:
            if tower in ["barrack"]:
                where_clause = f'type="{tower}"'
            else:
                where_clause = f'tower LIKE "%{tower}%"'
        else:
            if tower in ["barrack"]:
                where_clause = f'type="{tower}" AND tower.world={world}'
            else:
                where_clause = f'tower LIKE "%{tower}%" AND tower.world={world}'
        result = self.bot.db[context.guild.id].query(
            f"SELECT tower.tower, tower.world, basic, starUpgrade, lvUpgrade, leftBranchName, leftBranch, rightBranchName, rightBranch, reinforcement, buff, url "
            f"FROM tower JOIN buff ON tower.type=buff.unit AND tower.world=buff.world WHERE {where_clause} LIMIT {searchLimit}"
        )
        if len(result) == 0:
            raise custom_exceptions.DataNotFound(
                f"W{world} Tower" if world is not None else "Tower",
                string.capwords(tower))
        elif len(result) == searchLimit:  # too many results
            prefix = self.bot.get_guild_prefix(
                context.guild) if context.guild else context.prefix
            await context.send(
                f"There are more than {searchLimit-1} towers that match your input name, "
                f"please input a more accurate name to narrow down the search: `{prefix}{context.command.qualified_name} {context.command.signature}`"
            )
            return

        timeout = self.get_active_time(context.guild) * 60

        def getInteractiveMessage(ind):
            row = result[ind]
            tower = row[0]
            world = row[1]
            towerInfo = row[2:]
            return tower_guide.TowerIndividualMessage(world,
                                                      tower,
                                                      towerInfo=towerInfo,
                                                      context=context,
                                                      timeout=timeout)

        if len(result) > 1:
            prefix = self.bot.get_guild_prefix(
                context.guild) if context.guild else context.prefix
            towers = [
                f"`{prefix}tower w{result[i][1]} {result[i][0]}`"
                for i in range(len(result))
            ]
            content = f"There are {len(result)} results that match your keyword, please make a choice by reacting:"
            guide = InteractiveSelectionMessage(selections=towers,
                                                transfer=getInteractiveMessage,
                                                description=content,
                                                colour=discord.Colour.blue(),
                                                context=context,
                                                timeout=timeout)
            await guide.start()
        else:
            guide = getInteractiveMessage(0)
            await guide.start()