예제 #1
0
class SealOptionData(db.Model):
    __tablename__ = "seal_option_data"

    _mapper_utils = {
        "files": {
            "server": ["s_SealOptionValueData.bin"]
        },
    }

    code = CustomColumn(db.String(32), primary_key=True, mapper_key="코드")

    effect_code = CustomColumn(db.Enum(EffectCode),
                               nullable=False,
                               mapper_key="효과코드",
                               transform=lambda v: EffectCode(v))

    operator = CustomColumn(db.String(4),
                            mapper_key="Operator",
                            transform=lambda v: v if v != "#" else None)

    def to_dict(self) -> dict:
        intervalls = {}
        for cname in COLUMN_NAMES:
            intervalls[cname.lower()] = getattr(self, cname)

        return {
            "code": self.code,
            "effect_code": self.effect_code.to_dict(),
            "operator": self.operator,
            "intervalls": intervalls,
        }
예제 #2
0
class QuestMission(db.Model):
    __tablename__ = "quest_mission"

    index = db.Column(db.Integer, primary_key=True, autoincrement=True)
    work_type = db.Column(db.Enum(QuestWorkType), nullable=False)
    work_value = db.Column(db.String(32))

    quest_code = db.Column(db.String(32),
                           db.ForeignKey("quest.code"),
                           nullable=False)

    quest = db.relationship("Quest", foreign_keys=[quest_code])

    map_code = db.Column(db.String(32), db.ForeignKey("map.code"))
    map = db.relationship("Map", foreign_keys=[map_code], uselist=False)

    x = db.Column(db.Float)
    y = db.Column(db.Float)

    count = db.Column(db.Integer, nullable=False)

    npc_code = db.Column(db.String(32), db.ForeignKey("npc.code"))
    npc = db.relationship("Npc", foreign_keys=[npc_code], uselist=False)

    item_code = db.Column(db.String(32), db.ForeignKey("item_list.code"))
    item = db.relationship("ItemList", foreign_keys=[item_code], uselist=False)

    monster_code = db.Column(db.String(32), db.ForeignKey("monster.code"))
    monster = db.relationship("Monster",
                              foreign_keys=[monster_code],
                              uselist=False)

    quest_item_code = db.Column(db.String(32),
                                db.ForeignKey("quest_item.code"))
    quest_item = db.relationship("QuestItem",
                                 foreign_keys=[quest_item_code],
                                 uselist=False)

    def to_dict(self) -> dict:
        return {
            "work_type":
            self.work_type.to_dict(),
            "work_value":
            self.work_value,
            "map": (self.map.to_dict(minimal=True) if self.map else None),
            "pos": {
                "x": self.x,
                "y": self.y,
            },
            "count":
            self.count,
            "npc":
            self.npc.to_dict(minimal=True) if self.npc else None,
            "item":
            self.item.to_dict() if self.item else None,
            "monster":
            (self.monster.to_dict(minimal=True) if self.monster else None),
            "quest_item": (self.quest_item.to_dict(
                minimal=True) if self.quest_item else None)
        }
예제 #3
0
class RankingPlayerHistory(db.Model):
    __tablename__ = "ranking_player_history"

    index = db.Column(db.Integer, primary_key=True, autoincrement=True)
    server = db.Column(db.Enum(Server), nullable=False)
    name = db.Column(db.String(16), nullable=False)

    previous_level_land = db.Column(db.Integer)
    new_level_land = db.Column(db.Integer)

    previous_level_sea = db.Column(db.Integer)
    new_level_sea = db.Column(db.Integer)

    previous_character_class = db.Column(db.Enum(CharacterClass))
    new_character_class = db.Column(db.Enum(CharacterClass))

    previous_guild = db.Column(db.String(16))
    new_guild = db.Column(db.String(16))

    inserted_at = db.Column(db.DateTime, default=get_utc_now)

    def to_dict(self) -> dict:
        changes = {}

        if self.previous_level_land:
            changes["previous_level_land"] = self.previous_level_land
            changes["new_level_land"] = self.new_level_land

        if self.previous_level_sea:
            changes["previous_level_sea"] = self.previous_level_sea
            changes["new_level_sea"] = self.new_level_sea

        if self.previous_character_class:
            changes["previous_character_class"] = (
                self.previous_character_class.to_dict())
            changes["new_character_class"] = self.new_character_class.to_dict()

        if self.previous_guild or self.new_guild:
            changes["previous_guild"] = self.previous_guild
            changes["new_guild"] = self.new_guild

        return {
            "inserted_at": str(self.inserted_at),
            "changes": changes,
        }
