예제 #1
0
    def __init__(self, raw: Dict[str, str], server: Server):
        if not set(raw) <= set(Bonus.keys):
            raise ValueError('Unexpected keys: ' +
                             str(set(raw) - set(Bonus.keys)))

        # Start time as gungho time string
        self.start_time_str = str(raw['s'])
        self.start_timestamp = pad_util.gh_to_timestamp_2(
            self.start_time_str, server)

        # End time as gungho time string
        self.end_time_str = str(raw['e'])
        self.end_timestamp = pad_util.gh_to_timestamp_2(
            self.end_time_str, server)

        # Optional DungeonId
        self.dungeon_id = None  # type: Optional[DungeonId]
        if 'd' in raw:
            self.dungeon_id = DungeonId(int(raw['d']))

        # Optional DungeonFloorId
        # Stuff like rewards text in monthly quests
        self.sub_dungeon_id = None  # type: Optional[SubDungeonId]
        if 'f' in raw:
            self.sub_dungeon_id = SubDungeonId(int(raw['f']))

        # If REM/PEM, the ID of the machine
        self.egg_machine_id = None  # type: Optional[int]
        if 'i' in raw:
            self.egg_machine_id = int(raw['i'])

        # Optional human-readable message (with formatting)
        self.message = None  # type: Optional[str]
        # Optional human-readable message (no formatting)
        self.clean_message = None  # type: Optional[str]
        if 'm' in raw:
            self.message = str(raw['m'])
            self.clean_message = pad_util.strip_colors(self.message)

        bonus_id = int(raw['b'])
        self.bonus_info = TYPES_MAP.get(bonus_id, UNKNOWN_TYPE)

        # Bonus value, if provided, optionally processed
        self.bonus_value = None  # type: Optional[Union[float, int]]
        if 'a' in raw:
            self.bonus_value = raw['a']
            if self.bonus_info.mod_fn:
                self.bonus_value = self.bonus_info.mod_fn(self.bonus_value)

        # Human readable name for the bonus
        self.bonus_name = self.bonus_info.bonus_type.name
        if self.bonus_info.bonus_type == BonusType.unknown:
            self.bonus_name += '({})'.format(bonus_id)
        self.bonus_id = bonus_id
예제 #2
0
    def __init__(self, raw: Dict[str, Any], server: Server):
        if not set(raw) <= set(Bonus.keys):
            raise ValueError('Unexpected keys: ' +
                             str(set(raw) - set(Bonus.keys)))

        self.raw = raw

        # Start time as gungho time string
        self.start_time_str = str(raw['s'])
        self.start_timestamp = pad_util.gh_to_timestamp_2(
            self.start_time_str, server)

        # End time as gungho time string
        self.end_time_str = str(raw['e'])
        self.end_timestamp = pad_util.gh_to_timestamp_2(
            self.end_time_str, server)

        # Optional DungeonId
        self.dungeon_id = None  # type: Optional[DungeonId]
        if 'd' in raw:
            self.dungeon_id = DungeonId(int(raw['d']))

        # Optional DungeonFloorId
        # Stuff like rewards text in monthly quests
        self.sub_dungeon_id = None  # type: Optional[SubDungeonId]
        if 'f' in raw:
            self.sub_dungeon_id = SubDungeonId(int(raw['f']))

        # If REM/PEM, the ID of the machine
        self.egg_machine_id = None  # type: Optional[int]
        if 'i' in raw:
            self.egg_machine_id = int(raw['i'])

        # Optional human-readable message (with formatting)
        self.message = None  # type: Optional[str]
        # Optional human-readable message (no formatting)
        self.clean_message = None  # type: Optional[str]
        # Optional URL in message
        self.url = None  # type: Optional[str]
        if 'm' in raw:
            self.message = str(raw['m'])
            self.clean_message = pad_util.strip_colors(self.message)
            if (match := re.search(r'https?:.+?(?=\|)', self.message)):
                self.url = match.group()
