コード例 #1
0
ファイル: item.py プロジェクト: zhifuliu/sanguo-server
 def __init__(self, char_id):
     self.char_id = char_id
     try:
         self.item = MongoItem.objects.get(id=self.char_id)
     except DoesNotExist:
         self.item = MongoItem(id=self.char_id)
         self.item.save()
コード例 #2
0
ファイル: item.py プロジェクト: yueyoum/sanguo-server
 def __init__(self, char_id):
     self.char_id = char_id
     try:
         self.item = MongoItem.objects.get(id=self.char_id)
     except DoesNotExist:
         self.item = MongoItem(id=self.char_id)
         self.item.save()
コード例 #3
0
ファイル: item.py プロジェクト: yueyoum/sanguo-server
class Item(MessageEquipmentMixin):
    def __init__(self, char_id):
        self.char_id = char_id
        try:
            self.item = MongoItem.objects.get(id=self.char_id)
        except DoesNotExist:
            self.item = MongoItem(id=self.char_id)
            self.item.save()

    def has_equip(self, equip_id):
        return str(equip_id) in self.item.equipments

    def has_gem(self, gem_id, amount=1):
        return self.gem_amount(gem_id) >= amount

    def has_stuff(self, stuff_id, amount=1):
        return self.stuff_amount(stuff_id) >= amount

    def gem_amount(self, gem_id):
        return self.item.gems.get(str(gem_id), 0)

    def stuff_amount(self, stuff_id):
        return self.item.stuffs.get(str(stuff_id), 0)

    def equip_add(self, oid, level=1, notify=True):
        try:
            this_equip = EQUIPMENTS[oid]
        except KeyError:
            raise SanguoException(
                errormsg.EQUIPMENT_NOT_EXIST,
                self.char_id,
                "Equipment Add",
                "Equipment {0} NOT exist".format(oid)
            )

        new_id = id_generator('equipment')[0]
        me = MongoEmbeddedEquipment()
        me.oid = oid
        me.level = level
        me.gems = [0] * this_equip.slots

        self.item.equipments[str(new_id)] = me
        self.item.save()

        if notify:
            msg = protomsg.AddEquipNotify()
            msg_equip = msg.equips.add()
            self._msg_equip(msg_equip, new_id, me, Equipment(self.char_id, new_id, self.item))
            publish_to_char(self.char_id, pack_msg(msg))

        return new_id

    def equip_remove(self, ids):
        if not isinstance(ids, (set, list, tuple)):
            ids = [ids]

        ids = set(ids)
        for _id in ids:
            if not self.has_equip(_id):
                raise SanguoException(
                    errormsg.EQUIPMENT_NOT_EXIST,
                    self.char_id,
                    "Equipment Remove",
                    "Equipment {0} NOT exist".format(_id)
                )

        for _id in ids:
            self.item.equipments.pop(str(_id))

        self.item.save()

        msg = protomsg.RemoveEquipNotify()
        msg.ids.extend(ids)
        publish_to_char(self.char_id, pack_msg(msg))


    def equip_level_up(self, _id, quick):
        if not self.has_equip(_id):
            raise SanguoException(
                errormsg.EQUIPMENT_NOT_EXIST,
                self.char_id,
                "Equipment Level Up",
                "Equipment {0} NOT exist".format(_id)
            )

        e = Equipment(self.char_id, _id, self.item)
        return e.level_up(quick=quick)


    def equip_step_up(self, equip_id):
        if not self.has_equip(equip_id):
            raise SanguoException(
                errormsg.EQUIPMENT_NOT_EXIST,
                self.char_id,
                "Equipment Step Up",
                "Equipment {0} NOT exist".format(equip_id)
            )

        equip = Equipment(self.char_id, equip_id, self.item)
        equip.step_up()


    def equip_check_sell(self, ids):
        if not isinstance(ids, (set, list, tuple)):
            ids = [ids]

        f = Formation(self.char_id)
        ids = set(ids)
        for _id in ids:
            if not self.has_equip(_id):
                raise SanguoException(
                    errormsg.EQUIPMENT_NOT_EXIST,
                    self.char_id,
                    "Equipment Check Sell",
                    "Equipment {0} NOT exist".format(_id)
                )

            if f.find_socket_by_equip(_id):
                raise SanguoException(
                    errormsg.EQUIPMENT_CANNOT_SELL_FORMATION,
                    self.char_id,
                    "Equipment Check Sell",
                    "Equipment {0} in Formation, Can not sell".format(_id)
                )


    def equip_sell(self, ids):
        if not isinstance(ids, (set, list, tuple)):
            ids = [ids]

        self.equip_check_sell(ids)

        off_gems = {}

        gold = 0
        for _id in ids:
            e = Equipment(self.char_id, _id, self.item)
            gold += e.sell_gold()
            for gid in e.get_embedded_gems():
                if gid:
                    off_gems[gid] = off_gems.get(gid, 0) + 1

        resource = Resource(self.char_id, "Equipment Sell", "equipments {0}".format(ids))
        resource.check_and_remove(equipments=list(ids))
        resource.add(gold=gold)

        self.gem_add(off_gems.items())


    def equip_embed(self, _id, slot_id, gem_id):
        # gem_id = 0 表示取下slot_id对应的宝石
        if not self.has_equip(_id):
            raise SanguoException(
                errormsg.EQUIPMENT_NOT_EXIST,
                self.char_id,
                "Equipment Embed Gem",
                "Equipment {0} NOT exist".format(_id)
            )

        if gem_id and not self.has_gem(gem_id):
            raise SanguoException(
                errormsg.GEM_NOT_EXIST,
                self.char_id,
                "Equipment Embed Gem",
                "Gem {0} NOT exist".format(gem_id)
            )


        slot_index = slot_id - 1

        e = Equipment(self.char_id, _id, self.item)
        if gem_id:
            off_gem = e.add_gem(slot_index, gem_id)
            self.gem_remove(gem_id, 1)
            if off_gem:
                self.gem_add([(off_gem, 1)])
        else:
            off_gem = e.rem_gem(slot_index)
            self.gem_add([(off_gem, 1)])

        self.item.save()


    def gem_add(self, add_gems, send_notify=True):
        """

        @param add_gems: [(id, amount), (id, amount)]
        @type add_gems: list | tuple
        """

        for gid, _ in add_gems:
            if gid not in GEMS:
                raise SanguoException(
                    errormsg.GEM_NOT_EXIST,
                    self.char_id,
                    "Gem Add",
                    "Gem {0} not exist".format(gid)
                )


        gems = self.item.gems
        add_gems_dict = {}
        for gid, amount in add_gems:
            add_gems_dict[gid] = add_gems_dict.get(gid, 0) + amount

        new_gems = []
        update_gems = []
        for gid, amount in add_gems_dict.iteritems():
            gid = str(gid)
            if gid in gems:
                gems[gid] += amount
                update_gems.append((int(gid), gems[gid]))
            else:
                gems[gid] = amount
                new_gems.append((int(gid), amount))

        self.item.gems = gems
        self.item.save()

        for gid, amount in add_gems_dict.iteritems():
            gem_add_signal.send(
                sender=None,
                char_id=self.char_id,
                gem_id=gid,
                add_amount=amount,
                new_amount=gems[str(gid)]
            )

        if not send_notify:
            return
        if new_gems:
            msg = protomsg.AddGemNotify()
            for k, v in new_gems:
                g = msg.gems.add()
                g.id, g.amount = k, v

            publish_to_char(self.char_id, pack_msg(msg))

        if update_gems:
            msg = protomsg.UpdateGemNotify()
            for k, v in update_gems:
                g = msg.gems.add()
                g.id, g.amount = k, v

            publish_to_char(self.char_id, pack_msg(msg))

    def gem_remove(self, _id, amount):
        """

        @param _id: gem id
        @type _id: int
        @param amount: this gem amount
        @type amount: int
        """
        try:
            this_gem_amount = self.item.gems[str(_id)]
        except KeyError:
            raise SanguoException(
                errormsg.GEM_NOT_EXIST,
                self.char_id,
                "Gem Remove",
                "Gem {0} not exist".format(_id)
            )

        new_amount = this_gem_amount - amount
        if new_amount <= 0:
            self.item.gems.pop(str(_id))
            self.item.save()

            msg = protomsg.RemoveGemNotify()
            msg.ids.append(_id)
            publish_to_char(self.char_id, pack_msg(msg))
        else:
            self.item.gems[str(_id)] = new_amount
            self.item.save()
            msg = protomsg.UpdateGemNotify()
            g = msg.gems.add()
            g.id, g.amount = _id, new_amount

            publish_to_char(self.char_id, pack_msg(msg))

        gem_remove_signal.send(
            sender=None,
            char_id=self.char_id,
            gem_id=_id,
            rm_amount=amount,
            new_amount=self.item.gems.get(str(_id), 0)
        )


    def gem_check_sell(self, _id, _amount):
        if not self.has_gem(_id, _amount):
            raise SanguoException(
                errormsg.GEM_NOT_EXIST,
                self.char_id,
                "Gem Check Sell",
                "Gem {0}, amount {1} not exist/enough".format(_id, _amount)
            )

    def gem_sell(self, _id, amount):
        try:
            this_gem = GEMS[_id]
        except KeyError:
            raise SanguoException(
                errormsg.GEM_NOT_EXIST,
                self.char_id,
                "Gem Sell",
                "Gem {0} not exist".format(_id)
            )

        gold = this_gem.sell_gold * amount

        resource = Resource(self.char_id, "Gem Sell", "sell: {0}, amount {1}".format(_id, amount))
        resource.check_and_remove(gems=[(_id, amount)])
        resource.add(gold=gold)


    def gem_merge(self, _id, method):
        this_gem_amount = self.item.gems.get(str(_id), 0)
        if this_gem_amount == 0:
            raise SanguoException(
                errormsg.GEM_NOT_EXIST,
                self.char_id,
                "Gem Merge",
                "Gem {0} not exist".format(_id)
            )

        elif this_gem_amount < 4:
            raise SanguoException(
                errormsg.GEM_NOT_ENOUGH,
                self.char_id,
                "Gem Merge",
                "Gem {0} not enough. {1} < 4".format(_id, this_gem_amount)
            )

        to_id = GEMS[_id].merge_to
        if not to_id:
            raise SanguoException(
                errormsg.GEM_CAN_NOT_MERGE,
                self.char_id,
                "Gem Merge",
                "Gem {0} can not merge".format(_id)
            )

        if method == MergeGemRequest.SIMPLE:
            # 单次合成
            to_amount = 1
        else:
            # 自动全部合成
            to_amount, _ = divmod(this_gem_amount, 4)

        remove_amount = to_amount * 4

        self.gem_remove(_id, remove_amount)
        self.gem_add([(to_id, to_amount)])

        to_gem_obj = GEMS[to_id]

        achievement = Achievement(self.char_id)
        achievement.trig(25, to_amount)
        achievement.trig(26, to_gem_obj.level)

        tl = TimesLogGemMerge(self.char_id)
        for i in range(to_amount):
            tl.inc()

        return to_id, to_amount


    def stuff_add(self, add_stuffs, send_notify=True):
        """

        @param add_stuffs: [(id, amount), (id, amount)]
        @type add_stuffs: list | tuple
        """
        for _id, _ in add_stuffs:
            if _id not in STUFFS:
                raise SanguoException(
                    errormsg.STUFF_NOT_EXIST,
                    self.char_id,
                    "Stuff Add",
                    "Stuff Oid {0} not exist".format(_id)
                )

        stuffs = self.item.stuffs
        add_stuffs_dict = {}
        for _id, _amount in add_stuffs:
            add_stuffs_dict[_id] = add_stuffs_dict.get(_id, 0) + _amount

        new_stuffs = []
        update_stuffs = []
        for _id, _amount in add_stuffs_dict.iteritems():
            sid = str(_id)
            if sid in stuffs:
                stuffs[sid] += _amount
                update_stuffs.append((_id, stuffs[sid]))
            else:
                stuffs[sid] = _amount
                new_stuffs.append((_id, _amount))

        self.item.stuffs = stuffs
        self.item.save()

        for _id, _amount in add_stuffs_dict.iteritems():
            stuff_add_signal.send(
                sender=None,
                char_id=self.char_id,
                stuff_id=_id,
                add_amount=_amount,
                new_amount=stuffs[str(_id)]
            )

        if not send_notify:
            return
        if new_stuffs:
            msg = protomsg.AddStuffNotify()
            for k, v in new_stuffs:
                s = msg.stuffs.add()
                s.id, s.amount = k, v

            publish_to_char(self.char_id, pack_msg(msg))

        if update_stuffs:
            msg = protomsg.UpdateStuffNotify()
            for k, v in update_stuffs:
                s = msg.stuffs.add()
                s.id, s.amount = k, v

            publish_to_char(self.char_id, pack_msg(msg))



    def stuff_remove(self, _id, amount):
        """
        @param _id: stuff id
        @type _id: int
        @param amount: this stuff amount
        @type amount: int
        """
        try:
            this_stuff_amount = self.item.stuffs[str(_id)]
        except KeyError:
            raise SanguoException(
                errormsg.STUFF_NOT_EXIST,
                self.char_id,
                "Stuff Remove",
                "Stuff {0} not exist".format(_id)
            )

        new_amount = this_stuff_amount - amount

        if new_amount < 0:
            raise SanguoException(
                errormsg.STUFF_NOT_ENOUGH,
                self.char_id,
                "Stuff Remove",
                "Stuff {0} not enough".format(_id)
            )

        if new_amount == 0:
            self.item.stuffs.pop(str(_id))
            self.item.save()

            msg = protomsg.RemoveStuffNotify()
            msg.ids.append(_id)
            publish_to_char(self.char_id, pack_msg(msg))
        else:
            self.item.stuffs[str(_id)] = new_amount
            self.item.save()
            msg = protomsg.UpdateStuffNotify()
            g = msg.stuffs.add()
            g.id, g.amount = _id, new_amount

            publish_to_char(self.char_id, pack_msg(msg))

        stuff_remove_signal.send(
            sender=None,
            char_id=self.char_id,
            stuff_id=_id,
            rm_amount=amount,
            new_amount=self.item.stuffs.get(str(_id), 0)
        )


    def stuff_check_sell(self, _id, amount):
        if not self.has_stuff(_id, amount):
            raise SanguoException(
                errormsg.STUFF_NOT_EXIST,
                self.char_id,
                "Stuff Check Sell",
                "Stuff {0}, amount {1} not exist/enough".format(_id, amount)
            )


    def stuff_sell(self, _id, amount):
        try:
            this_stuff = STUFFS[_id]
        except KeyError:
            raise SanguoException(
                errormsg.STUFF_NOT_EXIST,
                self.char_id,
                "Stuff Sell",
                "Stuff {0} not exist".format(_id)
            )

        gold = this_stuff.sell_gold * amount

        resource = Resource(self.char_id, "Stuff Sell", "sell {0}, amount: {1}".format(_id, amount))
        resource.check_and_remove(stuffs=[(_id, amount)])
        resource.add(gold=gold)


    @classmethod
    def get_sutff_drop(cls, _id):
        # 获得宝箱中的 drop
        from core.attachment import get_drop, is_empty_drop, make_standard_drop_from_template

        s = STUFFS[_id]
        packages = s.packages
        if not packages:
            return make_standard_drop_from_template()

        package_ids = [int(i) for i in packages.split(',')]
        prepare_drop = get_drop(package_ids)
        if is_empty_drop(prepare_drop) and s.default_package:
            package_ids = [s.default_package]
            prepare_drop = get_drop(package_ids)

        return prepare_drop


    def stuff_use(self, _id, amount):
        from core.attachment import standard_drop_to_attachment_protomsg, is_empty_drop, merge_drop
        from core.resource import Resource
        try:
            s = STUFFS[_id]
        except KeyError:
            raise SanguoException(
                errormsg.STUFF_NOT_EXIST,
                self.char_id,
                "Stuff Use",
                "stuff {0} not exist".format(_id)
            )

        # XXX
        if s.tp != 3:
            raise SanguoException(
                errormsg.STUFF_CAN_NOT_USE,
                self.char_id,
                "Stuff Use",
                "stuff {0} tp is {1}. Can not use".format(_id, s.tp)
            )

        # XXX 忽略amount,只能一个一个用
        self.stuff_remove(_id, amount)

        # 活动 10001
        additional_drop_1 = ActivityEntry(self.char_id, 10001).get_additional_drop(_id)
        additional_drop_2 = ActivityEntry(self.char_id, 12001).get_additional_drop(_id)
        additional_drop_3 = ActivityEntry(self.char_id, 15001).get_additional_drop(_id)

        prepare_drop = self.get_sutff_drop(_id)
        drop = merge_drop([prepare_drop, additional_drop_1, additional_drop_2, additional_drop_3])
        if is_empty_drop(drop):
            return None

        resource = Resource(self.char_id, "Stuff Use", "use {0}".format(_id))
        standard_drop = resource.add(**drop)
        return standard_drop_to_attachment_protomsg(standard_drop)



    def send_equip_notify(self):
        msg = protomsg.EquipNotify()
        for _id, data in self.item.equipments.iteritems():
            equip = msg.equips.add()
            self._msg_equip(equip, int(_id), data, Equipment(self.char_id, int(_id), self.item))

        publish_to_char(self.char_id, pack_msg(msg))


    def send_gem_notify(self):
        msg = protomsg.GemNotify()
        for k, v in self.item.gems.iteritems():
            g = msg.gems.add()
            g.id, g.amount = int(k), v

        publish_to_char(self.char_id, pack_msg(msg))

    def send_stuff_notify(self):
        msg = protomsg.StuffNotify()
        for k, v in self.item.stuffs.iteritems():
            s = msg.stuffs.add()
            s.id, s.amount = int(k), v

        publish_to_char(self.char_id, pack_msg(msg))


    def send_notify(self):
        self.send_equip_notify()
        self.send_gem_notify()
        self.send_stuff_notify()