예제 #4
0
class SealOption(db.Model):
    __tablename__ = "seal_option"

    _mapper_utils = {
        "files": {
            "server": ["s_SealOptionData.bin"]
        },
    }

    code = CustomColumn(db.String(32), primary_key=True, mapper_key="코드")

    # Link seal option to table. Used to reference the table later.
    # This is done in the update_database.py loop.
    seal_option_type = CustomColumn(db.Enum(SealOptionType),
                                    nullable=False,
                                    mapper_key="_seal_option_type")
예제 #5
0
class Accessory(
        db.Model,
        ExtraEquipmentMixin,
        ItemSetMixin,
        DroppedByMixin,
        ProducedByMixin,
        NeededForMixin,
        RandomBoxMixin,
        SoldByMixin,
):
    __tablename__ = "accessory"

    _mapper_utils = {
        "files": {
            "server": ["s_AccessoryItem.bin"],
            "client": ["c_AccessoryItemRes.bin"],
            "string": ["AccessoryItemStr.dat"],
        },
    }

    accessory_type = CustomColumn(db.Enum(AccessoryType),
                                  nullable=False,
                                  mapper_key="구분코드",
                                  transform=lambda v: AccessoryType(v))

    def to_dict(self, minimal: bool = False) -> dict:
        minimal_dict = {
            **ExtraEquipmentMixin.to_dict(self, minimal),
            "accessory_type":
            self.accessory_type.to_dict(),
        }

        if minimal:
            return minimal_dict

        return {
            **minimal_dict,
            **ItemSetMixin.to_dict(self),
            **DroppedByMixin.to_dict(self),
            **ProducedByMixin.to_dict(self),
            **NeededForMixin.to_dict(self),
            **RandomBoxMixin.to_dict(self),
            **SoldByMixin.to_dict(self),
        }
