hxp
2024-06-12 f0eb36291076cebc207cf350c984147baec65059
10178 【越南】【香港】【主干】挂机奖励
9个文件已修改
1个文件已添加
661 ■■■■■ 已修改文件
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameFuncComm.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerGuaji.py 394 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerState.py 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
@@ -44982,6 +44982,119 @@
#------------------------------------------------------
# B1 09 玩家挂机系统信息 #tagMCGuajiInfo
class  tagMCGuajiInfo(Structure):
    Head = tagHead()
    QuickAwardCount = 0    #(BYTE QuickAwardCount)// 今日已快速挂机收益次数
    AwardType = 0    #(BYTE AwardType)// 收益类型: 0-已累计预览;1-领取结算结果(包含常规领取跟快速领取)
    AwardSeconds = 0    #(DWORD AwardSeconds)// 已累计收益时长,秒
    Exp = 0    #(DWORD Exp)// 已累计经验,求余亿部分
    ExpPoint = 0    #(DWORD ExpPoint)// 已累计经验,整除亿部分
    MoneyInfoLen = 0    #(BYTE MoneyInfoLen)
    MoneyInfo = ""    #(String MoneyInfo)// 已累计货币 [[货币类型, 货币值], ...]
    ItemInfoLen = 0    #(BYTE ItemInfoLen)
    ItemInfo = ""    #(String ItemInfo)// 已累计物品 [[物品ID, 个数], ...]
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xB1
        self.Head.SubCmd = 0x09
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        _pos = self.Head.ReadData(_lpData, _pos)
        self.QuickAwardCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.AwardType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.AwardSeconds,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.Exp,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.ExpPoint,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.MoneyInfoLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.MoneyInfo,_pos = CommFunc.ReadString(_lpData, _pos,self.MoneyInfoLen)
        self.ItemInfoLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.ItemInfo,_pos = CommFunc.ReadString(_lpData, _pos,self.ItemInfoLen)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xB1
        self.Head.SubCmd = 0x09
        self.QuickAwardCount = 0
        self.AwardType = 0
        self.AwardSeconds = 0
        self.Exp = 0
        self.ExpPoint = 0
        self.MoneyInfoLen = 0
        self.MoneyInfo = ""
        self.ItemInfoLen = 0
        self.ItemInfo = ""
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 1
        length += 1
        length += 4
        length += 4
        length += 4
        length += 1
        length += len(self.MoneyInfo)
        length += 1
        length += len(self.ItemInfo)
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteBYTE(data, self.QuickAwardCount)
        data = CommFunc.WriteBYTE(data, self.AwardType)
        data = CommFunc.WriteDWORD(data, self.AwardSeconds)
        data = CommFunc.WriteDWORD(data, self.Exp)
        data = CommFunc.WriteDWORD(data, self.ExpPoint)
        data = CommFunc.WriteBYTE(data, self.MoneyInfoLen)
        data = CommFunc.WriteString(data, self.MoneyInfoLen, self.MoneyInfo)
        data = CommFunc.WriteBYTE(data, self.ItemInfoLen)
        data = CommFunc.WriteString(data, self.ItemInfoLen, self.ItemInfo)
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                QuickAwardCount:%d,
                                AwardType:%d,
                                AwardSeconds:%d,
                                Exp:%d,
                                ExpPoint:%d,
                                MoneyInfoLen:%d,
                                MoneyInfo:%s,
                                ItemInfoLen:%d,
                                ItemInfo:%s
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.QuickAwardCount,
                                self.AwardType,
                                self.AwardSeconds,
                                self.Exp,
                                self.ExpPoint,
                                self.MoneyInfoLen,
                                self.MoneyInfo,
                                self.ItemInfoLen,
                                self.ItemInfo
                                )
        return DumpString
