Пример #1
0
    def __init__(self, char_id):
        self.char_id = char_id
        try:
            self.mongo_affairs = MongoAffairs.objects.get(id=char_id)
        except DoesNotExist:
            self.mongo_affairs = MongoAffairs(id=char_id)
            self.mongo_affairs.opened = []
            self.mongo_affairs.hang_city_id = 0
            self.mongo_affairs.hang_start_at = 0
            self.mongo_affairs.logs = []
            self.mongo_affairs.save()

        self.set_default_value()
Пример #2
0
    def __init__(self, char_id):
        self.char_id = char_id
        try:
            self.mongo_affairs = MongoAffairs.objects.get(id=char_id)
        except DoesNotExist:
            self.mongo_affairs = MongoAffairs(id=char_id)
            self.mongo_affairs.opened = []
            self.mongo_affairs.hang_city_id = 0
            self.mongo_affairs.hang_start_at = 0
            self.mongo_affairs.logs = []
            self.mongo_affairs.save()

        self.set_default_value()
Пример #3
0
    def search(cls, city_id, exclude_char_id=None, return_dumps=False):
        docs = MongoAffairs._get_collection().find({'hang_city_id': city_id},
                                                   {'_id': 1})
        affair_ids = [doc['_id'] for doc in docs]

        rival_id = 0
        while affair_ids:
            rival_id = random.choice(affair_ids)
            if rival_id != exclude_char_id:
                break

            affair_ids.remove(rival_id)
            rival_id = 0

        obj = cls(rival_id, city_id)
        if not return_dumps:
            return obj

        return base64.b64encode(dill.dumps(obj))
Пример #4
0
    def search(cls, city_id, exclude_char_id=None, return_dumps=False):
        docs = MongoAffairs._get_collection().find(
                {'hang_city_id': city_id},
                {'_id': 1}
        )
        affair_ids = [doc['_id'] for doc in docs]

        rival_id = 0
        while affair_ids:
            rival_id = random.choice(affair_ids)
            if rival_id != exclude_char_id:
                break

            affair_ids.remove(rival_id)
            rival_id = 0

        obj = cls(rival_id, city_id)
        if not return_dumps:
            return obj

        return base64.b64encode(dill.dumps(obj))
