Exemple #1
0
def v2DataTov3Data(userId, clientId):
    """
    v2版本用户属性继承到v3版本
    """
    # 金币数量调整
    totalChip = userchip.getUserChipAll(userId)
    incrChip = totalChip * 10 - totalChip
    userchip.incrChip(userId, FISH_GAMEID, incrChip, 0,
                      "BI_NFISH_NEW_USER_REWARDS", 0, clientId)

    # 处理宝藏相关数据
    from newfish.entity import treasure_system
    treasureList = config.getV2ToV3Conf("treasure")
    userAssets = hallitem.itemSystem.loadUserAssets(userId)
    for _, treasureConf in enumerate(treasureList):
        old_kindId = treasureConf["old_kindId"]
        new_kindId = treasureConf.get("new_kindId")
        ratio = treasureConf.get("ratio", 0)
        convert_kindId = treasureConf.get("convert_kindId")
        convert_num = treasureConf.get("convert_num", 999999)
        surplusCount = util.balanceItem(userId, old_kindId, userAssets)
        if surplusCount > 0:
            if new_kindId:
                treasureData = treasure_system.getTreasure(userId, new_kindId)
                if treasureData[treasure_system.INDEX_LEVEL] == 0:
                    treasureData[treasure_system.INDEX_LEVEL] = 1
                    treasure_system.setTreasure(userId, new_kindId,
                                                treasureData)
            if convert_kindId:
                convertNum = min(surplusCount, convert_num)
                convertNum = int(math.ceil(convertNum * ratio))
                rewards = [{"name": convert_kindId, "count": convertNum}]
                util.addRewards(userId, rewards, "BI_NFISH_NEW_USER_REWARDS",
                                old_kindId, surplusCount)
            consumeItems = [{"name": old_kindId, "count": surplusCount}]
            util.consumeItems(userId, consumeItems,
                              "BI_NFISH_NEW_USER_REWARDS")

    # 处理技能相关数据
    skillList = config.getV2ToV3Conf("skill")
    userAssets = hallitem.itemSystem.loadUserAssets(userId)
    for _, skillConf in enumerate(skillList):
        old_kindId = skillConf["old_kindId"]
        ratio = skillConf.get("ratio", 0)
        convert_kindId = skillConf.get("convert_kindId")
        surplusCount = util.balanceItem(userId, old_kindId, userAssets)
        if surplusCount > 0:
            if convert_kindId:
                convertNum = int(math.ceil(surplusCount * ratio))
                rewards = [{"name": convert_kindId, "count": convertNum}]
                util.addRewards(userId, rewards, "BI_NFISH_NEW_USER_REWARDS",
                                old_kindId, surplusCount)
            consumeItems = [{"name": old_kindId, "count": surplusCount}]
            util.consumeItems(userId, consumeItems,
                              "BI_NFISH_NEW_USER_REWARDS")
Exemple #2
0
def composeGunSkin(userId, gunId, skinId, mode):
    """
    合成火炮皮肤
    """
    clientId = util.getClientId(userId)
    if ftlog.is_debug():
        ftlog.debug("composeGunSkin, userId =", userId, "gunId =", gunId,
                    "skinId =", skinId, "clientId =", clientId, "mode =", mode)
    skinConf = config.getGunSkinConf(skinId, clientId, mode)
    mo = MsgPack()
    mo.setCmd("gun_compose_skin")
    mo.setResult("gameId", FISH_GAMEID)
    mo.setResult("userId", userId)
    mo.setResult("gunId", gunId)
    mo.setResult("skinId", skinId)
    mo.setResult("gameMode", mode)
    skins = config.getGunConf(gunId, clientId, mode=mode).get("skins")
    if skinId not in skins:
        mo.setResult("code", 99)  # 数据不对
        router.sendToUser(mo, userId)
        return False
    if not skinConf:
        mo.setResult("code", 99)  # 数据不对
        router.sendToUser(mo, userId)
        return False
    surplusCount = util.balanceItem(userId, skinConf["kindId"])
    ownGunSkinSkinsKey = GameData.ownGunSkinSkins
    ownGunSkinSkins = gamedata.getGameAttrJson(userId, FISH_GAMEID,
                                               ownGunSkinSkinsKey, [])
    if surplusCount < skinConf["consumeCount"]:
        mo.setResult("code", 1)  # 资源不足
        return False
    elif skinId in ownGunSkinSkins:
        mo.setResult("code", 2)  # 已经合成
        return False
    else:
        # 合成消耗皮肤碎片
        _consume = [{
            "name": skinConf["kindId"],
            "count": abs(skinConf["consumeCount"])
        }]
        util.consumeItems(userId, _consume, "ITEM_USE", int(gunId), mode)
        addEquipGunSkinSkin(userId, skinId, clientId, False)
        mo.setResult("code", 0)
        router.sendToUser(mo, userId)
    return True
def refreshQuestTaskId(userId, taskId):
    """
    手动刷新每日任务
    """
    code = 1
    newTaskId = 0
    spareQuests = getSpareQuest(userId)
    cost = config.getDailyQuestRefreshConf().get("cost")
    if spareQuests and cost:
        todayQuest, _ = getTodayQuest(userId)
        quest = todayQuest.get(taskId, None)
        if ftlog.is_debug():
            ftlog.debug("refreshQuestTaskId", "userId =", userId, "taskId =", taskId, "quest =", quest)
        if quest:
            questInfo = getUserQuestInfoData(userId)
            refreshTimes = gamedata.getGameAttrInt(userId, FISH_GAMEID, GameData.refreshDailyQuestTimes)
            process, state = questInfo.get(str(taskId), [0, QuestTaskState.Normal])
            if ftlog.is_debug():
                ftlog.debug("refreshQuestTaskId", "questInfo =", questInfo, "refreshTimes =", refreshTimes, process, state)
            if state == QuestTaskState.Normal and refreshTimes < config.getDailyQuestRefreshConf().get("maxTimes", 1):
                succ = True
                for item in cost:
                    if util.balanceItem(userId, item["name"]) < item["count"]:
                        succ = False
                        if ftlog.is_debug():
                            ftlog.debug("refreshQuestTaskId ====>", "资源不足", userId, taskId, item["name"], item["count"])
                        break
                else:
                    if not util.consumeItems(userId, cost, "ITEM_USE"):
                        succ = False
                if succ:
                    code = 0
                    gamedata.incrGameAttr(userId, FISH_GAMEID, GameData.refreshDailyQuestTimes, 1)
                    import random
                    new = random.choice(spareQuests)
                    newTaskId = new["taskId"]
                    if str(taskId) in questInfo:
                        questInfo.pop(str(taskId))
                        if ftlog.is_debug():
                            ftlog.debug("refreshQuestTaskId, pop !", userId, taskId, questInfo)
                    questInfo[str(newTaskId)] = [0, QuestTaskState.Normal]
                    setUserQuestInfoData(userId, questInfo)
            else:
                code = 3
        else:
            code = 2
    mo = MsgPack()
    mo.setCmd("task")
    mo.setResult("gameId", FISH_GAMEID)
    mo.setResult("userId", userId)
    mo.setResult("action", "refreshQuest")
    mo.setResult("taskId", taskId)
    mo.setResult("code", code)
    mo.setResult("newTaskId", newTaskId)
    dailyQuestData = getDailyQuestData(userId)
    mo.setResult("dailyTask", dailyQuestData)
    router.sendToUser(mo, userId)