m_NAtagMCGuajiInfo=tagMCGuajiInfo()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCGuajiInfo.Head.Cmd,m_NAtagMCGuajiInfo.Head.SubCmd))] = m_NAtagMCGuajiInfo
#------------------------------------------------------
# B1 06 通知玩家向目标点移动 #tagMCNotifyPlayerMove
class  tagMCNotifyPlayerMove(Structure):
ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
@@ -405,7 +405,8 @@
    Def_ViewExpType_LYZS,                   #烈焰战神 特殊特效 8
    Def_ViewExpType_Activity,               #活跃吸纳 9
    Def_ViewExpType_Chuangong,              #传功经验10
) = range(0, 11)
    Def_ViewExpType_Guaji,                  #挂机收益11
) = range(0, 12)
#物品相关操作类型
@@ -1191,6 +1192,7 @@
GameFuncID_LianTi = 207         # 炼体
GameFuncID_Championship = 210   # 排位
GameFuncID_MineArea = 227       # 福地
GameFuncID_Guaji = 228          # 挂机
# 以下为暂时无用的
GameFuncID_Truck = 33           # 运镖
GameFuncID_RunDaily = 34        # 日常跑环
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -4340,6 +4340,20 @@
Def_PDictType_TJGNotify_ItemID = "TJGItemID_%s"   #脱机挂指定物品掉落显示
Def_PDictType_TJGOnDayEx = "TJGOnDayEx"   #是否脱机挂中过天(5点)真实登录后重置
# 挂机收益
Def_PDict_GuajiCalcTime = "GuajiCalcTime"   # 上次统计收益时间戳
Def_PDict_GuajiAwardSeconds = "GuajiAwardSeconds"   # 已累计收益时长,秒
Def_PDict_GuajiQuickCount = "GuajiQuickCount"   # 今日已快速收益次数
Def_PDict_GuajiExp = "GuajiExp"   # 经验
Def_PDict_GuajiExpPoint = "GuajiExpPoint"   # 经验超过E部分
Def_PDict_GuajiMoneyType = "GuajiMoneyType_%s" # 获得货币类型,参数(索引)
Def_PDict_GuajiMoneyValue = "GuajiMoneyValue_%s" # 获得货币值,参数(索引)
Def_PDict_GuajiMoneyUnSeconds = "GuajiMoneyUnSeconds_%s" # 计算获得货币值时未处理收益的累计时长,秒,参数(货币类型)
Def_PDict_GuajiItemUnSeconds = "GuajiItemUnSeconds" # 计算获得物品次数时未处理收益的累计时长,秒
Def_PDict_GuajiItemID = "GuajiItemID_%s" # 获得物品ID,参数(索引)
Def_PDict_GuajiItemCount = "GuajiItemCount_%s" # 获得物品个数,参数(索引)
#仙魔之争
Def_PDict_XMZZLastStartTime = "XMZZLastStartTime" #上次开始战斗时间
@@ -5670,7 +5684,8 @@
VIPPrivilege_BossDogzBuy,    #44 神兽boss/蓬莱boss购买次数
VIPPrivilege_45,    #45 魔化之地boss购买次数
VIPPrivilege_46,    #46 情缘副本购买次数
) = range(1, 47)
VIPPrivilege_GuajiQuickBuy,    #47 快速挂机购买次数
) = range(1, 48)
(
@@ -5893,7 +5908,8 @@
Def_RewardType_ActLoginAwardNew, # 领取登录活动奖励70
Def_RewardType_ActTask, # 领取任务活动奖励71
Def_RewardType_ActBuyCountGift, # 领取购买次数礼包活动 72
)= range(73)
Def_RewardType_Guaji, # 领取挂机收益 73
)= range(74)
#boss复活相关活动定义
BossRebornActIDList = (
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -44982,6 +44982,119 @@
#------------------------------------------------------
# B1 09 玩家挂机系统信息 #tagMCGuajiInfo
class  tagMCGuajiInfo(Structure):
    Head = tagHead()
    QuickAwardCount = 0    #(BYTE QuickAwardCount)// 今日已快速挂机收益次数
    AwardType = 0    #(BYTE AwardType)// 收益类型: 0-已累计预览;1-领取结算结果(包含常规领取跟快速领取)
    AwardSeconds = 0    #(DWORD AwardSeconds)// 已累计收益时长,秒
    Exp = 0    #(DWORD Exp)// 已累计经验,求余亿部分
    ExpPoint = 0    #(DWORD ExpPoint)// 已累计经验,整除亿部分
    MoneyInfoLen = 0    #(BYTE MoneyInfoLen)
    MoneyInfo = ""    #(String MoneyInfo)// 已累计货币 [[货币类型, 货币值], ...]
    ItemInfoLen = 0    #(BYTE ItemInfoLen)
    ItemInfo = ""    #(String ItemInfo)// 已累计物品 [[物品ID, 个数], ...]
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xB1
        self.Head.SubCmd = 0x09
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        _pos = self.Head.ReadData(_lpData, _pos)
        self.QuickAwardCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.AwardType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.AwardSeconds,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.Exp,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.ExpPoint,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.MoneyInfoLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.MoneyInfo,_pos = CommFunc.ReadString(_lpData, _pos,self.MoneyInfoLen)
        self.ItemInfoLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.ItemInfo,_pos = CommFunc.ReadString(_lpData, _pos,self.ItemInfoLen)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xB1
        self.Head.SubCmd = 0x09
        self.QuickAwardCount = 0
        self.AwardType = 0
        self.AwardSeconds = 0
        self.Exp = 0
        self.ExpPoint = 0
        self.MoneyInfoLen = 0
        self.MoneyInfo = ""
        self.ItemInfoLen = 0
        self.ItemInfo = ""
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 1
        length += 1
        length += 4
        length += 4
        length += 4
        length += 1
        length += len(self.MoneyInfo)
        length += 1
        length += len(self.ItemInfo)
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteBYTE(data, self.QuickAwardCount)
        data = CommFunc.WriteBYTE(data, self.AwardType)
        data = CommFunc.WriteDWORD(data, self.AwardSeconds)
        data = CommFunc.WriteDWORD(data, self.Exp)
        data = CommFunc.WriteDWORD(data, self.ExpPoint)
        data = CommFunc.WriteBYTE(data, self.MoneyInfoLen)
        data = CommFunc.WriteString(data, self.MoneyInfoLen, self.MoneyInfo)
        data = CommFunc.WriteBYTE(data, self.ItemInfoLen)
        data = CommFunc.WriteString(data, self.ItemInfoLen, self.ItemInfo)
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                QuickAwardCount:%d,
                                AwardType:%d,
                                AwardSeconds:%d,
                                Exp:%d,
                                ExpPoint:%d,
                                MoneyInfoLen:%d,
                                MoneyInfo:%s,
                                ItemInfoLen:%d,
                                ItemInfo:%s
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.QuickAwardCount,
                                self.AwardType,
                                self.AwardSeconds,
                                self.Exp,
                                self.ExpPoint,
                                self.MoneyInfoLen,
                                self.MoneyInfo,
                                self.ItemInfoLen,
                                self.ItemInfo
                                )
        return DumpString
