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()
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()
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()
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()