def consumeUpgradeTreasureItem(userId, items, intEventParam=0, param01=0, param02=0):
    """
    升级所需道具
    """
    if checkUpgradeTreasureItemCount(userId, items):
        ret = util.consumeItems(userId, items, "BI_NFISH_TREASURE_UPGRADE", intEventParam, param01, param02)
        if len(ret) == len(items):
            return True
    return False
Exemple #5
0
 def consume(items, level):
     """消耗升级所需道具"""
     _consumeList = []
     for kindId, count in items.iteritems():
         if int(kindId) == config.PURPLE_CRYSTAL_KINDID:
             _consumeList.extend(
                 consumeBindOrNotBindItem(userId,
                                          config.BIND_PURPLE_CRYSTAL_KINDID,
                                          config.PURPLE_CRYSTAL_KINDID,
                                          count))
         elif int(kindId) == config.YELLOW_CRYSTAL_KINDID:
             _consumeList.extend(
                 consumeBindOrNotBindItem(userId,
                                          config.BIND_YELLOW_CRYSTAL_KINDID,
                                          config.YELLOW_CRYSTAL_KINDID,
                                          count))
         else:
             _consume = {"name": int(kindId), "count": count}
             _consumeList.append(_consume)
     util.consumeItems(userId, _consumeList, "ITEM_USE", level)
Exemple #6
0
def renameNickname(userId, clientId, nickname):
    """
    修改玩家昵称
    """
    lang = util.getLanguage(userId, clientId)
    surplusCount = util.balanceItem(userId, config.RENAME_KINDID)
    try:
        if surplusCount == 0:
            code = 1
            info = config.getMultiLangTextConf("ID_RENAME_CODE_INFO_1", lang=lang) # u"昵称修改失败"
        elif len(nickname) == 0:
            code = 2
            info = config.getMultiLangTextConf("ID_RENAME_CODE_INFO_2", lang=lang) # u"昵称不能为空,请重新输入!"
        elif len(nickname.decode("utf-8").encode("gbk", "ignore")) > 16:
            code = 3
            info = config.getMultiLangTextConf("ID_RENAME_CODE_INFO_3", lang=lang) # u"昵称过长,请重新输入!"
        elif re.search(u"[^\w\u4e00-\u9fff]+", nickname.decode("utf-8")):
            code = 4
            info = config.getMultiLangTextConf("ID_RENAME_CODE_INFO_4", lang=lang) # u"昵称不能含有特殊字符,请重新输入!"
        elif util.isTextCensorLimit(nickname):
            code = 5
            info = config.getMultiLangTextConf("ID_RENAME_CODE_INFO_5", lang=lang) # u"昵称含有违规内容,请重新输入!"
        else:
            _consume = [{"name": config.RENAME_KINDID, "count": 1}]
            util.consumeItems(userId, _consume, "ITEM_USE")
            gamedata.setGameAttr(userId, FISH_GAMEID, GameData.nickname, nickname)
            userdata.setAttr(userId, "name", nickname)
            code = 0
            info = config.getMultiLangTextConf("ID_RENAME_CODE_INFO_0", lang=lang) # u"昵称修改成功"
    except:
        ftlog.error()
        code = 1
        info = config.getMultiLangTextConf("ID_RENAME_CODE_INFO_1", lang=lang)  # u"昵称修改失败"
    message = MsgPack()
    message.setCmd("rename_nickname")
    message.setResult("gameId", FISH_GAMEID)
    message.setResult("userId", userId)
    message.setResult("info", info)
    message.setResult("code", code)
    router.sendToUser(message, userId)