m_NAtagMCGuajiInfo=tagMCGuajiInfo()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCGuajiInfo.Head.Cmd,m_NAtagMCGuajiInfo.Head.SubCmd))] = m_NAtagMCGuajiInfo
#------------------------------------------------------
# B1 06 通知玩家向目标点移动 #tagMCNotifyPlayerMove
class  tagMCNotifyPlayerMove(Structure):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -156,6 +156,7 @@
import PlayerLove
import GameObj
import PlayerChangeJob
import PlayerGuaji
import PlayerMineArea
import PlayerActLoginNew
import PlayerActBuyCountGift
@@ -975,6 +976,7 @@
    PlayerShentong.OnPlayerLogin(curPlayer)
    PlayerZhanling.OnPlayerLogin(curPlayer)
    PlayerMineArea.OnPlayerLogin(curPlayer)
    PlayerGuaji.OnPlayerLogin(curPlayer)
    
    # 上线查询一次充值订单
    curPlayer.SendDBQueryRecharge()
@@ -5584,6 +5586,9 @@
    # 活跃放置奖励
    elif rewardType == ChConfig.Def_RewardType_ActivityPlace:
        PlayerActivity.GetActivityPlaceReward(curPlayer)
    # 挂机奖励
    elif rewardType == ChConfig.Def_RewardType_Guaji:
        PlayerGuaji.OnGetGuajiAward(curPlayer, dataEx)
    # 每日免费直购礼包
    elif rewardType == ChConfig.Def_RewardType_DayFreeGoldGift:
        PlayerDailyGiftbag.OnGetDailyFreeGiftbag(curPlayer)
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameFuncComm.py
@@ -48,6 +48,7 @@
import PlayerLianTi
import PlayerArena
import PlayerFaQi
import PlayerGuaji
import PlayerTJG
@@ -73,6 +74,7 @@
                     ShareDefine.GameFuncID_FaQi:lambda curObj:PlayerFaQi.DoFaQiOpen(curObj),
                     ShareDefine.GameFuncID_LianTi:lambda curObj:PlayerLianTi.DoLianTiOpen(curObj),
                     ShareDefine.GameFuncID_Championship:lambda curObj:PlayerCrossChampionship.DoChampionshipOpen(curObj),
                     ShareDefine.GameFuncID_Guaji:lambda curObj:PlayerGuaji.DoGuajiOpen(curObj),
                     #ShareDefine.GameFuncID_RunDaily:lambda curObj:FBCommon.DoFuncOpen_RunDaily(curObj),
                     #ShareDefine.GameFuncID_RunFamily:lambda curObj:FBCommon.DoFuncOpen_RunFamily(curObj),
                     #ShareDefine.GameFuncID_RefineExp:lambda curObj:Operate_PlayerBuyZhenQi.DoFuncOpen_RefineExp(curObj),
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
@@ -129,6 +129,7 @@
import PlayerArena
import PyGameData
import PlayerTJG
import PlayerGuaji
import PlayerMineArea
import datetime
@@ -602,6 +603,8 @@
        PlayerAssist.DoPlayerOnDay(curPlayer)
        #福地
        PlayerMineArea.PlayerOnDay(curPlayer)
        #挂机
        PlayerGuaji.PlayerOnDay(curPlayer)
        #特殊时间点过天的,一般是游戏功能,此时立即同步一次跨服玩家数据
        CrossPlayerData.SendMergePlayerDataNow(curPlayer)
        
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerGuaji.py
New file
@@ -0,0 +1,394 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
##@package Player.PlayerGuaji
#
# @todo:挂机收益
# @author hxp
# @date 2024-06-12
# @version 1.0
#
# 详细描述: 挂机收益
#
#-------------------------------------------------------------------------------
#"""Version = 2024-06-12 18:00"""
#-------------------------------------------------------------------------------
import ChConfig
import ShareDefine
import PlayerControl
import ChPyNetSendPack
import PlayerWorldAverageLv
import FormulaControl
import NetPackCommon
import IpyGameDataPY
import ItemControler
import GameFuncComm
import GameWorld
import PlayerVip
import time
Def_Process_Seconds = 60 # 在线定时处理间隔,秒,离线上线后一次性处理
def DoGuajiOpen(curPlayer):
    openAwardMinutes = IpyGameDataPY.GetFuncCfg("GuajiTime", 1) # 功能开启获得收益时长,分钟
    AddGuajiAward(curPlayer, openAwardMinutes * 60)
    return
