def buy_card_from_store(self, index, purchasing_player: Player, other_players): card_to_buy: Card = self.__card_store[index] card_cost = card_to_buy.cost if purchasing_player.has_instance_of_card(AlienMetabolism()): card_cost = card_to_buy.cost - 1 if purchasing_player.energy < card_cost: raise InsufficientFundsException(constants.INSUFFICIENT_FUNDS_MSG) else: purchasing_player.update_energy_by(-card_cost) if purchasing_player.has_instance_of_card(DedicatedNewsTeam()): DedicatedNewsTeam().special_effect(purchasing_player, None) if isinstance(card_to_buy, DiscardCard): print("{} is a discard card".format(card_to_buy.name)) # if the card is DropFromHighAltitude, we have to prompt player, and then consumers.py will handle # triggering the immediate_effect if not isinstance(card_to_buy, DropFromHighAltitude): card_to_buy.immediate_effect(purchasing_player, other_players) self.discard(card_to_buy) elif isinstance(card_to_buy, KeepCard): card_to_buy.immediate_effect(purchasing_player, other_players) else: print("UNEXPECTED CARD TYPE!!!") raise UnexpectedCardTypeException self.__card_store.remove(card_to_buy) self.__fill_card_store() return card_to_buy
def uninit(self): self.globals = None self.locals = None self.player = None if 0: from game.player.player import Player self.player = Player()
def test_if_not_last_player_alive(): player1 = Player() player2 = Player() player_queue = GamePlayers() player_queue.add_player_to_game(player1) player_queue.add_player_to_game(player2) assert player_queue.is_last_player_alive(player2) is False
def __init__(self, player): if 0: from game.player.player import Player self.player = Player() self.items = {} self.types = {} self.player = player
def test_when_last_player_is_alive(): player1 = Player() player1.is_alive = False player2 = Player() player_queue = GamePlayers() player_queue.add_player_to_game(player1) player_queue.add_player_to_game(player2) assert player_queue.is_last_player_alive(player2) is True
def other_players(): player_a = Player() player_b = Player() player_c = Player() players = [player_a, player_b, player_c] for player in players: player.location = Locations.OUTSIDE return players
def test_get_dead_player(): player1 = Player() player1.is_alive = False player2 = Player() player_queue = GamePlayers() player_queue.add_player_to_game(player1) player_queue.add_player_to_game(player2) assert player_queue.get_dead_players() == [player1]
def __init__(self, gm, player): self.player = player self.gm = gm self._raw_return = 0 if 0: from game.player.player import Player self.player = Player() self.gm = GameMaster()
def test_get_current_player_when_player_order_set(): player1 = Player() player2 = Player() player_queue = GamePlayers() player_queue.add_player_to_game(player1) player_queue.add_player_to_game(player2) player_queue.set_player_order() player_queue.get_current_player() assert player_queue.current_player == player1
def sweep_store(self, player_invoking_sweep: Player): if player_invoking_sweep.energy < constants.SWEEP_CARD_STORE_COST: raise Exception(constants.INSUFFICIENT_FUNDS_TO_SWEEP_MSG) else: player_invoking_sweep.update_energy_by( -constants.SWEEP_CARD_STORE_COST) for _ in range(3): self.discard(self.store.pop()) self.__fill_card_store()
def test_sweep_store_puts_current_cards_in_discard(deck_handler): test_player = Player() test_player.energy = constants.SWEEP_CARD_STORE_COST initial_cards_in_store = [deck_handler.store[0], deck_handler.store[1], deck_handler.store[2]] deck_handler.sweep_store(test_player) assert len(deck_handler.discard_pile) == constants.CARD_STORE_SIZE_LIMITER for card in initial_cards_in_store: assert deck_handler.discard_pile.__contains__(card)
def test_roll_energy_updates_player(): player = Player() other_players = [Player(), Player()] starting_energy = player.energy dice = [ DieValue.ENERGY, DieValue.ENERGY, DieValue.ENERGY, DieValue.ENERGY, DieValue.ENERGY, DieValue.ENERGY ] dice_resolver.dice_resolution(dice, player, other_players) assert player.energy == starting_energy + 6
def test_sweep_store_takes_current_cards_from_store(deck_handler): test_player = Player() test_player.energy = constants.SWEEP_CARD_STORE_COST reset_deck_handler_to_single_card_only_deck(deck_handler, SAMPLE_KEEP_CARD) deck_handler.draw_pile.clear() for _ in itertools.repeat(None, 7): deck_handler.draw_pile.add_card_to_deck(SAMPLE_DISCARD_CARD) deck_handler.sweep_store(test_player) for card in deck_handler.store: assert isinstance(card, SAMPLE_DISCARD_CARD.__class__)
def test_gets_all_attackable_players_in_different_location(): attack_player = Player() player_two = Player() player_three = Player() player_four = Player() player_two.move_to_tokyo() player_four.move_to_tokyo() possible_players = [player_two, player_three, player_four] attackable_players = attack_actions.get_attackable_players( attack_player, possible_players) assert attackable_players == [player_two, player_four]
def __init__(self, player): if 0: from game.player.player import Player self.player = Player() self.player = player self.roles = {} self.rid2roles = {} self.main_role = None #保存武将随机培养值 {rid:attr} self.train_rand_data = None self.cls_init()
def test_is_winner_by_death(): game = BoardGame() game.add_player(Player()) game.add_player(Player()) game.start_game() assert game.status == Status.ACTIVE current_player: Player = game.get_next_player_turn() game.check_if_winner(current_player) assert game.status == Status.ACTIVE current_player.update_health_by(-current_player.current_health) current_player: Player = game.get_next_player_turn() game.check_if_winner(current_player) assert game.status == Status.COMPLETED
def test_dedicated_news_team_player_buys_card(player): player.energy = 100 deck_handler = DeckHandler() # Force the card this test will buy to be Heal since it doesn't affect victory points deck_handler.store.clear() deck_handler.store.append(Heal()) original_victory_points = player.victory_points DedicatedNewsTeam().immediate_effect(player, None) deck_handler.buy_card_from_store(0, player, [Player(), Player()]) assert player.victory_points == original_victory_points + 1
def test_frenzy_grants_bonus_turn(): board = BoardGame() board.add_player(Player("one")) board.add_player(Player("two")) board.start_game() current_player = board.players.get_current_player() current_player.energy = 100 board.deck_handler.store[0] = Frenzy() board.deck_handler.buy_card_from_store( 0, board.players.current_player, board.players.get_all_alive_players_minus_current_player()) board.players.get_next_player() assert current_player.username == board.players.current_player.username
def test_get_all_alive_players_minus_current_player(): player1 = Player() player1.is_alive = False player2 = Player() player3 = Player() player_queue = GamePlayers() player_queue.add_player_to_game(player1) player_queue.add_player_to_game(player2) player_queue.add_player_to_game(player3) player_queue.set_player_order() player_queue.get_current_player() assert player_queue.get_all_alive_players_minus_current_player() == [ player3 ]
def test_player_not_allowed_to_yield_after_attacked_out_of_tokyo(): attacker = Player() attacker.move_to_tokyo() yielder = Player() yielder.leave_tokyo() attack_actions.attack_players(attacker, [yielder]) assert not yielder.allowed_to_yield assert not attacker.allowed_to_yield
def test_full_turns(): player1 = Player("I AM NUMBER UNO!") player2 = Player("PLAYEER ONE SUX") game = BoardGame() game.add_player(player1) game.add_player(player2) game.start_game() for _ in range(10): print("CURRENT PLAYER:" + game.get_next_player_turn().username) game.dice_handler.roll_initial(6, 2) num_players = len(game.players.get_alive_players()) print("\n\nDEBUG OUTPUT:\n") print("CURRENT PLAYER:" + game.players.get_current_player().username) print(game.dice_handler.dice_values) game.dice_handler.re_roll_dice([1, 2, 3]) print(game.dice_handler.dice_values) game.dice_handler.re_roll_dice([1, 2, 3]) print(game.dice_handler.dice_values) try: game.dice_handler.re_roll_dice([1, 2, 3]) except ValueError: print("failed too many rerolls") returned_Player = game.get_next_player_turn() print("CURRENT PLAYER = " + returned_Player.username) game.dice_handler.roll_initial(6, 2) print(game.dice_handler.dice_values) game.dice_handler.re_roll_dice([1, 2, 3]) print(game.dice_handler.dice_values) game.dice_handler.re_roll_dice([1, 2, 3]) print(game.dice_handler.dice_values) try: game.dice_handler.re_roll_dice([1, 2, 3]) except ValueError: print("failed too many rerolls") returned_Player = game.get_next_player_turn() print("CURRENT PLAYER = " + returned_Player.username)
def new_copys(self, aid, node): """ 新建隐分身数据 """ res_node = Game.res_mgr.awar_strong_maps.get(node) if not res_node: return res_npc_configs = Game.res_mgr.awar_npc_configs_bykey.get(int(float(res_node.apcid))) ally_pids = Game.rpc_ally_mgr.member_pids_by_aid(aid) aname = Game.rpc_ally_mgr.ally_name_by_aid(aid) copys = [] num = len(res_npc_configs) pid_num = len(ally_pids) if pid_num < num: ally_pids *= int(math.ceil(float(num) / pid_num)) for res_npc_config in res_npc_configs: pid = ally_pids.pop() player = Player.load_player(pid) main_role = player.roles.main_role o = CopyData.new() o.ancid = res_npc_config.id o.pid = pid o.rid = main_role.data.rid o.q = main_role.data.q o.name = player.data.name o.aname = aname o.eqid = player.roles.main_role.body_equip_id copys.append(o) self.node2copys[node] = copys
def new_copys(self, aid, node): """ 新建隐分身数据 """ res_node = Game.res_mgr.awar_strong_maps.get(node) if not res_node: return res_npc_configs = Game.res_mgr.awar_npc_configs_bykey.get( int(float(res_node.apcid))) ally_pids = Game.rpc_ally_mgr.member_pids_by_aid(aid) aname = Game.rpc_ally_mgr.ally_name_by_aid(aid) copys = [] num = len(res_npc_configs) pid_num = len(ally_pids) if pid_num < num: ally_pids *= int(math.ceil(float(num) / pid_num)) for res_npc_config in res_npc_configs: pid = ally_pids.pop() player = Player.load_player(pid) main_role = player.roles.main_role o = CopyData.new() o.ancid = res_npc_config.id o.pid = pid o.rid = main_role.data.rid o.q = main_role.data.q o.name = player.data.name o.aname = aname o.eqid = player.roles.main_role.body_equip_id copys.append(o) self.node2copys[node] = copys
def test_board_pickling(): game = BoardGame() game.add_player(Player("Awesome_player_1")) game.add_player(Player("Please don't pickle me")) game.start_game() player_whos_turn_it_is = game.players.get_current_player() assert game.is_game_active() serial_game = pickle.dumps(game) de_pickled_game: BoardGame = pickle.loads(serial_game) players = de_pickled_game.players assert player_whos_turn_it_is == de_pickled_game.players.get_current_player( ) assert de_pickled_game.is_game_active() assert len(players.players) == 2
def test_game_stops(): game = BoardGame() game.add_player(Player()) game.start_game() assert game.status != Status.COMPLETED game.end_game() assert game.status == Status.COMPLETED
def test_get_view_2(self): m = TextLevel() g = Game() p = Player(g, 2, 3, 4) m.init_map( os.path.join(os.getcwd(), "game", "assets", "text_levels", "1")) self.assertEqual(m.height, 6) self.assertEqual(m.width, 11) view = m.get_view(p) self.assertEqual(len(view), 5) self.assertEqual( view, [[ CELL.UNKNOWN.value, CELL.UNKNOWN.value, CELL.EMPTY.value, CELL.UNKNOWN.value, CELL.UNKNOWN.value ], [ CELL.UNKNOWN.value, CELL.EMPTY.value, CELL.EMPTY.value, CELL.WALL.value, CELL.UNKNOWN.value ], [ CELL.EMPTY.value, CELL.EMPTY.value, CELL.PLAYER.value, CELL.EMPTY.value, CELL.EMPTY.value ], [ CELL.UNKNOWN.value, CELL.WALL.value, CELL.WALL.value, CELL.WALL.value, CELL.UNKNOWN.value ], [ CELL.UNKNOWN.value, CELL.UNKNOWN.value, CELL.UNKNOWN.value, CELL.UNKNOWN.value, CELL.UNKNOWN.value ]])
def send_reward(self): res_tbox = Game.res_mgr.tboxs.get(self.bid) if res_tbox is None: log.error('ally_team(%s) res_tbox is None, pids(%s)', self.tid, self.pids) return rw = Game.reward_mgr.get(res_tbox.trid) items = rw.reward(None) if items is None: log.error('ally_team(%s) reward_items is None, pids(%s)', self.tid, self.pids) return rw_mail = Game.res_mgr.reward_mails.get(RW_MAIL_ATBOX) boss = Game.res_mgr.monsters.get(res_tbox.tmid) content = rw_mail.content % dict(name=boss.name) pids = [] for pid in self.pids: player = Game.rpc_player_mgr.get_rpc_player(pid) if player is None: player = Player.load_player(pid) if player is None: continue data = player.get_ally_tbox_data() if not is_today(data['t']): data['bids'] = [] data['cr'] = 0 if len(data['bids']) == 0: data['bids'].append(self.bid) data['t'] = current_time() pids.append(pid) if pid == self.lid: data['cr'] += 1 player.set_ally_tbox_data(data) Game.mail_mgr.send_mails(pids, MAIL_REWARD, rw_mail.title, content, items)
def gm_del_pid(self, pid): """ 删除玩家数据 """ rs = Player.del_player(pid) if rs: self.log(u'删除玩家(%s)数据成功', pid) else: self.log(u'删除玩家(%s)数据失败', pid)
def __init__(self, player): if 0: from game.player.player import Player self.player = Player() self.items = {} self.types = {} self.player = player
def init_chat_handler(self, data): username = data['user'] room = data['room'] game, state = self.get_state(room, username) player: Player = Player(username) if player not in state.players.players and not state.is_game_active(): # free cards to demonstrate inventory # player.add_card(EnergyHoarder()) # player.add_card(SolarPowered()) # player.add_card(EvenBigger()) # player.update_energy_by(1000) state.add_player(player) # hack to start game after 2 players join temp_max_players = 4 if len(state.players.players) >= temp_max_players: self.start_web_game(room, state, username) else: msg = "Joined, waiting on additional players" self.send_to_client(SERVER_RESPONSE, username, room, username + msg) self.update_player_status(state, username, room, game)
def send_reward(self): res_tbox = Game.res_mgr.tboxs.get(self.bid) if res_tbox is None: log.error('ally_team(%s) res_tbox is None, pids(%s)', self.tid, self.pids) return rw = Game.reward_mgr.get(res_tbox.trid) items = rw.reward(None) if items is None: log.error('ally_team(%s) reward_items is None, pids(%s)', self.tid, self.pids) return rw_mail = Game.res_mgr.reward_mails.get(RW_MAIL_ATBOX) boss = Game.res_mgr.monsters.get(res_tbox.tmid) content = rw_mail.content % dict(name = boss.name) pids = [] for pid in self.pids: player = Game.rpc_player_mgr.get_rpc_player(pid) if player is None: player = Player.load_player(pid) if player is None: continue data = player.get_ally_tbox_data() if not is_today(data['t']): data['bids'] = [] data['cr'] = 0 if len(data['bids']) == 0: data['bids'].append(self.bid) data['t'] = current_time() pids.append(pid) if pid == self.lid: data['cr'] += 1 player.set_ally_tbox_data(data) Game.mail_mgr.send_mails(pids, MAIL_REWARD, rw_mail.title, content, items)
def __init__(self, player): self.player = player self.equips = {} self.items = {} self.fates = {} self.cars = {} self.gem = {} if 0: from game.player.player import Player self.player = Player() #default_size = Game.setting_mgr.setdefault(BAG_SIZE, BAG_SIZE_V) #self.set_size(default_size) #物品快速索引 #{iid1:([id1, id2, ...],[id3, id4]), ...} #{物品基础表id:([可交易物品id...],[不可交易物品id...])...} self.iid_to_items = {} self._used_count = 0
def init_player(self, vision_range, start_x, start_y): if start_x is None or start_y is None: x, y = choice( np.argwhere(self.level.level_map == CELL.EMPTY.value)) else: x = start_x y = start_y self.player = Player(self, vision_range, x, y) self.objects.put(self.player)
def handle_pay_back(pid, rid, first_reward, coin): """ 离线支付回调 """ from game.player.player import Player p = Player.load_player(pid) if not p: log.error('******pay_back error:player(%s) not found', pid) return 0, 0 rs = p.pay_back(rid, first_reward, coin) p.save() return rs
def get_pos(self): """获得阵型信息""" pos = {} pos.update(self.position) for pid in self.pids: player = Game.rpc_player_mgr.get_rpc_player(pid) if player is None: player = Player.load_player(pid) if player is None: continue rid, eid = player.get_main_role_eid() for data in pos.itervalues(): if data['pid'] == pid and data['rid'] == rid: data['eid'] = eid return pos
def get_fight(self): """获取战斗所需数据""" data = [] for pid in self.pids: player = Game.rpc_player_mgr.get_rpc_player(pid) if player is None: player = Player.load_player(pid) if player is None: continue rids = [] for d in self.position.itervalues(): if d['pid'] == pid: rids.append(d['rid']) info = player.team_look(rids) data.append(info) return data
def __init__(self, player): self.player = player self.equips = {} self.items = {} self.fates = {} self.cars = {} self.gem = {} if 0: from game.player.player import Player self.player = Player() #default_size = Game.setting_mgr.setdefault(BAG_SIZE, BAG_SIZE_V) #self.set_size(default_size) #物品快速索引 #{iid1:([id1, id2, ...],[id3, id4]), ...} #{物品基础表id:([可交易物品id...],[不可交易物品id...])...} self.iid_to_items = {} self._used_count = 0
def _get_other(self, pid, cache=1): """ 获取其它玩家信息 """ if cache: v = self.others.get(pid) if v is not None: return v p = self.get_player(pid) if not p: p = self._game.rpc_player_mgr.get_rpc_player(pid) if not p:#不在线 p = Player.load_player(pid) # p = OtherPlayer.new(pid) if not p: v = 0, errcode.EC_NOFOUND else: #先计算出战斗力 p.init() v = 1, p.look() self.others.set(pid, v) return v
class PlayerVip(object): """ 玩家vip类 """ def __init__(self, player): self.player = player if 0: from .player import Player self.player = Player() def uninit(self): self.player = None def _set_vip(self, value): self.player.data.vip = value self.update() def _get_vip(self): return self.player.data.vip vip = property(_get_vip, _set_vip) def load(self): """ 初始化vip相关数据 """ #背包格子数 self.update() def _send_reward(self, vip_lev): """ 发送vip奖励 """ p = self.player if self.vip > vip_lev: log.info('player(%s) cur vip:%s, upgrade vip:%s', p.data.name, self.vip, vip_lev) return rw_mail = Game.res_mgr.reward_mails.get(RW_MAIL_VIP) pid = p.data.id for vip in xrange(self.vip + 1, vip_lev + 1): try: cont_dict = dict(vip=vip) content = rw_mail.content % cont_dict rid = get_vip_rid(vip) t_rw = p._game.reward_mgr.get(rid) if not t_rw: log.info('vip reward_item is %s, please check data', t_rw) continue items = t_rw.reward(params=p.reward_params()) log.info('player(%s) vip_lv:%s send:%s', p.data.name, vip, items) Game.mail_mgr.send_mails(pid, MAIL_REWARD, rw_mail.title, RW_MAIL_VIP, items, param=content, rid=rid) except: log.log_except("the vip send_mail is error the vip level is:%s", vip) def _init_vip_level(self): """ 根据累计重置元宝数,确定vip等级 只升级,不降级,方便实现送vip等级等人为调整功能 """ lv = self.player._game.vip_mgr.get_vip_level(self.player.data.vipCoin) if lv > self.player.data.vip: self.player.log_normal(PL_VIP_UPGRADE, lv=lv) log.info('player(%s)vip level up:%s', self.player.data.name, lv) self._send_reward(int(lv)) self.vip = lv self.player.pub_vip_level() def update(self): p = self.player game = p._game mgr = game.vip_mgr vip = self.vip def first_charge(self, bag_item): """发送首冲奖励""" rw_mail = Game.res_mgr.reward_mails.get(RW_MAIL_FIRST_CHARGE) content = RW_MAIL_FIRST_CHARGE pid = self.player.data.id log.info("first_charge mailType:%s, pid:%s, items:%s", content, pid, bag_item) if not bag_item: return Game.mail_mgr.send_mails(pid, MAIL_REWARD, rw_mail.title, content, bag_item, param=rw_mail.content) def pay_back(self, bag_items): """ 支付回调,获取奖励 """ #_last = self.player.data.vipCoin #调整vip self.player.data.vipCoin += bag_items.coin2 #log.info("pay_back_vipCoin last:%s, now:%s", _last, self.player.data.vipCoin) self._init_vip_level() #支付奖励,马上保存 self.player.save(full=1) #通知前端 resp_f = 'goodsGive' data = dict(player=self.player.to_dict(), data=bag_items.pack_msg(), vipData=self.player.vip_attr.to_dict()) self.player.send_msg(pack_msg(resp_f, 1, data=data)) def copy_from(self, p_vip): """拷贝玩家数据""" self.vip = p_vip.vip
def __init__(self, player): self.player = player if 0: from .player import Player self.player = Player()
class PlayerWaitBag(object): """ 待收取物品列表 """ TYPE_TO_LOG = { WAITBAG_TYPE_HITFATE: ITEM_FETCH_HITFATE, WAITBAG_TYPE_TIMEBOX: ITEM_FETCH_TIMEBOX, WAITBAG_TYPE_EMAIL: ITEM_FETCH_EMAIL, } VALID_TYPES = (tuple, list, set) def __init__(self, player): if 0: from game.player.player import Player self.player = Player() self.items = {} self.types = {} self.player = player def uninit(self): self.player = None self.items = {} self.types = {} def add(self, witem): wid = witem.data.id self.items[wid] = witem ids = self.types.setdefault(witem.data.type, []) ids.append(wid) def delete(self, wid): if not self.items.has_key(wid): return witem = self.items.pop(wid) wtype = witem.data.type ids = self.types[wtype] ids.remove(wid) if not ids: self.types.pop(wtype) witem.delete(self.player._game.rpc_store) def deletes(self, type): witems = self.types.get(type) if not witems: return del_wids = [] for id in witems[:]: self.delete(id) del_wids.append(id) return del_wids def load(self): """ 加载数据 """ store = self.player._game.rpc_store querys = dict(pid=self.player.data.id) waits = store.query_loads(TN_P_WAIT, querys) for w in waits: item = WaitItem(adict=w) self.add(item) def load_item(self, wid): """ 动态加载待收物品 """ if wid in self.items: return data = self.player._game.rpc_store.load(TN_P_WAIT, wid) if data: item = WaitItem(adict=data) self.add(item) return item def save(self): store = self.player._game.rpc_store for key in self.items.keys(): if key not in self.items: continue w = self.items[key] w.save(store) def clear(self): store = self.player._game.rpc_store for w in self.items.itervalues(): w.delete(store) self.items.clear() self.types.clear() def copy_from(self, wait_bag): items = {} self.clear() for i in wait_bag.items.itervalues(): ni = WaitItem(adict=i.data.to_dict()) ni.data.id = None ni.data.pid = self.player.data.id ni.save(self.player._game.rpc_store) items[i.data.id] = ni.data.id self.load() return items def to_dict(self): return [i.to_dict() for i in self.items.itervalues()] def get_log_type(self, wtype): try: return self.TYPE_TO_LOG[wtype] except: return 100 + wtype def fetch(self, wtype, id=None, pack_msg=True, delete=True, log_type=None): """ 收取物品 """ if id is not None: ids = [id] else: ids = self.types.get(wtype, None) if not ids: return False, errcode.EC_VALUE ids = ids[:] witems = [self.items[i] for i in ids if i in self.items] if not witems: return False, errcode.EC_NOFOUND items = [] bag = self.player.bag rid = 0 for witem in witems: if not isinstance(witem.items, self.VALID_TYPES): continue items.extend(witem.items) if witem.data.rid: rid = witem.data.rid #是否可添加 if not bag.can_add_items(items): return False, errcode.EC_BAG_FULL if log_type is None: log_type = self.get_log_type(wtype) #添加背包 bag_items = bag.add_items(items, log_type=log_type, rid=rid) #删除 for item in witems: if delete: self.delete(item.data.id) #时光盒数据特殊处理 if wtype == WAITBAG_TYPE_TIMEBOX: ptbox_attr = self.player.play_attr.get(PLAYER_ATTR_TBOX) if ptbox_attr[PT_CH]: ptbox_attr[PT_CH] = 0 ptbox_attr[PT_WAITS] = [] if pack_msg: return True, bag_items.pack_msg(del_wids=ids) return True, bag_items def _handle_type_data(self, type): """ 处理特殊类型凌晨刷新的数据(主动发给客户端) """ #猎命 if type == WAITBAG_TYPE_HITFATE: hfate = getattr(self.player.runtimes, PLAYER_ATTR_HITFATE) if hfate.handle_pass_day(fetch=True): resp_f = 'enterHitFate' rs, data = hfate.enter() if rs: self.player.send_msg(resp_f, 1, data=data) #时光盒 elif type == WAITBAG_TYPE_TIMEBOX: ptbox = getattr(self.player.runtimes, TN_P_TBOX) ch = ptbox.handle_pass_day(fetch=True) if ch: resp_f = 'tBoxEnter' rs, data = ptbox.enter(ch) if rs: pack = pack_msg(resp_f, 1, data={'tbox':data.to_dict()}) else: pack = pack_msg(resp_f, 0, data=data) self.player.send_msg(pack) def add_waitItem(self, aType, aItems): """ 添加待收物品 """ if not isinstance(aItems, self.VALID_TYPES): raise ValueError('add_waitItem:aItems mush list type') oWaitItem = WaitItem.new(self.player.data.id, aType, aItems) oWaitItem.save(self.player._game.rpc_store, forced=True) self.add(oWaitItem) return oWaitItem
class Bag(object): """ 玩家物品列表管理类 """ def __init__(self, player): self.player = player self.equips = {} self.items = {} self.fates = {} self.cars = {} self.gem = {} if 0: from game.player.player import Player self.player = Player() #default_size = Game.setting_mgr.setdefault(BAG_SIZE, BAG_SIZE_V) #self.set_size(default_size) #物品快速索引 #{iid1:([id1, id2, ...],[id3, id4]), ...} #{物品基础表id:([可交易物品id...],[不可交易物品id...])...} self.iid_to_items = {} self._used_count = 0 def uninit(self): self.player = None self.equips = {} self.items = {} self.fates = {} self.cars = {} self.gem = {} self.iid_to_items = {} def _load_items(self, items): for item_dict in items: id = item_dict['id'] obj = self.items[id] = Item(adict=item_dict) self._add_bag_item(obj) self._used_count = len(items) def _load_single(self, mydict, items, cls): for item_dict in items: mydict[item_dict["id"]] = cls(adict=item_dict) if not item_dict['used']: self._used_count += 1 def load(self): """ 加载数据 """ store = self.player._game.rpc_store querys = dict(pid=self.player.data.id) tItemDicts = store.query_loads(TN_P_ITEM, querys) self._load_items(tItemDicts) tEquipDicts = store.query_loads(TN_P_EQUIP, querys) self._load_single(self.equips, tEquipDicts, Equip) tFateDicts = store.query_loads(TN_P_FATE, querys) self._load_single(self.fates, tFateDicts, Fate) tCarDicts = store.query_loads(TN_P_CAR, querys) for tCarDict in tCarDicts: self.cars[tCarDict["id"]] = Car(adict=tCarDict) tGemDicts = store.query_loads(TN_P_GEM, querys) self._load_single(self.gem, tGemDicts, Gem) def load_used(self): """ 加载配将使用中的装备和命格 """ store = self.player._game.rpc_store querys = dict(pid=self.player.data.id, used=1) tEquipDicts = store.query_loads(TN_P_EQUIP, querys) self._load_single(self.equips, tEquipDicts, Equip) tFateDicts = store.query_loads(TN_P_FATE, querys) self._load_single(self.fates, tFateDicts, Fate) tGemDicts = store.query_loads(TN_P_GEM, querys) self._load_single(self.gem, tGemDicts, Gem) def to_dict(self, used=0): """ 获取玩家物品列表 """ if not used: return { "equip":[equip.to_dict() for equip in self.equips.itervalues()], "item":[item.to_dict() for item in self.items.itervalues()], "fate":[fate.to_dict() for fate in self.fates.itervalues()], "car": [car.to_dict() for car in self.cars.itervalues()], "gem":[gem.to_dict() for gem in self.gem.itervalues()], } return { "equip":[equip.to_dict() for equip in self.equips.itervalues() if equip.data.used], "item":[], "fate":[fate.to_dict() for fate in self.fates.itervalues() if fate.data.used], "car": [], "gem":[gem.to_dict() for gem in self.gem.itervalues()], } def save(self): """ 保存至数据库 """ store = self.player._game.rpc_store for key in self.items.keys(): if key not in self.items: continue tItem = self.items[key] tItem.save(store) for key in self.fates.keys(): if key not in self.fates: continue tFate = self.fates[key] tFate.save(store) for key in self.equips.keys(): if key not in self.equips: continue tEq = self.equips[key] tEq.save(store) for key in self.cars.keys(): if key not in self.cars: continue tCar = self.cars[key] tCar.save(store) for key in self.gem.keys(): if key not in self.gem: continue tGem = self.gem[key] tGem.save(store) def clear(self): """ 清除所有数据 """ store = self.player._game.rpc_store for i in self.items.itervalues(): i.delete(store) for i in self.fates.itervalues(): i.delete(store) for i in self.equips.itervalues(): i.delete(store) for i in self.cars.itervalues(): i.delete(store) for i in self.gem.itervalues(): i.delete(store) self.player.roles.clear_attr() self.player.clear_attr_car() self.items.clear() self.fates.clear() self.equips.clear() self.cars.clear() self.gem.clear() self.iid_to_items.clear() self._used_count = 0 def copy_from(self, bag): #新旧id关联 items = {} self.clear() def _add(cls, data): item = cls(adict=data.to_dict()) item.data.id = None item.data.pid = self.player.data.id item.save(self.player._game.rpc_store) items[data.id] = item.data.id for i in bag.items.itervalues(): _add(Item, i.data) for i in bag.equips.itervalues(): _add(Equip, i.data) for i in bag.fates.itervalues(): _add(Fate, i.data) for i in bag.cars.itervalues(): _add(Car, i.data) for i in bag.gem.itervalues(): _add(Gem, i.data) self.load() return items #def set_size(self, aSize): # """ 背包大小设置 """ # self.size = aSize def check_item(self, iid, count, uses=None): """ 检查是否有足够物品消耗, uses: 指定使用的id列表 返回:是否足够,不可交易数,使用id列表""" ids = self.iid_to_items[iid] ids = ids[NOTRADE_IDX] + ids[TRADE_IDX] if uses: for i in uses[:]: if i not in ids: uses.remove(i) else: ids.remove(i) ids = uses + ids no_trade = 0 trade = 0 uses = [] for id in ids: item = self.get_item(id) if not item.data.isTrade: no_trade += item.data.count else: trade += item.data.count if item.data.count <= count: uses.append(id) count -= item.data.count else: uses.append((item, count)) count = 0 if not count: return True, trade, no_trade, uses return False, trade, no_trade, uses def has_item(self, iid, count): """ 是否有特定数量的物品 """ rs, trade, no_trade, uses = self.check_item(iid, count) return rs def cost_item(self, iid, count, unit=None, log_type=None, pack_msg=False, uses=None): """ 物品消耗 uses: 指定使用的物品id列表 成功返回 [[删除物品的id...], 更新后的item] #TODO: aUnit: 分组单位数量,要求返回1:可交易2:不可交易数3:两者都有 失败返回None 成功返回:可交易组数,不可交易组数,删除物品id列表,更新物品 """ iid = int(iid) count = int(count) if not self.iid_to_items.has_key(iid): return rs, trade_num, no_trade_num, use_ids = self.check_item(iid, count, uses=uses) if not rs: return up_item = None for id in use_ids: if isinstance(id, int): #删除使用的物品 self.del_item(id) continue #扣除使用的数目(更新物品) id[0].data.count -= id[1] up_item = id[0] self.update_item(up_item) #写物品消耗记录 if log_type: self.player.log_item(iid, count, log_type) if up_item:#最后一个是更新物品 use_ids = use_ids[:-1] up_item = [up_item] if unit: no_trade = int(math.ceil(no_trade_num / unit)) trade = count / unit - no_trade else: trade, no_trade = (0, 1) if no_trade_num else (1, 0) if pack_msg: return trade, no_trade, self.player.pack_msg_data(del_iids=use_ids, items=up_item) return trade, no_trade, use_ids, up_item def sell_all(self, equip_ids, item_ids, fate_ids, gem_ids): """ 批量卖出 """ tCoin1 = 0 del_eids, del_iids, del_fids, del_gids = [], [], [], [] item_mgr = self.player._game.item_mgr if equip_ids: gem_tmp = [] for tEquipId in equip_ids: tEquip = self.get_equip(tEquipId) if not tEquip: return False, errcode.EC_BAG_NO del_eids.append((tEquip.data.eid, tEquip.data.level)) gem_tmp.extend(tEquip.data.gem.values()) tResEquip = item_mgr.get_res_equip(tEquip.data.eid) tCoin1 += tResEquip.price if gem_ids is None: gem_ids = gem_tmp else: gem_ids.extend(gem_tmp) if item_ids: for tItemId in item_ids: tItem = self.get_item(tItemId) if not tItem: return False, errcode.EC_BAG_NO del_iids.append((tItem.data.iid, tItem.data.count)) tResItem = item_mgr.get_res_item(tItem.data.iid) tCoin1 += tResItem.price*tItem.data.count if fate_ids: for tFateId in fate_ids: tFate = self.get_fate(tFateId) if not tFate: return False, errcode.EC_BAG_NO del_fids.append((tFate.data.fid, tFate.data.exp)) tResFate = item_mgr.get_res_fate(tFate.data.fid) tCoin1 += tResFate.price if gem_ids: for tGemId in gem_ids: tGem = self.get_gem(tGemId) if not tGem: return False, errcode.EC_BAG_NO del_gids.append((tGem.data.gid, tGem.data.level)) tRemGem = item_mgr.get_res_gem(tGem.data.gid) tCoin1 += tRemGem.price #加钱 if tCoin1: self.player.add_coin(aCoin1=tCoin1, log_type=COIN_ADD_SELL) #删除物品 self.del_items(item_ids) self.del_equips(equip_ids) self.del_fates(fate_ids) self.del_gem(gem_ids) dels = {} if del_iids: dels['i'] = del_iids if del_eids: dels['e'] = del_eids if del_fids: dels['f'] = del_fids if del_gids: dels['g'] = del_gids self.player.log_item(dels, 0, ITEM_SELL) return True, self.player.pack_msg_data(coin=True, del_iids=item_ids, del_eids=equip_ids, del_fids=fate_ids, del_gids=gem_ids) def get_item(self, id): """ 物品获取 """ return self.items.get(id) def get_item_ex(self, id): """ 获取物品和其资源对象 """ item = self.items.get(id) if item is None: return None, None res_item = self.player._game.item_mgr.get_res_item(item.data.iid) return item, res_item def get_item_ids_ex(self, iid): """ 通过基础物品id获取物品 """ ids = self.iid_to_items.get(iid) if ids is None: return None, None res_item = self.player._game.item_mgr.get_res_item(iid) return ids[NOTRADE_IDX] + ids[TRADE_IDX], res_item def update_item(self, aItem): """ 物品更新 """ aItem.modify() def _add_bag_item(self, item, insert=False): """ 添加单个物品 """ self.items[item.data.id] = item iids = self.iid_to_items.setdefault(item.data.iid, ([], [])) if insert: if item.data.isTrade: iids[TRADE_IDX].insert(0, item.data.id) else: iids[NOTRADE_IDX].insert(0, item.data.id) self._used_count += 1 else: if item.data.isTrade: iids[TRADE_IDX].append(item.data.id) else: iids[NOTRADE_IDX].append(item.data.id) self._used_count += 1 def _add_items(self, res_item, count): """ 物品添加 """ def _add(aIid, add_count): tItem = Item() tItem.data.pid = self.player.data.id tItem.data.iid = aIid tItem.data.count = add_count tItem.save(self.player._game.rpc_store) self._add_bag_item(tItem, insert=True) return tItem.data.id, tItem items = [] tStack = res_item.stack tCnt = int(math.ceil(float(count)/tStack)) for i in xrange(tCnt): if count <= tStack: tAddCnt = count else: count -= tStack tAddCnt = tStack tId, tItemDict = _add(res_item.id, tAddCnt) items.append(tItemDict) return items def _stack_count(self, item, stack, count, update=True): """ update 是否更新数据 将count个物品堆叠到item物品上 返回 0 全部放上 非0则放不下 """ if stack <= item.data.count: return count free = stack - item.data.count if free >= count: if update: item.data.count += count self.update_item(item) return 0 count -= free if update: item.data.count += free self.update_item(item) return count def _stack_item(self, res_item, count, can_trade): """ 添加堆叠物品 """ stack = res_item.stack tItemIds = self.iid_to_items.get(res_item.id) rs = count, [] if not tItemIds: return rs tItemIds = tItemIds[TRADE_IDX if can_trade else NOTRADE_IDX] if not tItemIds: return rs rs = [] for tItemId in tItemIds: tItem = self.items.get(tItemId) tCount = count count = self._stack_count(tItem, stack, count) if count == tCount: continue rs.append(tItem) if count <= 0: break return count, rs def get_item_num_by_iid(self, iid): """得到物品的数目通过物品id""" num = 0 if iid not in self.iid_to_items: return num op_tuple = self.iid_to_items[iid] ids = op_tuple[NOTRADE_IDX] + op_tuple[TRADE_IDX] for id in ids: item = self.get_item(id) num += item.data.count return num def add_item(self, aIid, count, can_trade=False, log_type=None): """ 物品放入背包(包括更新或者增加) """ rs = None if aIid in DIFF_TITEM_IDS: rwitems = RewardItems() #处理特殊物品的添加 rwitems.add_special_item(aIid, count) self._add_special_item(rwitems) else: tResItem = self.player._game.item_mgr.get_res_item(aIid) if not tResItem: return aCount, stack_items = self._stack_item(tResItem, count, can_trade) new_items = [] if aCount: new_items = self._add_items(tResItem, aCount) rs = stack_items + new_items #写入log if log_type: self.player.log_item(aIid, count, log_type) #背包物品变化 self.player.safe_pub(msg_define.MSG_BAG_ITEM_CHANGE, aIid) return rs def has_car(self, cid): """ 判断是否已经有该坐骑,返回对应的car对象 """ for c in self.cars.itervalues(): if c.data.cid == cid: return c def add_car(self, cid): """ 添加坐骑 """ car = self.has_car(cid) if car is not None: return car car = Car() car.data.pid = self.player.data.id car.data.cid = cid car.save(self.player._game.rpc_store) self.cars[car.data.id] = car return car def can_add_item(self, aIid, aCount, can_trade=False, other_used=0): """ 是否可以添加物品, 返回:(是否可以, 占用新格子数) """ if aIid in DIFF_TITEM_IDS: return True, 0 res_item = self.player._game.item_mgr.get_res_item(aIid) if res_item is None: return False, 0 stack = res_item.stack free = self.size - self._used_count - other_used ids = self.iid_to_items.get(aIid) if ids is None: c = int(math.ceil(float(aCount) / stack)) return (True, c) if c <= free else (False, 0) ids = ids[TRADE_IDX] if can_trade else ids[NOTRADE_IDX] for id in ids: item = self.items[id] aCount = self._stack_count(item, stack, aCount, update=False) if aCount <=0: return True, 0 c = int(math.ceil(float(aCount) / stack)) return (True, c) if c <= free else (False, 0) def _add_special_item(self, rwitems, bag_items=None): #特殊物品处理id(1=银币,2=元宝,3=绑定元宝,4=经验,5=打坐时间, 6=练历) player = self.player #钱 coin = bool(rwitems.coin1 or rwitems.coin2 or rwitems.coin3) if coin: player.add_coin(aCoin1=rwitems.coin1, aCoin2=rwitems.coin2, aCoin3=rwitems.coin3, log_type=COIN_ADD_ITEM) if bag_items: #bag_items.coin = coin bag_items.add_coin(rwitems.coin1, rwitems.coin2, rwitems.coin3) #经验 site_exp = player._game.item_mgr.get_site_exp(player.data.level, rwitems.site_times) exp = site_exp + rwitems.exp if bool(exp): if bag_items: bag_items.exp += exp player.add_exp(exp) #练历 if bool(rwitems.train): if bag_items: bag_items.train += rwitems.train player.add_train(rwitems.train, log_type=TRAIN_BAG) #时光盒 if rwitems.tbox: if bag_items: bag_items.tbox = True tbox_mgr = player._game.tbox_mgr for bid in rwitems.tbox: tbox_mgr.add_monster(player, bid) def add_items(self, items, log_type=None, rid=0): """ 添加待收物品列表、奖励物品列表, 返回: BagItems对象 """ bag_items = BagItems(self) bag_items.reward_items = items rwitems = RewardItems(items) self._add_special_item(rwitems, bag_items=bag_items) item_mgr = self.player._game.item_mgr for _id, counts in rwitems.items.iteritems(): if counts[TRADE_IDX]: add_items = self.add_item(_id, counts[TRADE_IDX], 1) if add_items: bag_items.items.extend(add_items) if counts[NOTRADE_IDX]: add_items = self.add_item(_id, counts[NOTRADE_IDX], 0) if add_items: bag_items.items.extend(add_items) for _id, c, tr in rwitems.equips: for i in xrange(c): equip = item_mgr.new_equip(_id, is_trade=tr) if not equip: continue if self.add_equip(equip) is None: continue bag_items.equips.append(equip) for _id, c, tr in rwitems.fates: for i in xrange(c): fate = item_mgr.new_fate(_id, is_trade=tr) if not fate: continue if self.add_fate(fate) is None: continue bag_items.fates.append(fate) for rid in rwitems.roles: rs, err = self.player.roles.can_add(rid) if not rs: log.error(u'奖励配将失败:%s', err) else: bag_items.roles.append(self.player.roles.add_role(err)) for _id in rwitems.cars: res_car = self.player._game.res_mgr.cars.get(_id) if res_car: t_car = self.add_car(_id) bag_items.cars.append(t_car) else: log.error(u'奖励的坐骑id在资源标表中不存在') for _id, c, lv in rwitems.gem: for i in xrange(c): gem = item_mgr.new_gem(_id, lv) if not gem: continue if self.add_gem(gem) is None: continue bag_items.gem.append(gem) if log_type: self.player.log_items(items, log_type, rid=rid) return bag_items def can_add_items(self, items): """ 是否能添加待收物品列表、奖励物品列表 """ add, not_add = self.get_can_add_items(items) if len(not_add) == 0: return True return False def get_can_add_items(self, items): """ 是否能添加待收物品列表、奖励物品列表 """ used_count = 0 add = [] not_add = [] free = self.size - self._used_count waits = {} add_items = copy.deepcopy(items) for item in add_items: t = item[IKEY_TYPE] if t in (IT_CAR_STR, ): add.append(item) continue elif t in (IT_EQUIP_STR, IT_FATE_STR, IT_GEM_STR): if used_count + 1 > free: not_add.append(item) else: add.append(item) used_count += 1 continue elif t == IT_ITEM_STR: if int(item[IKEY_ID]) in DIFF_TITEM_IDS: add.append(item) continue iid = item[IKEY_ID] if waits.has_key(iid): o_item = waits[iid] o_item[IKEY_COUNT] = int(o_item[IKEY_COUNT]) + int(item[IKEY_COUNT]) else: waits[iid] = item for item in waits.itervalues(): id = int(item[IKEY_ID]) c = int(item.get(IKEY_COUNT, 1)) can_trade = int(item.get(IKEY_TRADE, 0)) rs, used = self.can_add_item(id, c, can_trade, other_used=used_count) if rs: add.append(item) used_count += used else: not_add.append(item) return add, not_add def del_item(self, id, store_delete=True): """ 物品删除 """ tItem = self.items.pop(id) if tItem.data.isTrade: self.iid_to_items[tItem.data.iid][TRADE_IDX].remove(id) else: self.iid_to_items[tItem.data.iid][NOTRADE_IDX].remove(id) if store_delete: self.player._game.rpc_store.delete(TN_P_ITEM, id) self._used_count -= 1 #背包物品变化 self.player.safe_pub(msg_define.MSG_BAG_ITEM_CHANGE, tItem.data.iid) def del_items(self, ids): if not ids: return for iid in ids: self.del_item(iid, store_delete=False) self.player._game.rpc_store.deletes(TN_P_ITEM, ids) def get_fate(self, id): """ 命格获取""" return self.fates.get(id) def get_fate_ex(self, fid): """ 获取命格和其资源对象 """ fate = self.fates.get(fid) if fate is None: return None, None res_fate = self.player._game.item_mgr.get_res_fate(fate.data.fid) return fate, res_fate def add_fate(self, fate): """ 将命格添加到背包 """ if self.size <= self._used_count: return fate.data.pid = self.player.data.id fate.save(self.player._game.rpc_store) self.fates[fate.data.id] = fate self._used_count += 1 #发送背包命格变化消息 self.player.safe_pub(msg_define.MSG_BAG_FATE_CHANGE, fid = fate.data.fid) return fate def update_fate(self, fate, used_count=0): """ 命格更新: used_count:增加或减少占用的格子数 """ fate.modify() if used_count in (1, -1): self._used_count += used_count def get_fate_num_by_quality(self, quality): num = 0 for fate in self.fates.itervalues(): res_fate = self.player._game.item_mgr.get_res_fate(fate.data.fid) if res_fate.quality == quality: num += 1 return num def del_fate(self, fid, store=1): """ 命格删除 """ if fid not in self.fates: return None fate = self.fates.pop(fid) if not fate.data.used: self._used_count -= 1 if store: self.player._game.rpc_store.delete(TN_P_FATE, fid) #发送背包命格变化消息 self.player.safe_pub(msg_define.MSG_BAG_FATE_CHANGE, fid = fate.data.fid) return fid def del_fates(self, ids): """ 多命格删除 """ if not ids: return rs = [] for fid in ids: if self.del_fate(fid, store=0): rs.append(fid) self.player._game.rpc_store.deletes(TN_P_FATE, ids) return rs def add_equip(self, equip, forced=0): """ 添加装备 """ if not forced and self.size <= self._used_count: return equip.data.pid = self.player.data.id equip.save(self.player._game.rpc_store) self.equips[equip.data.id] = equip self._used_count += 1 return equip def get_equip(self, id): """ 装备获取 """ return self.equips.get(id) def get_equip_ex(self, eid): """ 获取装备和其资源对象 """ equip = self.equips.get(eid) if equip is None: return None, None res_equip = self.player._game.item_mgr.get_res_equip(equip.data.eid) return equip, res_equip def get_equips_by_eid(self, eid): """ 通过基础装备id获取装备 """ return [e for e in self.equips.itervalues() if e.data.eid==eid] def has_equip(self, eid): """ 是否有特定装备 """ for e in self.equips.itervalues(): if eid == e.data.eid: return True return False def update_equip(self, equip, used_count=0): """ 装备更新: used_count增加或减少暂用的格子数""" equip.modify() if used_count in (1, -1): self._used_count += used_count def del_equips(self, ids): """ 多装备删除 """ if not ids: return rs = [] for eid in ids: if self.del_equip(eid, store=0): rs.append(eid) self.player._game.rpc_store.deletes(TN_P_EQUIP, ids) return rs def del_equip(self, id, store=1): """ 装备删除 """ if id not in self.equips: return None equip = self.equips.pop(id) if not equip.data.used: self._used_count -= 1 if store: self.player._game.rpc_store.delete(TN_P_EQUIP, id) return id def get_gem(self, id): """珠宝获取""" return self.gem.get(id) def get_gem_ex(self, gid): gem = self.gem.get(gid) if gem is None: return None, None res_gem = self.player._game.item_mgr.get_res_gem(gem.data.gid) return gem, res_gem def add_gem(self, gem): if self.size <= self._used_count: return gem.data.pid = self.player.data.id gem.save(self.player._game.rpc_store) self.gem[gem.data.id] = gem self._used_count += 1 return gem def del_gem(self, ids): if not ids: return for gid in ids: if gid not in self.gem: continue gem = self.gem.pop(gid) if not gem.data.used: self._used_count -= 1 self.player._game.rpc_store.deletes(TN_P_GEM, ids) def update_gem(self, gem, used_count=0): """ 珠宝更新: used_count:增加或减少占用的格子数 """ gem.modify() if used_count in (1, -1): self._used_count += used_count def bag_free(self): """ 返回背包格子剩余数 """ return self.size - self._used_count @property def size(self): return Game.setting_mgr.fetch_size(self.player.data.vip)
class PlayerRoles(object): """ 玩家配将管理类 """ ROLE_INIT_CMDS = { QUALITY_GREEN: (GREEN_ROLE_INIT_CMD, GREEN_ROLE_INIT_CMD_V), } def __init__(self, player): if 0: from game.player.player import Player self.player = Player() self.player = player self.roles = {} self.rid2roles = {} self.main_role = None #保存武将随机培养值 {rid:attr} self.train_rand_data = None self.cls_init() setting_data = {} _sub_reloaded = False @classmethod def cls_init(cls): if cls._sub_reloaded: return cls._sub_reloaded = True Game.setting_mgr.sub(MSG_RES_RELOAD, cls.handle_setting) cls.handle_setting() @classmethod def handle_setting(cls): """ 处理修改资源表 """ cls.setting_data = {} res_cost = Game.setting_mgr.setdefault(ROLEUP_COST_ITEM, ROLEUP_COST_ITEM_V) cls.setting_data[ROLEUP_COST_ITEM] = common.str2list(res_cost) #银币培养 res_coin1 = Game.setting_mgr.setdefault(ROLETRAIN_COIN1, ROLETRAIN_COIN1_V) cls.setting_data[ROLETRAIN_COIN1] = common.str2dict2(res_coin1) #元宝培养 res_coin2 = Game.setting_mgr.setdefault(ROLETRAIN_COIN2, ROLETRAIN_COIN2_V) cls.setting_data[ROLETRAIN_COIN2] = common.str2dict2(res_coin2) res_locklevel = Game.setting_mgr.setdefault(ROLETRAIN_LOCKLEVEL, ROLETRAIN_LOCKLEVEL_V) cls.setting_data[ROLETRAIN_LOCKLEVEL] = res_locklevel def uninit(self): self.player = None self.roles = {} self.rid2roles = {} self.main_role = None self.train_rand_data = None self.setting_data = {} def gm_add_num(self, num): """ gm改变升段次数 """ for role in self.roles.itervalues(): role.data.n = num role.modify() def load(self, querys=None): if querys is None: querys = dict(pid=self.player.data.id) roles = self.player._game.rpc_store.query_loads(TN_P_ROLE, querys) pass_day = self.player.play_attr.pass_day(FN_P_ATTR_KEY_ROLEUP) for r in roles: role = PlayerRole(self, adict=r) role.handle_roleup_data() if pass_day: role.pass_day() if role.is_main: self.main_role = role self.roles[role.data.id] = role self.rid2roles[role.data.rid] = role def load_used(self): querys = dict(pid=self.player.data.id) querys['status'] = STATUS_COME self.load(querys=querys) def save(self): store = self.player._game.rpc_store for r in self.roles.itervalues(): r.save(store) def clear(self, clear_main=0): store = self.player._game.rpc_store for r in self.roles.itervalues(): if not clear_main and r.is_main: continue r.delete(store) self.roles.clear() self.rid2roles.clear() if not clear_main and self.main_role: self.roles[self.main_role.data.id] = self.main_role self.rid2roles[self.main_role.data.rid] = self.main_role else: self.main_role = None def clear_attr(self): """ 清楚角色佩戴的命格和装备属性 """ for role in self.roles.itervalues(): for key, eid in role.iter_equips(): if not eid: continue setattr(role.data, key, 0) role.modify() for key, fid in role.iter_fates(): if not fid: continue setattr(role.data, key, 0) role.modify() def copy_from(self, roles, bag_items): """ 复制roles前,bag必须先复制好 """ self.clear(clear_main=1) for r in roles.roles.itervalues(): nr = PlayerRole(self, adict=r.data.to_dict()) nr.data.id = None nr.data.pid = self.player.data.id nr.update_items(bag_items) nr.save(self.player._game.rpc_store) self.load() def __contains__(self, item): return item.data.id in self.roles def to_dict(self, used=0): if not used: return [r.to_dict() for r in self.roles.itervalues()] return [r.to_dict() for r in self.iter_come_back_roles()] def roles_to_dict(self, rids): data = [] for r in self.roles.itervalues(): if r.data.rid in rids: data.append(r.to_dict()) return data def roles_bag_to_dict(self, rids): data = dict(equip = [], fate = [], gem = []) for rid in rids: role = self.get_role_by_rid(rid) if role is None: continue for key, fid in role.iter_fates(): if not fid: continue fate = self.player.bag.get_fate(fid) if fate is None: continue data['fate'].append(fate.to_dict()) for key, eid in role.iter_equips(): if not eid: continue equip = self.player.bag.get_equip(eid) if equip is None: continue data['equip'].append(equip.to_dict()) for gid in equip.data.gem.itervalues(): gem = self.player.bag.get_gem(gid) if gem is None: continue data['gem'].append(gem.to_dict()) return data def get_role(self, id): return self.roles.get(id) def iter_roles(self): return self.roles.itervalues() def get_role_by_rid(self, rid): return self.rid2roles.get(rid) def iter_fight_roles(self): """ 根据阵型,遍历角色 """ pos = self.player.positions.get_active() if not pos: return for p, rid in pos.iter_rids(): r = self.get_role_by_rid(rid) if not r or not r.is_come_back: continue yield r # def join_roles(self): # """ 获取参战角色人数 """ # pos = self.player.positions.get_active() # if not pos: # return 1 # num = 0 # for p, rid in pos.iter_rids(): # if not rid: # continue # num += 1 # return num def iter_come_back_roles(self): """ 遍历归队的角色 """ for r in self.roles.itervalues(): if not r.is_come_back: continue yield r def get_role_by_rid(self, rid): return self.rid2roles.get(rid) @property def come_back_count(self): """ 归队人数 """ return len([r for r in self.roles.itervalues() if r.is_come_back]) def can_come_back(self): """ 是否可以执行配将归队 """ return self.come_back_count < Game.setting_mgr.setdefault(ROLE_BACK_MAX, ROLE_BACK_MAX_V) def update_role(self, aRole): """ 角色更新 """ aRole.modify() def del_role(self, rid, send_msg=0): """ 删除角色 """ role = self.rid2roles.get(rid) if role is None: return 0, None if self.main_role == role: self.main_role = None self.roles.pop(role.data.id, None) self.rid2roles.pop(rid, None) eids, fids = role.delete_role(self.player) if send_msg: self.player.pack_msg_data(roles=[role], del_eids=eids, del_fids=fids, send=1) return 1, (role, eids, fids) def can_add(self, rid): if rid in self.rid2roles: return False, errcode.EC_ROLE_MAIN_REP res_role = Game.res_mgr.roles.get(rid) if res_role is None: return False, errcode.EC_ROLE_NOFOUND if res_role.is_main and self.main_role is not None: return False, errcode.EC_ROLE_MAIN_REP return True, res_role def add_role(self, res_role): """ 添加配将,不检查合法性,需要外面调用can_add """ role = PlayerRole(self) role.handle_roleup_data(res_role) role.data.rid = res_role.id role.data.sk = res_role.sk2 if res_role.is_main: self.main_role = role role.come_back() elif self.can_come_back(): role.come_back() role.save(self.player._game.rpc_store) self.roles[role.data.id] = role self.rid2roles[role.data.rid] = role #配将初始化 if res_role.quality in self.ROLE_INIT_CMDS: n, cmd_v = self.ROLE_INIT_CMDS[res_role.quality] cmd = self.player._game.setting_mgr.setdefault(n, cmd_v) gm = self.player._gm_cmd(cmd % res_role.to_dict()) news = gm.locals['equips'] self.player.pack_msg_data(equips=news, send=1) self.player.pub(MSG_ROLE_INVITE, role.data.rid, self.player) return role def invite(self, rid, gm=False, pack_msg=True): """ 招募配将, 失败抛出异常 成功返回: role, uses """ #rid资源必须存在,并且不能多次招募同一个rid rs, err = self.can_add(rid) if not rs: return False, err res_role = err if not res_role.is_main and not gm: #花费 use_id, use_num = res_role.useId, res_role.useNum uses = self.player.bag.cost_item(use_id, use_num, log_type=ITEM_COST_INVITE, pack_msg=pack_msg) if uses is None: return False, errcode.EC_COST_ERR _, _, items = uses else: items = {} self.player.log_normal(PL_ROLE, rid=rid) role = self.add_role(res_role) return role, items def _check_rid_fate(self, rid, fate1, fate2): """ 检测玩家是否穿此命格 """ role = self.roles.get(rid) used = 0 for key, fid in role.iter_fates(): if fid == fate1.data.id or fid == fate2.data.id: used += 1 if used and used == fate1.data.used + fate2.data.used: return True, None log.debug('check-rid-fate rid %s, fate1 %s, fate2 %s', rid, fate1.data.id, fate2.data.id) return False, errcode.EC_ROLE_WEARED def _merge_fate_exp(self, res_fate1, res_fate2, fate1, fate2): """ 经验命格的合并处理 """ if res_fate1.is_exp_fate: update_fate = self._merge_fate_handle(fate1, fate2) return True, update_fate if res_fate2.is_exp_fate: update_fate = self._merge_fate_handle(fate2, fate1) return True, update_fate return False, None def _merge_fate_noexp(self, rid, res_fate1, res_fate2, fate1, fate2): """ 非经验命格的合并处理 """ if rid: if res_fate1.quality > res_fate2.quality: best_id = fate1.data.id else: best_id = fate2.data.id #移动的命格未必使用且它的品质高时 判断是否重叠效果 if fate2.data.used and not fate1.data.used and best_id == fate1.data.id: fate, res_fate = self.player.bag.get_fate_ex(fate1.data.id) tRole = self.roles.get(rid) if tRole._is_fate_repeat(self.player, res_fate): return False, errcode.EC_ROLE_WEAR_REP #品质高的吞噬底的,品质相同时aFtId2吞噬aFtId1 if res_fate1.quality > res_fate2.quality: update_fate = self._merge_fate_handle(fate2, fate1) else: update_fate = self._merge_fate_handle(fate1, fate2) return True, update_fate def merge_fate(self, fid1, fid2, rid=0): """ 命格合并(fid1移动到fid2) """ if fid1 == fid2: return False, errcode.EC_FATE_NOMERGE fate1 = self.player.bag.get_fate(fid1) fate2 = self.player.bag.get_fate(fid2) if not fate1 or not fate2: return False, errcode.EC_FATE_NOFOUND if rid: rs, data = self._check_rid_fate(rid, fate1, fate2) if not rs: return rs, data item_mgr = self.player._game.item_mgr res_fate1 = item_mgr.get_res_fate(fate1.data.fid) res_fate2 = item_mgr.get_res_fate(fate2.data.fid) if res_fate1.is_exp_fate and res_fate2.is_exp_fate: return False, errcode.EC_MERGE_EXPS #经验命格的处理 is_exp_merge, data = self._merge_fate_exp(res_fate1, res_fate2, fate1, fate2) if not is_exp_merge: #非经验命格的处理 rs, data = self._merge_fate_noexp(rid, res_fate1, res_fate2, fate1, fate2) if not rs: return rs, data update_fate = data #合并完成后 对多种操作进行判断 if rid: tRs = self._wear_fate_update(rid, fate1, fate2, update_fate.data.id) if tRs: tRole, data = tRs update_fate.data.used = data self.player.bag.update_fate(update_fate) self.update_role(tRole) del_id = fid2 if update_fate.data.id == fid1 else fid1 return True, self.player.pack_msg_data(fates=[update_fate], del_fids=[del_id]) def _wear_fate_update(self, aRid, aFate1, aFate2, aFtIdBest): """ 处理穿着命格合并的多种情况 然会更新的配将和命格是否使用 """ tRole = self.roles.get(aRid) if not tRole: return None, errcode.EC_ROLE_NOFOUND tRoleWearFates = self._role_wear_fate_data(tRole) #全在身上 if aFate1.data.used and aFate2.data.used: setattr(tRole.data, tRoleWearFates[aFate1.data.id], 0) if aFtIdBest == aFate1.data.id: setattr(tRole.data, tRoleWearFates[aFate2.data.id], aFate1.data.id) return tRole, USED_DO #将身上的移到背包里 elif aFate1.data.used: setattr(tRole.data, tRoleWearFates[aFate1.data.id], 0) return tRole, USED_NOT #将背包里移到身上 elif aFate2.data.used and aFtIdBest == aFate1.data.id: setattr(tRole.data, tRoleWearFates[aFate2.data.id], aFate1.data.id) return tRole, USED_DO return def _role_wear_fate_data(self, aRole): """ 将配将身上的命格存为字典{WearFateId1:FatePlace,...} """ tDict = {} for tFatePlace, tWearFateId in aRole.iter_fates(): if tWearFateId: tDict[tWearFateId] = tFatePlace return tDict def _merge_fate_handle(self, aFate1, aFate2): """ 命格合并:aFate2将aFate1吞噬(固定吞噬方向)""" #写入log self.player.log_merge_fate(ufate=aFate2.to_dict(), dfate=aFate1.to_dict()) tResFateLevels = self.player._game.res_mgr.fate_level_by_fid.get(aFate2.data.fid) tExp = aFate1.data.exp + aFate2.data.exp #获取当前经验所在的等级 tNeedExp = 0 tLevel = 1 max_exp = 0 max_level = 0 for tResFateLevel in tResFateLevels: if tResFateLevel.exp > max_exp: max_exp = tResFateLevel.exp max_level = tResFateLevel.level if tExp < tResFateLevel.exp : tMoreExp = tResFateLevel.exp else: continue if not tNeedExp or tMoreExp<tNeedExp: tNeedExp = tMoreExp tLevel = tResFateLevel.level - 1 #如果无此值则说明合成的等级已经超过上限 if not tNeedExp: tExp = max_exp tLevel = max_level aFate2.data.level = tLevel aFate2.data.exp = tExp if not aFate1.data.isTrade or not aFate2.data.isTrade: aFate2.data.isTrade = CANNOT_TRADE #删除吞噬掉的命格 self.player.bag.del_fate(aFate1.data.id) self.player.bag.update_fate(aFate2) return aFate2 def merge_all_fate(self): """ 命格一键合成 """ #保存数据格式为{效果字段:{品质:tFate...}...} tEffDict = {} tDelFateIds = [] tUpdateFatesDict = {} for tFate in self.player.bag.fates.values(): if tFate.data.used or tFate.data.level == FATE_LEVEL_MAX: continue tResFate = self.player._game.item_mgr.get_res_fate(tFate.data.fid) tKeys = (tFate.data.fid, INIT_LEVEL+1) res_mgr = self.player._game.res_mgr #经验命格不处理 if not res_mgr.fate_level_by_keys.has_key(tKeys): tUpdateFatesDict[tFate.data.id] = tFate.to_dict() continue if tEffDict.has_key(tResFate.effect): if tEffDict[tResFate.effect].has_key(tResFate.quality): #相同影响效果且相同品质进行合并 tFateUp = self._merge_fate_handle(tFate, tEffDict[tResFate.effect][tResFate.quality]) if tFateUp: tDelFateIds.append(tFate.data.id) tUpdateFatesDict[tFateUp.data.id] = tFateUp.to_dict() else: tEffDict[tResFate.effect][tResFate.quality] = tFate else: tEffDict[tResFate.effect] = {tResFate.quality:tFate} if tDelFateIds: return True, {'delFids':tDelFateIds, 'fate':tUpdateFatesDict.values()} return False, errcode.EC_FATE_NOMERGE def role_up_enter(self): """ 进入武将升段 """ pass_day = self.player.play_attr.pass_day(FN_P_ATTR_KEY_ROLEUP) if pass_day: rid2updatens = {} for role in self.roles.itervalues(): rid2updaten = role.pass_day() if rid2updaten: rid2updatens.update(rid2updaten) if rid2updatens: return True, dict(update=rid2updatens) return True, None def role_train_do(self, rid, type): """ 武将培养 产生随机值 """ if self.player.data.level < self.fetch_train_locklevel: return False, errcode.EC_ROLETRAIN_UNLOCK role = self.rid2roles.get(rid) if not role: return False, errcode.EC_VALUE cost = self.train_cost(type) coin1 = coin3 = 0 if type == 0: res_add = self.fetch_train_coin1 coin1 = cost else: res_add = self.fetch_train_coin2 coin3 = cost if not self.player.enough_coin_ex(coin1, aCoin3=coin3): return False, errcode.EC_COST_ERR #产生随机值 rs, data = self._random_train(rid, self.player.data.level, res_add) if not rs: return rs, data if not self.player.cost_coin_ex(coin1, aCoin3=coin3, log_type=COIN_ROLETARIN): return False, errcode.EC_COST_ERR self.train_rand_data = (rid, data) pack = self.player.pack_msg_data(coin=True) return rs, dict(radd=data, update=pack) def _random_train(self, rid, level, res_add): """ 随机产生培养 """ res_role_level = self.player._game.res_mgr.get_role_level(int(rid), level) if not res_role_level: return False, errcode.EC_NORES t_data = {} for attr, (start, end) in res_add.iteritems(): value = getattr(res_role_level, attr) start = value * int(start) * 0.01 end = value * int(end) * 0.01 r_num = random.randint(int(start), int(end)) t_data[attr] = r_num return True, t_data def role_train_ok(self, rid): """ 保存培养 """ if not self.train_rand_data: return False, errcode.EC_ROLETRAIN_NO train_rid, attr = self.train_rand_data if rid != train_rid: return False, errcode.EC_ROLETRAIN_NO role = self.rid2roles.get(rid) if not role: return False, errcode.EC_ROLE_NOFOUND role.train_save(attr) self.train_rand_data = None return True, None def train_cost(self, type): """ 培养消耗 """ res_cost = self.player._game.setting_mgr.setdefault(ROLETRAIN_COST, ROLETRAIN_COST_V) res = common.str2list(res_cost) return res[type] @property def fetch_up_num(self): """ 获取每位武将每天能获得升段次数 """ return self.player._game.setting_mgr.setdefault(ROLEUP_DAY_NUM, ROLEUP_DAY_NUM_V) @property def fetch_up_cost(self): """ 获取武将升段所需要的物品id """ return PlayerRoles.setting_data.get(ROLEUP_COST_ITEM) @property def fetch_train_coin1(self): """ 银币培养 """ return PlayerRoles.setting_data.get(ROLETRAIN_COIN1) @property def fetch_train_coin2(self): """ 元宝培养 """ return PlayerRoles.setting_data.get(ROLETRAIN_COIN2) @property def fetch_train_locklevel(self): """ 培养解锁等级 """ return PlayerRoles.setting_data.get(ROLETRAIN_LOCKLEVEL)