コード例 #4
0
ファイル: item.py プロジェクト: zhifuliu/sanguo-server
class Item(MessageEquipmentMixin):
    def __init__(self, char_id):
        self.char_id = char_id
        try:
            self.item = MongoItem.objects.get(id=self.char_id)
        except DoesNotExist:
            self.item = MongoItem(id=self.char_id)
            self.item.save()

    def has_equip(self, equip_id):
        return str(equip_id) in self.item.equipments

    def has_gem(self, gem_id, amount=1):
        return self.gem_amount(gem_id) >= amount

    def has_stuff(self, stuff_id, amount=1):
        return self.stuff_amount(stuff_id) >= amount

    def gem_amount(self, gem_id):
        return self.item.gems.get(str(gem_id), 0)

    def stuff_amount(self, stuff_id):
        return self.item.stuffs.get(str(stuff_id), 0)

    def equip_add(self, oid, level=1, notify=True):
        try:
            this_equip = EQUIPMENTS[oid]
        except KeyError:
            raise SanguoException(errormsg.EQUIPMENT_NOT_EXIST, self.char_id,
                                  "Equipment Add",
                                  "Equipment {0} NOT exist".format(oid))

        new_id = id_generator('equipment')[0]
        me = MongoEmbeddedEquipment()
        me.oid = oid
        me.level = level
        me.gems = [0] * this_equip.slots

        self.item.equipments[str(new_id)] = me
        self.item.save()

        if notify:
            msg = protomsg.AddEquipNotify()
            msg_equip = msg.equips.add()
            self._msg_equip(msg_equip, new_id, me,
                            Equipment(self.char_id, new_id, self.item))
            publish_to_char(self.char_id, pack_msg(msg))

        return new_id

    def equip_remove(self, ids):
        if not isinstance(ids, (set, list, tuple)):
            ids = [ids]

        ids = set(ids)
        for _id in ids:
            if not self.has_equip(_id):
                raise SanguoException(errormsg.EQUIPMENT_NOT_EXIST,
                                      self.char_id, "Equipment Remove",
                                      "Equipment {0} NOT exist".format(_id))

        for _id in ids:
            self.item.equipments.pop(str(_id))

        self.item.save()

        msg = protomsg.RemoveEquipNotify()
        msg.ids.extend(ids)
        publish_to_char(self.char_id, pack_msg(msg))

    def equip_level_up(self, _id, quick):
        if not self.has_equip(_id):
            raise SanguoException(errormsg.EQUIPMENT_NOT_EXIST, self.char_id,
                                  "Equipment Level Up",
                                  "Equipment {0} NOT exist".format(_id))

        e = Equipment(self.char_id, _id, self.item)
        return e.level_up(quick=quick)

    def equip_step_up(self, equip_id):
        if not self.has_equip(equip_id):
            raise SanguoException(errormsg.EQUIPMENT_NOT_EXIST, self.char_id,
                                  "Equipment Step Up",
                                  "Equipment {0} NOT exist".format(equip_id))

        equip = Equipment(self.char_id, equip_id, self.item)
        equip.step_up()

    def equip_check_sell(self, ids):
        if not isinstance(ids, (set, list, tuple)):
            ids = [ids]

        f = Formation(self.char_id)
        ids = set(ids)
        for _id in ids:
            if not self.has_equip(_id):
                raise SanguoException(errormsg.EQUIPMENT_NOT_EXIST,
                                      self.char_id, "Equipment Check Sell",
                                      "Equipment {0} NOT exist".format(_id))

            if f.find_socket_by_equip(_id):
                raise SanguoException(
                    errormsg.EQUIPMENT_CANNOT_SELL_FORMATION, self.char_id,
                    "Equipment Check Sell",
                    "Equipment {0} in Formation, Can not sell".format(_id))

    def equip_sell(self, ids):
        if not isinstance(ids, (set, list, tuple)):
            ids = [ids]

        self.equip_check_sell(ids)

        off_gems = {}

        gold = 0
        for _id in ids:
            e = Equipment(self.char_id, _id, self.item)
            gold += e.sell_gold()
            for gid in e.get_embedded_gems():
                if gid:
                    off_gems[gid] = off_gems.get(gid, 0) + 1

        resource = Resource(self.char_id, "Equipment Sell",
                            "equipments {0}".format(ids))
        resource.check_and_remove(equipments=list(ids))
        resource.add(gold=gold)

        self.gem_add(off_gems.items())

    def equip_embed(self, _id, slot_id, gem_id):
        # gem_id = 0 表示取下slot_id对应的宝石
        if not self.has_equip(_id):
            raise SanguoException(errormsg.EQUIPMENT_NOT_EXIST, self.char_id,
                                  "Equipment Embed Gem",
                                  "Equipment {0} NOT exist".format(_id))

        if gem_id and not self.has_gem(gem_id):
            raise SanguoException(errormsg.GEM_NOT_EXIST, self.char_id,
                                  "Equipment Embed Gem",
                                  "Gem {0} NOT exist".format(gem_id))

        slot_index = slot_id - 1

        e = Equipment(self.char_id, _id, self.item)
        if gem_id:
            off_gem = e.add_gem(slot_index, gem_id)
            self.gem_remove(gem_id, 1)
            if off_gem:
                self.gem_add([(off_gem, 1)])
        else:
            off_gem = e.rem_gem(slot_index)
            self.gem_add([(off_gem, 1)])

        self.item.save()

    def gem_add(self, add_gems, send_notify=True):
        """

        @param add_gems: [(id, amount), (id, amount)]
        @type add_gems: list | tuple
        """

        for gid, _ in add_gems:
            if gid not in GEMS:
                raise SanguoException(errormsg.GEM_NOT_EXIST, self.char_id,
                                      "Gem Add",
                                      "Gem {0} not exist".format(gid))

        gems = self.item.gems
        add_gems_dict = {}
        for gid, amount in add_gems:
            add_gems_dict[gid] = add_gems_dict.get(gid, 0) + amount

        new_gems = []
        update_gems = []
        for gid, amount in add_gems_dict.iteritems():
            gid = str(gid)
            if gid in gems:
                gems[gid] += amount
                update_gems.append((int(gid), gems[gid]))
            else:
                gems[gid] = amount
                new_gems.append((int(gid), amount))

        self.item.gems = gems
        self.item.save()

        for gid, amount in add_gems_dict.iteritems():
            gem_add_signal.send(sender=None,
                                char_id=self.char_id,
                                gem_id=gid,
                                add_amount=amount,
                                new_amount=gems[str(gid)])

        if not send_notify:
            return
        if new_gems:
            msg = protomsg.AddGemNotify()
            for k, v in new_gems:
                g = msg.gems.add()
                g.id, g.amount = k, v

            publish_to_char(self.char_id, pack_msg(msg))

        if update_gems:
            msg = protomsg.UpdateGemNotify()
            for k, v in update_gems:
                g = msg.gems.add()
                g.id, g.amount = k, v

            publish_to_char(self.char_id, pack_msg(msg))

    def gem_remove(self, _id, amount):
        """

        @param _id: gem id
        @type _id: int
        @param amount: this gem amount
        @type amount: int
        """
        try:
            this_gem_amount = self.item.gems[str(_id)]
        except KeyError:
            raise SanguoException(errormsg.GEM_NOT_EXIST, self.char_id,
                                  "Gem Remove",
                                  "Gem {0} not exist".format(_id))

        new_amount = this_gem_amount - amount
        if new_amount <= 0:
            self.item.gems.pop(str(_id))
            self.item.save()

            msg = protomsg.RemoveGemNotify()
            msg.ids.append(_id)
            publish_to_char(self.char_id, pack_msg(msg))
        else:
            self.item.gems[str(_id)] = new_amount
            self.item.save()
            msg = protomsg.UpdateGemNotify()
            g = msg.gems.add()
            g.id, g.amount = _id, new_amount

            publish_to_char(self.char_id, pack_msg(msg))

        gem_remove_signal.send(sender=None,
                               char_id=self.char_id,
                               gem_id=_id,
                               rm_amount=amount,
                               new_amount=self.item.gems.get(str(_id), 0))

    def gem_check_sell(self, _id, _amount):
        if not self.has_gem(_id, _amount):
            raise SanguoException(
                errormsg.GEM_NOT_EXIST, self.char_id, "Gem Check Sell",
                "Gem {0}, amount {1} not exist/enough".format(_id, _amount))

    def gem_sell(self, _id, amount):
        try:
            this_gem = GEMS[_id]
        except KeyError:
            raise SanguoException(errormsg.GEM_NOT_EXIST, self.char_id,
                                  "Gem Sell", "Gem {0} not exist".format(_id))

        gold = this_gem.sell_gold * amount

        resource = Resource(self.char_id, "Gem Sell",
                            "sell: {0}, amount {1}".format(_id, amount))
        resource.check_and_remove(gems=[(_id, amount)])
        resource.add(gold=gold)

    def gem_merge(self, _id, method):
        this_gem_amount = self.item.gems.get(str(_id), 0)
        if this_gem_amount == 0:
            raise SanguoException(errormsg.GEM_NOT_EXIST, self.char_id,
                                  "Gem Merge", "Gem {0} not exist".format(_id))

        elif this_gem_amount < 4:
            raise SanguoException(
                errormsg.GEM_NOT_ENOUGH, self.char_id, "Gem Merge",
                "Gem {0} not enough. {1} < 4".format(_id, this_gem_amount))

        to_id = GEMS[_id].merge_to
        if not to_id:
            raise SanguoException(errormsg.GEM_CAN_NOT_MERGE, self.char_id,
                                  "Gem Merge",
                                  "Gem {0} can not merge".format(_id))

        if method == MergeGemRequest.SIMPLE:
            # 单次合成
            to_amount = 1
        else:
            # 自动全部合成
            to_amount, _ = divmod(this_gem_amount, 4)

        remove_amount = to_amount * 4

        self.gem_remove(_id, remove_amount)
        self.gem_add([(to_id, to_amount)])

        to_gem_obj = GEMS[to_id]

        achievement = Achievement(self.char_id)
        achievement.trig(25, to_amount)
        achievement.trig(26, to_gem_obj.level)

        tl = TimesLogGemMerge(self.char_id)
        for i in range(to_amount):
            tl.inc()

        return to_id, to_amount

    def stuff_add(self, add_stuffs, send_notify=True):
        """

        @param add_stuffs: [(id, amount), (id, amount)]
        @type add_stuffs: list | tuple
        """
        for _id, _ in add_stuffs:
            if _id not in STUFFS:
                raise SanguoException(errormsg.STUFF_NOT_EXIST, self.char_id,
                                      "Stuff Add",
                                      "Stuff Oid {0} not exist".format(_id))

        stuffs = self.item.stuffs
        add_stuffs_dict = {}
        for _id, _amount in add_stuffs:
            add_stuffs_dict[_id] = add_stuffs_dict.get(_id, 0) + _amount

        new_stuffs = []
        update_stuffs = []
        for _id, _amount in add_stuffs_dict.iteritems():
            sid = str(_id)
            if sid in stuffs:
                stuffs[sid] += _amount
                update_stuffs.append((_id, stuffs[sid]))
            else:
                stuffs[sid] = _amount
                new_stuffs.append((_id, _amount))

        self.item.stuffs = stuffs
        self.item.save()

        for _id, _amount in add_stuffs_dict.iteritems():
            stuff_add_signal.send(sender=None,
                                  char_id=self.char_id,
                                  stuff_id=_id,
                                  add_amount=_amount,
                                  new_amount=stuffs[str(_id)])

        if not send_notify:
            return
        if new_stuffs:
            msg = protomsg.AddStuffNotify()
            for k, v in new_stuffs:
                s = msg.stuffs.add()
                s.id, s.amount = k, v

            publish_to_char(self.char_id, pack_msg(msg))

        if update_stuffs:
            msg = protomsg.UpdateStuffNotify()
            for k, v in update_stuffs:
                s = msg.stuffs.add()
                s.id, s.amount = k, v

            publish_to_char(self.char_id, pack_msg(msg))

    def stuff_remove(self, _id, amount):
        """
        @param _id: stuff id
        @type _id: int
        @param amount: this stuff amount
        @type amount: int
        """
        try:
            this_stuff_amount = self.item.stuffs[str(_id)]
        except KeyError:
            raise SanguoException(errormsg.STUFF_NOT_EXIST, self.char_id,
                                  "Stuff Remove",
                                  "Stuff {0} not exist".format(_id))

        new_amount = this_stuff_amount - amount

        if new_amount < 0:
            raise SanguoException(errormsg.STUFF_NOT_ENOUGH, self.char_id,
                                  "Stuff Remove",
                                  "Stuff {0} not enough".format(_id))

        if new_amount == 0:
            self.item.stuffs.pop(str(_id))
            self.item.save()

            msg = protomsg.RemoveStuffNotify()
            msg.ids.append(_id)
            publish_to_char(self.char_id, pack_msg(msg))
        else:
            self.item.stuffs[str(_id)] = new_amount
            self.item.save()
            msg = protomsg.UpdateStuffNotify()
            g = msg.stuffs.add()
            g.id, g.amount = _id, new_amount

            publish_to_char(self.char_id, pack_msg(msg))

        stuff_remove_signal.send(sender=None,
                                 char_id=self.char_id,
                                 stuff_id=_id,
                                 rm_amount=amount,
                                 new_amount=self.item.stuffs.get(str(_id), 0))

    def stuff_check_sell(self, _id, amount):
        if not self.has_stuff(_id, amount):
            raise SanguoException(
                errormsg.STUFF_NOT_EXIST, self.char_id, "Stuff Check Sell",
                "Stuff {0}, amount {1} not exist/enough".format(_id, amount))

    def stuff_sell(self, _id, amount):
        try:
            this_stuff = STUFFS[_id]
        except KeyError:
            raise SanguoException(errormsg.STUFF_NOT_EXIST, self.char_id,
                                  "Stuff Sell",
                                  "Stuff {0} not exist".format(_id))

        gold = this_stuff.sell_gold * amount

        resource = Resource(self.char_id, "Stuff Sell",
                            "sell {0}, amount: {1}".format(_id, amount))
        resource.check_and_remove(stuffs=[(_id, amount)])
        resource.add(gold=gold)

    @classmethod
    def get_sutff_drop(cls, _id):
        # 获得宝箱中的 drop
        from core.attachment import get_drop, is_empty_drop, make_standard_drop_from_template

        s = STUFFS[_id]
        packages = s.packages
        if not packages:
            return make_standard_drop_from_template()

        package_ids = [int(i) for i in packages.split(',')]
        prepare_drop = get_drop(package_ids)
        if is_empty_drop(prepare_drop) and s.default_package:
            package_ids = [s.default_package]
            prepare_drop = get_drop(package_ids)

        return prepare_drop

    def stuff_use(self, _id, amount):
        from core.attachment import standard_drop_to_attachment_protomsg, is_empty_drop, merge_drop
        from core.resource import Resource
        try:
            s = STUFFS[_id]
        except KeyError:
            raise SanguoException(errormsg.STUFF_NOT_EXIST, self.char_id,
                                  "Stuff Use",
                                  "stuff {0} not exist".format(_id))

        # XXX
        if s.tp != 3:
            raise SanguoException(
                errormsg.STUFF_CAN_NOT_USE, self.char_id, "Stuff Use",
                "stuff {0} tp is {1}. Can not use".format(_id, s.tp))

        # XXX 忽略amount,只能一个一个用
        self.stuff_remove(_id, amount)

        # 活动 10001
        additional_drop_1 = ActivityEntry(self.char_id,
                                          10001).get_additional_drop(_id)
        additional_drop_2 = ActivityEntry(self.char_id,
                                          12001).get_additional_drop(_id)
        additional_drop_3 = ActivityEntry(self.char_id,
                                          15001).get_additional_drop(_id)

        prepare_drop = self.get_sutff_drop(_id)
        drop = merge_drop([
            prepare_drop, additional_drop_1, additional_drop_2,
            additional_drop_3
        ])
        if is_empty_drop(drop):
            return None

        resource = Resource(self.char_id, "Stuff Use", "use {0}".format(_id))
        standard_drop = resource.add(**drop)
        return standard_drop_to_attachment_protomsg(standard_drop)

    def send_equip_notify(self):
        msg = protomsg.EquipNotify()
        for _id, data in self.item.equipments.iteritems():
            equip = msg.equips.add()
            self._msg_equip(equip, int(_id), data,
                            Equipment(self.char_id, int(_id), self.item))

        publish_to_char(self.char_id, pack_msg(msg))

    def send_gem_notify(self):
        msg = protomsg.GemNotify()
        for k, v in self.item.gems.iteritems():
            g = msg.gems.add()
            g.id, g.amount = int(k), v

        publish_to_char(self.char_id, pack_msg(msg))

    def send_stuff_notify(self):
        msg = protomsg.StuffNotify()
        for k, v in self.item.stuffs.iteritems():
            s = msg.stuffs.add()
            s.id, s.amount = int(k), v

        publish_to_char(self.char_id, pack_msg(msg))

    def send_notify(self):
        self.send_equip_notify()
        self.send_gem_notify()
        self.send_stuff_notify()