def consumeUpgradeSkillItem(userId,
                            items,
                            intEventParam=0,
                            param01=0,
                            param02=0):
    """
    消耗升级/升星所需道具
    """
    if checkUpgradeSkillItemCount(userId, items):
        ret = util.consumeItems(userId, items, "BI_NFISH_SKILL_UPGRADE",
                                intEventParam, param01, param02)
        if len(ret) == len(items):
            return True
    return False
    def startGrandPrix(self):
        """
        大奖赛开始 grandPrixStartTS=0 报名大奖赛/ grandPrixStartTS > 0 直接进入渔场
        """
        curTime = int(time.time())
        dayStartTimestamp = util.getDayStartTimestamp(curTime)
        remainGrandPrixTimeSeconds = util.timeStrToInt(
            config.getGrandPrixConf("openTimeRange")[1]) - (
                curTime - dayStartTimestamp)  # 大奖赛剩余时间
        # 当局进入大奖赛
        if self.grandPrixStartTS == 0:
            event = JoinGrandPrixEvent(self.userId, FISH_GAMEID,
                                       self.table.bigRoomId)  # 参加大奖赛事件
            TGFish.getEventBus().publishEvent(event)
            # 距离大奖赛结束不足10秒不可参赛
            if not grand_prix.isGrandPrixOpenTime(
            ) or remainGrandPrixTimeSeconds < 10:
                code = SignupCode.SC_NOT_OPEN
            elif config.getVipConf(self.vipLevel).get(
                    "grandPrixFreeTimes", 0) > self._freeTimes:  # 用免费次数报名
                self._freeTimes = weakdata.incrDayFishData(
                    self.userId, WeakData.grandPrix_freeTimes, 1)
                code = SignupCode.SC_SUCC
            else:
                # 扣除报名费
                fee = config.getGrandPrixConf("fee")[0]
                _consume = [{
                    "name": fee.get("name"),
                    "count": fee.get("count")
                }]
                _ret = util.consumeItems(self.userId, _consume, "ITEM_USE",
                                         self.table.roomId)
                if _ret:
                    code = SignupCode.SC_SUCC
                else:
                    code = SignupCode.SC_FEE_NOT_ENOUGH
            if code == SignupCode.SC_SUCC:
                # 选择目标鱼
                for _val in config.getGrandPrixConf(
                        "group").values():  # 1、2、3个组
                    idx = random.randint(0, len(_val) - 1)  # 一组鱼
                    _cnt = config.getGrandPrixConf("target").get(
                        str(_val[idx]), {}).get("count", 999)  # 某一种鱼 捕获数量
                    _point = config.getGrandPrixConf("target").get(
                        str(_val[idx]), {}).get("point", 0)  # 某一种鱼 获得的积分
                    self.grandPrixTargetFish[str(
                        _val[idx])] = [0, _cnt, _point]

                # 备份技能数据.
                self.grandPrixUseSkillTimes = []
                for i in range(skill_system.MAX_INSTALL_NUM - 1):
                    self.grandPrixUseSkillTimes.append({
                        "skillId":
                        0,
                        "state":
                        0,
                        "star":
                        0,
                        "grade":
                        0,
                        "count":
                        config.getGrandPrixConf("fireCount")[1],  # 技能使用次数3
                        "skillType":
                        0 if i < skill_system.MAX_INSTALL_NUM else
                        1  # 0主技能 1辅助技能
                    })

                for idx, _skillId in enumerate(self.skillSlots):
                    _skill = self.getSkill(_skillId, 0)
                    self.grandPrixUseSkillTimes[idx]["skillId"] = _skillId
                    self.grandPrixUseSkillTimes[idx][
                        "state"] = _skill.skillState
                    self.grandPrixUseSkillTimes[idx]["star"] = _skill.skillStar
                    self.grandPrixUseSkillTimes[idx][
                        "grade"] = _skill.skillGrade

                if self.inGameTimes:
                    bireport.reportGameEvent("BI_NFISH_GRAND_PRIX_INGAMETIMES",
                                             self.userId, FISH_GAMEID, 0, 0,
                                             self.grandPrixStartTS,
                                             self.inGameTimes, 0, 0, [],
                                             util.getClientId(self.userId))
                    self.inGameTimes = 0

                self.grandPrixFishPoint = 0
                self.grandPrixSurpassCount = 0
                self.grandPrixStartTS = curTime  # 大奖赛开始的时间戳
                self.grandPrixFireCount = config.getGrandPrixConf(
                    "fireCount")[0]
                self._saveGrandPrixData()  # 保存大奖赛数据
        else:
            if not grand_prix.isGrandPrixOpenTime():  # 现在不可参赛
                code = SignupCode.SC_NOT_OPEN
            elif not self.isGrandPrixMode():
                code = SignupCode.SC_SUCC
            else:
                code = SignupCode.SC_UNFINISH

        if code in [SignupCode.SC_SUCC, SignupCode.SC_UNFINISH]:
            interval = max(0.1, remainGrandPrixTimeSeconds)
            if self.grandPrixFireCount == 0:  # 3秒之后结束大奖赛
                interval = 0.1
            if self.grandPrixEndTimer:
                self.grandPrixEndTimer.cancel()
                self.grandPrixEndTimer = None
            self.grandPrixEndTimer = FTLoopTimer(interval, 0,
                                                 self.endGrandPrix)  # 启动结束定时器
            self.grandPrixEndTimer.start()
            # 取消处于使用中的技能,以免干扰技能使用次数计数
            if self.offline == 0:  # 玩家在线
                self.cancelUsingSkills()
                self.unloadSkills()
                self.loadAllSkillData()
                self.syncSkillSlots()
        elif code == SignupCode.SC_NOT_OPEN:  # 没开启
            self._resetGrandPrixData()  # 重置大奖赛相关数据

        self._getSurpassTarget()  # 获取要超越的玩家数据
        mo = MsgPack()
        mo.setCmd("start_grand_prix")
        mo.setResult("gameId", FISH_GAMEID)
        mo.setResult("userId", self.userId)
        mo.setResult("seatId", self.seatId)
        mo.setResult("fireCount", self.grandPrixFireCount)
        mo.setResult("fishPoint", self.grandPrixFishPoint)
        mo.setResult("targetFish", self.grandPrixTargetFish)
        mo.setResult(
            "useSkillTimes", {
                val.get("skillId", 0): val.get("count", 0)
                for val in self.grandPrixUseSkillTimes
            })
        mo.setResult("pointsInfo", grand_prix.getPointInfo(
            self.userId))  # 奖励积分 道具Id、道具数量、是否领取了奖励0|1
        mo.setResult("todayMaxPoints",
                     weakdata.getDayFishData(self.userId,
                                             WeakData.grandPrix_point,
                                             0))  # 今日最高积分
        GameMsg.sendMsg(mo, self.userId)