Пример #5
0
class Affairs(_GetRealGoldMixin):
    def __init__(self, char_id):
        self.char_id = char_id
        try:
            self.mongo_affairs = MongoAffairs.objects.get(id=char_id)
        except DoesNotExist:
            self.mongo_affairs = MongoAffairs(id=char_id)
            self.mongo_affairs.opened = []
            self.mongo_affairs.hang_city_id = 0
            self.mongo_affairs.hang_start_at = 0
            self.mongo_affairs.logs = []
            self.mongo_affairs.save()

        self.set_default_value()


    def set_default_value(self):
        if self.mongo_affairs.opened:
            if 0 not in self.mongo_affairs.opened:
                self.mongo_affairs.opened.insert(0, 0)
                self.mongo_affairs.save()
            return

        opened = _get_opended_cities(self.char_id)
        if opened:
            self.mongo_affairs.opened = opened
            self.mongo_affairs.hang_city_id = opened[-1]
            self.mongo_affairs.hang_start_at = arrow.utcnow().timestamp
            self.mongo_affairs.save()


    def open_city(self, city_id):
        # 开启城镇
        need_opened = []
        for cid in CITY_IDS:
            if cid > city_id:
                # XXX 这里默认city_id是从小到大的!
                break

            need_opened.append(cid)

        for cid in need_opened:
            if cid in self.mongo_affairs.opened:
                continue

            self.mongo_affairs.opened.append(cid)
            opened = True

        self.mongo_affairs.save()
        self.send_city_notify()


    def start_hang(self, city_id, get_reward=True):
        if city_id not in BATTLES:
            raise SanguoException(
                errormsg.INVALID_OPERATE,
                self.char_id,
                "Start Hang",
                "hang at none exist city id {0}".format(city_id)
            )

        if city_id not in self.mongo_affairs.opened:
            raise SanguoException(
                errormsg.INVALID_OPERATE,
                self.char_id,
                "Start Hang",
                "city id {0} not opened".format(city_id)
            )

        if get_reward:
            drop_msg = self.get_hang_reward(auto_start=False)
        else:
            drop_msg = None

        self.mongo_affairs.hang_city_id = city_id
        self.mongo_affairs.hang_start_at = arrow.utcnow().timestamp
        self.mongo_affairs.logs = []
        self.mongo_affairs.save()

        self.send_hang_notify()
        return drop_msg


    def get_hang_obj(self):
        return HangObject(self.mongo_affairs.hang_city_id, self.mongo_affairs.hang_start_at, self.mongo_affairs.logs)

    def get_drop(self, passed_time=None, multi=1):
        ho = self.get_hang_obj()
        battle_data = BATTLES[self.mongo_affairs.hang_city_id]

        if not passed_time:
            passed_time = ho.passed_time

        percent = passed_time / float(ho.max_time) * 100
        for _pre, _add in HANG_REWARD_ADDITIONAL:
            if percent >= _pre:
                break
        else:
            _add = 1

        char = Char(self.char_id)
        vip_level = char.mc.vip
        vip_add = VIP_FUNCTION[vip_level].hang_addition

        passed_time = int(passed_time * _add * (1 + vip_add / 100.0))

        reward_gold = passed_time / 15 * battle_data.normal_gold
        reward_gold = self.get_real_gold(reward_gold, self.mongo_affairs.logs)

        reward_exp = passed_time / 15 * battle_data.normal_exp

        if battle_data.normal_drop:
            # 模拟损失物品
            drop_time = passed_time
            for log in self.mongo_affairs.logs:
                if log.tp == 1:
                    drop_time -= PLUNDER_GET_DROPS_MINUTES * 60

            drop_time_adjusted = max(int(passed_time * 0.25), drop_time)

            multi = int(drop_time_adjusted/15*multi)
            drops = get_drop([int(i) for i in battle_data.normal_drop.split(',')], multi=multi)
        else:
            drops = make_standard_drop_from_template()

        drops['exp'] = reward_exp
        drops['gold'] = reward_gold
        return drops


    def get_hang_reward(self, auto_start=True):
        """立即保存掉落,并且返回attachment消息"""
        # if not self.mongo_affairs.hang_city_id:
        #     raise SanguoException(
        #         errormsg.HANG_NOT_EXIST,
        #         self.char_id,
        #         "Get Hang Reward",
        #         "hang not exist"
        #     )

        drops = self.get_drop()

        resource = Resource(self.char_id, "Hang Reward")
        standard_drop = resource.add(**drops)

        if auto_start:
            # 领取奖励后自动开始
            self.start_hang(self.mongo_affairs.hang_city_id, get_reward=False)

        achievement = Achievement(self.char_id)
        achievement.trig(28, self.get_hang_obj().passed_time / 3600)
        achievement.trig(29, drops['exp'])

        return standard_drop_to_attachment_protomsg(standard_drop)


    def got_plundered(self, from_char_id, from_char_name, from_win, standard_drop):
        if from_win:
            tp = 1
        else:
            tp = 2

        gold = standard_drop['gold']
        item_text = standard_drop_to_readable_text(standard_drop, sign='-')

        log = MongoEmbeddedHangLog()
        log.timestamp = arrow.utcnow().timestamp
        log.tp = tp
        log.who = from_char_name
        log.gold = gold
        log.item_text = item_text

        self.mongo_affairs.logs.append(log)

        if len(self.mongo_affairs.logs) > PLUNDER_LOG_MAX_AMOUNT:
            self.mongo_affairs.logs.pop(0)

        self.mongo_affairs.save()
        self.send_hang_notify()

        achievement = Achievement(self.char_id)
        achievement.trig(33, 1)


    def send_city_notify(self):
        msg = CityNotify()
        for cid in CITY_IDS:
            city = msg.cities.add()
            city.id = cid
            city.status = CityMsg.OPEN if cid in self.mongo_affairs.opened else CityMsg.CLOSE

        publish_to_char(self.char_id, pack_msg(msg))


    def send_hang_notify(self):
        ho = HangObject(self.mongo_affairs.hang_city_id, self.mongo_affairs.hang_start_at, self.mongo_affairs.logs)
        gold = self.get_drop()['gold']
        msg = ho.make_hang_notify(gold)
        publish_to_char(self.char_id, pack_msg(msg))
