Beispiel #1
0
 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()
Beispiel #2
0
 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()
Beispiel #3
0
 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()
Beispiel #4
0
 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()
Beispiel #5
0
    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()
Beispiel #6
0
    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()
Beispiel #7
0
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))
Beispiel #8
0
 def cron_job():
     MongoPlunder._get_collection().update({},
                                           {'$set': {
                                               'plunder_times': 0
                                           }},
                                           multi=True)
Beispiel #9
0
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)
Beispiel #10
0
 def cron_job():
     MongoPlunder._get_collection().update({}, {'$set': {'plunder_times': 0}}, multi=True)
Beispiel #11
0
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)
Beispiel #12
0
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))
Beispiel #13
0
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))
Beispiel #14
0
 def cron_job():
     MongoPlunder._get_collection().update({}, {"$set": {"plunder_times": 0}}, multi=True)