Exemple #9
0
def doBuyGift(userId, clientId, giftId, buyType, itemId=0):
    """
    购买礼包
    """
    if ftlog.is_debug():
        ftlog.debug("doBuyGift===>", userId, clientId, giftId, buyType)
    giftConf = config.getDailyGiftConf(clientId).get(str(giftId), {})
    continuousDay = _getContinuousDay(userId, giftId)
    dayIdx = _getGiftDayIdx(clientId, giftId, continuousDay)
    lang = util.getLanguage(userId, clientId)
    commonRewards = []
    chestRewards = []
    chestId = 0
    giftName = config.getMultiLangTextConf(giftConf["giftName"], lang=lang)
    # 使用其他货币(非direct)购买
    if giftConf.get("otherBuyType", {}).get(buyType):
        price = giftConf.get("otherBuyType", {}).get(buyType)
        # 代购券购买礼包
        if buyType == BT_VOUCHER:
            _consume = [{"name": VOUCHER_KINDID, "count": abs(price)}]
            _ret = util.consumeItems(userId,
                                     _consume,
                                     "BI_NFISH_BUY_ITEM_CONSUME",
                                     intEventParam=int(giftId),
                                     param01=int(giftId))
            if not _ret:
                code = 1
                _sendBuyGiftRet(userId, clientId, giftId, code, chestId,
                                commonRewards, chestRewards)
                return
            else:
                code = 0
                vip_system.addUserVipExp(FISH_GAMEID,
                                         userId,
                                         abs(price) * 10,
                                         "BUY_PRODUCT",
                                         pokerconf.productIdToNumber(
                                             giftConf["productId"]),
                                         giftConf["productId"],
                                         rmbs=abs(price))
                # message = u"您使用%s代购券,购买商品【%s】, 获得%s" % (price, giftConf["giftName"], giftConf["giftName"])
                message = config.getMultiLangTextConf(
                    "ID_BUY_GIFT_RET_BY_VOUCHER",
                    lang=lang).format(price, giftName, giftName)
                GameMsg.sendPrivate(FISH_GAMEID, userId, 0, message)
        else:
            code = 1
            _sendBuyGiftRet(userId, clientId, giftId, code, chestId,
                            commonRewards, chestRewards)
            return
    elif buyType == config.BT_DIAMOND:
        price = giftConf.get("price", 0)
        price, isSucc = store.getUseRebateItemPrice(userId, itemId, price,
                                                    buyType, giftId, clientId)
        code = 0
        if price > 0:
            consumeCount = 0
            if isSucc:
                store.autoConvertVoucherToDiamond(userId, price)
                consumeCount, final = userchip.incrDiamond(
                    userId,
                    FISH_GAMEID,
                    -abs(price),
                    0,
                    "BI_NFISH_BUY_ITEM_CONSUME",
                    int(giftId),
                    util.getClientId(userId),
                    param01=giftId)
            if not isSucc or abs(consumeCount) != price:
                code = 1
                _sendBuyGiftRet(userId, clientId, giftId, code, chestId,
                                commonRewards, chestRewards)
                return
    else:
        code = 0
        # message = u"您购买商品【%s】, 获得%s" % (giftConf["giftName"], giftConf["giftName"])
        message = config.getMultiLangTextConf("ID_BUY_GIFT_RET_BY_DRIECT",
                                              lang=lang).format(
                                                  giftName, giftName)
        GameMsg.sendPrivate(FISH_GAMEID, userId, 0, message)

    # 记录存档
    boughtGift = weakdata.getDayFishData(userId, WeakData.buyFishDailyGift, [])
    boughtGift.append(giftId)
    weakdata.setDayFishData(userId, WeakData.buyFishDailyGift,
                            json.dumps(boughtGift))

    # 记录每日礼包购买次数.
    buyFishDailyGiftTimes = gamedata.getGameAttrJson(
        userId, FISH_GAMEID, GameData.buyFishDailyGiftTimes, {})
    buyFishDailyGiftTimes.setdefault(str(giftId), 0)
    buyFishDailyGiftTimes[str(giftId)] += 1
    gamedata.setGameAttr(userId, FISH_GAMEID, GameData.buyFishDailyGiftTimes,
                         json.dumps(buyFishDailyGiftTimes))

    purchaseData = gamedata.getGameAttrJson(userId, FISH_GAMEID,
                                            GameData.continuousPurchase, {})
    data = purchaseData.get(str(giftId), [0, 0])
    if util.getDayStartTimestamp(
            data[0]) + 24 * 60 * 60 < util.getDayStartTimestamp(
                int(time.time())):
        data[1] = 1
    else:
        data[1] += 1
    data[0] = int(time.time())
    purchaseData[str(giftId)] = data
    gamedata.setGameAttr(userId, FISH_GAMEID, GameData.continuousPurchase,
                         json.dumps(purchaseData))
    # 发奖励
    mail_rewards = []
    giftInfo = giftConf.get("giftInfo", [])
    for gift in giftInfo:
        if gift["day_idx"] == dayIdx:
            for item in gift.get("items", []):
                if util.isChestRewardId(item["itemId"]):  # 宝箱
                    chestId = item["itemId"]
                    rewards = chest_system.getChestRewards(userId, chestId)
                    if buyType == BT_VOUCHER or buyType == config.BT_DIAMOND:
                        code = chest_system.deliveryChestRewards(
                            userId, chestId, rewards, "BI_NFISH_BUY_ITEM_GAIN")
                    else:
                        code = 0
                        gamedata.incrGameAttr(userId, FISH_GAMEID,
                                              GameData.openChestCount, 1)
                        bireport.reportGameEvent("BI_NFISH_GE_CHEST_OPEN",
                                                 userId, FISH_GAMEID, 0, 0,
                                                 int(chestId), 0, 0, 0, [],
                                                 util.getClientId(userId))
                    chestRewards.extend(rewards)
                    mail_rewards.extend([{"name": item["itemId"], "count": 1}])
                else:  # 资产/道具
                    rewards = [{
                        "name": item["itemId"],
                        "count": item["count"]
                    }]
                    if buyType == BT_VOUCHER or buyType == config.BT_DIAMOND:
                        code = util.addRewards(userId,
                                               rewards,
                                               "BI_NFISH_BUY_ITEM_GAIN",
                                               int(giftId),
                                               param01=int(giftId))
                    else:
                        code = 0
                    commonRewards.extend(rewards)
                    mail_rewards.extend(rewards)
            break
    if buyType == BT_VOUCHER or buyType == config.BT_DIAMOND:
        _sendBuyGiftRet(userId, clientId, giftId, code, chestId, commonRewards,
                        chestRewards)
    else:
        message = config.getMultiLangTextConf("ID_DO_BUY_GIFT_MSG",
                                              lang=lang) % giftName
        title = config.getMultiLangTextConf("ID_MAIL_TITLE_DAILY_GIFT",
                                            lang=lang)
        mail_system.sendSystemMail(userId,
                                   mail_system.MailRewardType.SystemReward,
                                   mail_rewards, message, title)
        doSendGift(userId, clientId)
    # 购买礼包事件
    from newfish.game import TGFish
    from newfish.entity.event import GiftBuyEvent
    event = GiftBuyEvent(userId, FISH_GAMEID, giftConf["productId"], buyType,
                         giftId)
    TGFish.getEventBus().publishEvent(event)
    util.addProductBuyEvent(userId, giftConf["productId"], clientId)