Пример #6
0
class Affairs(_GetRealGoldMixin):
    def __init__(self, char_id):
        self.char_id = char_id
        try:
            self.mongo_affairs = MongoAffairs.objects.get(id=char_id)
        except DoesNotExist:
            self.mongo_affairs = MongoAffairs(id=char_id)
            self.mongo_affairs.opened = []
            self.mongo_affairs.hang_city_id = 0
            self.mongo_affairs.hang_start_at = 0
            self.mongo_affairs.logs = []
            self.mongo_affairs.save()

        self.set_default_value()

    def set_default_value(self):
        if self.mongo_affairs.opened:
            return

        opened = _get_opended_cities(self.char_id)
        if opened:
            self.mongo_affairs.opened = opened
            self.mongo_affairs.hang_city_id = opened[-1]
            self.mongo_affairs.hang_start_at = arrow.utcnow().timestamp
            self.mongo_affairs.save()

    def open_city(self, city_id):
        # 开启城镇

        # 因为从signals调用 open_city的时候
        # 对Affairs初始化时,会先把 1 开启,
        # 然后这里判断就是 没有开启……
        # 这里特殊处理

        if city_id == FIRST_CITY_ID and len(
                self.mongo_affairs.opened
        ) == 1 and self.mongo_affairs.opened[0] == FIRST_CITY_ID:
            opened = True
        else:
            need_opened = []
            for cid in CITY_IDS:
                if cid > city_id:
                    # XXX 这里默认city_id是从小到大的!
                    break

                need_opened.append(cid)

            opened = False
            for cid in need_opened:
                if cid in self.mongo_affairs.opened:
                    continue

                self.mongo_affairs.opened.append(cid)
                opened = True

        self.mongo_affairs.save()
        self.send_city_notify()
        return opened

    def start_hang(self, city_id, get_reward=True):
        if city_id not in BATTLES:
            raise SanguoException(
                errormsg.INVALID_OPERATE, self.char_id, "Start Hang",
                "hang at none exist city id {0}".format(city_id))

        if city_id not in self.mongo_affairs.opened:
            raise SanguoException(errormsg.INVALID_OPERATE, self.char_id,
                                  "Start Hang",
                                  "city id {0} not opened".format(city_id))

        if get_reward:
            if self.mongo_affairs.hang_city_id:
                # 上次有挂机,先结算
                drop_msg = self.get_hang_reward(auto_start=False)
            else:
                drop_msg = None
        else:
            drop_msg = None

        self.mongo_affairs.hang_city_id = city_id
        self.mongo_affairs.hang_start_at = arrow.utcnow().timestamp
        self.mongo_affairs.logs = []
        self.mongo_affairs.save()

        self.send_hang_notify()
        return drop_msg

    def get_hang_obj(self):
        return HangObject(self.mongo_affairs.hang_city_id,
                          self.mongo_affairs.hang_start_at,
                          self.mongo_affairs.logs)

    def get_hang_reward(self, auto_start=True):
        """立即保存掉落,并且返回attachment消息"""
        if not self.mongo_affairs.hang_city_id:
            raise SanguoException(errormsg.HANG_NOT_EXIST, self.char_id,
                                  "Get Hang Reward", "hang not exist")

        ho = self.get_hang_obj()
        battle_data = BATTLES[self.mongo_affairs.hang_city_id]

        percent = ho.passed_time / float(ho.max_time) * 100
        for _pre, _add in HANG_REWARD_ADDITIONAL:
            if percent >= _pre:
                break
        else:
            _add = 1

        char = Char(self.char_id)
        vip_level = char.mc.vip
        vip_add = VIP_FUNCTION[vip_level].hang_addition

        passed_time = int(ho.passed_time * _add * (1 + vip_add / 100.0))

        reward_gold = passed_time / 15 * battle_data.normal_gold
        reward_gold = self.get_real_gold(reward_gold, self.mongo_affairs.logs)

        reward_exp = passed_time / 15 * battle_data.normal_exp

        if battle_data.normal_drop:
            # 模拟损失物品
            drop_time = passed_time
            for log in self.mongo_affairs.logs:
                if log.tp == 1:
                    drop_time -= PLUNDER_GET_DROPS_MINUTES * 60

            drop_time_adjusted = max(int(passed_time * 0.25), drop_time)

            drops = get_drop(
                [int(i) for i in battle_data.normal_drop.split(',')],
                multi=drop_time_adjusted / 15)
        else:
            drops = make_standard_drop_from_template()

        drops['exp'] += reward_exp
        drops['gold'] += reward_gold

        resource = Resource(self.char_id, "Hang Reward")
        standard_drop = resource.add(**drops)

        if auto_start:
            # 领取奖励后自动开始
            self.start_hang(self.mongo_affairs.hang_city_id, get_reward=False)

        achievement = Achievement(self.char_id)
        achievement.trig(28, ho.passed_time / 3600)
        achievement.trig(29, reward_exp)

        return standard_drop_to_attachment_protomsg(standard_drop)

    def got_plundered(self, from_char_id, from_win, standard_drop):
        from_char = Char(from_char_id)
        from_name = from_char.mc.name

        if from_win:
            tp = 1
        else:
            tp = 2

        gold = standard_drop['gold']
        item_text = standard_drop_to_readable_text(standard_drop, sign='-')

        log = MongoEmbeddedHangLog()
        log.timestamp = arrow.utcnow().timestamp
        log.tp = tp
        log.who = from_name
        log.gold = gold
        log.item_text = item_text

        self.mongo_affairs.logs.append(log)

        if len(self.mongo_affairs.logs) > PLUNDER_LOG_MAX_AMOUNT:
            self.mongo_affairs.logs.pop(0)

        self.mongo_affairs.save()
        self.send_hang_notify()

    def send_city_notify(self):
        msg = CityNotify()
        for cid in CITY_IDS:
            city = msg.cities.add()
            city.id = cid
            city.status = CityMsg.OPEN if cid in self.mongo_affairs.opened else CityMsg.CLOSE

        publish_to_char(self.char_id, pack_msg(msg))

    def send_hang_notify(self):
        if not self.mongo_affairs.hang_city_id:
            return

        ho = HangObject(self.mongo_affairs.hang_city_id,
                        self.mongo_affairs.hang_start_at,
                        self.mongo_affairs.logs)
        msg = ho.make_hang_notify()
        publish_to_char(self.char_id, pack_msg(msg))