hxp
2025-12-05 c80c8718c507a7e52f065eee9e35bb4f27573f48
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -16,7 +16,6 @@
import GameWorld
import SkillShell
import ChConfig
import PlayerHorse
import SkillCommon
import GameMap
import FBLogic
@@ -45,21 +44,20 @@
import GameFuncComm
import IpyGameDataPY
import PyGameData
import PlayerFeastTravel
import PlayerActTurntable
import PlayerCostRebate
import PlayerActLunhuidian
import GY_Query_CrossRealmReg
import FunctionNPCCommon
import PlayerGoldInvest
import OpenServerActivity
import CrossRealmPlayer
import CrossPlayerData
import PlayerActivity
import ChNetSendPack
import PlayerState
import PlayerOnline
import PlayerTask
import PlayerMail
import PlayerLLMJ
import TurnAttack
import ChPlayer
import GameObj
@@ -415,24 +413,6 @@
        return False
    
    return True
##地图特殊限制检查, 装备检查
# @param curPlayer
# @return bool
def CheckEquipCanTrans(curPlayer, destMapID):
    if destMapID != 10060:
        return True
    #有翅膀可以上天空
    playerEquip = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptEquip)
    curEquip = playerEquip.GetAt(IPY_GameWorld.retWing)
    if curEquip and not curEquip.IsEmpty():
        return True
    #GeRen_lhs_861048
    NotifyCode(curPlayer, "GeRen_lhs_861048", [destMapID])
    return False
#---------------------------------------------------------------------
##通知客户端, 玩家Loading开始
@@ -932,19 +912,6 @@
    return (curPlayerAction in ChConfig.Def_Player_Can_Transfer_State)
#------------------------------玩家离开服务器的逻辑------------------------------------
#---------------------------------------------------------------------
##骑马下线逻辑
# @param curPlayer 玩家实例
# @return 返回值无意义
# @remarks 骑马下线逻辑
def __RidingHorsePlayerDisconnect(curPlayer):
    #在骑马
    if curPlayer.GetPlayerVehicle() == IPY_GameWorld.pvHorse:
        #执行下马逻辑
        PlayerHorse.PlayerRideHorseDown(curPlayer, False)
    return
#---------------------------------------------------------------------
##玩家下线/玩家切换地图公用逻辑
# @param curPlayer 玩家实例
# @param tick 时间戳
@@ -1111,8 +1078,6 @@
    
    #玩家下线/玩家切换地图公用逻辑
    __PlayerLeaveServerLogic(curPlayer, tick, True)
    #骑马玩家下线逻辑
    __RidingHorsePlayerDisconnect(curPlayer)
    #召唤兽死亡
    KillPlayerSummonNPC(curPlayer)
    #更新从本地图离线信息
@@ -2484,17 +2449,12 @@
    return
def GetUnXiantaoCntEquip(curPlayer):
    '''因为战锤对应装备是1个战锤可能对应多个装备掉落,所以分解装备的时候1个战锤需要支持可拆分
    所以需要支持小数存储,暂定以支持3位小数存储
    '''
    return curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UnXiantaoCntEquip) / 1000.0
    return curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UnXiantaoCntEquip)
def AddUnXiantaoCntEquip(curPlayer, addCnt):
    unXiantaoCntEquip = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UnXiantaoCntEquip) + addCnt * 1000
    unXiantaoCntEquip = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UnXiantaoCntEquip) + addCnt
    return NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_UnXiantaoCntEquip, unXiantaoCntEquip)
def SetUnXiantaoCntEquip(curPlayer, unXiantaoCntEquip):
    ## 保存装备未结算战锤数,保留3位小数
    # @param unXiantaoCntEquip: 实际的未结算数量,支持小数
    unXiantaoCntEquip = int(round(unXiantaoCntEquip, 3) * 1000) # 保留3为小数
    ## 保存装备未结算战锤数
    return NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_UnXiantaoCntEquip, unXiantaoCntEquip)