Exemple #10
0
def buyPiggyBank(userId, clientId, productId, buyType=None, itemId=0):
    """
    购买存钱罐
    """
    code = 3
    rewards = []
    product = config.getPiggyBankProduct(clientId, productId)
    if product is None:
        mo = MsgPack()
        mo.setCmd("piggyBankBuy")
        mo.setResult("gameId", config.FISH_GAMEID)
        mo.setResult("userId", userId)
        mo.setResult("productId", productId)
        mo.setResult("code", code)
        router.sendToUser(mo, userId)
        ftlog.warn("piggy_bank, userId =", userId, "productId =", productId,
                   "buyType =", buyType, "code =", code)
        return
    # if buyType:
    #     if buyType not in product.get("otherBuyType", {}):
    #         return
    # else:
    #     buyType = product.get("buyType")
    type = product.get("type")
    key = UserData.piggyBankData % (FISH_GAMEID, userId)
    piggyBankData = daobase.executeUserCmd(userId, "HGET", key, type)
    dailyMaxTimes = product.get("dailyTimes", 0)
    if piggyBankData:
        piggyBankData = json.loads(piggyBankData)
    else:
        piggyBankData = {}
    ts = int(time.time()) / 60 * 60
    if piggyBankData.get(GameData.pb_enable,
                         0) == 0 and weakdata.getDayFishData(
                             userId, "pb_buyTimes", 0) < dailyMaxTimes:
        isSucc = False
        if buyType in product.get("otherBuyType", {}):
            price = product["otherBuyType"].get(buyType, 0)
            if buyType == config.BT_VOUCHER and price > 0:
                _consume = [{
                    "name": config.VOUCHER_KINDID,
                    "count": abs(price)
                }]
                _ret = util.consumeItems(
                    userId,
                    _consume,
                    "BI_NFISH_BUY_ITEM_CONSUME",
                    pokerconf.productIdToNumber(productId),
                    param01=productId)
                vip_system.addUserVipExp(
                    config.FISH_GAMEID,
                    userId,
                    abs(price) * 10,
                    "BUY_PRODUCT",
                    pokerconf.productIdToNumber(productId),
                    productId,
                    rmbs=abs(price))
                if _ret:
                    isSucc = True
                else:
                    code = 2
            else:
                isSucc = True
        elif buyType == config.BT_DIRECT or config.isThirdBuyType(buyType):
            isSucc = True
        elif buyType == config.BT_DIAMOND:
            price = product.get("price_diamond", 0)
            price, _ret = store.getUseRebateItemPrice(userId, itemId, price,
                                                      buyType, productId,
                                                      clientId)  # 满减券之后的钻石 满减券
            if price > 0:
                consumeCount = 0
                if _ret:
                    store.autoConvertVoucherToDiamond(userId, price)  # 代购券
                    consumeCount, final = userchip.incrDiamond(
                        userId,
                        FISH_GAMEID,
                        -abs(price),
                        0,
                        "BI_NFISH_BUY_ITEM_CONSUME",
                        int(config.DIAMOND_KINDID),
                        util.getClientId(userId),
                        param01=productId)
                if not _ret or abs(consumeCount) != price:
                    code = 2
                else:
                    isSucc = True
        if isSucc:
            piggyBankData[GameData.pb_enable] = 1
            # piggyBankData[GameData.pb_saveMoneyTS] = ts
            piggyBankData[GameData.pb_getMoneyTS] = 0
            # piggyBankData[GameData.pb_moneyCount] = conf.get("initVal", 0)
            pb_buyTimes = weakdata.incrDayFishData(userId, "pb_buyTimes", 1)
            # piggyBankData[GameData.pb_buyTimes] = piggyBankData.get(GameData.pb_buyTimes, 0) + 1
            daobase.executeUserCmd(userId, "HSET", key, type,
                                   json.dumps(piggyBankData))
            code, rewards = getMoney(userId, clientId, productId)

    mo = MsgPack()
    mo.setCmd("piggyBankBuy")
    mo.setResult("gameId", config.FISH_GAMEID)
    mo.setResult("userId", userId)
    mo.setResult("productId", productId)
    mo.setResult("code", code)
    if code == 0:
        util.addProductBuyEvent(userId, productId, clientId)
        mo.setResult("reward", rewards)
    router.sendToUser(mo, userId)
    vipLevel = hallvip.userVipSystem.getVipInfo(userId).get("level", 0)
    ftlog.debug("piggy_bank, userId =", userId, "vip =", vipLevel, "type =",
                type, "code =", code, "piggyBankData =", piggyBankData,
                util.timestampToStr(ts), product)

    getPiggyBankInfo(userId, clientId)
    def onCmdQuickStart(cls, msg, userId, gameId, roomId, tableId, clientId,
                        kindId):
        """UT server中处理来自客户端的quick_start请求  
        Args:
            msg
                cmd : quick_start
                if roomId == 0:
                    表示快速开始,服务器为玩家选择房间,然后将请求转给GR
                    
                if roomId > 0 and tableId == 0 : 
                    表示玩家选择了房间,将请求转给GR
                    
                if roomId > 0 and tableId == roomId * 10000 :
                    表示玩家在队列里断线重连,将请求转给GR
                    
                if roomId > 0 and tableId > 0:
                    if onlineSeatId > 0: 
                        表示玩家在牌桌里断线重连,将请求转给GT
                    else:
                        表示玩家选择了桌子,将请求转给GR
        """
        assert isinstance(userId, int) and userId > 0
        assert isinstance(roomId, int) and roomId >= 0
        assert isinstance(tableId, int) and tableId >= 0
        if ftlog.is_debug():
            ftlog.debug("onCmdQuickStart->", userId, "msg =", msg, "roomId =",
                        roomId, "tableId =", tableId, "clientId =", clientId)
        isRobot = userId < config.ROBOT_MAX_USER_ID
        if not isRobot and not util.isUsableClientVersion(userId):
            cls.onQuickStartFailed(cls.ENTER_ROOM_REASON_VERSION_DISABLE,
                                   userId, clientId, roomId)
            return

        # 单开, 无论何时quick_start进入都检查loc
        if not pokerconf.isOpenMoreTable(clientId):
            locList = onlinedata.getOnlineLocList(userId)
            if ftlog.is_debug():
                ftlog.debug("onCmdQuickStart->getOnlineLocList->", userId,
                            locList)
            try:
                for lRoomId, lTableId, lSeatId in locList:
                    roomGameId = strutil.getGameIdFromInstanceRoomId(lRoomId)
                    if roomGameId == FISH_GAMEID:
                        roomId = lRoomId
                        tableId = lTableId
                        ftlog.info(
                            "onCmdQuickStart->reconnect roomId, tableId->",
                            userId, roomId, tableId)
                    else:
                        cls.onQuickStartFailed(
                            cls.ENTER_ROOM_REASON_STATE_ERROR, userId,
                            clientId, roomId)
                        return
                    break
            except:
                ftlog.warn("onCmdQuickStart->error", userId, roomId, tableId)

        redState = gamedata.getGameAttrInt(userId, FISH_GAMEID,
                                           GameData.redState)
        if isRobot is False and redState == 0:
            ctrlRoomId = config.getCommonValueByKey("newbieRoomId")
            chosenTableId = 0
            shadowRoomId = None
            if gdata.getBigRoomId(roomId) == gdata.getBigRoomId(
                    ctrlRoomId) and tableId:
                chosenTableId = tableId
                shadowRoomId = tableId / 10000
            TYRoomMixin.queryRoomQuickStartReq(
                msg, ctrlRoomId, chosenTableId,
                shadowRoomId=shadowRoomId)  # 请求转给GR
            return

        if roomId == 0:  # 玩家点击快速开始
            chosenRoomId, reason = cls._chooseRoom(userId, gameId)
            ftlog.info("onCmdQuickStart->chosenRoomId", chosenRoomId,
                       "userId =", userId, "reason =", reason)
            if reason == cls.ENTER_ROOM_REASON_OK:
                TYRoomMixin.queryRoomQuickStartReq(msg, chosenRoomId,
                                                   0)  # 请求转给GR
            else:
                cls.onQuickStartFailed(reason, userId, clientId, roomId)
            return

        if tableId == 0:  # 玩家只选择了房间
            bigRoomId = gdata.getBigRoomId(roomId)
            if bigRoomId == 0:
                cls.onQuickStartFailed(cls.ENTER_ROOM_REASON_ROOM_ID_ERROR,
                                       userId, clientId, roomId)
                return
            ctrlRoomIds = gdata.bigRoomidsMap()[bigRoomId]
            ctrlRoomId = ctrlRoomIds[userId % len(ctrlRoomIds)]
            reason = cls.canQuickEnterRoom(userId, gameId, ctrlRoomId, kindId)
            if reason == cls.ENTER_ROOM_REASON_OK:
                roomConf = gdata.roomIdDefineMap()[roomId].configure
                fee = roomConf.get("fee_%s" % kindId, {}) or roomConf.get(
                    "fee", {})
                rewards = fee.get("rewards", [])
                if fee:
                    _consume = [{"name": fee["kindId"], "count": fee["count"]}]
                    ret = util.consumeItems(userId, _consume, "ROOM_GAME_FEE")
                    if ret and rewards:
                        util.addRewards(userId, rewards,
                                        "BI_NFISH_VOUCHER_REWARDS", kindId)
                TYRoomMixin.queryRoomQuickStartReq(msg, ctrlRoomId,
                                                   0)  # 请求转给GR或GT
            else:
                cls.onQuickStartFailed(reason, userId, clientId, roomId)
            return

        if tableId == roomId * 10000:  # 玩家在队列里断线重连
            TYRoomMixin.queryRoomQuickStartReq(msg, roomId, tableId)  # 请求转给GR
            return

        onlineSeat = onlinedata.getOnlineLocSeatId(userId, roomId, tableId)

        if onlineSeat:
            TYRoomMixin.querySitReq(userId, roomId, tableId, clientId,
                                    {"seatId": onlineSeat})  # 玩家断线重连,请求转给GT
        else:  # 玩家选择了桌子
            shadowRoomId = tableId / 10000
            ctrlRoomId = gdata.roomIdDefineMap()[shadowRoomId].parentId
            TYRoomMixin.queryRoomQuickStartReq(
                msg, ctrlRoomId, tableId, shadowRoomId=shadowRoomId)  # 请求转给GR