def OnPlayerLogin(curPlayer):
    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Guaji):
        return
    if not ProcessGuaji(curPlayer):
        Sync_GuajiAward(curPlayer)
    return
def PlayerOnDay(curPlayer):
    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Guaji):
        return
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GuajiQuickCount, 0)
    Sync_GuajiAward(curPlayer)
    return
def ProcessGuaji(curPlayer):
    ## 挂机定时处理收益
    if GameWorld.IsCrossServer():
        return
    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Guaji):
        return
    curTime = int(time.time())
    lastCalcTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GuajiCalcTime)
    if not lastCalcTime:
        lastCalcTime = curTime
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GuajiCalcTime, curTime)
    awardSeconds = passSeconds = curTime - lastCalcTime
    if passSeconds <= Def_Process_Seconds:
        # 每满x秒统计一次
        return
    if awardSeconds < Def_Process_Seconds + 10:
        awardSeconds = Def_Process_Seconds
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GuajiCalcTime, lastCalcTime + awardSeconds)
    else:
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GuajiCalcTime, curTime)
    return AddGuajiAward(curPlayer, awardSeconds)
def AddGuajiAward(curPlayer, awardSeconds):
    ## 增加挂机奖励
    if awardSeconds <= 0:
        return
    playerID = curPlayer.GetPlayerID()
    curAwardSeconds = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GuajiAwardSeconds)
    maxSeconds = GetGuajiSecondsMax(curPlayer)
    if curAwardSeconds >= maxSeconds:
        GameWorld.DebugLog("挂机收益时长已达上限: curAwardSeconds=%s >= %s" % (curAwardSeconds, maxSeconds), playerID)
        return
    awardSeconds = min(maxSeconds - curAwardSeconds, awardSeconds)
    if awardSeconds <= 0:
        return
    addExp, giveMoneyDict, giveItemDict = CalcGuajiAward(curPlayer, awardSeconds, False)
    updAwardSeconds = curAwardSeconds + awardSeconds
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GuajiAwardSeconds, updAwardSeconds)
    GameWorld.DebugLog("保存挂机累计收益: curAwardSeconds=%s,updAwardSeconds=%s,maxSeconds=%s" % (curAwardSeconds, updAwardSeconds, maxSeconds), playerID)
    # 经验
    exp = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GuajiExpPoint) * ChConfig.Def_PerPointValue \
        + curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GuajiExp) + addExp
    updExpPoint = exp / ChConfig.Def_PerPointValue
    updExp = exp % ChConfig.Def_PerPointValue
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GuajiExpPoint, updExpPoint)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GuajiExp, updExp)
    GameWorld.DebugLog("    累计经验: %s亿%s" % (updExpPoint, updExp), playerID)
    # 货币
    for moneyType, addValue in giveMoneyDict.items():
        saveNum = GetSaveNum(curPlayer, ChConfig.Def_PDict_GuajiMoneyType, moneyType)
        if saveNum == None:
            continue
        moneyValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GuajiMoneyValue % saveNum)
        updMoney = min(moneyValue + addValue, ChConfig.Def_UpperLimit_DWord)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GuajiMoneyType % saveNum, moneyType)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GuajiMoneyValue % saveNum, updMoney)
        GameWorld.DebugLog("    累计货币: moneyType=%s,updMoney=%s,saveNum=%s" % (moneyType, updMoney, saveNum), playerID)
    # 物品
    for itemID, addCount in giveItemDict.items():
        saveNum = GetSaveNum(curPlayer, ChConfig.Def_PDict_GuajiItemID, itemID)
        if saveNum == None:
            continue
        curCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GuajiItemCount % saveNum)
        updCount = min(curCount + addCount, ChConfig.Def_UpperLimit_DWord)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GuajiItemID % saveNum, itemID)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GuajiItemCount % saveNum, updCount)
        GameWorld.DebugLog("    累计物品: itemID=%s,updCount=%s,saveNum=%s" % (itemID, updCount, saveNum), playerID)
    Sync_GuajiAward(curPlayer)
    return True