##玩家是否有钱款
@@ -2799,10 +2759,7 @@
                unXiantaoCntBooty = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UnXiantaoCntBooty % itemID)
                NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_UnXiantaoCntBooty % itemID, unXiantaoCntBooty + price)
                
        PlayerLLMJ.AddUseZhanchui(curPlayer, price)
        PlayerPrestigeSys.AddRealmTaskValue(curPlayer, PlayerPrestigeSys.RealmTaskType_UseXiantao, price)
        PlayerTask.AddTaskValue(curPlayer, ChConfig.TaskType_CutTree, price)
        TurnAttack.GetMainFightMgr(curPlayer).useZhanchui += price
        
    unitPrice = price if quantity == 1 else int(math.ceil(price * 1.0 / quantity)) # 单价
    #reason_name = "Unknown" if not costType else costType
@@ -2882,7 +2839,6 @@
    # 消费返利
    if costType not in ChConfig.CostRebate_DisableType:
        PlayerCostRebate.AddCostRebateGold(curPlayer, costType, price, infoDict)
        PlayerFeastTravel.AddFeastTravelTaskValue(curPlayer, ChConfig.Def_FeastTravel_UseGold, price)
    else:
        GameWorld.DebugLog("不计入消费活动的消费类型!costType=%s" % costType, curPlayer.GetPlayerID())
        
@@ -2990,8 +2946,9 @@
            return
        SetMoney(curPlayer, priceType, updPlayerGold)
        
        if isGiveBourseMoney and updPlayerGold > 0:
            GiveMoney(curPlayer, ShareDefine.TYPE_Price_BourseMoney, min(value, updPlayerGold))
        #废弃交易所额度
        #if isGiveBourseMoney and updPlayerGold > 0:
        #    GiveMoney(curPlayer, ShareDefine.TYPE_Price_BourseMoney, min(value, updPlayerGold))
        addDataDict["BourseMoney"] = GetMoney(curPlayer, ShareDefine.TYPE_Price_BourseMoney)
        
    elif priceType == IPY_GameWorld.TYPE_Price_Gold_Paper:
@@ -3060,9 +3017,13 @@
    # 除钻石及绑钻外,未指定操作类型的不记录
    
    PlayerTask.AddTaskValue(curPlayer, ChConfig.TaskType_GetMoney, value, [priceType])
    PlayerActivity.AddDailyTaskValue(curPlayer, ChConfig.DailyTask_GetMoney, value, [priceType])
    PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_OSAGetMoney, value, [priceType])
    
    if priceType == ShareDefine.TYPE_Price_FamilyCoin:
        PlayerFamily.AddFamilyContrib(curPlayer, value) # 公会币同步增加公会贡献
    elif priceType == ShareDefine.TYPE_Price_OSAPoint:
        OpenServerActivity.AddOSACelebrationPoint(curPlayer, value)
        
    if priceType not in [IPY_GameWorld.TYPE_Price_Gold_Money, IPY_GameWorld.TYPE_Price_Gold_Paper, ShareDefine.TYPE_Price_PayCoin] \
        and giveType == ChConfig.Def_GiveMoney_Unknown:
@@ -3525,11 +3486,6 @@
            #if curPlayer.GetMaxMP() > 0:
            #    curPlayer.SetMP(curPlayer.GetMaxMP())
            
            # 记录开服活动冲级数据
            #OpenServerCampaign.UpdOpenServerCampaignRecordData(curPlayer, ShareDefine.Def_Campaign_Type_LV, curPlayer.GetLV())
            #神秘限购
            FunctionNPCCommon.MysticalLimitShopOpen(curPlayer, befLV, aftLV)
        #不需要做升级任务, 设置玩家经验
        SetPlayerTotalExp(curPlayer, curTotalExp) 
        return
@@ -4072,14 +4028,6 @@
    
    if curPlayerAction == IPY_GameWorld.paPreparing:
        DoExitPreparing(curPlayer)
    #---玩家交通工具处理---
    curPlayerVehicle = curPlayer.GetPlayerVehicle()
    #玩家骑马中, 下马
    if curPlayerVehicle == IPY_GameWorld.pvHorse:
        #执行下马逻辑
        PlayerHorse.PlayerRideHorseDown(curPlayer, False)
        
    #---其他系统处理---
    