Exemple #12
0
def playMinigame(roomId, userId, idx, mode, userIds, groupIdx):
    """
    点击小游戏
    """
    bigRoomId, _ = util.getBigRoomId(roomId)
    subkey = "%s_%d" % (bigRoomId, mode)
    mgType = config.getSuperBossCommonConf().get(str(subkey), {}).get("mgType", "")
    key = "%s_%d" % (mgType, mode)
    mo = MsgPack()
    mo.setCmd("superboss_minigame")
    mo.setResult("gameId", FISH_GAMEID)
    mo.setResult("userId", userId)
    mo.setResult("roomId", roomId)
    mo.setResult("mode", mode)
    mo.setResult("idx", idx)
    mo.setResult("type", mgType)
    code = 1
    data = {}
    gainItems =[]
    if mgType in MINIGAME_TYPE_LIST:
        superbossPlayedTimes = weakdata.getDayFishData(userId, WeakData.superbossMGPlayedTimes, {})
        playedTimes = superbossPlayedTimes.setdefault(key, 0)
        conf = config.getSuperBossMiniGameConf()
        vipLevel = hallvip.userVipSystem.getUserVip(userId).vipLevel.level
        maxTimesList = conf.get("info", {}).get(key, {}).get("maxTimes", [])
        maxTimes = maxTimesList[vipLevel] if maxTimesList and len(maxTimesList) > vipLevel else 0
        items = conf.get("game", {}).get(key, [])
        rewards = []
        _idx = 0
        isCanPlay = True
        # 只能抽取满足消耗的最高等级抽奖.
        # if mgType == "queen":
        #     # 抽奖消耗由多到少配置。
        #     for _idx, _val in enumerate(itemsinfo):
        #         # 检查消耗是否满足条件
        #         for v in _val["costs"]:
        #             if util.balanceItem(userId, v["name"]) < v["count"]:
        #                 break
        #         else:
        #             isCanPlay = (idx == _idx)
        #             break
        if 0 <= idx < len(items) and (maxTimes == -1 or maxTimes > playedTimes) and isCanPlay:
            costItems = items[idx]["costs"]
            if mgType == "box":
                gainItems = items[idx]["rewards"][groupIdx].values()[0]
            else:
                gainItems = items[idx]["rewards"]
            for _val in costItems:
                if util.balanceItem(userId, _val["name"]) < _val["count"]:
                    code = 2
                    break
            else:
                _ret = util.consumeItems(userId, costItems, "BI_NFISH_SUPERBOSS_EXCHANGE", bigRoomId, mode)
                if not _ret:
                    code = 2
                else:
                    superbossPlayedTimes[key] += 1
                    weakdata.setDayFishData(userId, WeakData.superbossMGPlayedTimes, json.dumps(superbossPlayedTimes))
                    _idx = util.selectIdxByWeight([v["probb"] for v in gainItems])
                    if _idx >= 0:
                        rewards = [{"name": gainItems[_idx]["name"], "count": gainItems[_idx]["count"]}]
                        isIn, roomId, tableId, _ = util.isInFishTable(userId)
                        if isIn:
                            code = table_remote.addRewardsToTable(roomId, tableId, userId, rewards, "BI_NFISH_SUPERBOSS_BOX", mode)
                        else:
                            code = util.addRewards(userId, rewards, "BI_NFISH_SUPERBOSS_BOX", bigRoomId, mode)
                        if code != 0:
                            ftlog.error("minigame, userId =", userId, "bigRoomId =", key, "idx =", idx, "rewards =", rewards)
            playedTimes = superbossPlayedTimes.get(key, 0)
            remainTimes = max(0, maxTimes - playedTimes) if maxTimes >= 0 else -1
            data = {"remainTimes": remainTimes, "rewards": rewards, "rewardIndex": _idx}
    else:
        ftlog.warn("minigame, type error, userId =", userId, "roomId =", roomId, "mode =", mode, "idx =", idx, "mgType =", mgType)
    mo.setResult("code", code)
    turntable_rewards = []
    if mgType == "dragon":
        for gainItem in gainItems:
            for key in gainItem.keys():
                if key == "count":
                    turntable_rewards.append(gainItem[key])
        data["turntable_rewards"] = turntable_rewards
    mo.setResult("data", data)
    router.sendToUser(mo, userId)
    if mgType == "dragon" and code == 0:
        userIds = userIds
        GameMsg.sendMsg(mo, userIds)
    if code == 0:
        from newfish.game import TGFish
        event = PlayMiniGame(userId, config.FISH_GAMEID)
        TGFish.getEventBus().publishEvent(event)
    checkModuleTip(bigRoomId, userId, mode)