コード例 #5
0
class Item(MessageEquipmentMixin):
    def __init__(self, char_id):
        self.char_id = char_id
        try:
            self.item = MongoItem.objects.get(id=self.char_id)
        except DoesNotExist:
            self.item = MongoItem(id=self.char_id)
            self.item.save()

    def has_equip(self, equip_id):
        return str(equip_id) in self.item.equipments

    def has_gem(self, gem_id, amount=1):
        return self.item.gems.get(str(gem_id), 0) >= amount

    def has_stuff(self, stuff_id, amount=1):
        return self.item.stuffs.get(str(stuff_id), 0) >= amount

    def equip_add(self, oid, level=1, notify=True):
        try:
            this_equip = EQUIPMENTS[oid]
        except KeyError:
            raise SanguoException(
                errormsg.EQUIPMENT_NOT_EXIST,
                self.char_id,
                "Equipment Add",
                "Equipment {0} NOT exist".format(oid)
            )

        new_id = document_ids.inc('equipment')
        me = MongoEmbeddedEquipment()
        me.oid = oid
        me.level = level
        me.gems = [0] * this_equip.slots

        self.item.equipments[str(new_id)] = me
        self.item.save()

        if notify:
            msg = protomsg.AddEquipNotify()
            msg_equip = msg.equips.add()
            self._msg_equip(msg_equip, new_id, me, Equipment(self.char_id, new_id, self.item))
            publish_to_char(self.char_id, pack_msg(msg))

        return new_id

    def equip_remove(self, ids):
        if not isinstance(ids, (set, list, tuple)):
            ids = [ids]

        ids = set(ids)
        for _id in ids:
            if not self.has_equip(_id):
                raise SanguoException(
                    errormsg.EQUIPMENT_NOT_EXIST,
                    self.char_id,
                    "Equipment Remove",
                    "Equipment {0} NOT exist".format(_id)
                )

        for _id in ids:
            self.item.equipments.pop(str(_id))

        self.item.save()

        msg = protomsg.RemoveEquipNotify()
        msg.ids.extend(ids)
        publish_to_char(self.char_id, pack_msg(msg))


    def equip_level_up(self, _id, quick):
        if not self.has_equip(_id):
            raise SanguoException(
                errormsg.EQUIPMENT_NOT_EXIST,
                self.char_id,
                "Equipment Level Up",
                "Equipment {0} NOT exist".format(_id)
            )

        e = Equipment(self.char_id, _id, self.item)
        return e.level_up(quick=quick)


    def equip_step_up(self, equip_id):
        if not self.has_equip(equip_id):
            raise SanguoException(
                errormsg.EQUIPMENT_NOT_EXIST,
                self.char_id,
                "Equipment Step Up",
                "Equipment {0} NOT exist".format(equip_id)
            )

        equip = Equipment(self.char_id, equip_id, self.item)
        equip.step_up()



    def equip_sell(self, ids):
        if not isinstance(ids, (set, list, tuple)):
            ids = [ids]

        f = Formation(self.char_id)
        ids = set(ids)
        for _id in ids:
            if not self.has_equip(_id):
                raise SanguoException(
                    errormsg.EQUIPMENT_NOT_EXIST,
                    self.char_id,
                    "Equipment Sell",
                    "Equipment {0} NOT exist".format(_id)
                )

            if f.find_socket_by_equip(_id):
                raise SanguoException(
                    errormsg.EQUIPMENT_CANNOT_SELL_FORMATION,
                    self.char_id,
                    "Equipment Sell",
                    "Equipment {0} in Formation, Can not sell".format(_id)
                )

        gold = 0
        for _id in ids:
            e = Equipment(self.char_id, _id, self.item)
            gold += e.sell_gold()

        resource = Resource(self.char_id, "Equipment Sell", "equipments {0}".format(ids))
        resource.check_and_remove(equipments=list(ids))
        resource.add(gold=gold)


    def equip_embed(self, _id, slot_id, gem_id):
        # gem_id = 0 表示取下slot_id对应的宝石
        if not self.has_equip(_id):
            raise SanguoException(
                errormsg.EQUIPMENT_NOT_EXIST,
                self.char_id,
                "Equipment Embed Gem",
                "Equipment {0} NOT exist".format(_id)
            )

        if gem_id and not self.has_gem(gem_id):
            raise SanguoException(
                errormsg.GEM_NOT_EXIST,
                self.char_id,
                "Equipment Embed Gem",
                "Gem {0} NOT exist".format(gem_id)
            )


        slot_index = slot_id - 1

        e = Equipment(self.char_id, _id, self.item)
        if gem_id:
            off_gem = e.add_gem(slot_index, gem_id)
            self.gem_remove(gem_id, 1)
            if off_gem:
                self.gem_add([(off_gem, 1)])
        else:
            off_gem = e.rem_gem(slot_index)
            self.gem_add([(off_gem, 1)])

        self.item.save()


    def special_buy(self, socket_id, tp):
        f = Formation(self.char_id)
        f.special_buy(socket_id, tp)


    def gem_add(self, add_gems, send_notify=True):
        """

        @param add_gems: [(id, amount), (id, amount)]
        @type add_gems: list | tuple
        """

        for gid, _ in add_gems:
            if gid not in GEMS:
                raise SanguoException(
                    errormsg.GEM_NOT_EXIST,
                    self.char_id,
                    "Gem Add",
                    "Gem {0} not exist".format(gid)
                )


        gems = self.item.gems
        add_gems_dict = {}
        for gid, amount in add_gems:
            add_gems_dict[gid] = add_gems_dict.get(gid, 0) + amount

        new_gems = []
        update_gems = []
        for gid, amount in add_gems_dict.iteritems():
            gid = str(gid)
            if gid in gems:
                gems[gid] += amount
                update_gems.append((int(gid), gems[gid]))
            else:
                gems[gid] = amount
                new_gems.append((int(gid), amount))

        self.item.gems = gems
        self.item.save()

        if not send_notify:
            return
        if new_gems:
            msg = protomsg.AddGemNotify()
            for k, v in new_gems:
                g = msg.gems.add()
                g.id, g.amount = k, v

            publish_to_char(self.char_id, pack_msg(msg))

        if update_gems:
            msg = protomsg.UpdateGemNotify()
            for k, v in update_gems:
                g = msg.gems.add()
                g.id, g.amount = k, v

            publish_to_char(self.char_id, pack_msg(msg))

    def gem_remove(self, _id, amount):
        """

        @param _id: gem id
        @type _id: int
        @param amount: this gem amount
        @type amount: int
        """
        try:
            this_gem_amount = self.item.gems[str(_id)]
        except KeyError:
            raise SanguoException(
                errormsg.GEM_NOT_EXIST,
                self.char_id,
                "Gem Remove",
                "Gem {0} not exist".format(_id)
            )

        new_amount = this_gem_amount - amount
        if new_amount <= 0:
            self.item.gems.pop(str(_id))
            self.item.save()

            msg = protomsg.RemoveGemNotify()
            msg.ids.append(_id)
            publish_to_char(self.char_id, pack_msg(msg))
        else:
            self.item.gems[str(_id)] = new_amount
            self.item.save()
            msg = protomsg.UpdateGemNotify()
            g = msg.gems.add()
            g.id, g.amount = _id, new_amount

            publish_to_char(self.char_id, pack_msg(msg))


    def gem_sell(self, _id, amount):
        gold = 10 * amount

        resource = Resource(self.char_id, "Gem Sell", "sell: {0}, amount {1}".format(_id, amount))
        resource.check_and_remove(gems=[(_id, amount)])
        resource.add(gold=gold)


    def gem_merge(self, _id):
        this_gem_amount = self.item.gems.get(str(_id), 0)
        if this_gem_amount == 0:
            raise SanguoException(
                errormsg.GEM_NOT_EXIST,
                self.char_id,
                "Gem Merge",
                "Gem {0} not exist".format(_id)
            )

        elif this_gem_amount < 4:
            raise SanguoException(
                errormsg.GEM_NOT_ENOUGH,
                self.char_id,
                "Gem Merge",
                "Gem {0} not enough. {1} < 4".format(_id, this_gem_amount)
            )

        to_id = GEMS[_id].merge_to
        if not to_id:
            raise SanguoException(
                errormsg.GEM_CAN_NOT_MERGE,
                self.char_id,
                "Gem Merge",
                "Gem {0} can not merge".format(_id)
            )

        self.gem_remove(_id, 4)
        self.gem_add([(to_id, 1)])

        to_gem_obj = GEMS[to_id]

        achievement = Achievement(self.char_id)
        achievement.trig(25, 1)
        achievement.trig(26, to_gem_obj.level)

        t = Task(self.char_id)
        t.trig(4)


    def stuff_add(self, add_stuffs, send_notify=True):
        """

        @param add_stuffs: [(id, amount), (id, amount)]
        @type add_stuffs: list | tuple
        """
        for _id, _ in add_stuffs:
            if _id not in STUFFS:
                raise SanguoException(
                    errormsg.STUFF_NOT_EXIST,
                    self.char_id,
                    "Stuff Add",
                    "Stuff Oid {0} not exist".format(_id)
                )

        stuffs = self.item.stuffs
        add_stuffs_dict = {}
        for _id, _amount in add_stuffs:
            add_stuffs_dict[_id] = add_stuffs_dict.get(_id, 0) + _amount

        new_stuffs = []
        update_stuffs = []
        for _id, _amount in add_stuffs_dict.iteritems():
            sid = str(_id)
            if sid in stuffs:
                stuffs[sid] += _amount
                update_stuffs.append((_id, stuffs[sid]))
            else:
                stuffs[sid] = _amount
                new_stuffs.append((_id, _amount))

        self.item.stuffs = stuffs
        self.item.save()

        if not send_notify:
            return
        if new_stuffs:
            msg = protomsg.AddStuffNotify()
            for k, v in new_stuffs:
                s = msg.stuffs.add()
                s.id, s.amount = k, v

            publish_to_char(self.char_id, pack_msg(msg))

        if update_stuffs:
            msg = protomsg.UpdateStuffNotify()
            for k, v in update_stuffs:
                s = msg.stuffs.add()
                s.id, s.amount = k, v

            publish_to_char(self.char_id, pack_msg(msg))



    def stuff_remove(self, _id, amount):
        """
        @param _id: stuff id
        @type _id: int
        @param amount: this stuff amount
        @type amount: int
        """
        try:
            this_stuff_amount = self.item.stuffs[str(_id)]
        except KeyError:
            raise SanguoException(
                errormsg.STUFF_NOT_EXIST,
                self.char_id,
                "Stuff Remove",
                "Stuff {0} not exist".format(_id)
            )

        new_amount = this_stuff_amount - amount

        if new_amount < 0:
            raise SanguoException(
                errormsg.STUFF_NOT_ENOUGH,
                self.char_id,
                "Stuff Remove",
                "Stuff {0} not enough".format(_id)
            )

        if new_amount == 0:
            self.item.stuffs.pop(str(_id))
            self.item.save()

            msg = protomsg.RemoveStuffNotify()
            msg.ids.append(_id)
            publish_to_char(self.char_id, pack_msg(msg))
        else:
            self.item.stuffs[str(_id)] = new_amount
            self.item.save()
            msg = protomsg.UpdateStuffNotify()
            g = msg.stuffs.add()
            g.id, g.amount = _id, new_amount

            publish_to_char(self.char_id, pack_msg(msg))


    def stuff_sell(self, _id, amount):
        # TODO get gold
        gold = 10 * amount

        resource = Resource(self.char_id, "Stuff Sell", "sell {0}, amount: {1}".format(_id, amount))
        resource.check_and_remove(stuffs=[(_id, amount)])
        resource.add(gold=gold)


    def send_equip_notify(self):
        msg = protomsg.EquipNotify()
        for _id, data in self.item.equipments.iteritems():
            equip = msg.equips.add()
            self._msg_equip(equip, int(_id), data, Equipment(self.char_id, int(_id), self.item))

        publish_to_char(self.char_id, pack_msg(msg))


    def send_gem_notify(self):
        msg = protomsg.GemNotify()
        for k, v in self.item.gems.iteritems():
            g = msg.gems.add()
            g.id, g.amount = int(k), v

        publish_to_char(self.char_id, pack_msg(msg))

    def send_stuff_notify(self):
        msg = protomsg.StuffNotify()
        for k, v in self.item.stuffs.iteritems():
            s = msg.stuffs.add()
            s.id, s.amount = int(k), v

        publish_to_char(self.char_id, pack_msg(msg))


    def send_notify(self):
        self.send_equip_notify()
        self.send_gem_notify()
        self.send_stuff_notify()