@@ -4190,7 +4138,6 @@
def Sync_ExpRateChange(curPlayer):
    totalExpRate = GetPlayerExpRate(curPlayer)
    fightExpRate = curPlayer.GetFightExpRate() # 系统及功能累加
    fightExpRate += PlayerGoldInvest.GetAddFightExpRate(curPlayer)
    
    actExpRateInfo = PyGameData.g_operationActionDict.get(ShareDefine.OperationActionName_ExpRate, {})# 多倍经验活动加成
    if actExpRateInfo.get(ShareDefine.ActKey_State):
@@ -4245,6 +4192,15 @@
                totalExpRate -= effExpRate
                
    return totalExpRate
##外观额外数据:  其他 * 1000 + 坐骑外观
def GetHorseSkinID(curPlayer): return GameWorld.GetValue(curPlayer.GetEquipShowSwitch(), 3, 3)
def SetHorseSkinID(curPlayer, horseSkinID):
    showValue = curPlayer.GetEquipShowSwitch()
    updShowValue = GameWorld.SetValue(showValue, 3, 3, min(horseSkinID, 999))
    curPlayer.SetEquipShowSwitch(updShowValue)
    GameWorld.DebugLog("使用坐骑外观: horseSkinID=%s,showValue=%s,updShowValue=%s" % (horseSkinID, showValue, updShowValue))
    return
#===============================================================================
#---玩家扩展字段---
@@ -4341,14 +4297,31 @@
def IsMainLevelPass(curPlayer, lvID):
    ## 判断玩家是否过关某个主线关卡ID
    # @param lvID: 关卡唯一ID,与策划约定好 = 章节*100+关卡编号
    passChapterID, passLevelNum, _ = GetMainLevelPassInfo(curPlayer)
    passValue = passChapterID * 100 + passLevelNum # 因为pass的记录是带波数的,即当前关卡boss还没过关,所以只有大于该记录值的才算过关
    return passValue > lvID
    return GetPassMainLevelID(curPlayer) >= lvID
def GetPassMainLevelID(curPlayer):
    ## 获取已过关主线关卡ID
    passChapterID, passLevelNum, _ = GetMainLevelPassInfo(curPlayer) # 当前过关进度包含波,所以需要取上一关的
    passLVID = 0 # 关卡唯一ID,与策划约定好 = 章节*100+关卡编号
    if passLevelNum > 1:
        preLevelNum = passLevelNum - 1
        passLVID = passChapterID * 100 + preLevelNum
        GameWorld.DebugLog("非某章节的第1关直接减1即可: passLVID=%s,passChapterID=%s,passLevelNum=%s" % (passLVID, passChapterID, passLevelNum))
    elif passChapterID > 1: # 取上一章节
        preChapterID = passChapterID - 1
        levelDataList = IpyGameDataPY.GetIpyGameDataByCondition("MainLevel", {"ChapterID":preChapterID}, True)
        levelCount = len(levelDataList) if levelDataList else 0
        if levelCount:
            passLVID = preChapterID * 100 + levelCount
        GameWorld.DebugLog("取上一章节作为已过关关卡: passLVID=%s,preChapterID=%s,levelCount=%s,passChapterID=%s,passLevelNum=%s"
                           % (passLVID, preChapterID, levelCount, passChapterID, passLevelNum))
    return passLVID
## 主线关卡过关进度值 = 章节*10000+关卡编号*100+第x波
def GetMainLevelPassValue(curPlayer): return curPlayer.GetExAttr1()
def SetMainLevelPassValue(curPlayer, value): curPlayer.SetExAttr1(value, False, False) # 不通知GameServer
def SetMainLevelPassValue(curPlayer, value):
    curPlayer.SetExAttr1(value, False, False) # 不通知GameServer
    GameFuncComm.DoFuncOpenLogic(curPlayer)
def SetMainLevelPassInfo(curPlayer, chapterID, levelNum, wave=0):
    ## 设置主线关卡过关进度
    # @param chapterID: 章节ID