def GetSaveNum(curPlayer, key, compValue):
    for num in range(100):
        value = curPlayer.NomalDictGetProperty(key % num)
        if not value or compValue == value:
            # 空值或者命中
            return num
    return
def GetGuajiSecondsMax(curPlayer):
    ## 挂机收益时长上限,秒
    # 初始
    initHours = IpyGameDataPY.GetFuncCfg("GuajiTime", 2) # 初始时长,小时
    # 境界增加
    curRealmLV = curPlayer.GetOfficialRank()
    realmAddHours = 0
    realmAddHoursDict = IpyGameDataPY.GetFuncEvalCfg("GuajiTime", 3, {})
    realmLVList = realmAddHoursDict.keys()
    realmLVList.sort()
    for realmLV in realmLVList:
        if curRealmLV >= realmLV:
            realmAddHours = realmAddHoursDict[realmLV]
        else:
            break
    totalHours = initHours + realmAddHours
    return totalHours * 3600
def GetGuajiAwardInfoSave(curPlayer):
    ## 获取已保存的累计挂机收益信息
    lastCalcTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GuajiCalcTime)
    awardSeconds = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GuajiAwardSeconds)
    if lastCalcTime:
        awardSeconds += max(0, int(time.time() - lastCalcTime))
    awardSeconds = min(awardSeconds, GetGuajiSecondsMax(curPlayer))
    exp = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GuajiExpPoint) * ChConfig.Def_PerPointValue + \
        curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GuajiExp)
    moneyDict = {}
    for num in range(100):
        moneyType = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GuajiMoneyType % num)
        if not moneyType:
            break
        moneyDict[moneyType] = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GuajiMoneyValue % num)
    itemDict = {}
    for num in range(100):
        itemID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GuajiItemID % num)
        if not itemID:
            break
        itemDict[itemID] = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GuajiItemCount % num)
    return awardSeconds, exp, moneyDict, itemDict
