Exemple #1
0
    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
Exemple #2
0
 def uninit(self):
     self.globals = None
     self.locals = None
     self.player = None
     if 0:
         from game.player.player import Player
         self.player = Player()
Exemple #3
0
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
Exemple #4
0
 def __init__(self, player):
     if 0:
         from game.player.player import Player
         self.player = Player()
     self.items = {}
     self.types = {}
     self.player = player
Exemple #5
0
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
Exemple #6
0
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
Exemple #7
0
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]
Exemple #8
0
 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()
Exemple #9
0
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
Exemple #10
0
 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()
Exemple #11
0
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)
Exemple #12
0
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
Exemple #13
0
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__)
Exemple #14
0
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]
Exemple #15
0
 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()
Exemple #16
0
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
Exemple #18
0
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
Exemple #19
0
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
    ]
Exemple #20
0
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
Exemple #21
0
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)
Exemple #22
0
 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
Exemple #23
0
 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
Exemple #24
0
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
Exemple #25
0
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
Exemple #26
0
 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
          ]])
Exemple #27
0
 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)
Exemple #28
0
 def gm_del_pid(self, pid):
     """ 删除玩家数据 """
     rs = Player.del_player(pid)
     if rs:
         self.log(u'删除玩家(%s)数据成功', pid)
     else:
         self.log(u'删除玩家(%s)数据失败', pid)
Exemple #29
0
 def __init__(self, player):
     if 0:
         from game.player.player import Player
         self.player = Player()
     self.items = {}
     self.types = {}
     self.player = player
Exemple #30
0
    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)
Exemple #31
0
 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)
Exemple #32
0
 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
Exemple #33
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)
Exemple #34
0
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
Exemple #35
0
 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
Exemple #36
0
 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
Exemple #37
0
 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
Exemple #38
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
Exemple #39
0
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
Exemple #40
0
 def __init__(self, player):
     self.player = player
     if 0:
         from .player import Player
         self.player = Player()
Exemple #41
0
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
Exemple #42
0
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)
Exemple #43
0
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)