@@ -4357,10 +4330,13 @@
    value = ComMainLevelValue(chapterID, levelNum, wave)
    SetMainLevelPassValue(curPlayer, value)
    if wave == 0:
        lvID = chapterID * 100 + levelNum
        lvID = GetPassMainLevelID(curPlayer)
        PlayerBillboard.UpdatePlayerBillboard(curPlayer, ShareDefine.Def_BT_MainLevel, lvID)
        PlayerTask.UpdTaskValue(curPlayer, ChConfig.TaskType_MainLevel)
        PlayerSuccess.UptateSuccessProgress(curPlayer, ShareDefine.SuccType_MainLevel, lvID)
        PlayerSuccess.UptateSuccessProgress(curPlayer, ShareDefine.SuccType_OSAMainLevel, lvID)
        if OpenServerActivity.GetOSAState(curPlayer, ShareDefine.Def_BT_OSA_MainLevel) == 1:
            PlayerBillboard.UpdatePlayerBillboard(curPlayer, ShareDefine.Def_BT_OSA_MainLevel, lvID)
    return value
def GetMainLevelPassInfo(curPlayer):
    ## 获取主线关卡过关进度信息
@@ -4539,19 +4515,10 @@
def SetFightPower(curPlayer, value):
    beforeFightPower = GetFightPower(curPlayer)
    curPlayer.SetFightPower(value % ChConfig.Def_PerPointValue, value / ChConfig.Def_PerPointValue, False) # 不通知GameServer bNotifyGameServer False
    if value < beforeFightPower:
        DataRecordPack.DR_FightPowerChangeInfo(curPlayer, beforeFightPower)
    highestFightPower = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FightPower_Highest)
    highestFightPower += curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FightPower_HighestEx) * ChConfig.Def_PerPointValue
    if value > highestFightPower:
        highestFightPower = value
        NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FightPower_Highest, highestFightPower % ChConfig.Def_PerPointValue)
        NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FightPower_HighestEx, highestFightPower / ChConfig.Def_PerPointValue)
    GameWorld.DebugLog("总战力: %s, 历史最高战力: %s, beforeFightPower=%s" % (value, highestFightPower, beforeFightPower), curPlayer.GetPlayerID())
    #if value < beforeFightPower:
    #    DataRecordPack.DR_FightPowerChangeInfo(curPlayer, beforeFightPower)
    GameWorld.DebugLog("总战力: %s, beforeFightPower=%s" % (value, beforeFightPower), curPlayer.GetPlayerID())
    #PlayerBillboard.UpdatePlayerFPTotalBillboard(curPlayer)
    # 记录开服活动数据
    #OpenServerCampaign.UpdOpenServerCampaignRecordData(curPlayer, ShareDefine.Def_Campaign_Type_FightPower, totalFightPower)
    #if beforeFightPower != totalFightPower:
    #    CrossPlayerData.OnPlayerFightPowerChange(curPlayer)
    return
@@ -4586,14 +4553,14 @@
# @return 无意义
def SetSight(curPlayer, sight):
    #外挂号 视野验证
    if curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_AutoCheckHack_State) \
                                      == ChConfig.Def_AutoCheck_State_Danger:
        if curPlayer.GetSight() > sight:
            curPlayer.SetSight(sight)
        return
#    if curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_AutoCheckHack_State) \
#                                      == ChConfig.Def_AutoCheck_State_Danger:
#
#        if curPlayer.GetSight() > sight:
#            curPlayer.SetSight(sight)
#
#        return
#
    curPlayer.SetSight(sight)
##获取攻击间隔
@@ -4603,9 +4570,9 @@
    atkInterval = curPlayer.GetAtkInterval()
    
    #外挂号 攻击间隔验证
    if curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_AutoCheckHack_State) \
                                      == ChConfig.Def_AutoCheck_State_Danger:
        atkInterval *= 100
    #if curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_AutoCheckHack_State) \
    #                                  == ChConfig.Def_AutoCheck_State_Danger:
    #    atkInterval *= 100
    
    return atkInterval
@@ -4899,7 +4866,7 @@
## 设置玩家字典值, 存库
def NomalDictSetProperty(curPlayer, key, value, dType=0):
    if CrossPlayerData.IsNeedProcessCrossPlayer(curPlayer) and key not in \
        [ChConfig.Def_PDict_FightPower_Total, ChConfig.Def_PDict_FightPower_TotalEx, ChConfig.Def_PlayerKey_CrossRegisterMap]:
        [ChConfig.Def_PlayerKey_CrossRegisterMap]:
        playerID = curPlayer.GetPlayerID()
        changeDict = PyGameData.g_crossPlayerDictChangeInfo.get(playerID, {})
        changeDict[(key, dType)] = value