예제 #6
0
class Monster(db.Model):
    __tablename__ = "monster"

    _mapper_utils = {
        "files": {
            "server": ["s_MonsterChar.bin"],
            "client": ["c_MonsterCharRes.bin"],
            "string": ["MonsterCharStr.dat"],
        },
        "options": {
            "image_key": "모델명"
        },
    }

    index = db.Column(db.Integer, nullable=False)

    code = CustomColumn(db.String(32), primary_key=True, mapper_key="코드")

    name = CustomColumn(db.String(256), nullable=False, mapper_key="_name")

    icon = CustomColumn(db.String(32), nullable=False, mapper_key="_icon")

    rating_type = CustomColumn(db.Enum(RatingType),
                               nullable=False,
                               mapper_key="몬스터등급타입",
                               transform=lambda val: RatingType(val))

    level = CustomColumn(db.Integer, nullable=False, mapper_key="기준레벨")

    hp = CustomColumn(db.Integer, nullable=False, mapper_key="기준최대HP")

    range = CustomColumn(db.Enum(MonsterRange),
                         nullable=False,
                         mapper_key="공격거리타입",
                         transform=lambda val: MonsterRange(val))

    area = CustomColumn(db.Enum(Area),
                        nullable=False,
                        mapper_key="필드구분",
                        transform=lambda val: Area(val))

    experience = CustomColumn(db.Integer, nullable=False, mapper_key="보상경험치")

    minimal_damage = CustomColumn(db.Integer,
                                  nullable=False,
                                  mapper_key="최소물공력")

    maximal_damage = CustomColumn(db.Integer,
                                  nullable=False,
                                  mapper_key="최대물공력")

    physical_defense = CustomColumn(db.Integer,
                                    nullable=False,
                                    mapper_key="물방력")

    magic_defense = CustomColumn(db.Integer, nullable=False, mapper_key="마항력")

    attack_range = CustomColumn(db.Float,
                                nullable=False,
                                mapper_key="기본사정거리",
                                transform=florensia_meter_transform)

    tameable = CustomColumn(db.Boolean, mapper_key="테이밍", nullable=False)

    drops = db.relationship(
        "Drop", primaryjoin="foreign(Drop.monster_code) == Monster.code")

    map_points = db.relationship(
        "MapPoint",
        primaryjoin="foreign(MapPoint.monster_code) == Monster.code")

    quest_missions = db.relationship(
        "QuestMission",
        primaryjoin="foreign(QuestMission.monster_code) == Monster.code")

    vision_range = CustomColumn(db.Float,
                                nullable=False,
                                mapper_key="선공시야",
                                transform=florensia_meter_transform)

    # If you perform an action close to the range
    # attack vision range of the monster, you will
    # also get aggro
    attack_vision_range = CustomColumn(db.Float,
                                       nullable=False,
                                       mapper_key="요청시야",
                                       transform=florensia_meter_transform)

    messages_code = CustomColumn(db.String(32),
                                 mapper_key="오브젝트채팅",
                                 transform=lambda v: v if v != "#" else None)

    monster_message = db.relationship("MonsterMessage", uselist=False)

    # Skill 1
    skill_1_code = CustomColumn(db.String(32),
                                db.ForeignKey("monster_skill.code"),
                                mapper_key="부가Action1코드",
                                transform=lambda v: v if v != "#" else None)

    skill_1_chance = CustomColumn(db.Float,
                                  mapper_key="부가Action1선택율",
                                  transform=florensia_probability_transform)

    skill_1 = db.relationship("MonsterSkill", foreign_keys=[skill_1_code])

    # Skill 2
    skill_2_code = CustomColumn(db.String(32),
                                db.ForeignKey("monster_skill.code"),
                                mapper_key="부가Action2코드",
                                transform=lambda v: v if v != "#" else None)

    skill_2_chance = CustomColumn(db.Float,
                                  mapper_key="부가Action2선택율",
                                  transform=florensia_probability_transform)

    skill_2 = db.relationship("MonsterSkill", foreign_keys=[skill_2_code])

    def to_dict(self, minimal: bool = False) -> dict:
        minimal_dict = {
            "code": self.code,
            "name": self.name,
            "icon": self.icon,
            "rating": self.rating_type.to_dict(),
            "level": self.level,
            "area": self.area.to_dict(),
        }

        if minimal:
            return minimal_dict

        # Get monster skills as a list
        skills = []
        for i in range(1, 3):
            skill = getattr(self, f"skill_{i}")
            if skill:
                skill_dict = skill.to_dict()
                skill_dict["chance"] = getattr(self, f"skill_{i}_chance")
                skills.append(skill_dict)

        return {
            **minimal_dict, "hp":
            self.hp,
            "range":
            self.range.to_dict(),
            "experience":
            self.experience,
            "minimal_damage":
            self.minimal_damage,
            "maximal_damage":
            self.maximal_damage,
            "physical_defense":
            self.physical_defense,
            "magic_defense":
            self.magic_defense,
            "attack_range":
            self.attack_range,
            "tamable":
            self.tameable,
            "vision_range":
            self.vision_range,
            "attack_vision_range":
            self.attack_vision_range,
            "messages":
            (self.monster_message.to_dict() if self.monster_message else None),
            "skills":
            skills,
            "map_points":
            [point.to_dict(map_dict=True) for point in self.map_points],
            "drops": [drop.to_dict(item_dict=True) for drop in self.drops],
            "quests": [
                mission.quest.to_dict(minimal=True)
                for mission in self.quest_missions
            ]
        }
예제 #7
0
        return {
            "items": [
                item.to_dict(with_item_data=True) for item in item_columns
                if item
            ],
            "effects":
            effects,
        }