Exemple #13
0
def _exchange(userId, mgType, mode, idx, count):
    """
    兑换逻辑, 通过mgType+mode+idx可以唯一确定兑换数据.
    """
    code = 1
    key = "%s_%d" % (mgType, mode)
    exchangedTimes = weakdata.getDayFishData(userId,
                                             WeakData.superbossExchangedTimes,
                                             {})
    exchangedTimes.setdefault(key, {})
    conf = config.getSuperBossExchangeConf("exchange").get(key, {})
    rewards = []
    reList = ""
    costList = ""
    lang = util.getLanguage(userId)
    info = config.getMultiLangTextConf("ID_EXCHANGE_ERR_INFO_8", lang=lang)
    # 根据兑换类型找到bigRoomId,用于bi事件参数.
    bigRoomId = 0
    for _bigRoomId, val in config.getSuperBossCommonConf().iteritems():
        if val["mgType"] == mgType:
            bigRoomId = int(str(_bigRoomId)[0:5])
            break
    for _exchangeItem in conf.get("exchangeItems", []):
        _id = _exchangeItem["idx"]
        if _id != idx:
            continue
        remainTimes = _exchangeItem["exchangeTimes"]
        remainTimes = max(0, remainTimes - exchangedTimes[key].get(
            str(_id), 0)) if remainTimes >= 0 else remainTimes
        if not (count >= 1 and (remainTimes == -1 or remainTimes >= count)):
            continue
        costItems = _exchangeItem.get("costItems", [])
        gainItems = _exchangeItem.get("gainItems", [])
        for _val in costItems:
            _val["count"] *= count
            kindName = config.getMultiLangTextConf("ID_CONFIG_KINDID_ITEM:%s" %
                                                   _val["name"],
                                                   lang=lang)
            costDes = kindName + "x" + str(_val["count"])
            costList = costList + costDes + " "
            if util.balanceItem(userId, _val["name"]) < _val["count"]:
                code = 2
                break
        _ret = util.consumeItems(userId, costItems,
                                 "BI_NFISH_SUPERBOSS_EXCHANGE", bigRoomId,
                                 mode)
        if not _ret:
            code = 2
        else:
            code = 0
            if remainTimes > 0:
                exchangedTimes[key][str(_id)] = exchangedTimes[key].setdefault(
                    str(_id), 0) + count
                weakdata.setDayFishData(userId,
                                        WeakData.superbossExchangedTimes,
                                        json.dumps(exchangedTimes))
            reDict = {}
            for i in range(count):
                for val in gainItems:
                    if val.get("minCount", 0) and val.get("maxCount", 0):
                        reDict.setdefault(val["name"], 0)
                        reDict[val["name"]] += random.randint(
                            val["minCount"], val["maxCount"])
            for k, v in reDict.iteritems():
                rewards.append({"name": k, "count": v})
                if k == config.CHIP_KINDID:
                    kindName = config.getMultiLangTextConf(
                        "ID_CONFIG_KINDID_USER:CHIP", lang=lang)
                else:
                    kindName = config.getMultiLangTextConf(
                        "ID_CONFIG_KINDID_ITEM:%s" % k, lang=lang)
                reDes = kindName + "x" + str(v)
                reList = reList + reDes + " "
            if util.addRewards(userId, rewards, "BI_NFISH_SUPERBOSS_EXCHANGE",
                               bigRoomId, mode) != 0:
                ftlog.error("item_exchange, userId =", userId, "bigRoomId =",
                            bigRoomId, "mode =", mode, "idx =", idx, "count =",
                            count, "rewards =", rewards, "key =", key)
    if code == 0:
        bireport.reportGameEvent("BI_NFISH_GE_ITEM_EXCHANGE", userId,
                                 FISH_GAMEID, 0, 0, 0, 0, 0, 0,
                                 [userId, mgType, mode, idx],
                                 util.getClientId(userId))
        from newfish.game import TGFish
        event = MiniGameBossExchange(userId, config.FISH_GAMEID, count)
        TGFish.getEventBus().publishEvent(event)
        info = config.getMultiLangTextConf(
            "ID_EXCHANGE_RESULT_INFO_1",
            lang=lang).format(time.strftime("%X", time.localtime()), reList,
                              costList)
    return code, rewards, info