def CalcGuajiAward(curPlayer, awardSeconds, isQuick):
    ## 计算挂机收益,只计算收益,不做结算,结算逻辑由外层决定
    playerID = curPlayer.GetPlayerID()
    reLV = curPlayer.GetLV()
    lvIpyData = PlayerControl.GetPlayerLVIpyData(reLV)
    reExp = lvIpyData.GetReExp() if lvIpyData else 0
    worldLV = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_WorldAverageLv)
    GameWorld.DebugLog("计算挂机收益: awardSeconds=%s,isQuick=%s,reLV=%s,reExp=%s,worldLV=%s"
                       % (awardSeconds, isQuick, reLV, reExp, worldLV), playerID)
    # 经验
    expRate = GetGuajiExpRate(curPlayer)
    secondBaseExp = int(eval(FormulaControl.GetCompileFormula("GuajiExp", IpyGameDataPY.GetFuncCfg("GuajiAward", 1))))
    secondExp = int(secondBaseExp * expRate / float(ChConfig.Def_MaxRateValue))
    addExp = awardSeconds * secondExp
    GameWorld.DebugLog("    每秒经验: %s, addExp=%s,secondBaseExp=%s,expRate=%s" % (secondExp, addExp, secondBaseExp, expRate), playerID)
    # 每秒产出货币
    moneyDict = {}
    perSecondMoneyFromulaDict = IpyGameDataPY.GetFuncEvalCfg("GuajiAward", 2, {}) # 每秒获得货币公式 {货币类型:"每秒获得数量公式", ...}
    for moneyType, formula in perSecondMoneyFromulaDict.items():
        secondMoney = int(eval(FormulaControl.GetCompileFormula("GuajiMoney_%s" % moneyType, formula)))
        moneyValue = awardSeconds * secondMoney
        moneyDict[moneyType] = moneyValue
        GameWorld.DebugLog("    每秒货币: moneyType=%s,secondMoney=%s,moneyValue=%s" % (moneyType, secondMoney, moneyValue), playerID)
    # 每x秒产出1货币
    perMoneyTimeFromulaDict = IpyGameDataPY.GetFuncEvalCfg("GuajiAward", 3, {}) # 每x秒获得1个货币公式 {货币类型:"x秒公式", ...}
    for moneyType, formula in perMoneyTimeFromulaDict.items():
        moneyAwardSeconds = awardSeconds
        if not isQuick:
            moneyAwardSeconds += curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GuajiMoneyUnSeconds % moneyType)
        oneMoneyNeedSeconds = int(eval(FormulaControl.GetCompileFormula("GuajiMoney_%s" % moneyType, formula)))
        moneyValue = moneyAwardSeconds / oneMoneyNeedSeconds
        moneyDict[moneyType] = moneyValue
        GameWorld.DebugLog("    每X秒货币: moneyType=%s,oneMoneyNeedSeconds=%s,moneyValue=%s,moneyAwardSeconds=%s"
                           % (moneyType, oneMoneyNeedSeconds, moneyValue, moneyAwardSeconds), playerID)
        if not isQuick:
            unSeconds = moneyAwardSeconds % oneMoneyNeedSeconds
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GuajiMoneyUnSeconds % moneyType, unSeconds)
            GameWorld.DebugLog("        moneyType=%s,unSeconds=%s" % (moneyType, unSeconds), playerID)
    # 物品
    giveItemSecondsSet = IpyGameDataPY.GetFuncCfg("GuajiAward", 4) # 每x秒获得一次随机物品机会
    lvItemRateDict = IpyGameDataPY.GetFuncEvalCfg("GuajiAward", 5, {})
    itemAwardSeconds = awardSeconds
    if not isQuick:
        itemAwardSeconds += curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GuajiItemUnSeconds)
    itemAwardTimes = itemAwardSeconds / giveItemSecondsSet # 给物品次数
    GameWorld.DebugLog("    给物品次数: %s, itemAwardSeconds=%s,giveItemSecondsSet=%s" % (itemAwardTimes, itemAwardSeconds, giveItemSecondsSet), playerID)
    if not isQuick:
        unSeconds = itemAwardSeconds % giveItemSecondsSet
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GuajiItemUnSeconds, unSeconds)
        GameWorld.DebugLog("    给物品未处理秒数=%s" % unSeconds, playerID)
    lvList = lvItemRateDict.keys()
    lvList.sort()
    itemRateList = []
    for lv in lvList:
        if reLV >= lv:
            itemRateList = lvItemRateDict[lv]
        else:
            break
    dropCountTotal = 0
    itemDict = {}
    maxRate = itemRateList[-1][0]
    GameWorld.DebugLog("    itemRateList=%s,maxRate=%s" % (itemRateList, maxRate), playerID)
    if itemAwardTimes > 100: # 超过x次的,先进行批量处理
        preRate = 0
        for rateInfo in itemRateList:
            rate, itemInfo = rateInfo
            curRate = rate - preRate
            preRate = rate
            if curRate <= 0:
                continue
            totalRate = curRate * itemAwardTimes # 总概率
            dropCount = totalRate / maxRate # 可掉落件数
            rateEx = totalRate % maxRate # 剩余概率
            if GameWorld.CanHappen(rateEx, maxRate):
                dropCount += 1
            dropCountTotal += dropCount # 产出是是空物品也要算执行掉落次数
            GameWorld.DebugLog("    挂机物品: itemInfo=%s,curRate=%s,totalRate=%s,rateEx=%s,dropCount=%s,dropCountTotal=%s"
                               % (itemInfo, curRate, totalRate, rateEx, dropCount, dropCountTotal), playerID)
            if not dropCount:
                continue
            if not itemInfo:
                continue
            itemID, itemCount = itemInfo
            itemDict[itemID] = itemDict.get(itemID, 0) + itemCount * dropCount
    awardTimesEx = itemAwardTimes - dropCountTotal
    GameWorld.DebugLog("    awardTimesEx=%s" % awardTimesEx, playerID)
    if awardTimesEx > 0:
        for _ in range(awardTimesEx):
            itemInfo = GameWorld.GetResultByRandomList(itemRateList)
            if not itemInfo:
                continue
            itemID, itemCount = itemInfo
            itemDict[itemID] = itemDict.get(itemID, 0) + itemCount
    GameWorld.DebugLog("    itemDict=%s" % (itemDict), playerID)
    return addExp, moneyDict, itemDict