예제 #3
0
    def __init__(self, dungeon_id: DungeonId, raw: List[Any]):
        self.sub_dungeon_id = SubDungeonId(dungeon_id * 1000 + int(raw[0]))
        self.simple_sub_dungeon_id = int(raw[0])
        self.raw_name = raw[1]
        self.clean_name = pad_util.strip_colors(self.raw_name)
        self.floors = int(raw[2])
        self.rflags1 = int(raw[3])
        self.stamina = raw[4]
        self.bgm1 = raw[5]
        self.bgm2 = raw[6]
        self.rflags2 = int(raw[7])

        # If monsters can use skills in this dungeon.
        self.technical = self.rflags1 & 0x80 > 0

        # This next loop runs through the elements from raw[8] until it hits a 0. The 0 indicates the end of the list
        # of drops for the floor, the following segments are the dungeon modifiers
        pos = 8
        while int(raw[pos]) != 0:
            pos += 1
        pos += 1

        self.flags = int(raw[pos])
        self.remaining_fields = raw[pos + 1:]

        # Modifiers parsing doesn't seem to always work
        # Hacked up version for dungeon modifiers, needed for
        # enemy parsing.
        self.hp_mult = 1.0
        self.atk_mult = 1.0
        self.def_mult = 1.0

        for field in self.remaining_fields:
            if 'hp:' in field or 'at:' in field or 'df:' in field:
                for mod in field.split('|'):
                    if mod.startswith('hp:'):
                        self.hp_mult = float(mod[3:]) / 10000
                    elif mod.startswith('at:'):
                        self.atk_mult = float(mod[3:]) / 10000
                    elif mod.startswith('df:'):
                        self.def_mult = float(mod[3:]) / 10000
                break

        # Modifiers parsing also seems to skip fixed teams sometimes.
        # Hacked up version for just that here.
        self.fixed_team = {}

        for field in self.remaining_fields:
            if not 'fc1' in field:
                continue
            else:
                # TODO: this broke, look into re-enabling it
                continue
            for sub_field in field.split('|'):
                if not sub_field.startswith('fc'):
                    continue
                idx = int(sub_field[2])
                contents = sub_field[4:]
                details = contents.split(';')
                full_record = len(details) > 1
                self.fixed_team[idx] = {
                    'monster_id': details[0],
                    'hp_plus': details[1] if full_record else 0,
                    'atk_plus': details[2] if full_record else 0,
                    'rcv_plus': details[3] if full_record else 0,
                    'awakening_count': details[4] if full_record else 0,
                    'skill_level': details[5] if full_record else 0,
                }

        # This code imported from Rikuu, need to clean it up and merge
        # with the other modifiers parsing code. For now just importing
        # the score parsing, needed for dungeon loading.
        self.score = None
        i = 0

        if (self.flags & 0x1) != 0:
            i += 2
            # self.requirement = {
            #  dungeonId: Number(self.remaining_fields[i++]),
            #  floorId: Number(self.remaining_fields[i++])
            # };
        if (self.flags & 0x4) != 0:
            i += 1
            # self.beginTime = fromPADTime(self.remaining_fields[i++]);
        if (self.flags & 0x8) != 0:
            self.score = int(self.remaining_fields[i])
            i += 1
        if (self.flags & 0x10) != 0:
            i += 1
            # self.minRank = Number(self.remaining_fields[i++]);
        if (self.flags & 0x40) != 0:
            i += 1
예제 #4
0
    def __init__(self, dungeon_id: DungeonId, raw: List[Any]):
        # https://github.com/TsubakiBotPad/pad-data-pipeline/wiki/Subdungeon-Arguments
        self.sub_dungeon_id = SubDungeonId(dungeon_id * 1000 + int(raw[0]))
        self.simple_sub_dungeon_id = int(raw[0])
        self.raw_name = self.name = raw[1]
        self.clean_name = pad_util.strip_colors(self.raw_name)
        self.floors = int(raw[2])
        self.rflags1 = int(raw[3])
        self.stamina = raw[4]
        self.bgm1 = raw[5]
        self.bgm2 = raw[6]
        self.disables = int(raw[7])

        # If monsters can use skills in this dungeon.
        self.technical = self.rflags1 & 0x80 > 0

        # This next loop runs through the elements from raw[8] until it hits a 0. The 0 indicates the end of the list
        # of drops for the floor, the following segments are the dungeon modifiers
        pos = 8
        while int(raw[pos]) != 0:
            pos += 1
        pos += 1

        flags = int(raw[pos])
        pos += 1

        self.prev_dungeon_id = None
        self.prev_floor_id = None
        self.start_timestamp = None
        self.score = None
        self.unknown_f4 = None
        pipe_hell = ""
        self.end_timestamp = None

        if flags & 1 << 0:  # Prev Floor
            self.prev_dungeon_id = int(raw[pos])
            self.prev_floor_id = int(raw[pos + 1])
            pos += 2

        if flags & 1 << 2:  # Start Timestamp
            self.start_timestamp = ghtime(raw[pos], 'utc')
            pos += 1

        if flags & 1 << 3:  # S-Rank Score
            self.score = int(raw[pos])
            pos += 1

        if flags & 1 << 4:  # Unknown Value
            self.unknown_f4 = int(raw[pos])
            pos += 1

        if flags & 1 << 6:  # Pipe Hell
            pipe_hell = raw[pos]
            pos += 1

        if flags & 1 << 7:  # Start Timestamp
            self.end_timestamp = ghtime(raw[pos], 'utc')
            pos += 1

        self.restriction_type = int(raw[pos])
        self.restriction_args = raw[pos + 1:]

        modifiers = parse_modifiers(pipe_hell)
        self.hp_mult = default_int(modifiers, 'hp', 10000) / 10000
        self.atk_mult = default_int(modifiers, 'at', 10000) / 10000
        self.def_mult = default_int(modifiers, 'df', 10000) / 10000

        self.fixed_monsters: Dict[int, FixedTeamMonster] = {}
        for idx in range(6):
            if None is (fc := modifiers.get(f'fc{idx + 1}')):
                # Not all dungeons have fixed cards in all slots
                continue
            self.fixed_monsters[idx] = FixedTeamMonster(fc)