# Add effect columns
for i in range(1, 13):
    # Code
    setattr(
        ItemSet, f"effect_{i}_code",
        CustomColumn(db.Enum(EffectCode),
                     mapper_key=f"효과코드_{i}",
                     transform=(lambda v: EffectCode(v)
                                if v != MAX_INT else None)))
    # Operator
    setattr(
        ItemSet, f"effect_{i}_operator",
        CustomColumn(db.String(4),
                     mapper_key=f"수치연산자_{i}",
                     transform=lambda v: v if v != "#" else None))

    # Value
    setattr(
        ItemSet, f"effect_{i}_value",
        CustomColumn(db.Float,
                     mapper_key=f"효과값_{i}",
예제 #8
0
class Essence(
        db.Model,
        BaseMixin,
        BonusMixin,
        DroppedByMixin,
        NeededForMixin,
        ProducedByMixin,
        RandomBoxMixin,
):
    __tablename__ = "essence"

    _mapper_utils = {
        "files": {
            "server": ["s_ArtifactItem.bin"],
            "client": ["c_ArtifactRes.bin"],
            "string": ["ArtifactStr.dat"],
        },
    }

    equip_type = CustomColumn(db.Enum(EssenceEquipType),
                              nullable=False,
                              mapper_key="장착대상",
                              transform=lambda v: EssenceEquipType(int(v)))

    required_weapon_level = CustomColumn(db.Integer,
                                         nullable=False,
                                         mapper_key="육상LV")

    is_core_essence = CustomColumn(db.Boolean,
                                   nullable=False,
                                   mapper_key="AtI타입")

    mounting_cost = CustomColumn(db.Integer, nullable=False, mapper_key="고정비용")

    mounting_item_level_cost = CustomColumn(db.Integer,
                                            nullable=False,
                                            mapper_key="LV비용")

    mounting_unit_cost = CustomColumn(db.Integer,
                                      nullable=False,
                                      mapper_key="비용단위")

    def to_dict(self, minimal: bool = False) -> dict:
        minimal_dict = {
            **BaseMixin.to_dict(self, minimal),
            **BonusMixin.to_dict(self),
            "equip_type": self.equip_type.to_dict(),
            "is_core_essence": self.is_core_essence,
            "required_weapon_level": self.required_weapon_level,
        }

        if minimal:
            return minimal_dict

        return {
            **minimal_dict,
            **DroppedByMixin.to_dict(self),
            **ProducedByMixin.to_dict(self),
            **NeededForMixin.to_dict(self),
            **RandomBoxMixin.to_dict(self),
        }
예제 #9
0
class StatusData(db.Model):
    """
    Includes data for all status points (up to ~1000).

    point_type can be either the listed columns (max_hp, max_mp ...)
    or level.
    If it is level, the values are the base values.
    For all other types, just the increment is stored.
    (e.g. from 5 to 6 con, you get +30 max hp).

    level is either the real level for the character or the level of the
    status point (e.g. 300, if you have 300 points invested in con).
    """
    __tablename__ = "status_data"

    index = db.Column(db.Integer, primary_key=True, autoincrement=True)

    point_type = db.Column(db.String(32), nullable=False)
    character_class = db.Column(db.Enum(CharacterClass), nullable=False)
    level = db.Column(db.Integer, nullable=False)

    max_hp = db.Column(db.Integer, nullable=False)
    max_mp = db.Column(db.Integer, nullable=False)
    avoidance = db.Column(db.Integer, nullable=False)

    melee_min_attack = db.Column(db.Integer, nullable=False)
    melee_max_attack = db.Column(db.Integer, nullable=False)
    melee_hitrate = db.Column(db.Integer, nullable=False)
    melee_critical_rate = db.Column(db.Integer, nullable=False)

    range_min_attack = db.Column(db.Integer, nullable=False)
    range_max_attack = db.Column(db.Integer, nullable=False)
    range_hitrate = db.Column(db.Integer, nullable=False)
    range_critical_rate = db.Column(db.Integer, nullable=False)

    magic_min_attack = db.Column(db.Integer, nullable=False)
    magic_max_attack = db.Column(db.Integer, nullable=False)
    magic_hitrate = db.Column(db.Integer, nullable=False)
    magic_critical_rate = db.Column(db.Integer, nullable=False)

    def to_dict(self) -> dict:
        # Dict only contains values that are non-zero
        fields = [
            "max_hp",
            "max_mp",
            "avoidance",
            "melee_min_attack",
            "melee_max_attack",
            "melee_hitrate",
            "melee_critical_rate",
            "range_min_attack",
            "range_max_attack",
            "range_hitrate",
            "range_critical_rate",
            "magic_min_attack",
            "magic_max_attack",
            "magic_hitrate",
            "magic_critical_rate",
        ]

        dic = {
            "level": self.level,
            # "point_type": self.point_type,
            # "character_class": self.character_class.to_dict(),
        }

        for field in fields:
            value = getattr(self, field)
            if value != 0:
                dic[field] = value

        return dic
예제 #10
0
class Quest(db.Model):
    __tablename__ = "quest"

    index = db.Column(db.Integer, nullable=False)
    code = db.Column(db.String(32), primary_key=True, nullable=False)

    level = db.Column(db.Integer, nullable=False)
    area = db.Column(db.Enum(Area), nullable=False)
    class_ = db.Column(db.String(16))
    money = db.Column(db.Integer)
    experience = db.Column(db.Integer)
    title = db.Column(db.String(256), nullable=False)

    selectable_items_count = db.Column(db.Integer)

    before_quest_code = db.Column(db.String(32))
    before_quest = db.relationship(
        "Quest",
        primaryjoin="foreign(Quest.code) == Quest.before_quest_code",
        uselist=False)

    after_quest = db.relationship(
        "Quest",
        primaryjoin="foreign(Quest.before_quest_code) == Quest.code",
        uselist=False)

    start_npc_code = db.Column(db.String(32), db.ForeignKey("npc.code"))
    start_npc = db.relationship("Npc",
                                foreign_keys=[start_npc_code],
                                uselist=False)

    end_npc_code = db.Column(db.String(32), db.ForeignKey("npc.code"))
    end_npc = db.relationship("Npc",
                              foreign_keys=[end_npc_code],
                              uselist=False)

    start_area_code = db.Column(db.String(32), db.ForeignKey("map.code"))
    start_area = db.relationship("Map", foreign_keys=[start_area_code])

    missions = db.relationship("QuestMission")
    selectable_items = db.relationship("QuestSelectableItem")
    give_items = db.relationship("QuestGiveItem")
    descriptions = db.relationship(
        "QuestDescription",
        primaryjoin="foreign(QuestDescription.quest_code) == Quest.code")

    def to_dict(self, minimal: bool = False) -> dict:
        minimal_dict = {
            "code": self.code,
            "area": self.area.to_dict(),
            "class": self.class_,
            "level": self.level,
            "title": self.title,
        }

        if minimal:
            return minimal_dict

        return {
            **minimal_dict,
            "money":
            self.money,
            "experience":
            self.experience,
            "selectable_items_count":
            self.selectable_items_count,
            "start_npc":
            (self.start_npc.to_dict(minimal=True) if self.start_npc else None),
            "end_npc":
            (self.end_npc.to_dict(minimal=True) if self.end_npc else None),
            "start_area": (self.start_area.to_dict(
                minimal=True) if self.start_area else None),
            "before_quest": (self.before_quest.to_dict(
                minimal=True) if self.before_quest else None),
            "after_quest": (self.after_quest.to_dict(
                minimal=True) if self.after_quest else None),
            "missions": [mission.to_dict() for mission in self.missions],
            "give_items": [gitem.to_dict() for gitem in self.give_items],
            "selectable_items":
            [sitem.to_dict() for sitem in self.selectable_items],
            "descriptions":
            {desc.language: desc.to_dict()
             for desc in self.descriptions},
        }