def GetGuajiExpRate(curPlayer):
    ## 挂机收益经验加成
    expRate = curPlayer.GetFightExpRate() # 系统及功能累加
    expRate += PlayerWorldAverageLv.GetWorldAverageLvExpRate(curPlayer) # 世界等级
    expRate += PlayerVip.GetPrivilegeValue(curPlayer, ChConfig.VIPPrivilege_FightExpRate) # VIP加成
    return expRate
def OnGetGuajiAward(curPlayer, isQuick):
    ## 领取挂机收益
    # @param isQuick: 是否快速收益
    playerID = curPlayer.GetPlayerID()
    GameWorld.DebugLog("领取挂机收益!  isQuick=%s" % isQuick, playerID)
    if isQuick:
        quickCountToday = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GuajiQuickCount)
        quickCountFree = IpyGameDataPY.GetFuncCfg("GuajiQuick", 2)
        vipCanBuyCount = PlayerVip.GetPrivilegeValue(curPlayer, ChConfig.VIPPrivilege_GuajiQuickBuy)
        quickCountMax = quickCountFree + vipCanBuyCount
        if quickCountToday >= quickCountMax:
            GameWorld.DebugLog("快速挂机收益次数已达每日上限!  quickCountToday=%s" % quickCountToday, playerID)
            return
        if quickCountToday >= quickCountFree:
            todayBuyCount = quickCountToday - quickCountFree # 今日已购买次数
            costMoneyType = IpyGameDataPY.GetFuncCfg("GuajiQuick", 3)
            costMoneyList = IpyGameDataPY.GetFuncEvalCfg("GuajiQuick", 4)
            if not costMoneyType or not costMoneyList:
                return
            costMoneyValue = costMoneyList[todayBuyCount] if len(costMoneyList) > todayBuyCount else costMoneyList[-1]
            GameWorld.DebugLog("    todayBuyCount=%s,costMoneyType=%s,costMoneyValue=%s"
                               % (todayBuyCount, costMoneyType, costMoneyValue), playerID)
            if not PlayerControl.PayMoney(curPlayer, costMoneyType, costMoneyValue, "Guaji"):
                return
        awardSeconds = IpyGameDataPY.GetFuncCfg("GuajiQuick", 1) * 3600
        exp, moneyDict, itemDict = CalcGuajiAward(curPlayer, awardSeconds, True)
        quickCountToday += 1
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GuajiQuickCount, quickCountToday)
        GameWorld.DebugLog("    更新快速挂机收益次数: quickCountToday=%s,quickCountMax=%s" % (quickCountToday, quickCountMax), playerID)
    else:
        awardSeconds, exp, moneyDict, itemDict = GetGuajiAwardInfoSave(curPlayer)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GuajiCalcTime, int(time.time())) # 设置统计时间,重新统计
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GuajiAwardSeconds, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GuajiExp, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GuajiExpPoint, 0)
        for num in range(100):
            if not curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GuajiMoneyType % num):
                break
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GuajiMoneyType % num, 0)
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GuajiMoneyValue % num, 0)
        for num in range(100):
            if not curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GuajiItemID % num):
                break
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GuajiItemID % num, 0)
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GuajiItemCount % num, 0)
        Sync_GuajiAward(curPlayer)
    GameWorld.DebugLog("    挂机收益: awardSeconds=%s,exp=%s,moneyDict=%s,itemDict=%s" % (awardSeconds, exp, moneyDict, itemDict), playerID)
    playerControl = PlayerControl.PlayerControl(curPlayer)
    playerControl.AddExp(exp, ShareDefine.Def_ViewExpType_Guaji)
    for moneyType, moneyValue in moneyDict.items():
        PlayerControl.GiveMoney(curPlayer, moneyType, moneyValue, "Guaji")
    giveItemList = [[itemID, itemCount, 0] for itemID, itemCount in itemDict.items()]
    ItemControler.GivePlayerItemOrMail(curPlayer, giveItemList, event=["Guaji", False, {}])
    Sync_GuajiAward(curPlayer, 1, awardSeconds, exp, moneyDict, itemDict)
    return