Exemple #14
0
 def reason(self, kindId, fIds, lockFid=0):
     """是否使用道具"""
     if kindId not in self.player.skills_item_slots:
         return 1
     if kindId == config.FREEZE_KINDID:
         frozenNum = 0
         for fId in fIds:
             isOK = self.table.findFish(fId)
             if not isOK:
                 continue
             bufferEffect = [
                 1 for buffer in self.table.fishMap[fId]["buffer"]
                 if buffer[0] == 5104 and time.time() < buffer[1]
             ]
             if len(bufferEffect) > 0 and lockFid != fId:
                 frozenNum += 1
                 continue
         if frozenNum >= SkillItem.FREEZE_NUM:
             return 7
     data = self.player.skills_item_slots[kindId]
     if not data:
         return 2
     if data["state"] == State.USING:
         if float("%.2f" % time.time()) - data["start_time"] + data[
                 "progress"][0] < data["progress"][1]:
             return 4
         self.player.end_skill_item(kindId)
         data = self.player.skills_item_slots[kindId]
     if data and data["state"] != State.NO_USE:
         return 5
     conf = data["conf"]
     name = conf["name"]
     count_0 = conf["count_0"]
     replace_name = conf["replace_name"]
     count_1 = conf["count_1"]
     bind_name = conf["bind_name"]
     bind_count = conf["bind_count"]
     # 不是新手阶段或者宝藏不消耗道具阶段
     if not (self.table.typeName == config.FISH_NEWBIE
             or treasure_system.isUseItemFree(self.userId, int(kindId))):
         if balanceItem(
                 self.userId,
                 bind_name) >= bind_count and bind_count > 0:  # 先使用绑定的锁定道具
             consumeItems(
                 self.userId, [{
                     "name": bind_name,
                     "count": bind_count
                 }], "BI_SKILL_ITEM_CONSUME_%s_%s_%s" %
                 (kindId, bind_name, bind_count))
         elif balanceItem(self.userId,
                          name) >= count_0 and count_0 > 0:  # 在使用锁定道具
             consumeItems(
                 self.userId, [{
                     "name": name,
                     "count": count_0
                 }],
                 "BI_SKILL_ITEM_CONSUME_%s_%s_%s" % (kindId, name, count_0))
         elif balanceItem(self.userId,
                          replace_name) >= count_1 and count_1 > 0:  # 使用珍珠
             consumeItems(
                 self.userId, [{
                     "name": replace_name,
                     "count": count_1
                 }], "BI_SKILL_ITEM_CONSUME_ITEM_%s_%s_%s" %
                 (kindId, replace_name, count_1))
         else:
             return 6
     data["state"] = State.USING
     data["start_time"] = float("%.2f" % time.time())
     return 0
def doBuyLevelFunds(userId, clientId, buyType, productId, rebateItemId=0):
    """
    购买成长基金
    """
    # 根据商品Id确定游戏模式.
    mode = config.CLASSIC_MODE
    for _m in [config.CLASSIC_MODE, config.MULTIPLE_MODE]:
        fundsConf = config.getLevelFundsConf(clientId, _m)
        for val in fundsConf.get("funds"):
            if val.get("productId") == productId:
                mode = _m
                break
    fundsConf = config.getLevelFundsConf(clientId, mode)
    funds = fundsConf.get("funds")
    productConf = None
    canBuyIdxs = fundsConf.get("canBuyIdx")
    for val in funds:
        if val.get("idx") in canBuyIdxs and val.get("productId") == productId:
            productConf = val
            break
    if not productConf:
        sendBuyLevelFundsRet(userId, clientId, productId, 0, 5, mode)
        return
    buyType = buyType or productConf.get("buyType")
    lf_funds = daobase.executeUserCmd(userId, "HGET", _getRdKey(userId, mode), GameData.lf_funds) or "[]"
    lf_funds = json.loads(lf_funds)
    lf_types = [val.get("type") for val in funds if val.get("idx") in lf_funds]
    if productConf.get("idx") in lf_funds or productConf.get("type") in lf_types:       # 重复购买同一商品或是同一类型的商品.
        sendBuyLevelFundsRet(userId, clientId, productId, 0, 6, mode)
        return
    lang = util.getLanguage(userId, clientId)
    productName = config.getMultiLangTextConf(productConf["name"], lang=lang)
    if buyType == BT_DIRECT or config.isThirdBuyType(buyType):                          # 直充购买或者三方渠道支付
        message = config.getMultiLangTextConf("ID_BUY_GIFT_RET_BY_DRIECT", lang=lang).format(productName, productName)
        GameMsg.sendPrivate(FISH_GAMEID, userId, 0, message)
        code = 0
    else:
        # 使用代购券购买
        if productConf.get("otherBuyType", {}).get(buyType):
            price = productConf.get("otherBuyType", {}).get(buyType)
            if buyType == BT_VOUCHER:
                _consume = [{"name": VOUCHER_KINDID, "count": abs(price)}]
                _ret = util.consumeItems(userId, _consume, "BI_NFISH_BUY_ITEM_CONSUME", param01=productId)
                if not _ret:
                    code = 2
                else:
                    vip_system.addUserVipExp(FISH_GAMEID, userId, abs(price) * 10, "BUY_PRODUCT", pokerconf.productIdToNumber(productId), productId, rmbs=abs(price))
                    message = config.getMultiLangTextConf("ID_BUY_GIFT_RET_BY_VOUCHER", lang=lang).format(price, productName, productName)
                    GameMsg.sendPrivate(FISH_GAMEID, userId, 0, message)
                    code = 0
            else:
                code = 3
        # 使用钻石购买
        elif buyType == config.BT_DIAMOND:                                              # 钻石购买
            price = productConf["price_diamond"]
            price, isSucc = store.getUseRebateItemPrice(userId, rebateItemId, price, buyType, productId, clientId)
            # 不能出现使用满减券后不需要花钱的情况!!!
            if price > 0 and isSucc:
                store.autoConvertVoucherToDiamond(userId, price)                        # 钻石足够优先使用钻石、在使用代购券
                consumeCount, final = userchip.incrDiamond(userId, FISH_GAMEID, -abs(price), 0, "BI_NFISH_BUY_LEVEL_FUNDS_CONSUME", int(config.DIAMOND_KINDID), clientId, param01=productId)
                if abs(consumeCount) != price:
                    code = 4
                else:
                    code = 0
            else:
                code = 5
        else:
            code = 6
    if code == 0:
        util.addProductBuyEvent(userId, productId, clientId)
        lf_funds.append(productConf.get("idx"))
        daobase.executeUserCmd(userId, "HSET", _getRdKey(userId, mode), GameData.lf_funds, json.dumps(lf_funds))
    sendBuyLevelFundsRet(userId, clientId, productId, productConf.get("idx"), code, mode)