def load_mongo_record(self): try: self.mongo_plunder = MongoPlunder.objects.get(id=self.char_id) self.set_default_value() except DoesNotExist: self.mongo_plunder = MongoPlunder(id=self.char_id) self.mongo_plunder.current_times = self.max_plunder_times() self.mongo_plunder.save()
def __init__(self, char_id): self.char_id = char_id try: self.mongo_plunder = MongoPlunder.objects.get(id=self.char_id) except DoesNotExist: self.mongo_plunder = MongoPlunder(id=self.char_id) self.mongo_plunder.points = 0 self.mongo_plunder.chars = {} self.mongo_plunder.target_char = 0 self.mongo_plunder.got_reward = [] self.mongo_plunder.save()
def change_current_plunder_times(self, change_value, allow_overflow=True): max_times = self.max_plunder_times() if change_value > 0 and not allow_overflow and self.mongo_plunder.current_times > max_times: return # for i in range(10): # self.load_mongo_record() # if not self.mongo_plunder.current_times_lock: # self.mongo_plunder.current_times_lock = True # self.mongo_plunder.save() # break # else: # time.sleep(0.2) # else: # raise PlunderCurrentTimeOut() # # try: # self.mongo_plunder.current_times += change_value # if self.mongo_plunder.current_times < 0: # self.mongo_plunder.current_times = 0 # # if not allow_overflow and change_value > 0: # if self.mongo_plunder.current_times > max_times: # self.mongo_plunder.current_times = max_times # finally: # self.mongo_plunder.current_times_lock = False # self.mongo_plunder.save() # self.send_notify() MongoPlunder._get_collection().update( {'_id': self.char_id}, {'$inc': { 'current_times': change_value }}) self.load_mongo_record() if self.mongo_plunder.current_times < 0: MongoPlunder._get_collection().update( {'_id': self.char_id}, {'$set': { 'current_times': 0 }}) if not allow_overflow: if self.mongo_plunder.current_times > max_times: MongoPlunder._get_collection().update( {'_id': self.char_id}, {'$set': { 'current_times': max_times }}) self.send_notify()
def change_current_plunder_times(self, change_value, allow_overflow=True): max_times = self.max_plunder_times() if change_value > 0 and not allow_overflow and self.mongo_plunder.current_times > max_times: return # for i in range(10): # self.load_mongo_record() # if not self.mongo_plunder.current_times_lock: # self.mongo_plunder.current_times_lock = True # self.mongo_plunder.save() # break # else: # time.sleep(0.2) # else: # raise PlunderCurrentTimeOut() # # try: # self.mongo_plunder.current_times += change_value # if self.mongo_plunder.current_times < 0: # self.mongo_plunder.current_times = 0 # # if not allow_overflow and change_value > 0: # if self.mongo_plunder.current_times > max_times: # self.mongo_plunder.current_times = max_times # finally: # self.mongo_plunder.current_times_lock = False # self.mongo_plunder.save() # self.send_notify() MongoPlunder._get_collection().update( {'_id': self.char_id}, {'$inc': {'current_times': change_value}} ) self.load_mongo_record() if self.mongo_plunder.current_times < 0: MongoPlunder._get_collection().update( {'_id': self.char_id}, {'$set': {'current_times': 0}} ) if not allow_overflow: if self.mongo_plunder.current_times > max_times: MongoPlunder._get_collection().update( {'_id': self.char_id}, {'$set': {'current_times': max_times}} ) self.send_notify()
class Plunder(object): def __init__(self, char_id): self.char_id = char_id try: self.mongo_plunder = MongoPlunder.objects.get(id=self.char_id) except DoesNotExist: self.mongo_plunder = MongoPlunder(id=self.char_id) self.mongo_plunder.points = 0 self.mongo_plunder.chars = {} self.mongo_plunder.target_char = 0 self.mongo_plunder.got_reward = [] self.mongo_plunder.save() def get_plunder_list(self): """ @return: [[id, name, power, formation, is_robot, gold], ...] @rtype: list """ char = Char(self.char_id) cache_char = char.cacheobj char_level = cache_char.level choosing_list = MongoHangDoing.objects( Q(char_level__gte=char_level - PLUNDER_LEVEL_DIFF) & Q(char_level__lte=char_level + PLUNDER_LEVEL_DIFF) & Q(id__ne=self.char_id)) choosing_id_list = [c.id for c in choosing_list] ids = [] while True: if len(ids) >= 20 or not choosing_id_list: break c = random.choice(choosing_id_list) choosing_id_list.remove(c) if c == self.char_id: continue if c not in ids: ids.append(c) random.shuffle(ids) ids = ids[:10] res = [] for i in ids: char = Char(i) f = Formation(i) res.append([ i, char.cacheobj.name, char.power, f.in_formation_hero_original_ids(), False ]) robot_ids = [] robot_amount = 10 - len(ids) if len(robot_ids) < robot_amount: # 添加机器人 min_level = char_level - 20 if min_level <= 1: min_level = 1 real_chars = get_char_ids_by_level_range(cache_char.server_id, min_level, char_level + 10) for c in real_chars: if c == self.char_id: continue if c in ids: continue robot_ids.append(c) if len(robot_ids) >= robot_amount: break for i in robot_ids: char = Char(i) f = Formation(i) res.append([ i, char.cacheobj.name, char.power, f.in_formation_hero_original_ids(), True ]) final_ids = [r[0] for r in res] this_stages = MongoStage.objects.filter(id__in=final_ids) this_stages_dict = {s.id: s.max_star_stage for s in this_stages} for r in res: _id = r[0] max_star_stage = this_stages_dict.get(_id, 1) if not max_star_stage: max_star_stage = 1 got_gold = max_star_stage * 400 * random.uniform(1.0, 1.2) got_gold = int(got_gold) r.append(got_gold) for _id, _, _, _, is_robot, gold in res: c = MongoEmbededPlunderChars() c.is_robot = is_robot c.gold = gold self.mongo_plunder.chars[str(_id)] = c self.mongo_plunder.save() return res def plunder(self, _id): if str(_id) not in self.mongo_plunder.chars: raise SanguoException( errormsg.PLUNDER_NOT_IN_LIST, self.char_id, "Plunder Plunder", "Plunder, {0} not in plunder list".format(_id)) counter = Counter(self.char_id, 'plunder') if counter.remained_value <= 0: char = Char(self.char_id).mc if char.vip < VIP_MAX_LEVEL: raise SanguoException( errormsg.PLUNDER_NO_TIMES, self.char_id, "Plunder Battle", "Plunder no times. vip current: {0}, max: {1}".format( char.vip, VIP_MAX_LEVEL)) raise SanguoException( errormsg.PLUNDER_NO_TIMES_FINAL, self.char_id, "Plunder Battle", "Plunder no times. vip reach max level {0}".format( VIP_MAX_LEVEL)) msg = MsgBattle() pvp = PVP(self.char_id, _id, msg) pvp.start() if not self.mongo_plunder.chars[str(_id)].is_robot: char = Char(self.char_id) h = Hang(_id) h.plundered(char.cacheobj.name, not msg.self_win) t = Task(self.char_id) t.trig(3) ground_win_times = 0 if msg.first_ground.self_win: ground_win_times += 1 if msg.second_ground.self_win: ground_win_times += 1 if msg.third_ground.self_win: ground_win_times += 1 got_point = PLUNDER_POINT.get(ground_win_times, 0) if got_point: self.mongo_plunder.points += got_point if msg.self_win: counter.incr() self.mongo_plunder.target_char = _id drop_official_exp = PLUNDER_GET_OFFICIAL_EXP_WHEN_WIN drop_gold = PLUNDER_DEFENSE_FAILURE_GOLD resource = Resource(self.char_id, "Plunder") resource.add(gold=drop_gold, official_exp=drop_official_exp) else: self.mongo_plunder.target_char = 0 self.mongo_plunder.got_reward = [] self.mongo_plunder.save() self.send_notify() return msg def get_reward(self, tp): if not self.mongo_plunder.target_char: raise SanguoException(errormsg.PLUNDER_GET_REWARD_NO_TARGET, self.char_id, "Plunder Get Reward", "no Target char") if tp in self.mongo_plunder.got_reward: raise SanguoException(errormsg.PLUNDER_GET_REWARD_ALREADY_GOT, self.char_id, "Plunder Get Reward", "tp {0} already got".format(tp)) need_points = PLUNDER_REWARD_NEEDS_POINT[tp] if self.mongo_plunder.points < need_points: raise SanguoException( errormsg.PLUNDER_GET_REWARD_POINTS_NOT_ENOUGH, self.char_id, "Plunder Get Reward", "points not enough. {0} < {1}".format( self.mongo_plunder.points, need_points)) self.mongo_plunder.points -= need_points self.mongo_plunder.got_reward.append(tp) self.mongo_plunder.save() standard_drop = make_standard_drop_from_template() plunder_gold = self.mongo_plunder.chars[str( self.mongo_plunder.target_char)].gold char = Char(self.char_id).mc vip_plus = VIP_FUNCTION[char.vip].plunder_addition got_hero_id = 0 if tp == PLUNDER_HERO: f = Formation(self.mongo_plunder.target_char) heros = f.in_formation_hero_original_ids() got_hero_id = random.choice([hid for hid in heros if hid]) p = Prison(self.char_id) p.prisoner_add(got_hero_id, plunder_gold / 2) elif tp == PLUNDER_STUFF: stage = Stage(self.mongo_plunder.target_char) max_star_stage = stage.stage.max_star_stage if not max_star_stage: max_star_stage = 1 drop_ids = [ int(i) for i in STAGES[max_star_stage].normal_drop.split(',') ] drop = get_drop(drop_ids, multi=int(PLUNDER_GOT_ITEMS_HOUR * 3600 * (1 + vip_plus / 100.0) / 15)) standard_drop.update(drop) elif tp == PLUNDER_GOLD: standard_drop['gold'] = int(plunder_gold * (1 + vip_plus / 100.0)) resource = Resource(self.char_id, "Plunder Reward") resource.add(**standard_drop) self.send_notify() if got_hero_id: standard_drop['heros'] = [got_hero_id] return standard_drop_to_attachment_protomsg(standard_drop) def send_notify(self): counter = Counter(self.char_id, 'plunder') msg = PlunderNotify() msg.remained_free_times = counter.remained_value msg.points = self.mongo_plunder.points publish_to_char(self.char_id, pack_msg(msg))
def cron_job(): MongoPlunder._get_collection().update({}, {'$set': { 'plunder_times': 0 }}, multi=True)
class Plunder(object): def __init__(self, char_id): self.char_id = char_id self.load_mongo_record() def load_mongo_record(self): try: self.mongo_plunder = MongoPlunder.objects.get(id=self.char_id) self.set_default_value() except DoesNotExist: self.mongo_plunder = MongoPlunder(id=self.char_id) self.mongo_plunder.current_times = self.max_plunder_times() self.mongo_plunder.save() def set_default_value(self): # 后面新增加的fileds需要初始化数值的。 比如 current_times data = { 'current_times': self.max_plunder_times(), 'current_times_lock': False, 'char_id': 0, 'char_name': "", 'char_gold': 0, 'char_power': 0, 'char_leader': 0, 'char_formation': [], 'char_hero_original_ids': [], 'char_city_id': 0 } changed = False record = self.mongo_plunder._get_collection().find_one( {'_id': self.char_id}) for k, v in data.iteritems(): if k not in record: setattr(self.mongo_plunder, k, v) changed = True if changed: self.mongo_plunder.save() def get_plunder_target(self, city_id): """ @:rtype: PlunderRival """ target = PlunderRival.search_all_servers(city_id, exclude_char_id=self.char_id) self.mongo_plunder.char_id = target.char_id self.mongo_plunder.char_name = target.name self.mongo_plunder.char_gold = target.get_plunder_gold( Char(self.char_id).mc.level) self.mongo_plunder.char_power = target.power self.mongo_plunder.char_leader = target.leader self.mongo_plunder.char_formation = target.formation self.mongo_plunder.char_hero_original_ids = target.hero_original_ids self.mongo_plunder.char_city_id = target.city_id self.mongo_plunder.battle_heros = target.battle_heros self.mongo_plunder.server_url = target.server_url self.mongo_plunder.save() if target: gold_needs = BATTLES[city_id].refresh_cost_gold resource = Resource(self.char_id, "Plunder Refresh") resource.check_and_remove(gold=-gold_needs) return target def max_plunder_times(self): char = Char(self.char_id) times = VIP_FUNCTION[char.mc.vip].plunder ae = ActivityEntry(self.char_id, 40007) if not ae or not ae.is_ok(): return times if times > 10: return times return 10 def clean_plunder_target(self): self.mongo_plunder.char_id = 0 self.mongo_plunder.char_name = "" self.mongo_plunder.char_gold = 0 self.mongo_plunder.char_power = 0 self.mongo_plunder.char_leader = 0 self.mongo_plunder.char_formation = [] self.mongo_plunder.char_hero_original_ids = [] self.mongo_plunder.char_city_id = 0 self.mongo_plunder.battle_heros = "" self.mongo_plunder.server_url = "" self.mongo_plunder.save() def change_current_plunder_times(self, change_value, allow_overflow=True): max_times = self.max_plunder_times() if change_value > 0 and not allow_overflow and self.mongo_plunder.current_times > max_times: return # for i in range(10): # self.load_mongo_record() # if not self.mongo_plunder.current_times_lock: # self.mongo_plunder.current_times_lock = True # self.mongo_plunder.save() # break # else: # time.sleep(0.2) # else: # raise PlunderCurrentTimeOut() # # try: # self.mongo_plunder.current_times += change_value # if self.mongo_plunder.current_times < 0: # self.mongo_plunder.current_times = 0 # # if not allow_overflow and change_value > 0: # if self.mongo_plunder.current_times > max_times: # self.mongo_plunder.current_times = max_times # finally: # self.mongo_plunder.current_times_lock = False # self.mongo_plunder.save() # self.send_notify() MongoPlunder._get_collection().update( {'_id': self.char_id}, {'$inc': { 'current_times': change_value }}) self.load_mongo_record() if self.mongo_plunder.current_times < 0: MongoPlunder._get_collection().update( {'_id': self.char_id}, {'$set': { 'current_times': 0 }}) if not allow_overflow: if self.mongo_plunder.current_times > max_times: MongoPlunder._get_collection().update( {'_id': self.char_id}, {'$set': { 'current_times': max_times }}) self.send_notify() def plunder(self): if not self.mongo_plunder.char_id: raise SanguoException(errormsg.PLUNDER_NO_RIVAL, self.char_id, "Plunder Battle", "no rival target") if self.mongo_plunder.current_times <= 0: raise SanguoException(errormsg.PLUNDER_NO_TIMES, self.char_id, "Plunder Battle", "no times") self.change_current_plunder_times(change_value=-1) rival_battle_heros = dill.loads( base64.b64decode(self.mongo_plunder.battle_heros)) msg = MsgBattle() pvp = PlunderBattle( self.char_id, self.mongo_plunder.char_id, msg, self.mongo_plunder.char_name, rival_battle_heros, ) pvp.start() t = Task(self.char_id) t.trig(3) to_char_id = self.mongo_plunder.char_id target_server_url = self.mongo_plunder.server_url if msg.self_win: standard_drop = self._get_plunder_reward( self.mongo_plunder.char_city_id, self.mongo_plunder.char_gold, self.mongo_plunder.char_hero_original_ids) self.clean_plunder_target() achievement = Achievement(self.char_id) achievement.trig(12, 1) PlunderLeaderboardWeekly.incr(self.char_id) TimesLogPlunder(self.char_id).inc() else: standard_drop = make_standard_drop_from_template() self.mongo_plunder.plunder_times += 1 self.mongo_plunder.save() self.send_notify() plunder_finished_signal.send( sender=None, from_char_id=self.char_id, from_char_name=Char(self.char_id).mc.name, to_char_id=to_char_id, from_win=msg.self_win, standard_drop=standard_drop, target_server_url=target_server_url, ) return (msg, standard_drop) def _get_plunder_reward(self, city_id, gold, hero_original_ids): def _get_prisoner(): prison = 0 heros = [hid for hid in hero_original_ids if hid] while heros: hid = random.choice(heros) heros.remove(hid) if hid in PRISONER_POOL: prison = hid break ac = ActivityEntry(self.char_id, 30005) """@type: core.activity.Activity30005""" if not ac: _prob = PLUNDER_GET_PRISONER_PROB else: _prob = ac.get_prisoner_prob() ae = ActivityEntry(self.char_id, 50005) if ae and ae.is_valid(): _vip = ae.get_current_value(self.char_id) if _vip == 6: _prob = 50 elif _vip >= 7: _prob = 100 if random.randint(1, 100) <= _prob: return prison return 0 char = Char(self.char_id).mc vip_plus = VIP_FUNCTION[char.vip].plunder_addition standard_drop = make_standard_drop_from_template() standard_drop['gold'] = int(gold * (1 + vip_plus / 100.0)) # 战俘 got_hero_id = _get_prisoner() if got_hero_id: p = Prison(self.char_id) p.prisoner_add(got_hero_id, gold / 2) achievement = Achievement(self.char_id) achievement.trig(13, 1) # 掉落 city = BATTLES[city_id] if city.normal_drop: drop_ids = [int(i) for i in city.normal_drop.split(',')] drop_prob = max( PLUNDER_GET_DROPS_TIMES - (self.mongo_plunder.plunder_times - 1) * PLUNDER_DROP_DECREASE_FACTOR, PLUNDER_GET_DROPS_TIMES * PLUNDER_DROP_MIN_FACTOR) drop = get_drop(drop_ids, multi=int(drop_prob)) drop.pop('gold') standard_drop.update(drop) resource = Resource(self.char_id, "Plunder Reward") resource.add(**standard_drop) self.send_notify() if got_hero_id: standard_drop['heros'] = [(got_hero_id, 1)] return standard_drop def send_notify(self): self.load_mongo_record() msg = PlunderNotify() msg.current_times = self.mongo_plunder.current_times msg.max_times = self.max_plunder_times() msg.success_times_weekly = PlunderLeaderboardWeekly.get_char_times( self.char_id) publish_to_char(self.char_id, pack_msg(msg)) @staticmethod def cron_job(): MongoPlunder._get_collection().update({}, {'$set': { 'plunder_times': 0 }}, multi=True)
def cron_job(): MongoPlunder._get_collection().update({}, {'$set': {'plunder_times': 0}}, multi=True)
class Plunder(object): def __init__(self, char_id): self.char_id = char_id self.load_mongo_record() def load_mongo_record(self): try: self.mongo_plunder = MongoPlunder.objects.get(id=self.char_id) self.set_default_value() except DoesNotExist: self.mongo_plunder = MongoPlunder(id=self.char_id) self.mongo_plunder.current_times = self.max_plunder_times() self.mongo_plunder.save() def set_default_value(self): # 后面新增加的fileds需要初始化数值的。 比如 current_times data = { 'current_times': self.max_plunder_times(), 'current_times_lock': False, 'char_id': 0, 'char_name': "", 'char_gold': 0, 'char_power': 0, 'char_leader': 0, 'char_formation': [], 'char_hero_original_ids': [], 'char_city_id': 0 } changed = False record = self.mongo_plunder._get_collection().find_one({'_id': self.char_id}) for k, v in data.iteritems(): if k not in record: setattr(self.mongo_plunder, k, v) changed = True if changed: self.mongo_plunder.save() def get_plunder_target(self, city_id): """ @:rtype: PlunderRival """ target = PlunderRival.search_all_servers(city_id, exclude_char_id=self.char_id) self.mongo_plunder.char_id = target.char_id self.mongo_plunder.char_name = target.name self.mongo_plunder.char_gold = target.get_plunder_gold(Char(self.char_id).mc.level) self.mongo_plunder.char_power = target.power self.mongo_plunder.char_leader = target.leader self.mongo_plunder.char_formation = target.formation self.mongo_plunder.char_hero_original_ids = target.hero_original_ids self.mongo_plunder.char_city_id = target.city_id self.mongo_plunder.battle_heros = target.battle_heros self.mongo_plunder.server_url = target.server_url self.mongo_plunder.save() if target: gold_needs = BATTLES[city_id].refresh_cost_gold resource = Resource(self.char_id, "Plunder Refresh") resource.check_and_remove(gold=-gold_needs) return target def max_plunder_times(self): char = Char(self.char_id) times = VIP_FUNCTION[char.mc.vip].plunder ae = ActivityEntry(self.char_id, 40007) if not ae or not ae.is_ok(): return times if times > 10: return times return 10 def clean_plunder_target(self): self.mongo_plunder.char_id = 0 self.mongo_plunder.char_name = "" self.mongo_plunder.char_gold = 0 self.mongo_plunder.char_power = 0 self.mongo_plunder.char_leader = 0 self.mongo_plunder.char_formation = [] self.mongo_plunder.char_hero_original_ids = [] self.mongo_plunder.char_city_id = 0 self.mongo_plunder.battle_heros = "" self.mongo_plunder.server_url = "" self.mongo_plunder.save() def change_current_plunder_times(self, change_value, allow_overflow=True): max_times = self.max_plunder_times() if change_value > 0 and not allow_overflow and self.mongo_plunder.current_times > max_times: return # for i in range(10): # self.load_mongo_record() # if not self.mongo_plunder.current_times_lock: # self.mongo_plunder.current_times_lock = True # self.mongo_plunder.save() # break # else: # time.sleep(0.2) # else: # raise PlunderCurrentTimeOut() # # try: # self.mongo_plunder.current_times += change_value # if self.mongo_plunder.current_times < 0: # self.mongo_plunder.current_times = 0 # # if not allow_overflow and change_value > 0: # if self.mongo_plunder.current_times > max_times: # self.mongo_plunder.current_times = max_times # finally: # self.mongo_plunder.current_times_lock = False # self.mongo_plunder.save() # self.send_notify() MongoPlunder._get_collection().update( {'_id': self.char_id}, {'$inc': {'current_times': change_value}} ) self.load_mongo_record() if self.mongo_plunder.current_times < 0: MongoPlunder._get_collection().update( {'_id': self.char_id}, {'$set': {'current_times': 0}} ) if not allow_overflow: if self.mongo_plunder.current_times > max_times: MongoPlunder._get_collection().update( {'_id': self.char_id}, {'$set': {'current_times': max_times}} ) self.send_notify() def plunder(self): if not self.mongo_plunder.char_id: raise SanguoException( errormsg.PLUNDER_NO_RIVAL, self.char_id, "Plunder Battle", "no rival target" ) if self.mongo_plunder.current_times <= 0: raise SanguoException( errormsg.PLUNDER_NO_TIMES, self.char_id, "Plunder Battle", "no times" ) self.change_current_plunder_times(change_value=-1) rival_battle_heros = dill.loads(base64.b64decode(self.mongo_plunder.battle_heros)) msg = MsgBattle() pvp = PlunderBattle( self.char_id, self.mongo_plunder.char_id, msg, self.mongo_plunder.char_name, rival_battle_heros, ) pvp.start() t = Task(self.char_id) t.trig(3) to_char_id = self.mongo_plunder.char_id target_server_url = self.mongo_plunder.server_url if msg.self_win: standard_drop = self._get_plunder_reward( self.mongo_plunder.char_city_id, self.mongo_plunder.char_gold, self.mongo_plunder.char_hero_original_ids ) self.clean_plunder_target() achievement = Achievement(self.char_id) achievement.trig(12, 1) PlunderLeaderboardWeekly.incr(self.char_id) TimesLogPlunder(self.char_id).inc() else: standard_drop = make_standard_drop_from_template() self.mongo_plunder.plunder_times += 1 self.mongo_plunder.save() self.send_notify() plunder_finished_signal.send( sender=None, from_char_id=self.char_id, from_char_name=Char(self.char_id).mc.name, to_char_id=to_char_id, from_win=msg.self_win, standard_drop=standard_drop, target_server_url=target_server_url, ) return (msg, standard_drop) def _get_plunder_reward(self, city_id, gold, hero_original_ids): def _get_prisoner(): prison = 0 heros = [hid for hid in hero_original_ids if hid] while heros: hid = random.choice(heros) heros.remove(hid) if hid in PRISONER_POOL: prison = hid break ac = ActivityEntry(self.char_id, 30005) """@type: core.activity.Activity30005""" if not ac: _prob = PLUNDER_GET_PRISONER_PROB else: _prob = ac.get_prisoner_prob() ae = ActivityEntry(self.char_id, 50005) if ae and ae.is_valid(): _vip = ae.get_current_value(self.char_id) if _vip == 6: _prob = 50 elif _vip >= 7: _prob = 100 if random.randint(1, 100) <= _prob: return prison return 0 char = Char(self.char_id).mc vip_plus = VIP_FUNCTION[char.vip].plunder_addition standard_drop = make_standard_drop_from_template() standard_drop['gold'] = int(gold * (1 + vip_plus / 100.0)) # 战俘 got_hero_id = _get_prisoner() if got_hero_id: p = Prison(self.char_id) p.prisoner_add(got_hero_id, gold/2) achievement = Achievement(self.char_id) achievement.trig(13, 1) # 掉落 city = BATTLES[city_id] if city.normal_drop: drop_ids = [int(i) for i in city.normal_drop.split(',')] drop_prob = max( PLUNDER_GET_DROPS_TIMES - (self.mongo_plunder.plunder_times - 1) * PLUNDER_DROP_DECREASE_FACTOR, PLUNDER_GET_DROPS_TIMES * PLUNDER_DROP_MIN_FACTOR ) drop = get_drop(drop_ids, multi=int(drop_prob)) drop.pop('gold') standard_drop.update(drop) resource = Resource(self.char_id, "Plunder Reward") resource.add(**standard_drop) self.send_notify() if got_hero_id: standard_drop['heros'] = [(got_hero_id, 1)] return standard_drop def send_notify(self): self.load_mongo_record() msg = PlunderNotify() msg.current_times = self.mongo_plunder.current_times msg.max_times = self.max_plunder_times() msg.success_times_weekly = PlunderLeaderboardWeekly.get_char_times(self.char_id) publish_to_char(self.char_id, pack_msg(msg)) @staticmethod def cron_job(): MongoPlunder._get_collection().update({}, {'$set': {'plunder_times': 0}}, multi=True)
class Plunder(object): def __init__(self, char_id): self.char_id = char_id self.load_mongo_record() def load_mongo_record(self): try: self.mongo_plunder = MongoPlunder.objects.get(id=self.char_id) self.set_default_value() except DoesNotExist: self.mongo_plunder = MongoPlunder(id=self.char_id) self.mongo_plunder.current_times = self.max_plunder_times() self.mongo_plunder.save() def set_default_value(self): # 后面新增加的fileds需要初始化数值的。 比如 current_times data = { 'current_times': self.max_plunder_times(), 'current_times_lock': False, 'char_id': 0, 'char_name': "", 'char_gold': 0, 'char_power': 0, 'char_leader': 0, 'char_formation': [], 'char_hero_original_ids': [], 'char_city_id': 0 } record = self.mongo_plunder._get_collection().find_one({'_id': self.char_id}) for k, v in data.iteritems(): if k not in record: setattr(self.mongo_plunder, k, v) self.mongo_plunder.save() def get_plunder_target(self, city_id): """ @:rtype: PlunderRival """ target = PlunderRival.search(city_id, exclude_char_id=self.char_id) self.mongo_plunder.char_id = target.char_id self.mongo_plunder.char_name = target.name self.mongo_plunder.char_gold = target.get_plunder_gold(Char(self.char_id).mc.level) self.mongo_plunder.char_power = target.power self.mongo_plunder.char_leader = target.leader self.mongo_plunder.char_formation = target.formation self.mongo_plunder.char_hero_original_ids = target.hero_original_ids self.mongo_plunder.char_city_id = target.city_id self.mongo_plunder.save() if target: gold_needs = BATTLES[city_id].refresh_cost_gold resource = Resource(self.char_id, "Plunder Refresh") resource.check_and_remove(gold=-gold_needs) return target def max_plunder_times(self): char = Char(self.char_id) return VIP_FUNCTION[char.mc.vip].plunder def clean_plunder_target(self): self.mongo_plunder.char_id = 0 self.mongo_plunder.char_name = "" self.mongo_plunder.char_gold = 0 self.mongo_plunder.char_power = 0 self.mongo_plunder.char_leader = 0 self.mongo_plunder.char_formation = [] self.mongo_plunder.char_hero_original_ids = [] self.mongo_plunder.char_city_id = 0 self.mongo_plunder.save() def change_current_plunder_times(self, change_value, allow_overflow=False): max_times = self.max_plunder_times() if change_value > 0 and not allow_overflow and self.mongo_plunder.current_times > max_times: return for i in range(10): self.load_mongo_record() if not self.mongo_plunder.current_times_lock: self.mongo_plunder.current_times_lock = True self.mongo_plunder.save() break else: time.sleep(0.2) else: raise PlunderCurrentTimeOut() try: self.mongo_plunder.current_times += change_value if self.mongo_plunder.current_times < 0: self.mongo_plunder.current_times = 0 if not allow_overflow and change_value > 0: max_times = self.max_plunder_times() if self.mongo_plunder.current_times > max_times: self.mongo_plunder.current_times = max_times finally: self.mongo_plunder.current_times_lock = False self.mongo_plunder.save() self.send_notify() def plunder(self): if not self.mongo_plunder.char_id: raise SanguoException( errormsg.PLUNDER_NO_RIVAL, self.char_id, "Plunder Battle", "no rival target" ) if self.mongo_plunder.current_times <= 0: raise SanguoException( errormsg.PLUNDER_NO_TIMES, self.char_id, "Plunder Battle", "no times" ) self.change_current_plunder_times(change_value=-1) msg = MsgBattle() pvp = PVPFromRivalCache( self.char_id, self.mongo_plunder.char_id, msg, self.mongo_plunder.char_name, self.mongo_plunder.char_formation ) pvp.start() t = Task(self.char_id) t.trig(3) to_char_id = self.mongo_plunder.char_id if msg.self_win: standard_drop = self._get_plunder_reward( self.mongo_plunder.char_city_id, self.mongo_plunder.char_gold, self.mongo_plunder.char_hero_original_ids ) self.clean_plunder_target() achievement = Achievement(self.char_id) achievement.trig(12, 1) else: standard_drop = make_standard_drop_from_template() self.mongo_plunder.save() self.send_notify() plunder_finished_signal.send( sender=None, from_char_id=self.char_id, to_char_id=to_char_id, from_win=msg.self_win, standard_drop=standard_drop ) return (msg, standard_drop) def _get_plunder_reward(self, city_id, gold, hero_original_ids): def _get_prisoner(): prison = 0 heros = [hid for hid in hero_original_ids if hid] while heros: hid = random.choice(heros) heros.remove(hid) if hid in PRISONER_POOL: prison = hid break if random.randint(1, 100) <= PLUNDER_GET_PRISONER_PROB: return prison return 0 char = Char(self.char_id).mc vip_plus = VIP_FUNCTION[char.vip].plunder_addition standard_drop = make_standard_drop_from_template() standard_drop['gold'] = int(gold * (1 + vip_plus / 100.0)) # 战俘 got_hero_id = _get_prisoner() if got_hero_id: p = Prison(self.char_id) p.prisoner_add(got_hero_id, gold/2) achievement = Achievement(self.char_id) achievement.trig(13, 1) # 掉落 city = BATTLES[city_id] if city.normal_drop: drop_ids = [int(i) for i in city.normal_drop.split(',')] drop = get_drop(drop_ids, multi=int(4 * PLUNDER_GET_DROPS_MINUTES * 60 / 15)) drop.pop('gold') standard_drop.update(drop) resource = Resource(self.char_id, "Plunder Reward") resource.add(**standard_drop) self.send_notify() if got_hero_id: standard_drop['heros'] = [(got_hero_id, 1)] return standard_drop def send_notify(self): self.load_mongo_record() msg = PlunderNotify() msg.current_times = self.mongo_plunder.current_times msg.max_times = self.max_plunder_times() publish_to_char(self.char_id, pack_msg(msg))
class Plunder(object): def __init__(self, char_id): self.char_id = char_id try: self.mongo_plunder = MongoPlunder.objects.get(id=self.char_id) except DoesNotExist: self.mongo_plunder = MongoPlunder(id=self.char_id) self.mongo_plunder.points = 0 self.mongo_plunder.chars = {} self.mongo_plunder.target_char = 0 self.mongo_plunder.got_reward = [] self.mongo_plunder.save() def get_plunder_list(self): """ @return: [[id, name, power, formation, is_robot, gold], ...] @rtype: list """ char = Char(self.char_id) cache_char = char.cacheobj char_level = cache_char.level choosing_list = MongoHangDoing.objects(Q(char_level__gte=char_level-PLUNDER_LEVEL_DIFF) & Q(char_level__lte=char_level+PLUNDER_LEVEL_DIFF) & Q(id__ne=self.char_id)) choosing_id_list = [c.id for c in choosing_list] ids = [] while True: if len(ids) >= 20 or not choosing_id_list: break c = random.choice(choosing_id_list) choosing_id_list.remove(c) if c == self.char_id: continue if c not in ids: ids.append(c) random.shuffle(ids) ids = ids[:10] res = [] for i in ids: char = Char(i) f = Formation(i) res.append([i, char.cacheobj.name, char.power, f.in_formation_hero_original_ids(), False]) robot_ids = [] robot_amount = 10 - len(ids) if len(robot_ids) < robot_amount: # 添加机器人 min_level = char_level - 20 if min_level <= 1: min_level = 1 real_chars = get_char_ids_by_level_range(cache_char.server_id, min_level, char_level + 10) for c in real_chars: if c == self.char_id: continue if c in ids: continue robot_ids.append(c) if len(robot_ids) >= robot_amount: break for i in robot_ids: char = Char(i) f = Formation(i) res.append([i, char.cacheobj.name, char.power, f.in_formation_hero_original_ids(), True]) final_ids = [r[0] for r in res] this_stages = MongoStage.objects.filter(id__in=final_ids) this_stages_dict = {s.id: s.max_star_stage for s in this_stages} for r in res: _id = r[0] max_star_stage = this_stages_dict.get(_id, 1) if not max_star_stage: max_star_stage = 1 got_gold = max_star_stage * 400 * random.uniform(1.0, 1.2) got_gold = int(got_gold) r.append(got_gold) for _id, _, _, _, is_robot, gold in res: c = MongoEmbededPlunderChars() c.is_robot = is_robot c.gold = gold self.mongo_plunder.chars[str(_id)] = c self.mongo_plunder.save() return res def plunder(self, _id): if str(_id) not in self.mongo_plunder.chars: raise SanguoException( errormsg.PLUNDER_NOT_IN_LIST, self.char_id, "Plunder Plunder", "Plunder, {0} not in plunder list".format(_id) ) counter = Counter(self.char_id, 'plunder') if counter.remained_value <= 0: char = Char(self.char_id).mc if char.vip < VIP_MAX_LEVEL: raise SanguoException( errormsg.PLUNDER_NO_TIMES, self.char_id, "Plunder Battle", "Plunder no times. vip current: {0}, max: {1}".format(char.vip, VIP_MAX_LEVEL) ) raise SanguoException( errormsg.PLUNDER_NO_TIMES_FINAL, self.char_id, "Plunder Battle", "Plunder no times. vip reach max level {0}".format(VIP_MAX_LEVEL) ) msg = MsgBattle() pvp = PVP(self.char_id, _id, msg) pvp.start() if not self.mongo_plunder.chars[str(_id)].is_robot: char = Char(self.char_id) h = Hang(_id) h.plundered(char.cacheobj.name, not msg.self_win) t = Task(self.char_id) t.trig(3) ground_win_times = 0 if msg.first_ground.self_win: ground_win_times += 1 if msg.second_ground.self_win: ground_win_times += 1 if msg.third_ground.self_win: ground_win_times += 1 got_point = PLUNDER_POINT.get(ground_win_times, 0) if got_point: self.mongo_plunder.points += got_point if msg.self_win: counter.incr() self.mongo_plunder.target_char = _id drop_official_exp = PLUNDER_GET_OFFICIAL_EXP_WHEN_WIN drop_gold = PLUNDER_DEFENSE_FAILURE_GOLD resource = Resource(self.char_id, "Plunder") resource.add(gold=drop_gold, official_exp=drop_official_exp) else: self.mongo_plunder.target_char = 0 self.mongo_plunder.got_reward = [] self.mongo_plunder.save() self.send_notify() return msg def get_reward(self, tp): if not self.mongo_plunder.target_char: raise SanguoException( errormsg.PLUNDER_GET_REWARD_NO_TARGET, self.char_id, "Plunder Get Reward", "no Target char" ) if tp in self.mongo_plunder.got_reward: raise SanguoException( errormsg.PLUNDER_GET_REWARD_ALREADY_GOT, self.char_id, "Plunder Get Reward", "tp {0} already got".format(tp) ) need_points = PLUNDER_REWARD_NEEDS_POINT[tp] if self.mongo_plunder.points < need_points: raise SanguoException( errormsg.PLUNDER_GET_REWARD_POINTS_NOT_ENOUGH, self.char_id, "Plunder Get Reward", "points not enough. {0} < {1}".format(self.mongo_plunder.points, need_points) ) self.mongo_plunder.points -= need_points self.mongo_plunder.got_reward.append(tp) self.mongo_plunder.save() standard_drop = make_standard_drop_from_template() plunder_gold = self.mongo_plunder.chars[str(self.mongo_plunder.target_char)].gold char = Char(self.char_id).mc vip_plus = VIP_FUNCTION[char.vip].plunder_addition got_hero_id = 0 if tp == PLUNDER_HERO: f = Formation(self.mongo_plunder.target_char) heros = f.in_formation_hero_original_ids() got_hero_id = random.choice([hid for hid in heros if hid]) p = Prison(self.char_id) p.prisoner_add(got_hero_id, plunder_gold/2) elif tp == PLUNDER_STUFF: stage = Stage(self.mongo_plunder.target_char) max_star_stage = stage.stage.max_star_stage if not max_star_stage: max_star_stage = 1 drop_ids = [int(i) for i in STAGES[max_star_stage].normal_drop.split(',')] drop = get_drop(drop_ids, multi=int(PLUNDER_GOT_ITEMS_HOUR * 3600 * (1+vip_plus/100.0) / 15)) standard_drop.update(drop) elif tp == PLUNDER_GOLD: standard_drop['gold'] = int(plunder_gold * (1+vip_plus/100.0)) resource = Resource(self.char_id, "Plunder Reward") resource.add(**standard_drop) self.send_notify() if got_hero_id: standard_drop['heros'] = [got_hero_id] return standard_drop_to_attachment_protomsg(standard_drop) def send_notify(self): counter = Counter(self.char_id, 'plunder') msg = PlunderNotify() msg.remained_free_times = counter.remained_value msg.points = self.mongo_plunder.points publish_to_char(self.char_id, pack_msg(msg))
def cron_job(): MongoPlunder._get_collection().update({}, {"$set": {"plunder_times": 0}}, multi=True)