def Sync_GuajiAward(curPlayer, awardType=0, awardSeconds=0, exp=0, moneyDict=None, itemDict=None):
    ## 同步挂机收益信息
    #  收益类型: 0-已累计预览;1-领取结算结果(包含常规领取跟快速领取)
    if awardType == 0:
        awardSeconds, exp, moneyDict, itemDict = GetGuajiAwardInfoSave(curPlayer)
    clientPack = ChPyNetSendPack.tagMCGuajiInfo()
    clientPack.QuickAwardCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GuajiQuickCount)
    clientPack.AwardType = awardType
    clientPack.AwardSeconds = awardSeconds
    clientPack.Exp = exp % ChConfig.Def_PerPointValue
    clientPack.ExpPoint = exp / ChConfig.Def_PerPointValue
    clientPack.MoneyInfo = str([[moneyType, moneyValue] for moneyType, moneyValue in moneyDict.items()]).replace(" ", "") if moneyDict else "[]"
    clientPack.MoneyInfoLen = len(clientPack.MoneyInfo)
    clientPack.ItemInfo = str([[itemID, itemCount] for itemID, itemCount in itemDict.items()]).replace(" ", "") if itemDict else "[]"
    clientPack.ItemInfoLen = len(clientPack.ItemInfo)
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerState.py
@@ -45,6 +45,7 @@
import time
import PetControl
import ItemControler
import PlayerGuaji
import PlayerTJG
import AICommon
import PlayerSuccess
@@ -1267,6 +1268,8 @@
    
    #脱机计算
    PlayerTJG.ProcessPlayerTJG(curPlayer, tick)
    #挂机收益
    PlayerGuaji.ProcessGuaji(curPlayer)
    
    #PK/boss״̬
    ProcessPKBossState(curPlayer, tick)
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -405,7 +405,8 @@
    Def_ViewExpType_LYZS,                   #烈焰战神 特殊特效 8
    Def_ViewExpType_Activity,               #活跃吸纳 9
    Def_ViewExpType_Chuangong,              #传功经验10
) = range(0, 11)
    Def_ViewExpType_Guaji,                  #挂机收益11
) = range(0, 12)
#物品相关操作类型
@@ -1191,6 +1192,7 @@
GameFuncID_LianTi = 207         # 炼体
GameFuncID_Championship = 210   # 排位
GameFuncID_MineArea = 227       # 福地
GameFuncID_Guaji = 228          # 挂机
# 以下为暂时无用的
GameFuncID_Truck = 33           # 运镖
GameFuncID_RunDaily = 34        # 日常跑环