def overPVP(self): ''' 战斗结算 ''' for _uid in self.__users.iterkeys(): yield redis.zadd(SET_RANK_ROOM_EAT%self.__id, _uid, -self.__eat_num.get(_uid, 0)) yield redis.zadd(SET_RANK_ROOM_EATED%self.__id, _uid, -self.__be_eated_num.get(_uid, 0)) _user_mgr = g_UserMgr.getUserByUid(_uid) _user_mgr.attrib.paly_num += 1 _volume = yield redis.zscore(SET_RANK_ROOM_VOLUME%self.__id, _uid) _weight = int(_volume) * 10 if _volume else 0 if _user_mgr.attrib.max_weight < _weight: _user_mgr.attrib.max_weight = _weight yield redis.zadd(SET_RANK_PVP_WEIGHT, _uid, -_weight) yield redis.hset(HASH_PVP_ROOM_USER_NUM, self.__id, self.count)
def __migrate_accounts_registered(self): try: yield redis.delete(HASH_NICKNAME_REGISTERED, HASH_MACHINE_CODE_REGISTERED, HASH_UID_MACHINE_CODE, SET_RANK_PVP_WEIGHT) db_conf = {'host': setting.DB_CONF['host'], 'port' : setting.DB_CONF['port'], 'user' : setting.DB_CONF['user'], 'passwd' : setting.DB_CONF['pass'], 'db' : setting.DB_CONF['userdb'], 'charset' : 'utf8' } conn = MySQLdb.connect(**db_conf) cu = conn.cursor() cu.execute('SELECT `id`,`machine_code`,`nickname`,`max_weight` FROM tb_character') _dataset = cu.fetchall() for _id, _machine_code, _nickname, _max_weight in _dataset: yield redis.hset(HASH_NICKNAME_REGISTERED, _nickname, _id) yield redis.hset(HASH_MACHINE_CODE_REGISTERED, _machine_code, _id) yield redis.hset(HASH_UID_MACHINE_CODE, _id, _machine_code) yield redis.zadd(SET_RANK_PVP_WEIGHT, _id, -_max_weight) cu.close() conn.close() conn = None cu = None except Exception, e: reactor.callLater(1, self.__migrate_accounts_registered) print 'ERROR:', e print 'WARNING. Redis connection fail, callLater 1 second. redis:', redis
def rank(self): _rank = yield redis.zrank(RANK_WORLDBOSS_DAMAGE, self._cid) if not _rank: yield redis.zadd(RANK_WORLDBOSS_DAMAGE, self._cid, -self._damage_total) _rank = yield redis.zrank(RANK_WORLDBOSS_DAMAGE, self._cid) defer.returnValue(_rank)
def get_char_score(self, cid, redis_key=SET_JOUST_CID_SCORE): ''' 获取玩家的积分 ''' _score = yield redis.zscore(redis_key, cid) if _score is None: _score = JOUST_BASIC_SCORE yield redis.zadd(redis_key, cid, -JOUST_BASIC_SCORE) else: _score = -int(_score) defer.returnValue(_score)
def get_battle_score(self, cid, other_cid, redis_key=SET_JOUST_CID_SCORE): ''' 挑战胜利后计算积分 ''' _score = yield self.get_char_score(cid) # 机器人 _score_reduce = 0 if other_cid < JOUST_ROBOT_CID: _other_score = JOUST_BASIC_SCORE if _score > _other_score: _score += SCORE_BASIC_2 elif _score < _other_score: _score += SCORE_BASIC_4 else: _score += SCORE_BASIC_3 yield redis.zadd(redis_key, cid, -_score) defer.returnValue((_score, _score_reduce)) # 玩家 _other_score = yield self.get_char_score(other_cid) if _score > _other_score: _score_add = (_other_score * SCORE_RATE_2 + SCORE_PERCENT - 1) / SCORE_PERCENT _score_reduce = _score / SCORE_PERCENT elif _score < _other_score: _score_add = (_other_score * SCORE_RATE_4 + SCORE_PERCENT - 1) / SCORE_PERCENT + SCORE_BASIC_4 _score_reduce = _score * SCORE_RATE_4 / SCORE_PERCENT else: _score_add = (_other_score * SCORE_RATE_3 + SCORE_PERCENT - 1) / SCORE_PERCENT + SCORE_BASIC_3 _score_reduce = _score * SCORE_RATE_2 / SCORE_PERCENT #log.info('For Test. cid<{0}> score: {1} add<{2}>, other_cid<{3}> score: {4} reduce<{5}>.'.format( cid, _score, _score_add, other_cid, _other_score, _score_reduce )) _score += _score_add yield redis.zadd(redis_key, cid, -_score) _other_score = (_other_score - _score_reduce) if _other_score > _score_reduce else 0 yield redis.zadd(redis_key, other_cid, -_other_score) defer.returnValue((_score, _score_reduce))
def reward_to_award_center(self, total_count, interval): try: timestamp = int(time()) start_rank = total_count - interval + 1 if total_count > interval else 0 all_cids = yield redis.zrange(SET_JOUST_LAST_CID_SCORE, start_rank, total_count) for _idx, _cid in enumerate(all_cids): _rank = (_idx + start_rank + 1) yield g_AwardCenterMgr.new_award(_cid, AWARD_TYPE_JOUSTRANK, [timestamp, _rank]) # Reset score yield redis.zadd(SET_JOUST_CID_SCORE, _cid, -JOUST_BASIC_SCORE) except Exception as e: log.exception() if total_count > interval: total_count -= interval reactor.callLater(1, self.reward_to_award_center, total_count, interval)
def __migrate_accounts_registered(self): try: yield redis.delete(HASH_NICKNAME_REGISTERED, HASH_MACHINE_CODE_REGISTERED, HASH_UID_MACHINE_CODE, SET_RANK_PVP_WEIGHT) db_conf = { 'host': setting.DB_CONF['host'], 'port': setting.DB_CONF['port'], 'user': setting.DB_CONF['user'], 'passwd': setting.DB_CONF['pass'], 'db': setting.DB_CONF['userdb'], 'charset': 'utf8' } conn = MySQLdb.connect(**db_conf) cu = conn.cursor() cu.execute( 'SELECT `id`,`machine_code`,`nickname`,`max_weight` FROM tb_character' ) _dataset = cu.fetchall() for _id, _machine_code, _nickname, _max_weight in _dataset: yield redis.hset(HASH_NICKNAME_REGISTERED, _nickname, _id) yield redis.hset(HASH_MACHINE_CODE_REGISTERED, _machine_code, _id) yield redis.hset(HASH_UID_MACHINE_CODE, _id, _machine_code) yield redis.zadd(SET_RANK_PVP_WEIGHT, _id, -_max_weight) cu.close() conn.close() conn = None cu = None except Exception, e: reactor.callLater(1, self.__migrate_accounts_registered) print 'ERROR:', e print 'WARNING. Redis connection fail, callLater 1 second. redis:', redis
def attack(self, user, damage): _now = time() if self._attack_time: if (_now - self._attack_time) < ATTACK_CD: log.warn('[ attack ]CD time. last attack time:{0}, now:{1}.', self._attack_time, _now) defer.returnValue((WORLDBOSS_CD, None)) _current_life = worldBoss.life if _current_life <= 0: defer.returnValue((WORLDBOSS_DEAD_ALREADY, None)) self._attack_count += 1 ''' 转到客户端算 _attack_extra = self._attack_extra_level * 5 damage = int(int(damage) * (100 + _attack_extra) / 100) ''' self._damage_total += damage _farm = 10 user.base_att.prestige += _farm worldBoss.on_attack(self._cid, user.nick_name, damage) self._attack_time = _now self.sync() yield redis.zadd(RANK_WORLDBOSS_DAMAGE, self._cid, -self._damage_total) yield redis.hset(DICT_WORLDBOSS_RANKER_DATA, self._cid, dumps((user.nick_name, user.level, user.alliance_id))) #log.debug('attack come here...', self, self.__dict__) _current_rank = yield self.rank defer.returnValue((NO_ERROR, (self._damage_total, _farm, worldBoss.life, _current_rank + 1)))
def attack(self, user, damage): _now = time() if self._attack_time: if (_now - self._attack_time) < ATTACK_CD: log.warn('[ attack ]CD time. last attack time:{0}, now:{1}.', self._attack_time, _now) defer.returnValue((WORLDBOSS_CD, None)) _current_life = worldBoss.life if _current_life <= 0: defer.returnValue((WORLDBOSS_DEAD_ALREADY, None)) self._attack_count += 1 ''' 转到客户端算 _attack_extra = self._attack_extra_level * 5 damage = int(int(damage) * (100 + _attack_extra) / 100) ''' self._damage_total += damage _farm = 10 user.base_att.prestige += _farm worldBoss.on_attack(self._cid, user.nick_name, damage) self._attack_time = _now self.sync() yield redis.zadd(RANK_WORLDBOSS_DAMAGE, self._cid, -self._damage_total) yield redis.hset(DICT_WORLDBOSS_RANKER_DATA, self._cid, dumps((user.nick_name, user.level, user.alliance_id))) #log.debug('attack come here...', self, self.__dict__) _current_rank = yield self.rank defer.returnValue((NO_ERROR, (self._damage_total, _farm, worldBoss.life, _current_rank+1)))
def newUser(self, uid): if not self.__users: # common foodball and spineball self.__foodball = get_all_foodball() self.__spineball = get_all_spineball() foodball_conf = self.__foodball.values() spineball_conf = self.__spineball.values() self.__end_time = int((time() + PVP_SECONDS)*1000) #reactor.callLater(PVP_SECONDS, self._broadcastFoodball) else: foodball_conf = self.__foodball.values() spineball_conf = self.__spineball.values() self.__eat_num.setdefault(uid, 0) self.__be_eated_num.setdefault(uid, 0) userball_obj = Userball(uid) self.__users[uid] = userball_obj all_userball = userball_obj.initBall(self.count) for _ub in self.__users.itervalues(): if _ub.uid == uid: continue all_userball.extend(_ub.getAllBall()) yield redis.zadd(SET_RANK_ROOM_VOLUME%self.__id, uid, -INIT_USERBALL_VOLUME) rank = yield redis.zrank(SET_RANK_ROOM_VOLUME%self.__id, uid) rank = 0 if rank is None else int(rank) + 1 data = {'userball': all_userball, \ 'foodball': foodball_conf, \ 'spineball': spineball_conf, \ 'end_time': self.__end_time, \ 'total': self.count, 'rank': rank, \ 'room_id': self.__id, } defer.returnValue(data)
def syncUserball(self, character, ball_info, status): uid = character.attrib_id if not (ball_info and isinstance(ball_info[0], list)): log.error("args error. uid:{0}, ball_info:{1}.".format(uid, ball_info)) defer.returnValue((ARGS_ERROR, None)) if uid not in self.__users: log.error("user not in room error. uid:{0}, room_id:{1}.".format(uid, self.__id)) defer.returnValue((PVPROOM_LOSE, None)) _hide_fb_ids = list() userball_obj = self.__users[uid] if userball_obj.isDead: log.warn("room uids:{0}, __eat_num:{1}, __be_eated_num:{2}, uid:{3}, isDead:{4}, status:{5}.".format(self.__users.keys(), self.__eat_num, self.__be_eated_num, uid, userball_obj.isDead, status)) if status: userball_obj.revive() else: log.error("user is dead. uid:{0}, isDead:{1}, status:{2}.".format(uid, userball_obj.isDead, status)) defer.returnValue((USER_IS_DEAD, None)) _hide_ub_ids, _delta_volume, ball_info = userball_obj.checkHideBall(ball_info) #_delta_br = int(FOODBALL_RADIUS * MULTIPLE_ENLARGE_FOODBALL * 0.01) _max_hide = 1 for _bid, _bx, _by, _bz in self.__foodball.itervalues(): for _, ball_id, ball_x, ball_y, ball_z, ball_r, ball_v, ball_s, pow_r in ball_info: # 和食物球 其它玩家球比较半径大小 计算直线距离 # 玩家球 分裂后的半径也会比食物球大吗? _distance = pow(ball_x-_bx, 2) + pow(ball_y-_by, 2) + pow(ball_z-_bz, 2) if _distance < pow_r: log.warn('--------------- eated foodball uid:{0}, pow_r:{1}, _distance:{2}, source:{3}, target:{4}, _delta_volume:{5}.'.format(uid, pow_r, _distance, (ball_id, ball_x, ball_y, ball_z, ball_r), (_bid, _bx, _by, _bz), _delta_volume)) # 自身体积增长 _delta_volume[ball_id] = _delta_volume.setdefault(ball_id, ball_v) + INIT_FOODBALL_VOLUME _hide_fb_ids.append(_bid) if len(_hide_fb_ids) > 2: break for _bid in _hide_fb_ids: self.__hide_foodball_ids[_bid] = 0 if _bid in self.__foodball: del self.__foodball[_bid] # uid and ballid for _ub in self.__users.itervalues(): if _ub.isDead: log.error('----------------- user is dead. room_id:{0}, uid:{1}, isDead:{2}'.format(self.__id, _ub.uid, _ub.isDead)) if _ub.uid == uid or _ub.isDead: continue _all_ball = _ub.getAllBall() for _uid, _bid, _bx, _by, _bz, _br, _bv, _bs in iter(_all_ball): _be_eated_user = g_UserMgr.getUserByUid(_uid) for _, ball_id, ball_x, ball_y, ball_z, ball_r, ball_v, ball_s, pow_r in ball_info: if MULTIPLE_HIDE_USERBALL*_bv > ball_v: continue _distance = pow(ball_x-_bx, 2) + pow(ball_y-_by, 2) + pow(ball_z-_bz, 2) if _distance < pow_r: log.warn('---------------- eated userball uid:{0}, pow_r:{1}, _distance:{2}, source:{3}, target:{4}.'.format(uid, pow_r, _distance, (_uid, _bid, _bx, _by, _bz, _br), (ball_id, ball_x, ball_y, ball_z, ball_r))) # 记录吞噬/被吞噬 玩家球的个数 character.eat_num += 1 self.__eat_num[uid] += 1 if _be_eated_user and _be_eated_user.attrib: _be_eated_user.attrib.be_eated_num += 1 self.__be_eated_num[_uid] = self.__be_eated_num.setdefault(_uid, 0) + 1 # 自身体积增长 _delta_volume[ball_id] = _delta_volume.setdefault(ball_id, ball_v) + _bv _ub.setHideBall(_bid) _hide_ub_ids.append((_uid, _bid)) yield redis.zincrby(SET_RANK_ROOM_VOLUME%self.__id, _uid, _bv) data = list() _delta_ub_data = list() _delta_ub_volume = 0 for _, ball_id, ball_x, ball_y, ball_z, ball_r, ball_v, ball_s, pow_r in ball_info: ball_v = _delta_volume[ball_id] if ball_id in _delta_volume else ball_v _delta_ub_data.append((uid, ball_id, ball_x, ball_y, ball_z, ball_r, ball_v, ball_s)) _delta_ub_volume += ball_v # 更新自己的球体积排行榜 yield redis.zadd(SET_RANK_ROOM_VOLUME%self.__id, uid, -_delta_ub_volume) # 更新自己的球体积信息 userball_obj.updateVolume(_delta_volume) if (_hide_ub_ids or _hide_fb_ids or _delta_ub_data): data = [_hide_ub_ids, _hide_fb_ids, _delta_ub_data] #TODO broadcast uids = self.__users.keys() uids.remove(uid) if uids: send2client(uids, 'broadcastUserball', data) if _hide_ub_ids or _hide_fb_ids: log.error("-------------- final hide info. room_id:{0}, uid:{1}, _hide_ub_ids:{2}, _hide_fb_ids:{3}".format(self.__id, uid, _hide_ub_ids, _hide_fb_ids)) _rank = yield redis.zrank(SET_RANK_ROOM_VOLUME%self.__id, uid) _rank = 0 if _rank is None else int(_rank) + 1 _total = len(self.__users) data.append((_rank, _total)) defer.returnValue((NO_ERROR, data))
def climbing_reward(self, fight_layer, status): ''' @summary: 单次通关失败扣挑战次数, 更新玩家当前所在塔层及最大塔层, 给通关后的奖励 ''' self.system_daily_reset() # 可挑战的塔层数据不同步 if fight_layer != self.climbing.cur_layer: log.error( 'User request fight_layer error. cid: {0}, fight_layer: {1}, cur_layer: {2}.' .format(self.cid, fight_layer, self.climbing.cur_layer)) defer.returnValue(REQUEST_LIMIT_ERROR) # 没有挑战次数不能挑战 climbing_data = self.get_vip_conf_of_climbing() if (climbing_data[0] + self.climbing.buyed_fight < 1): log.error( 'User no fight count. cid: {0}, had_free_fight: {1}, buyed_fight: {2}.' .format(self.cid, self.climbing.free_fight, self.climbing.buyed_fight)) defer.returnValue(REQUEST_LIMIT_ERROR) # 已经到了最大塔层 不能继续挑战 if self.climbing.cur_layer >= self.MAX_LAYER: log.error( 'Had been the max layer. cur_layer: {0}, climbing_tower MAX_LAYER: {1}.' .format(self.climbing.cur_layer, self.MAX_LAYER)) defer.returnValue(IN_CLIMBING_MAX_LAYER) # 每日任务计数 yield self.user.daily_quest_mgr.update_daily_quest(DAILY_QUEST_ID_9, 1) yield self.user.open_server_mgr.update_open_server_activity_quest( OPEN_SERVER_QUEST_ID_10, self.climbing.cur_layer) #成就 yield self.user.achievement_mgr.update_achievement_status( ACHIEVEMENT_QUEST_ID_10, self.climbing.cur_layer) if not status: # 通关失败 if self.climbing.buyed_fight > 0: self.climbing.buyed_fight -= 1 elif climbing_data[0] > 0: climbing_data[0] -= 1 self.climbing.free_fight += 1 defer.returnValue( (status, self.climbing.cur_layer, self.climbing.max_layer, climbing_data[0] + self.climbing.buyed_fight, [], 0, 0, 0, self.user.base_att.energy)) # 获取塔层通过的奖励 conf = get_climbing_conf(self.climbing.cur_layer) if not conf: log.error('No conf. cid: {0}, cur_layer: {0}.'.format( cid, self.climbing.cur_layer)) defer.returnValue(NOT_FOUND_CONF) #self.user.base_att.golds += conf['RewardGold'] self.user.get_golds(conf['RewardGold'], WAY_CLIMBING_AWARD) self.user.base_att.soul += conf['RewardSoul'] items_return = [] #log.info('For Test. cur_layer: {0}, BonusList: {1}.'.format( self.climbing.cur_layer, conf['BonusList'] )) for _type, _id, _num in conf['BonusList']: model = ITEM_MODELs.get(_type, None) if not model: log.error('Unknown item type. item: {0}.'.format( (_type, _id, _num))) continue res_err, value = yield model(self.user, ItemID=_id, ItemNum=_num, AddType=WAY_CLIMBING_AWARD, CapacityFlag=False) if not res_err and value: #log.info('For Test. value: {0}.'.format( value )) for _v in value: items_return = total_new_items(_v, items_return) #log.info('For Test. after BonusList: {0}.'.format( conf['BonusList'] )) if self.climbing.cur_layer >= self.MAX_LAYER: self.climbing.cur_layer = self.MAX_LAYER else: self.climbing.cur_layer += 1 # 挑战更高的塔层 if (self.climbing.cur_layer <= self.MAX_LAYER) and ( self.climbing.cur_layer > self.climbing.max_layer): self.climbing.max_layer += 1 if self.climbing.max_layer > self.MAX_LAYER: self.climbing.max_layer = self.MAX_LAYER # 更新天外天排行榜 yield redis.zadd(SET_CLIMBING_CID_LAYER, self.cid, -self.climbing.max_layer) defer.returnValue( (status, self.climbing.cur_layer, self.climbing.max_layer, climbing_data[0] + self.climbing.buyed_fight, items_return, conf['RewardGold'], conf['RewardSoul'], 0, self.user.base_att.energy))
def get_battle_reward(self, status, scene_id, dungeon_id, dungeon_star): ''' @summary: 战斗结束领取奖励 @param : 战斗结果 status 0:lose, 1:win ''' yield self._load() if scene_id != self.cur_scene_id or dungeon_id != self.cur_dungeon_id or dungeon_star != self.cur_dungeon_star: log.error('Player battle info not match. old_scene_id: {0}, old_dungeon_id: {1}, old_dungeon_star: {2}.'.format( self.cur_scene_id, self.cur_dungeon_id, self.cur_dungeon_star )) #defer.returnValue( REQUEST_LIMIT_ERROR ) dungeon = yield self.get_dungeon( scene_id, dungeon_id ) if not dungeon: log.error('Unknown dungeon id. scene_id: {0}, dungeon_id: {1}.'.format( scene_id, dungeon_id )) defer.returnValue( REQUEST_LIMIT_ERROR ) self.cur_scene_id, self.cur_dungeon_id, self.cur_dungeon_star = 0, 0, 0 # 战斗失败 if not status: syslogger(LOG_SCENE_BATTLE, self.cid, self.user.level, self.user.vip_level, self.user.alliance_id, 1, status, dungeon_id, dungeon_star, 0, 0, 0, '') defer.returnValue( (1, status, dungeon_id, dungeon.dungeon_star, dungeon.dungeon_today_count, [], 0, 0, 0, self.user.base_att.energy) ) # monster奖励金币、仙魂、经验 exp_reward, golds_reward, soul_reward = 0, 0, 0 monster_conf = get_monster_conf(dungeon_id, dungeon_star) no_energy = False if monster_conf: # 策划修改-副本的精力消耗改为5点 if self.user.base_att.energy >= 5: self.user.base_att.energy -= 5 exp_reward = self.user.base_att.level * BATTLE_MONSTER_EXP_RATIO else: no_energy = True exp_reward = self.user.base_att.level soul_reward = monster_conf['Soul'] golds_reward = monster_conf['Money'] else: log.error('Can not find monster.') # 获取怪物组掉落 drop_items = yield self.dungeon_star_drop( dungeon_id, dungeon_star, no_energy ) # 判断是否是第一次挑战更高星级难度 if dungeon_star > dungeon.dungeon_star: dungeon.dungeon_star = dungeon_star # 新增混沌星数 self.user.base_att.scene_star += 1 # 新增副本总星数 self.total_star += 1 yield redis.zadd(SET_SCENE_CID_STAR, self.cid, -self.total_star) # 更新最大副本ID if scene_id > self.max_scene_id: self.max_scene_id = scene_id syslogger(LOG_SCENESTAR_GET, self.cid, self.user.level, self.user.vip_level, self.user.alliance_id, 1, self.user.base_att.scene_star, dungeon_id, dungeon_star) dungeon.dungeon_today_count += 1 dungeon.dungeon_last_time = datetime.now() # 新增掉落 way_others = str((FIGHT_TYPE_NORMAL, dungeon_id, dungeon_star)) dungeon_drop_items = yield self.get_dungeon_drop( drop_items, way_others ) # 发放奖励 yield self.user.update_battle_attr( soul_reward, golds_reward, exp_reward ) # 每日任务计数 yield self.user.daily_quest_mgr.update_daily_quest( DAILY_QUEST_ID_3, 1 ) # 开服七天 yield self.user.open_server_mgr.update_open_server_activity_quest( OPEN_SERVER_QUEST_ID_3, dungeon_id) #成就 yield self.user.achievement_mgr.update_achievement_status(ACHIEVEMENT_QUEST_ID_3, dungeon_id) yield self.user.achievement_mgr.update_alliance_level() # add syslog str_drop_items = str(dungeon_drop_items).replace('[', '(') str_drop_items = str_drop_items.replace(']', ')') syslogger(LOG_SCENE_BATTLE, self.cid, self.user.level, self.user.vip_level, self.user.alliance_id, FIGHT_TYPE_NORMAL, status, dungeon_id, dungeon_star, exp_reward, soul_reward, golds_reward, str_drop_items) defer.returnValue( (1, status, dungeon_id, dungeon.dungeon_star, dungeon.dungeon_today_count, dungeon_drop_items, golds_reward, soul_reward, exp_reward, self.user.base_att.energy) )
def randcard(self, rand_type): ''' 免费抽卡、钻石抽卡 ''' _status, _data = yield self.status() if _status < 0: defer.returnValue( LIMIT_FELLOW_NO_ERROR ) _need_time = self.left_free_timestamp( _data[3], LIMIT_FELLOW_FREE_TIME ) _last_time = _data[3] # 检查抽卡条件是否满足 _score = yield redis.zscore( SET_LIMIT_FELLOW_NAME_SCORE, self.user.nick_name ) _score = int(_score) if _score else 0 _cost_flag = True # 扣钻石的标识位 if rand_type == RANDCARD_TYPE_FREE: if _need_time > 0: defer.returnValue( LIMIT_FELLOW_FREE_ERROR ) else: _last_time = int(time()) _cost_flag = False _need_time = LIMIT_FELLOW_FREE_TIME else: # 某积分的整数倍时免费钻石抽卡 if not _score or _score%RAND_COST_FREE_SCORE != 0: if self.user.credits < LIMIT_FELLOW_RAND_COST: defer.returnValue( CHAR_CREDIT_NOT_ENOUGH ) else: _cost_flag = False # 卡池升级 res_err, shrine_data = self.update_shrine(_data[1], _data[2]) if res_err: defer.returnValue( res_err ) #log.info('For Test. shrine_data: {0}, redis_data: {1}.'.format( shrine_data, _data )) # 获取抽卡池并抽卡 card_conf = self.get_randcard_frompool(_data[1], shrine_data[3]-_data[2]) if not card_conf: defer.returnValue( NOT_FOUND_CONF ) # 更新免费时间或扣钻石 yield redis.hset( HASH_LIMIT_FELLOW_SHRINE, self.cid, dumps([_data[0], shrine_data[0], shrine_data[1], _last_time]) ) if _cost_flag: yield self.user.consume_credits( LIMIT_FELLOW_RAND_COST, WAY_LIMIT_FELLOW_RANDCARD ) _score += RANDCARD_ONCE_SCORE yield redis.zadd( SET_LIMIT_FELLOW_NAME_SCORE, self.user.nick_name, _score ) # 新增fellow try: # args: fellow_id, is_major, camp_id, on_troop new_fellow = [] fellow_id = card_conf['ItemId'] res_err, attrib = yield self.user.fellow_mgr.create_table_data( fellow_id, 0, 0, 0 ) if not res_err: new_fellow = [attrib.attrib_id, fellow_id] conf = get_fellow_by_fid( fellow_id ) if conf and conf['Quality'] == QUALITY_PURPLE: syslogger(LOG_FELLOW_GET, self.cid, self.user.level, self.user.vip_level, self.user.alliance_id, \ attrib.attrib_id, fellow_id, conf['QualityLevel'], conf['Star'], RANDCARD_TYPE_CREDITS, '') message = [RORATE_MESSAGE_ACHIEVE, [ACHIEVE_TYPE_LIMIT_FELLOW, [self.user.nick_name, fellow_id]]] gw_broadcast('sync_broadcast', [message]) except Exception as e: log.warn('Create fellow fail! e:', e) defer.returnValue(res_err) _rank = yield redis.zrevrank( SET_LIMIT_FELLOW_NAME_SCORE, self.user.nick_name ) _rank = int(_rank) + 1 if _rank >= 0 else 0 _ranklist = yield self.ranklist() defer.returnValue( [self.user.credits, _rank, _score, _need_time, shrine_data[2], _ranklist, new_fellow] )
def lottery_items(self, user, client_my_rank, enemy_rank, battle_status): ''' @summary: 挑战胜利后,替换双方的排名,并返回可供翻牌的道具列表。长度为3。 ''' items_list = [] # 判断是否处于结算时间 22:00-22:15 _dt_now = datetime.now() if _dt_now.hour == ARENA_RANK_REWARD_HOUR and _dt_now.minute < 15: defer.returnValue( ARENA_IN_REWARD_TIME ) # 扣斗战点 2点 if user.base_att.douzhan < PVP_NEED_DOUZHAN: log.error('user douzhan is 0. cid: {0}.'.format( user.cid )) defer.returnValue( CHAR_DOUZHAN_NOT_ENOUGH ) user.base_att.douzhan -= PVP_NEED_DOUZHAN # 获取我的排名 my_rank = yield self.get_char_rank( user.cid ) if my_rank != client_my_rank: log.error('Client arena rank info need update. cid: {0}, client_my_rank: {1}, my_rank: {2}.'.format( user.cid, client_my_rank, my_rank )) # 每日任务计数 yield user.daily_quest_mgr.update_daily_quest( DAILY_QUEST_ID_6, 1 ) if not battle_status: # 失败获得10声望值 user.get_prestige( 10, WAY_ARENA_BATTLE ) enemy_detail = yield self.get_rank_detail( enemy_rank, flag=False ) if not enemy_detail: log.error('No enemy rank data. cid: {0}, enemy_rank: {1}.'.format( user.cid, enemy_rank )) defer.returnValue( (items_list, user.base_att.douzhan) ) ms_send('write_mail', (enemy_detail[0], MAIL_PAGE_BATTLE, MAIL_BATTLE_1, [user.base_att.lead_id, user.base_att.nick_name])) defer.returnValue( (items_list, user.base_att.douzhan) ) # 胜利获得20声望值 user.get_prestige( 20, WAY_ARENA_BATTLE ) items_list = yield random_lottery_items( user.cid, user.base_att.level, user.base_att.vip_level ) # 名次越靠前, 数字越小; 没有排名时也直接替换 enemy_detail = yield self.get_rank_detail( enemy_rank, flag=False ) if not enemy_detail: log.error('No enemy rank data. cid: {0}, enemy_rank: {1}.'.format( user.cid, enemy_rank )) defer.returnValue( (items_list, user.base_att.douzhan) ) if my_rank == 0 or enemy_rank < my_rank: # 对方是玩家时 互换玩家信息 if enemy_detail[0] > 0: old_enemy_rank = yield self.get_char_rank( enemy_detail[0] ) if my_rank == 0: # 在排名5000(机器人总数)之外 yield redis.zrem( SET_ARENA_CID_RANK, enemy_detail[0] ) alli_send('sync_char_data', (enemy_detail[0], SYNC_ARENA_RANK, 0)) else: if old_enemy_rank == enemy_rank: ms_send('write_mail', (enemy_detail[0], MAIL_PAGE_BATTLE, MAIL_BATTLE_2, [user.base_att.lead_id, user.base_att.nick_name, my_rank])) yield redis.zadd( SET_ARENA_CID_RANK, enemy_detail[0], my_rank ) alli_send('sync_char_data', (enemy_detail[0], SYNC_ARENA_RANK, my_rank)) old_rank_detail = dumps( [enemy_detail[0], enemy_detail[1], enemy_detail[2], my_rank, 0, 0, [], enemy_detail[7]] ) yield redis.hset( HASH_ARENA_RANK, my_rank, old_rank_detail ) elif my_rank > 0: # 对手是机器人, 恢复当前排名机器人数据 old_rank_detail = dumps( [0, 0, '', my_rank, 0, 0, [], 0] ) yield redis.hset( HASH_ARENA_RANK, my_rank, old_rank_detail ) # 更新自己的rank数据 yield redis.zadd( SET_ARENA_CID_RANK, user.cid, enemy_rank ) alli_send('sync_char_data', (user.cid, SYNC_ARENA_RANK, enemy_rank)) # 保存当前的camp #yield user.sync_camp_to_redis(update=True) new_rank_detail = dumps( [user.cid, user.level, user.nick_name, enemy_rank, 0, 0, [], user.lead_id] ) yield redis.hset( HASH_ARENA_RANK, enemy_rank, new_rank_detail ) # 夺得竞技场前十名, 全服广播 if enemy_rank < 11: message = [RORATE_MESSAGE_ACHIEVE, [ACHIEVE_TYPE_ARENA, [user.base_att.nick_name, enemy_rank]]] gw_broadcast('sync_broadcast', [message]) elif enemy_rank > my_rank: ms_send('write_mail', (enemy_detail[0], MAIL_PAGE_BATTLE, MAIL_BATTLE_3, [user.base_att.lead_id, user.base_att.nick_name])) #开服狂欢 enemy_rank = enemy_rank if enemy_rank < my_rank else my_rank yield user.open_server_mgr.update_open_server_activity_quest( OPEN_SERVER_QUEST_ID_7, enemy_rank) yield user.achievement_mgr.update_achievement_status( ACHIEVEMENT_QUEST_ID_7, enemy_rank) defer.returnValue( (items_list, user.base_att.douzhan) )
def climbing_reward(self, fight_layer, status): ''' @summary: 单次通关失败扣挑战次数, 更新玩家当前所在塔层及最大塔层, 给通关后的奖励 ''' self.system_daily_reset() # 可挑战的塔层数据不同步 if fight_layer != self.climbing.cur_layer: log.error('User request fight_layer error. cid: {0}, fight_layer: {1}, cur_layer: {2}.'.format( self.cid, fight_layer, self.climbing.cur_layer )) defer.returnValue( REQUEST_LIMIT_ERROR ) # 没有挑战次数不能挑战 climbing_data = self.get_vip_conf_of_climbing() if (climbing_data[0] + self.climbing.buyed_fight < 1): log.error('User no fight count. cid: {0}, had_free_fight: {1}, buyed_fight: {2}.'.format( self.cid, self.climbing.free_fight, self.climbing.buyed_fight )) defer.returnValue( REQUEST_LIMIT_ERROR ) # 已经到了最大塔层 不能继续挑战 if self.climbing.cur_layer >= self.MAX_LAYER: log.error('Had been the max layer. cur_layer: {0}, climbing_tower MAX_LAYER: {1}.'.format( self.climbing.cur_layer, self.MAX_LAYER )) defer.returnValue( IN_CLIMBING_MAX_LAYER ) # 每日任务计数 yield self.user.daily_quest_mgr.update_daily_quest( DAILY_QUEST_ID_9, 1 ) yield self.user.open_server_mgr.update_open_server_activity_quest( OPEN_SERVER_QUEST_ID_10, self.climbing.cur_layer) #成就 yield self.user.achievement_mgr.update_achievement_status( ACHIEVEMENT_QUEST_ID_10, self.climbing.cur_layer) if not status: # 通关失败 if self.climbing.buyed_fight > 0: self.climbing.buyed_fight -= 1 elif climbing_data[0] > 0: climbing_data[0] -= 1 self.climbing.free_fight += 1 defer.returnValue( (status, self.climbing.cur_layer, self.climbing.max_layer, climbing_data[0]+self.climbing.buyed_fight, [], 0, 0, 0, self.user.base_att.energy) ) # 获取塔层通过的奖励 conf = get_climbing_conf( self.climbing.cur_layer ) if not conf: log.error('No conf. cid: {0}, cur_layer: {0}.'.format( cid, self.climbing.cur_layer )) defer.returnValue( NOT_FOUND_CONF ) #self.user.base_att.golds += conf['RewardGold'] self.user.get_golds( conf['RewardGold'], WAY_CLIMBING_AWARD ) self.user.base_att.soul += conf['RewardSoul'] items_return = [] #log.info('For Test. cur_layer: {0}, BonusList: {1}.'.format( self.climbing.cur_layer, conf['BonusList'] )) for _type, _id, _num in conf['BonusList']: model = ITEM_MODELs.get( _type, None ) if not model: log.error('Unknown item type. item: {0}.'.format( (_type, _id, _num) )) continue res_err, value = yield model(self.user, ItemID=_id, ItemNum=_num, AddType=WAY_CLIMBING_AWARD, CapacityFlag=False) if not res_err and value: #log.info('For Test. value: {0}.'.format( value )) for _v in value: items_return = total_new_items( _v, items_return ) #log.info('For Test. after BonusList: {0}.'.format( conf['BonusList'] )) if self.climbing.cur_layer >= self.MAX_LAYER: self.climbing.cur_layer = self.MAX_LAYER else: self.climbing.cur_layer += 1 # 挑战更高的塔层 if (self.climbing.cur_layer <= self.MAX_LAYER) and (self.climbing.cur_layer > self.climbing.max_layer): self.climbing.max_layer += 1 if self.climbing.max_layer > self.MAX_LAYER: self.climbing.max_layer = self.MAX_LAYER # 更新天外天排行榜 yield redis.zadd(SET_CLIMBING_CID_LAYER, self.cid, -self.climbing.max_layer) defer.returnValue( (status, self.climbing.cur_layer, self.climbing.max_layer, climbing_data[0]+self.climbing.buyed_fight, items_return, conf['RewardGold'], conf['RewardSoul'], 0, self.user.base_att.energy) )
def randcard(self, rand_type): ''' 免费抽卡、钻石抽卡 ''' _status, _data = yield self.status() if _status < 0: defer.returnValue(LIMIT_FELLOW_NO_ERROR) _need_time = self.left_free_timestamp(_data[3], LIMIT_FELLOW_FREE_TIME) _last_time = _data[3] # 检查抽卡条件是否满足 _score = yield redis.zscore(SET_LIMIT_FELLOW_NAME_SCORE, self.user.nick_name) _score = int(_score) if _score else 0 _cost_flag = True # 扣钻石的标识位 if rand_type == RANDCARD_TYPE_FREE: if _need_time > 0: defer.returnValue(LIMIT_FELLOW_FREE_ERROR) else: _last_time = int(time()) _cost_flag = False _need_time = LIMIT_FELLOW_FREE_TIME else: # 某积分的整数倍时免费钻石抽卡 if not _score or _score % RAND_COST_FREE_SCORE != 0: if self.user.credits < LIMIT_FELLOW_RAND_COST: defer.returnValue(CHAR_CREDIT_NOT_ENOUGH) else: _cost_flag = False # 卡池升级 res_err, shrine_data = self.update_shrine(_data[1], _data[2]) if res_err: defer.returnValue(res_err) #log.info('For Test. shrine_data: {0}, redis_data: {1}.'.format( shrine_data, _data )) # 获取抽卡池并抽卡 card_conf = self.get_randcard_frompool(_data[1], shrine_data[3] - _data[2]) if not card_conf: defer.returnValue(NOT_FOUND_CONF) # 更新免费时间或扣钻石 yield redis.hset( HASH_LIMIT_FELLOW_SHRINE, self.cid, dumps([_data[0], shrine_data[0], shrine_data[1], _last_time])) if _cost_flag: yield self.user.consume_credits(LIMIT_FELLOW_RAND_COST, WAY_LIMIT_FELLOW_RANDCARD) _score += RANDCARD_ONCE_SCORE yield redis.zadd(SET_LIMIT_FELLOW_NAME_SCORE, self.user.nick_name, _score) # 新增fellow try: # args: fellow_id, is_major, camp_id, on_troop new_fellow = [] fellow_id = card_conf['ItemId'] res_err, attrib = yield self.user.fellow_mgr.create_table_data( fellow_id, 0, 0, 0) if not res_err: new_fellow = [attrib.attrib_id, fellow_id] conf = get_fellow_by_fid(fellow_id) if conf and conf['Quality'] == QUALITY_PURPLE: syslogger(LOG_FELLOW_GET, self.cid, self.user.level, self.user.vip_level, self.user.alliance_id, \ attrib.attrib_id, fellow_id, conf['QualityLevel'], conf['Star'], RANDCARD_TYPE_CREDITS, '') message = [ RORATE_MESSAGE_ACHIEVE, [ ACHIEVE_TYPE_LIMIT_FELLOW, [self.user.nick_name, fellow_id] ] ] gw_broadcast('sync_broadcast', [message]) except Exception as e: log.warn('Create fellow fail! e:', e) defer.returnValue(res_err) _rank = yield redis.zrevrank(SET_LIMIT_FELLOW_NAME_SCORE, self.user.nick_name) _rank = int(_rank) + 1 if _rank >= 0 else 0 _ranklist = yield self.ranklist() defer.returnValue([ self.user.credits, _rank, _score, _need_time, shrine_data[2], _ranklist, new_fellow ])
def get_battle_reward(self, status, scene_id, dungeon_id, dungeon_star): ''' @summary: 战斗结束领取奖励 @param : 战斗结果 status 0:lose, 1:win ''' yield self._load() if scene_id != self.cur_scene_id or dungeon_id != self.cur_dungeon_id or dungeon_star != self.cur_dungeon_star: log.error( 'Player battle info not match. old_scene_id: {0}, old_dungeon_id: {1}, old_dungeon_star: {2}.' .format(self.cur_scene_id, self.cur_dungeon_id, self.cur_dungeon_star)) #defer.returnValue( REQUEST_LIMIT_ERROR ) dungeon = yield self.get_dungeon(scene_id, dungeon_id) if not dungeon: log.error( 'Unknown dungeon id. scene_id: {0}, dungeon_id: {1}.'.format( scene_id, dungeon_id)) defer.returnValue(REQUEST_LIMIT_ERROR) self.cur_scene_id, self.cur_dungeon_id, self.cur_dungeon_star = 0, 0, 0 # 战斗失败 if not status: syslogger(LOG_SCENE_BATTLE, self.cid, self.user.level, self.user.vip_level, self.user.alliance_id, 1, status, dungeon_id, dungeon_star, 0, 0, 0, '') defer.returnValue((1, status, dungeon_id, dungeon.dungeon_star, dungeon.dungeon_today_count, [], 0, 0, 0, self.user.base_att.energy)) # monster奖励金币、仙魂、经验 exp_reward, golds_reward, soul_reward = 0, 0, 0 monster_conf = get_monster_conf(dungeon_id, dungeon_star) no_energy = False if monster_conf: # 策划修改-副本的精力消耗改为5点 if self.user.base_att.energy >= 5: self.user.base_att.energy -= 5 exp_reward = self.user.base_att.level * BATTLE_MONSTER_EXP_RATIO else: no_energy = True exp_reward = self.user.base_att.level soul_reward = monster_conf['Soul'] golds_reward = monster_conf['Money'] else: log.error('Can not find monster.') # 获取怪物组掉落 drop_items = yield self.dungeon_star_drop(dungeon_id, dungeon_star, no_energy) # 判断是否是第一次挑战更高星级难度 if dungeon_star > dungeon.dungeon_star: dungeon.dungeon_star = dungeon_star # 新增混沌星数 self.user.base_att.scene_star += 1 # 新增副本总星数 self.total_star += 1 yield redis.zadd(SET_SCENE_CID_STAR, self.cid, -self.total_star) # 更新最大副本ID if scene_id > self.max_scene_id: self.max_scene_id = scene_id syslogger(LOG_SCENESTAR_GET, self.cid, self.user.level, self.user.vip_level, self.user.alliance_id, 1, self.user.base_att.scene_star, dungeon_id, dungeon_star) dungeon.dungeon_today_count += 1 dungeon.dungeon_last_time = datetime.now() # 新增掉落 way_others = str((FIGHT_TYPE_NORMAL, dungeon_id, dungeon_star)) dungeon_drop_items = yield self.get_dungeon_drop( drop_items, way_others) # 发放奖励 yield self.user.update_battle_attr(soul_reward, golds_reward, exp_reward) # 每日任务计数 yield self.user.daily_quest_mgr.update_daily_quest(DAILY_QUEST_ID_3, 1) # 开服七天 yield self.user.open_server_mgr.update_open_server_activity_quest( OPEN_SERVER_QUEST_ID_3, dungeon_id) #成就 yield self.user.achievement_mgr.update_achievement_status( ACHIEVEMENT_QUEST_ID_3, dungeon_id) yield self.user.achievement_mgr.update_alliance_level() # add syslog str_drop_items = str(dungeon_drop_items).replace('[', '(') str_drop_items = str_drop_items.replace(']', ')') syslogger(LOG_SCENE_BATTLE, self.cid, self.user.level, self.user.vip_level, self.user.alliance_id, FIGHT_TYPE_NORMAL, status, dungeon_id, dungeon_star, exp_reward, soul_reward, golds_reward, str_drop_items) defer.returnValue( (1, status, dungeon_id, dungeon.dungeon_star, dungeon.dungeon_today_count, dungeon_drop_items, golds_reward, soul_reward, exp_reward, self.user.base_att.energy))