hxp
6 天以前 26958aff1b844a743a805b4f9075bee800b72a46
332 【主界面】座骑系统-服务端
30个文件已修改
6个文件已删除
3883 ■■■■ 已修改文件
PySysDB/PySysDBPY.h 79 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script.ini 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py 63 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py 548 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py 665 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBStruct.py 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBPlayerViewCache.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DataRecordPack.py 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/EventReport.py 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/ClearFightPowerHistor.py 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Horse.py 186 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/imba.py 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py 203 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChEquip.py 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/OperControlManager.py 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossPlayerData.py 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameFuncComm.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py 48 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHorse.py 1423 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerPet.py 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerState.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCache.py 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/Collections/DataServerPlayerData.py 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameBuffs/Buff_510.py 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameBuffs/Buff_511.py 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameBuffs/Buff_521.py 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveBuff/PassiveBuff_4511.py 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveBuffEffMng.py 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/SkillShell.py 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnSkill.py 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PySysDB/PySysDBPY.h
@@ -863,68 +863,35 @@
    DWORD        UpEatItemPerCount;    //每次培养消耗x个
};
//坐骑升级表
//坐骑阶级表
struct tagHorseLVUp
struct HorseClass
{
    BYTE        _HorseLV;    //坐骑等级
    DWORD        HorseSkinID;    //外观物品ID
    WORD        NeedEatCount;    //升级所需个数(非累计)
    list        LVAttrType;    //每级额外属性类型(非累积)
    list        LVAttrValue;    //每级额外属性值(非累积)
    list        UpItemAttrType;    //每x个培养丹增加属性类型,x=UpEatItemPerCount
    list        UpItemAttrValue;    //每x个培养丹增加属性值,x=UpEatItemPerCount
    DWORD        UpEatItemPerCount;    //每次培养消耗x个
    BYTE        _ClassLV;    //阶级
    WORD        MaxHorseLV;    //最高等级
    WORD        LVUPItemCnt;    //升级道具数
    WORD        ClassUPItemCnt;    //进阶道具数
    list        ClassSpecAttrIDList;    //本阶特殊属性ID列表
    list        ClassSpecAttrValueList;    //本阶特殊属性值列表
    list        AttrIDList;    //基础属性ID列表
    list        ClassAttrValueList;    //本阶基础属性值列表
    list        PerLVAttrValueList;    //本阶每级基础属性值列表
};
//坐骑培养表
//坐骑外观表
struct tagHorseTrain
struct    HorseSkin
{
    BYTE        _TrainType;    //培养类型
    BYTE        _TrainLV;    //培养等阶
    WORD        NeedRealmLV;    //培养所需境界
    DWORD        EatCntTotal;    //升阶所需个数(非累计)
    DWORD        EatCntEverytime;    //每次培养消耗x个
    list        EatItemAttrTypeList;    //每X个培养丹增加属性类型=EatCntEverytime
    list        EatItemAttrValueList;    //每X个培养丹增加属性值=EatCntEverytime
    list        LVAttrTypeList;    //每级额外属性类(非累积)
    list        LVAttrValueList;    //每级额外属性值(非累积)
};
//坐骑幻化表
struct tagHorseSkinPlus
{
    BYTE        _ID;    //幻化编号ID
    DWORD        HorseSkinPlusID;    //外观物品ID
    DWORD        UnlockItemID;    //解锁坐骑物品编号
    BYTE        UnlockItemCnt;    //解锁所需物品数量
    list        AttrType;    //激活加成属性类型
    list        AttrValue;    //激活加成属性值
    DWORD        InitFightPower;    //皮肤额外战力
    DWORD        HorseID;    //对应坐骑ID
    DWORD        SkinValidTime;    //有效时长秒
};
//坐骑表
struct tagHorse
{
    DWORD        _HorseID;    //坐骑ID
    DWORD        HorseSkinID;    //外观物品ID
    BYTE        Quality;    //坐骑品质
};
//坐骑升星表
struct tagHorseStarUp
{
    DWORD        _HorseID;    //坐骑ID
    BYTE        _HorseStar;    //坐骑星级
    list        StarUpNeedItemList;    //升下一星所需道具 [[物品ID,个数], ...]
    list        StarAttrType;    //累计总属性类型
    list        StarAttrValue;    //累计总属性值
    DWORD        _SkinID;    //外观ID
    DWORD        ExpireMinutes;    //时效分钟,0永久
    BYTE        UnlockWay;    //解锁方式
    DWORD        UnlockValue;    //解锁方式值
    BYTE        UnlockNeedCnt;    //解锁所需个数
    BYTE        UpNeedCnt;    //升级所需个数
    BYTE        StarMax;    //最高星级
    list        AttrIDList;    //属性ID列表
    list        InitAttrValueList;    //初始属性值列表
    list        AttrPerStarAddList;    //每星加成值列表
};
//古宝表
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
@@ -101,38 +101,22 @@
;坐骑培养
[PlayerHorse]
ScriptName = Player\PlayerHorse.py
Writer = wdb
Releaser = wdb
Writer = hxp
Releaser = hxp
RegType = 0
RegisterPackCount = 7
RegisterPackCount = 3
PacketCMD_1=0xA5
PacketCMD_1=0xB2
PacketSubCMD_1=0x01
PacketCallFunc_1=ActivateHorseSkinItem
PacketCallFunc_1=OnHorseLVUP
PacketCMD_2=0xA5
PacketCMD_2=0xB2
PacketSubCMD_2=0x02
PacketCallFunc_2=OnPlayerChangeHorse
PacketCallFunc_2=OnHorseClassUP
PacketCMD_3=0xA5
PacketSubCMD_3=0x27
PacketCallFunc_3=OnHorseClassLVUP
PacketCMD_4=0xA5
PacketSubCMD_4=0x29
PacketCallFunc_4=OnHorsePetAwake
PacketCMD_5=0xA5
PacketSubCMD_5=0x30
PacketCallFunc_5=OnHorsePetSkinSelect
PacketCMD_6=0xA5
PacketSubCMD_6=0x31
PacketCallFunc_6=OnHorseTrain
PacketCMD_7=0xA5
PacketSubCMD_7=0x35
PacketCallFunc_7=OnHorseStarUp
PacketCMD_3=0xB2
PacketSubCMD_3=0x03
PacketCallFunc_3=OnHorseSkinOP
;npc交互
[FunctionNPCCommon]
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script.ini
@@ -481,19 +481,6 @@
PacketSubCMD_4=0xE
PacketCallFunc_4=ClearRecycle
;骑马
[Horse]
ScriptName = Player\PlayerHorse.py
Writer = eggxp
Releaser = eggxp
RegType = 0
RegisterPackCount = 1
PacketCMD_1=0x3
PacketSubCMD_1=0x9
PacketCallFunc_1=OnRideHorse
;家族争霸赛
[PlayerFamilyBattle]
ScriptName = Player\PlayerFamilyBattle.py
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -166,7 +166,9 @@
AttrID_PursueDamPerDef,                     # 追击减伤 68
AttrID_ComboDamPer,                         # 连击增伤 69
AttrID_ComboDamPerDef,                      # 连击减伤 70
) = range(1, 1 + 70)
AttrID_ArenaDamPer,                         # 竞技增伤 71
AttrID_ArenaDamPerDef,                      # 竞技减伤 72
) = range(1, 1 + 72)
# 需要计算的武将战斗属性ID列表
CalcBattleAttrIDList = [AttrID_Atk, AttrID_Def, AttrID_MaxHP, AttrID_StunRate, AttrID_StunRateDef, 
@@ -180,7 +182,7 @@
                        AttrID_WeiFinalDamPer, AttrID_WeiFinalDamPerDef, AttrID_ShuFinalDamPer, AttrID_ShuFinalDamPerDef,
                        AttrID_WuFinalDamPer, AttrID_WuFinalDamPerDef, AttrID_QunFinalDamPer, AttrID_QunFinalDamPerDef,
                        AttrID_SkillPer, AttrID_SkillPerDef, AttrID_PursueDamPer, AttrID_PursueDamPerDef,
                        AttrID_ComboDamPer, AttrID_ComboDamPerDef, AttrID_XPRecoverPer,
                        AttrID_ComboDamPer, AttrID_ComboDamPerDef, AttrID_XPRecoverPer, AttrID_ArenaDamPer, AttrID_ArenaDamPerDef
                        ]
# 基础三维属性ID列表
@@ -216,7 +218,8 @@
Def_CalcAttr_Realm, # 官职 3
Def_CalcAttr_Gubao, # 古宝 4
Def_CalcAttr_HJG, # 幻境阁 5
) = range(6)
Def_CalcAttr_Horse, # 坐骑 6
) = range(7)
CalcAttrName = {
                Def_CalcAttr_LV:"主公等级",
@@ -225,6 +228,7 @@
                Def_CalcAttr_Realm:"官职",
                Def_CalcAttr_Gubao:"古宝",
                Def_CalcAttr_HJG:"幻境阁",
                Def_CalcAttr_Horse:"坐骑",
                }
##-----------------------------------------------------------------------------------------------
@@ -508,9 +512,6 @@
Def_ItemType_MissionItem = 17      #任务物品
Def_ItemType_TransMissionItem = 18      #转职任务物品
Def_ItemType_RealmStuff = 19      #头衔(境界)升级道具
Def_ItemType_HorseStuff = 21      #坐骑丹
Def_ItemType_HorseSoul = 22      #坐骑兽魂
Def_ItemType_HorseBook = 23      #坐骑技能书
Def_ItemType_Mine = 24      #矿藏资源
Def_ItemType_Stone = 25            #宝石
Def_ItemType_PetItem = 26         #灵宠碎片(宠物)
@@ -580,9 +581,6 @@
Def_ItemType_CanUseByCDTime = 145 # 创建后根据CDTime到后可开启
Def_ItemType_Hero = 150 # 武将英雄
#以下定义物品类型下次删除
Def_Item_Type_Horse = 1000036          #坐骑
#虚拟背包最大格子数 功能配置表对应的key
Def_VPackCnt_Dict = {
@@ -660,7 +658,7 @@
Def_Effect_ItemGiveWeekPartyPoint1 = 246      #使用道具给予节日巡礼积分
Def_Effect_AddRealmExpRate = 251 #增加聚灵效率
Def_Effect_TouchMission = 252 #触发任务
Def_Effect_HorsePetSkinExp = 253 #骑宠觉醒值
#253 #骑宠觉醒值
Def_Effect_ItemGiveTreasureScore = 254      #使用道具给予寻宝积分
Def_Effect_VIPLVCard = 256    #VIP等级直升卡 直接升到VIPx级,只加经验,享受VIP特权    效果值A: vip等级    效果值B: 领取是否默认直接使用
Def_Effect_AddArenaBattleCount = 257    #增加竞技场挑战次数,A值为增加次数
@@ -761,8 +759,6 @@
Def_Effect_Add_FreePoint_3 = 1185
#鱼竿
Def_Item_Effect_FishTool = 2000
#坐骑进阶
Def_Item_Eff_HorseUpdate = 2819
#官爵进阶
Def_Item_Eff_OfficialRankUpdate = 2820
#物品使用阶级
@@ -934,7 +930,6 @@
Def_SkillID_TianxuanBuff = 5100   # 天玄丹特殊掉落buff
Def_SkillID_PetSignDay = 47111   # 灵宠签到属性技能, 单次签到的加成
Def_SkillID_LFZ = 47100   # 龙凤镯技能(打怪概率经验加成)
Def_SkillID_HorsePetRobBossKillCntBuff = 21020   # 骑宠的怨念buff
Def_SkillID_RealmBuff = 6100   # 境界经验buff
Def_SkillID_LXHY_AddExpRate = 47113 # 流星火雨杀死的怪增加经验
@@ -1745,8 +1740,6 @@
#---------------------进度条------------------------
#挖宝进度条时间为5秒
Def_DigMaxTime = 5000
#上马进度条时间为0秒
Def_RidehorseTime = 1
#回城卷进度条时间为10秒
#Def_TownPortalTime = 10000
#捕捉宠物进度条时间为60秒
@@ -3110,7 +3103,6 @@
Def_PlayerKey_Frist_Lock = "Frist_Lock"  # 是否接受了任务1
Def_PlayerKey_TaskExpRewardMultiple = "TaskExpRewardMultiple"  # 任务经验奖励倍值
Def_PlayerKey_BuyItemCnt = "BuyItemCnt"  # 购买物品数量
Def_PlayerKey_SpeedHorse = "SpeedHorse"  # 骑乘时附加移动速度值
Def_PlayerKey_QueryOpenServerAwardState = "QueryOpenServerAwardState"  # 查询开服奖励状态
Def_PlayerKey_QueryMarkIdCardIndex = 'QueryMarkIdCardIndex'  # 指定账号生成卡类型
@@ -3172,22 +3164,14 @@
(
Def_PDictType_Default,  # 默认
Def_PDictType_FlashSale, #限时抢购
Def_PDictType_TJGNotify,  # 脱机挂结果通知
Def_PDictType_LVAward,  # 等级奖励领取信息记录
Def_PDictType_4,  # 开服活动
Def_PDictType_WeekParty, #周狂欢
Def_PDictType_FeastWeekParty,    # 节日巡礼
Def_PDictType_LoginAward,    # 登录奖励运营活动
Def_PDictType_Horse,    # 坐骑
Def_PDictType_FB,    # 副本相关
Def_PDictType_FightPower,    # 战斗力
Def_PDictType_GoldInvest,    # 投资理财
Def_PDictType_Success,   #成就
Def_PDictType_GFPassive, # 被动功法
Def_PDictType_GreatMaster, # 大师
Def_PDictType_FlashSaleMix, #限时抢购 合服
Def_PDictType_FlashSaleFeast, #限时抢购 节日
) = range(17)
) = range(9)
# 玩家字典key定义规则, key的长度不能超过29个字节, 注意尽量避免命名重复
# 新增参数TYPE 用于字典分类,默认0
@@ -3711,17 +3695,12 @@
Def_PDict_LianTiEatItemCount = "LianTiEatItemCount"  # 当前级已吃丹个数
# 坐骑
Def_PDict_HorserLV = "HorserLV"  # 坐骑等级
Def_PDict_HorserStar = "HorserStar_%s"  # 坐骑星级,参数(坐骑ID)
Def_PDict_HorserEatItemCount = "HorserEatItemCount"  # 当前阶已吃培养丹个数
Def_PDict_HorserSkinPlusState = "HorserSkinPlusState%s"  # 坐骑幻化皮肤激活状态,按二进制位存储,每位代表幻化ID是否已激活,支持多值
Def_PDict_HorserSkinEndTime = "HorserSkinEndTime_%s"  # 坐骑幻化皮肤激活结束时间戳,仅针对非永久的幻化皮肤
Def_PDict_HorserTrainLV = "HorserTrainLV_%s"  # 坐骑培养等阶,参数(培养类型)
Def_PDict_HorserTrainItemCount = "HorserTrainItemCount_%s"  # 坐骑培养当前阶已吃培养丹个数,参数(培养类型)
#骑宠觉醒
Def_PDict_HorsePetSkinData = "HorsePetSkinData%d_%s"  #觉醒等级*100+外观索引  参数(类型,关联ID) 1-坐骑 2-灵宠
Def_PDict_HorsePetSkinExp = "HorsePetSkinExp%d_%s"  #经验  参数(类型,关联ID) 1-坐骑 2-灵宠
Def_PDict_HorseClassLV = "HorseClassLV"  # 坐骑阶级
Def_PDict_HorseLV = "HorseLV"  # 坐骑阶等级
Def_PDict_HorseExp = "HorseExp"  # 坐骑阶等级经验
Def_PDict_HorseSkinState = "HorseSkinState_%s"  # 坐骑外观状态,参数(key编号)
Def_PDict_HorseSkinEndTime = "HorseSkinEndTime_%s"  # 坐骑外观到期时间戳,0为永久,参数(外观ID)
Def_PDict_HorseSkinStar = "HorseSkinStar_%s"  # 坐骑外观星级,参数(外观ID)
# 符印
Def_PDict_Rune_HoleOpenState = "Rune_HoleOpenState"  # 符印解锁状态
@@ -3730,14 +3709,6 @@
# 副本 Def_PDictType_FB
Def_PDict_LastEnterFBPropertyID = "LastEnterFBPropertyID_%s"  # 上次进入副本的propertyID%s副本id
Def_PDict_LastEnterFBTick = "LastEnterFBTick_%s"  # 上次进入副本的时间%s副本id
# 战斗力 Def_PDictType_FightPower
Def_PDict_FightPower_Highest = "FightPower_Highest"  # 历史最高总战斗力
Def_PDict_FightPower_HighestEx = "FightPower_HighestEx"  # 历史最高总战斗力
Def_PDict_FightPower_Total = "FightPower_Total"  # 总战斗力
Def_PDict_FightPower_TotalEx = "FightPower_TotalEx"  # 总战斗力
Def_PDict_FightPower_List = [Def_PDict_FightPower_Total, Def_PDict_FightPower_TotalEx]
# 投资理财
Def_PDict_InvestTime = "InvestTime_%s"  # 投资时的时间,参数为投资类型
@@ -4981,14 +4952,14 @@
Def_WPAct_CrossPK, #跨服pk 11
Def_WPAct_Recharge, #充值X仙玉 12
Def_WPAct_GiftBag,  #购买限时礼包 13
Def_WPAct_HorsePetBoss, #骑宠争夺 14
Def_WPAct_14, #骑宠争夺 14
Def_WPAct_SWRH, #守卫人皇 15
Def_WPAct_ElderBattlefield, #上古战场 16
Def_WPAct_ChaosDemon, #混乱妖域 17
Def_WPAct_XMZZ, #仙魔之争 18
Def_WPAct_FamilyWar,  #仙魔联赛 19
Def_WPAct_Login,  #每日登录 20
Def_WPAct_Horse,  #激活某只坐骑 21
Def_WPAct_21,  #激活某只坐骑 21
Def_WPAct_Pet,  #激活某只灵宠 22
Def_WPAct_Dogz,  #出战某只神兽 23
Def_WPAct_Stone,  #宝石总等级 24
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -4593,58 +4593,6 @@
#------------------------------------------------------
#A5 01 坐骑激活 #tagPlayerActivateHorse
class  tagPlayerActivateHorse(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("HorseID", c_int),    #坐骑幻化ID
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xA5
        self.SubCmd = 0x01
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.Cmd = 0xA5
        self.SubCmd = 0x01
        self.HorseID = 0
        return
    def GetLength(self):
        return sizeof(tagPlayerActivateHorse)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''//A5 01 坐骑激活 //tagPlayerActivateHorse:
                                Cmd:%s,
                                SubCmd:%s,
                                HorseID:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.HorseID
                                )
        return DumpString
m_NAtagPlayerActivateHorse=tagPlayerActivateHorse()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagPlayerActivateHorse.Cmd,m_NAtagPlayerActivateHorse.SubCmd))] = m_NAtagPlayerActivateHorse
#------------------------------------------------------
# A5 C7 激活大师强化等级 #tagCMActivateMasterPlusLV
class  tagCMActivateMasterPlusLV(Structure):
@@ -6556,290 +6504,6 @@
#------------------------------------------------------
# A5 29 骑宠觉醒 #tagCMHorsePetAwake
class  tagCMHorsePetAwake(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("Type", c_ushort),    # 1-坐骑 2-灵宠
                  ("ID", c_int),    # 对应坐骑表灵宠表ID
                  ("EatItemID", c_int),    # 吞噬的物品ID
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xA5
        self.SubCmd = 0x29
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.Cmd = 0xA5
        self.SubCmd = 0x29
        self.Type = 0
        self.ID = 0
        self.EatItemID = 0
        return
    def GetLength(self):
        return sizeof(tagCMHorsePetAwake)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// A5 29 骑宠觉醒 //tagCMHorsePetAwake:
                                Cmd:%s,
                                SubCmd:%s,
                                Type:%d,
                                ID:%d,
                                EatItemID:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.Type,
                                self.ID,
                                self.EatItemID
                                )
        return DumpString
m_NAtagCMHorsePetAwake=tagCMHorsePetAwake()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMHorsePetAwake.Cmd,m_NAtagCMHorsePetAwake.SubCmd))] = m_NAtagCMHorsePetAwake
#------------------------------------------------------
# A5 30 骑宠外观选择 #tagCMHorsePetSkinSelect
class  tagCMHorsePetSkinSelect(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("Type", c_ushort),    # 1-坐骑 2-灵宠
                  ("ID", c_int),    # 对应坐骑表灵宠表ID
                  ("SkinIndex", c_ubyte),    # 外观索引
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xA5
        self.SubCmd = 0x30
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.Cmd = 0xA5
        self.SubCmd = 0x30
        self.Type = 0
        self.ID = 0
        self.SkinIndex = 0
        return
    def GetLength(self):
        return sizeof(tagCMHorsePetSkinSelect)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// A5 30 骑宠外观选择 //tagCMHorsePetSkinSelect:
                                Cmd:%s,
                                SubCmd:%s,
                                Type:%d,
                                ID:%d,
                                SkinIndex:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.Type,
                                self.ID,
                                self.SkinIndex
                                )
        return DumpString
m_NAtagCMHorsePetSkinSelect=tagCMHorsePetSkinSelect()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMHorsePetSkinSelect.Cmd,m_NAtagCMHorsePetSkinSelect.SubCmd))] = m_NAtagCMHorsePetSkinSelect
#------------------------------------------------------
# A5 35 坐骑升星 #tagCMHorseStarUp
class  tagCMHorseStarUp(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("HorseID", c_int),    #坐骑ID,对应坐骑表ID
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xA5
        self.SubCmd = 0x35
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.Cmd = 0xA5
        self.SubCmd = 0x35
        self.HorseID = 0
        return
    def GetLength(self):
        return sizeof(tagCMHorseStarUp)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// A5 35 坐骑升星 //tagCMHorseStarUp:
                                Cmd:%s,
                                SubCmd:%s,
                                HorseID:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.HorseID
                                )
        return DumpString
m_NAtagCMHorseStarUp=tagCMHorseStarUp()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMHorseStarUp.Cmd,m_NAtagCMHorseStarUp.SubCmd))] = m_NAtagCMHorseStarUp
#------------------------------------------------------
# A5 31 坐骑培养 #tagCMHorseTrain
class  tagCMHorseTrain(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("TrainType", c_ubyte),    #培养类型: 1-基础培养,2-特殊培养,3-百分比培养
                  ("UseItemCnt", c_ushort),    #消耗材料个数
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xA5
        self.SubCmd = 0x31
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.Cmd = 0xA5
        self.SubCmd = 0x31
        self.TrainType = 0
        self.UseItemCnt = 0
        return
    def GetLength(self):
        return sizeof(tagCMHorseTrain)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// A5 31 坐骑培养 //tagCMHorseTrain:
                                Cmd:%s,
                                SubCmd:%s,
                                TrainType:%d,
                                UseItemCnt:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.TrainType,
                                self.UseItemCnt
                                )
        return DumpString
m_NAtagCMHorseTrain=tagCMHorseTrain()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMHorseTrain.Cmd,m_NAtagCMHorseTrain.SubCmd))] = m_NAtagCMHorseTrain
#------------------------------------------------------
# A5 27 坐骑提升 #tagCMHorseUp
class  tagCMHorseUp(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("UseItemCnt", c_ushort),    #消耗材料个数
                  ("IsAutoBuy", c_ubyte),    #是否自动购买
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xA5
        self.SubCmd = 0x27
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.Cmd = 0xA5
        self.SubCmd = 0x27
        self.UseItemCnt = 0
        self.IsAutoBuy = 0
        return
    def GetLength(self):
        return sizeof(tagCMHorseUp)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// A5 27 坐骑提升 //tagCMHorseUp:
                                Cmd:%s,
                                SubCmd:%s,
                                UseItemCnt:%d,
                                IsAutoBuy:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.UseItemCnt,
                                self.IsAutoBuy
                                )
        return DumpString
m_NAtagCMHorseUp=tagCMHorseUp()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMHorseUp.Cmd,m_NAtagCMHorseUp.SubCmd))] = m_NAtagCMHorseUp
#------------------------------------------------------
# A5 34 炼体突破 #tagCMLianTiLVUp
class  tagCMLianTiLVUp(Structure):
@@ -6989,62 +6653,6 @@
m_NAtagCMOpenRealmFB=tagCMOpenRealmFB()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMOpenRealmFB.Cmd,m_NAtagCMOpenRealmFB.SubCmd))] = m_NAtagCMOpenRealmFB
#------------------------------------------------------
#A5 02 坐骑选择 #tagPlayerChooseHorse
class  tagPlayerChooseHorse(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("ChooseType", c_ubyte),    # 1-按等阶,2-按幻化
                  ("LVID", c_ubyte),    # 阶等级或幻化ID
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xA5
        self.SubCmd = 0x02
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.Cmd = 0xA5
        self.SubCmd = 0x02
        self.ChooseType = 0
        self.LVID = 0
        return
    def GetLength(self):
        return sizeof(tagPlayerChooseHorse)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''//A5 02 坐骑选择 //tagPlayerChooseHorse:
                                Cmd:%s,
                                SubCmd:%s,
                                ChooseType:%d,
                                LVID:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.ChooseType,
                                self.LVID
                                )
        return DumpString
m_NAtagPlayerChooseHorse=tagPlayerChooseHorse()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagPlayerChooseHorse.Cmd,m_NAtagPlayerChooseHorse.SubCmd))] = m_NAtagPlayerChooseHorse
#------------------------------------------------------
@@ -12875,6 +12483,162 @@
#------------------------------------------------------
# B2 02 坐骑进阶 #tagCSHorseClassUP
class  tagCSHorseClassUP(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xB2
        self.SubCmd = 0x02
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.Cmd = 0xB2
        self.SubCmd = 0x02
        return
    def GetLength(self):
        return sizeof(tagCSHorseClassUP)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B2 02 坐骑进阶 //tagCSHorseClassUP:
                                Cmd:%s,
                                SubCmd:%s
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd
                                )
        return DumpString
m_NAtagCSHorseClassUP=tagCSHorseClassUP()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCSHorseClassUP.Cmd,m_NAtagCSHorseClassUP.SubCmd))] = m_NAtagCSHorseClassUP
#------------------------------------------------------
# B2 03 坐骑外观操作 #tagCSHorseSkinOP
class  tagCSHorseSkinOP(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("OPType", c_ubyte),    # 操作 1-激活;2-佩戴;3-升星
                  ("SkinID", c_ubyte),    # 外观ID,佩戴时发0即为卸下
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xB2
        self.SubCmd = 0x03
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.Cmd = 0xB2
        self.SubCmd = 0x03
        self.OPType = 0
        self.SkinID = 0
        return
    def GetLength(self):
        return sizeof(tagCSHorseSkinOP)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B2 03 坐骑外观操作 //tagCSHorseSkinOP:
                                Cmd:%s,
                                SubCmd:%s,
                                OPType:%d,
                                SkinID:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.OPType,
                                self.SkinID
                                )
        return DumpString
m_NAtagCSHorseSkinOP=tagCSHorseSkinOP()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCSHorseSkinOP.Cmd,m_NAtagCSHorseSkinOP.SubCmd))] = m_NAtagCSHorseSkinOP
#------------------------------------------------------
# B2 01 坐骑升级 #tagCSHorseLVUP
class  tagCSHorseLVUP(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("IsQuick", c_ubyte),    # 是否快速升级,0-只消耗1个道具;1-消耗升1级的道具
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xB2
        self.SubCmd = 0x01
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.Cmd = 0xB2
        self.SubCmd = 0x01
        self.IsQuick = 0
        return
    def GetLength(self):
        return sizeof(tagCSHorseLVUP)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B2 01 坐骑升级 //tagCSHorseLVUP:
                                Cmd:%s,
                                SubCmd:%s,
                                IsQuick:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.IsQuick
                                )
        return DumpString
m_NAtagCSHorseLVUP=tagCSHorseLVUP()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCSHorseLVUP.Cmd,m_NAtagCSHorseLVUP.SubCmd))] = m_NAtagCSHorseLVUP
#------------------------------------------------------
# B2 07 重置加点 #tagCMResetAttrPoint
class  tagCMResetAttrPoint(Structure):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -5117,129 +5117,6 @@
#------------------------------------------------------
#A3 04 玩家扫荡信息 #tagMCFBWipeOutData
class  tagMCFBData(Structure):
    _pack_ = 1
    _fields_ = [
                  ("FBID", c_int),    #fbId
                  ("LineIndex", c_ubyte),    #副本通关场次
                  ("WipeOutCnt", c_ubyte),    #扫荡次数
                  ("passGrade", c_ubyte),    #通关评级
                  ]
    def __init__(self):
        self.Clear()
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.FBID = 0
        self.LineIndex = 0
        self.WipeOutCnt = 0
        self.passGrade = 0
        return
    def GetLength(self):
        return sizeof(tagMCFBData)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''//A3 04 玩家扫荡信息 //tagMCFBWipeOutData:
                                FBID:%d,
                                LineIndex:%d,
                                WipeOutCnt:%d,
                                passGrade:%d
                                '''\
                                %(
                                self.FBID,
                                self.LineIndex,
                                self.WipeOutCnt,
                                self.passGrade
                                )
        return DumpString
class  tagMCFBWipeOutData(Structure):
    Head = tagHead()
    WipeOutFBID = 0    #(DWORD WipeOutFBID)//当前扫荡的副本id
    FBDataCnt = 0    #(BYTE FBDataCnt)//
    FBDataList = list()    #(vector<tagMCFBData> FBDataList)//
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xA3
        self.Head.SubCmd = 0x04
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        _pos = self.Head.ReadData(_lpData, _pos)
        self.WipeOutFBID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.FBDataCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.FBDataCnt):
            temFBDataList = tagMCFBData()
            _pos = temFBDataList.ReadData(_lpData, _pos)
            self.FBDataList.append(temFBDataList)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xA3
        self.Head.SubCmd = 0x04
        self.WipeOutFBID = 0
        self.FBDataCnt = 0
        self.FBDataList = list()
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 4
        length += 1
        for i in range(self.FBDataCnt):
            length += self.FBDataList[i].GetLength()
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteDWORD(data, self.WipeOutFBID)
        data = CommFunc.WriteBYTE(data, self.FBDataCnt)
        for i in range(self.FBDataCnt):
            data = CommFunc.WriteString(data, self.FBDataList[i].GetLength(), self.FBDataList[i].GetBuffer())
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                WipeOutFBID:%d,
                                FBDataCnt:%d,
                                FBDataList:%s
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.WipeOutFBID,
                                self.FBDataCnt,
                                "..."
                                )
        return DumpString
m_NAtagMCFBWipeOutData=tagMCFBWipeOutData()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCFBWipeOutData.Head.Cmd,m_NAtagMCFBWipeOutData.Head.SubCmd))] = m_NAtagMCFBWipeOutData
#------------------------------------------------------
# A3 18 极品白拿信息 #tagMCFreeGoodsInfo
class  tagMCFreeGoods(Structure):
@@ -5824,20 +5701,22 @@
#------------------------------------------------------
# A3 12 通知骑宠觉醒信息 #tagMCHorsePetSkinData
# A3 03 坐骑阶级信息 #tagSCHorseClassInfo
class  tagMCHorsePetSkinInfo(Structure):
class  tagSCHorseClassInfo(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Type", c_ubyte),    # 1-坐骑 2-灵宠
                  ("ID", c_int),    # 对应坐骑表灵宠表ID
                  ("Exp", c_int),    #经验
                  ("SkinLV", c_ubyte),    #觉醒等级
                  ("SkinIndex", c_ubyte),    #当前选择外观
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("ClassLV", c_ubyte),    #当前阶级,从0开始
                  ("HorseLV", c_ushort),    #当前阶等级,从1开始
                  ("Exp", c_ushort),    #当前阶等级经验,每级从0开始
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xA3
        self.SubCmd = 0x03
        return
    def ReadData(self, stringData, _pos=0, _len=0):
@@ -5846,111 +5725,51 @@
        return _pos + self.GetLength()
    def Clear(self):
        self.Type = 0
        self.ID = 0
        self.Cmd = 0xA3
        self.SubCmd = 0x03
        self.ClassLV = 0
        self.HorseLV = 0
        self.Exp = 0
        self.SkinLV = 0
        self.SkinIndex = 0
        return
    def GetLength(self):
        return sizeof(tagMCHorsePetSkinInfo)
        return sizeof(tagSCHorseClassInfo)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// A3 12 通知骑宠觉醒信息 //tagMCHorsePetSkinData:
                                Type:%d,
                                ID:%d,
                                Exp:%d,
                                SkinLV:%d,
                                SkinIndex:%d
        DumpString = '''// A3 03 坐骑阶级信息 //tagSCHorseClassInfo:
                                Cmd:%s,
                                SubCmd:%s,
                                ClassLV:%d,
                                HorseLV:%d,
                                Exp:%d
                                '''\
                                %(
                                self.Type,
                                self.ID,
                                self.Exp,
                                self.SkinLV,
                                self.SkinIndex
                                self.Cmd,
                                self.SubCmd,
                                self.ClassLV,
                                self.HorseLV,
                                self.Exp
                                )
        return DumpString
class  tagMCHorsePetSkinData(Structure):
    Head = tagHead()
    Num = 0    #(BYTE Num)//个数
    InfoList = list()    #(vector<tagMCHorsePetSkinInfo> InfoList)// 数据列表
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xA3
        self.Head.SubCmd = 0x12
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        _pos = self.Head.ReadData(_lpData, _pos)
        self.Num,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.Num):
            temInfoList = tagMCHorsePetSkinInfo()
            _pos = temInfoList.ReadData(_lpData, _pos)
            self.InfoList.append(temInfoList)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xA3
        self.Head.SubCmd = 0x12
        self.Num = 0
        self.InfoList = list()
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 1
        for i in range(self.Num):
            length += self.InfoList[i].GetLength()
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteBYTE(data, self.Num)
        for i in range(self.Num):
            data = CommFunc.WriteString(data, self.InfoList[i].GetLength(), self.InfoList[i].GetBuffer())
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                Num:%d,
                                InfoList:%s
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.Num,
                                "..."
                                )
        return DumpString
m_NAtagMCHorsePetSkinData=tagMCHorsePetSkinData()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCHorsePetSkinData.Head.Cmd,m_NAtagMCHorsePetSkinData.Head.SubCmd))] = m_NAtagMCHorsePetSkinData
m_NAtagSCHorseClassInfo=tagSCHorseClassInfo()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagSCHorseClassInfo.Cmd,m_NAtagSCHorseClassInfo.SubCmd))] = m_NAtagSCHorseClassInfo
#------------------------------------------------------
# A3 10 通知坐骑幻化时效信息 #tagMCHorseSkinTimeInfoList
# A3 04 坐骑外观信息 #tagSCHorseSkinInfo
class  tagMCHorseSkinTimeInfo(Structure):
class  tagSCHorseSkin(Structure):
    _pack_ = 1
    _fields_ = [
                  ("ID", c_int),    # 对应坐骑幻化表ID
                  ("InvalidTime", c_int),    # 失效时间戳
                  ("HorseSkinID", c_ubyte),    #坐骑外观ID
                  ("State", c_ubyte),    #是否已激活
                  ("EndTime", c_int),    #到期时间戳,0为永久
                  ("Star", c_ubyte),    #星级
                  ]
    def __init__(self):
@@ -5963,146 +5782,44 @@
        return _pos + self.GetLength()
    def Clear(self):
        self.ID = 0
        self.InvalidTime = 0
        return
    def GetLength(self):
        return sizeof(tagMCHorseSkinTimeInfo)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// A3 10 通知坐骑幻化时效信息 //tagMCHorseSkinTimeInfoList:
                                ID:%d,
                                InvalidTime:%d
                                '''\
                                %(
                                self.ID,
                                self.InvalidTime
                                )
        return DumpString
class  tagMCHorseSkinTimeInfoList(Structure):
    Head = tagHead()
    TimeCnt = 0    #(BYTE TimeCnt)//个数
    TimeInfoList = list()    #(vector<tagMCHorseSkinTimeInfo> TimeInfoList)// 数据列表
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xA3
        self.Head.SubCmd = 0x10
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        _pos = self.Head.ReadData(_lpData, _pos)
        self.TimeCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.TimeCnt):
            temTimeInfoList = tagMCHorseSkinTimeInfo()
            _pos = temTimeInfoList.ReadData(_lpData, _pos)
            self.TimeInfoList.append(temTimeInfoList)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xA3
        self.Head.SubCmd = 0x10
        self.TimeCnt = 0
        self.TimeInfoList = list()
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 1
        for i in range(self.TimeCnt):
            length += self.TimeInfoList[i].GetLength()
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteBYTE(data, self.TimeCnt)
        for i in range(self.TimeCnt):
            data = CommFunc.WriteString(data, self.TimeInfoList[i].GetLength(), self.TimeInfoList[i].GetBuffer())
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                TimeCnt:%d,
                                TimeInfoList:%s
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.TimeCnt,
                                "..."
                                )
        return DumpString
m_NAtagMCHorseSkinTimeInfoList=tagMCHorseSkinTimeInfoList()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCHorseSkinTimeInfoList.Head.Cmd,m_NAtagMCHorseSkinTimeInfoList.Head.SubCmd))] = m_NAtagMCHorseSkinTimeInfoList
#------------------------------------------------------
# A3 CD 坐骑星级信息 #tagMCHorseStarInfo
class  tagMCHorseStar(Structure):
    _pack_ = 1
    _fields_ = [
                  ("HorseID", c_int),    # 坐骑表ID
                  ("Star", c_ubyte),    # 星级
                  ]
    def __init__(self):
        self.Clear()
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.HorseID = 0
        self.HorseSkinID = 0
        self.State = 0
        self.EndTime = 0
        self.Star = 0
        return
    def GetLength(self):
        return sizeof(tagMCHorseStar)
        return sizeof(tagSCHorseSkin)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// A3 CD 坐骑星级信息 //tagMCHorseStarInfo:
                                HorseID:%d,
        DumpString = '''// A3 04 坐骑外观信息 //tagSCHorseSkinInfo:
                                HorseSkinID:%d,
                                State:%d,
                                EndTime:%d,
                                Star:%d
                                '''\
                                %(
                                self.HorseID,
                                self.HorseSkinID,
                                self.State,
                                self.EndTime,
                                self.Star
                                )
        return DumpString
class  tagMCHorseStarInfo(Structure):
class  tagSCHorseSkinInfo(Structure):
    Head = tagHead()
    Count = 0    #(BYTE Count)
    HorseStarList = list()    #(vector<tagMCHorseStar> HorseStarList)
    HorseSkinList = list()    #(vector<tagSCHorseSkin> HorseSkinList)
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xA3
        self.Head.SubCmd = 0xCD
        self.Head.SubCmd = 0x04
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
@@ -6110,18 +5827,18 @@
        _pos = self.Head.ReadData(_lpData, _pos)
        self.Count,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.Count):
            temHorseStarList = tagMCHorseStar()
            _pos = temHorseStarList.ReadData(_lpData, _pos)
            self.HorseStarList.append(temHorseStarList)
            temHorseSkinList = tagSCHorseSkin()
            _pos = temHorseSkinList.ReadData(_lpData, _pos)
            self.HorseSkinList.append(temHorseSkinList)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xA3
        self.Head.SubCmd = 0xCD
        self.Head.SubCmd = 0x04
        self.Count = 0
        self.HorseStarList = list()
        self.HorseSkinList = list()
        return
    def GetLength(self):
@@ -6129,7 +5846,7 @@
        length += self.Head.GetLength()
        length += 1
        for i in range(self.Count):
            length += self.HorseStarList[i].GetLength()
            length += self.HorseSkinList[i].GetLength()
        return length
@@ -6138,14 +5855,14 @@
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteBYTE(data, self.Count)
        for i in range(self.Count):
            data = CommFunc.WriteString(data, self.HorseStarList[i].GetLength(), self.HorseStarList[i].GetBuffer())
            data = CommFunc.WriteString(data, self.HorseSkinList[i].GetLength(), self.HorseSkinList[i].GetBuffer())
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                Count:%d,
                                HorseStarList:%s
                                HorseSkinList:%s
                                '''\
                                %(
                                self.Head.OutputString(),
@@ -6155,8 +5872,8 @@
        return DumpString
m_NAtagMCHorseStarInfo=tagMCHorseStarInfo()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCHorseStarInfo.Head.Cmd,m_NAtagMCHorseStarInfo.Head.SubCmd))] = m_NAtagMCHorseStarInfo
m_NAtagSCHorseSkinInfo=tagSCHorseSkinInfo()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagSCHorseSkinInfo.Head.Cmd,m_NAtagSCHorseSkinInfo.Head.SubCmd))] = m_NAtagSCHorseSkinInfo
#------------------------------------------------------
@@ -9241,121 +8958,6 @@
#------------------------------------------------------
#A3 01 坐骑培养信息 #tagTrainHorseData
class  tagTrainHorseData(Structure):
    Head = tagHead()
    LV = 0    #(BYTE LV)//等阶
    EatItemCount = 0    #(DWORD EatItemCount)//当前阶已吃丹个数
    SkinPlusState = 0    #(DWORD SkinPlusState)//幻化激活状态,按位存储是否激活,幻化编号ID对应位,废弃,使用 SkinPlusStateList
    TrainTypes = 0    #(BYTE TrainTypes)//培养类型数
    TrainLVList = list()    #(vector<DWORD> TrainLVList)//培养等阶列表,索引为培养类型减1
    TrainItemCountList = list()    #(vector<DWORD> TrainItemCountList)//培养当前阶已吃培养丹个数列表,索引为培养类型减1
    SkinPlusStateCount = 0    #(BYTE SkinPlusStateCount)//幻化激活状态值数
    SkinPlusStateList = list()    #(vector<DWORD> SkinPlusStateList)//幻化激活状态值列表,按位存储是否激活,幻化编号ID对应位
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xA3
        self.Head.SubCmd = 0x01
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        _pos = self.Head.ReadData(_lpData, _pos)
        self.LV,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.EatItemCount,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.SkinPlusState,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.TrainTypes,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.TrainTypes):
            value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
            self.TrainLVList.append(value)
        for i in range(self.TrainTypes):
            value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
            self.TrainItemCountList.append(value)
        self.SkinPlusStateCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.SkinPlusStateCount):
            value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
            self.SkinPlusStateList.append(value)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xA3
        self.Head.SubCmd = 0x01
        self.LV = 0
        self.EatItemCount = 0
        self.SkinPlusState = 0
        self.TrainTypes = 0
        self.TrainLVList = list()
        self.TrainItemCountList = list()
        self.SkinPlusStateCount = 0
        self.SkinPlusStateList = list()
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 1
        length += 4
        length += 4
        length += 1
        length += 4 * self.TrainTypes
        length += 4 * self.TrainTypes
        length += 1
        length += 4 * self.SkinPlusStateCount
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteBYTE(data, self.LV)
        data = CommFunc.WriteDWORD(data, self.EatItemCount)
        data = CommFunc.WriteDWORD(data, self.SkinPlusState)
        data = CommFunc.WriteBYTE(data, self.TrainTypes)
        for i in range(self.TrainTypes):
            data = CommFunc.WriteDWORD(data, self.TrainLVList[i])
        for i in range(self.TrainTypes):
            data = CommFunc.WriteDWORD(data, self.TrainItemCountList[i])
        data = CommFunc.WriteBYTE(data, self.SkinPlusStateCount)
        for i in range(self.SkinPlusStateCount):
            data = CommFunc.WriteDWORD(data, self.SkinPlusStateList[i])
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                LV:%d,
                                EatItemCount:%d,
                                SkinPlusState:%d,
                                TrainTypes:%d,
                                TrainLVList:%s,
                                TrainItemCountList:%s,
                                SkinPlusStateCount:%d,
                                SkinPlusStateList:%s
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.LV,
                                self.EatItemCount,
                                self.SkinPlusState,
                                self.TrainTypes,
                                "...",
                                "...",
                                self.SkinPlusStateCount,
                                "..."
                                )
        return DumpString
m_NAtagTrainHorseData=tagTrainHorseData()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagTrainHorseData.Head.Cmd,m_NAtagTrainHorseData.Head.SubCmd))] = m_NAtagTrainHorseData
#------------------------------------------------------
# A3 51 寻宝功能信息 #tagMCTreasureInfo
class  tagMCTreasureGridLimit(Structure):
@@ -9638,152 +9240,6 @@
m_NAtagMCTreasureResult=tagMCTreasureResult()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCTreasureResult.Head.Cmd,m_NAtagMCTreasureResult.Head.SubCmd))] = m_NAtagMCTreasureResult
#------------------------------------------------------
#A3 05 扫荡奖励信息 #tagMCWipeOutPrize
class  tagMCPrizeItemInfo(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("ItemID", c_int),    #物品id
                  ("ItemCnt", c_ubyte),    #物品数量
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xA3
        self.SubCmd = 0x05
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.Cmd = 0xA3
        self.SubCmd = 0x05
        self.ItemID = 0
        self.ItemCnt = 0
        return
    def GetLength(self):
        return sizeof(tagMCPrizeItemInfo)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''//A3 05 扫荡奖励信息 //tagMCWipeOutPrize:
                                Cmd:%s,
                                SubCmd:%s,
                                ItemID:%d,
                                ItemCnt:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.ItemID,
                                self.ItemCnt
                                )
        return DumpString
class  tagMCWipeOutPrize(Structure):
    Head = tagHead()
    FBID = 0    #(DWORD FBID)//副本id
    WipeOutCnt = 0    #(DWORD WipeOutCnt)//扫荡次数
    GiveExp = 0    #(DWORD GiveExp)//给予经验
    SilverCnt = 0    #(DWORD SilverCnt)//给予金币
    PrizeCnt = 0    #(BYTE PrizeCnt)//״̬
    PrizeInfo = list()    #(vector<tagMCPrizeItemInfo> PrizeInfo)//״̬
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xA3
        self.Head.SubCmd = 0x05
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        _pos = self.Head.ReadData(_lpData, _pos)
        self.FBID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.WipeOutCnt,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.GiveExp,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.SilverCnt,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.PrizeCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.PrizeCnt):
            temPrizeInfo = tagMCPrizeItemInfo()
            _pos = temPrizeInfo.ReadData(_lpData, _pos)
            self.PrizeInfo.append(temPrizeInfo)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xA3
        self.Head.SubCmd = 0x05
        self.FBID = 0
        self.WipeOutCnt = 0
        self.GiveExp = 0
        self.SilverCnt = 0
        self.PrizeCnt = 0
        self.PrizeInfo = list()
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 4
        length += 4
        length += 4
        length += 4
        length += 1
        for i in range(self.PrizeCnt):
            length += self.PrizeInfo[i].GetLength()
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteDWORD(data, self.FBID)
        data = CommFunc.WriteDWORD(data, self.WipeOutCnt)
        data = CommFunc.WriteDWORD(data, self.GiveExp)
        data = CommFunc.WriteDWORD(data, self.SilverCnt)
        data = CommFunc.WriteBYTE(data, self.PrizeCnt)
        for i in range(self.PrizeCnt):
            data = CommFunc.WriteString(data, self.PrizeInfo[i].GetLength(), self.PrizeInfo[i].GetBuffer())
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                FBID:%d,
                                WipeOutCnt:%d,
                                GiveExp:%d,
                                SilverCnt:%d,
                                PrizeCnt:%d,
                                PrizeInfo:%s
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.FBID,
                                self.WipeOutCnt,
                                self.GiveExp,
                                self.SilverCnt,
                                self.PrizeCnt,
                                "..."
                                )
        return DumpString
m_NAtagMCWipeOutPrize=tagMCWipeOutPrize()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCWipeOutPrize.Head.Cmd,m_NAtagMCWipeOutPrize.Head.SubCmd))] = m_NAtagMCWipeOutPrize
#------------------------------------------------------
@@ -14491,6 +13947,7 @@
    Face = 0    #(DWORD Face)
    FacePic = 0    #(DWORD FacePic)
    ModelMark = 0    #(DWORD ModelMark)//变形模型mark
    EquipShowSwitch = 0    #(DWORD EquipShowSwitch)//其他外观信息
    TitleID = 0    #(DWORD TitleID)//佩戴的称号
    ServerID = 0    #(DWORD ServerID)
    FightPower = 0    #(DWORD FightPower)
@@ -14520,6 +13977,7 @@
        self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.ModelMark,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.EquipShowSwitch,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.TitleID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.ServerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.FightPower,_pos = CommFunc.ReadDWORD(_lpData, _pos)
@@ -14545,6 +14003,7 @@
        self.Face = 0
        self.FacePic = 0
        self.ModelMark = 0
        self.EquipShowSwitch = 0
        self.TitleID = 0
        self.ServerID = 0
        self.FightPower = 0
@@ -14573,6 +14032,7 @@
        length += 4
        length += 4
        length += 4
        length += 4
        length += 33
        length += 4
        length += 3
@@ -14592,6 +14052,7 @@
        data = CommFunc.WriteDWORD(data, self.Face)
        data = CommFunc.WriteDWORD(data, self.FacePic)
        data = CommFunc.WriteDWORD(data, self.ModelMark)
        data = CommFunc.WriteDWORD(data, self.EquipShowSwitch)
        data = CommFunc.WriteDWORD(data, self.TitleID)
        data = CommFunc.WriteDWORD(data, self.ServerID)
        data = CommFunc.WriteDWORD(data, self.FightPower)
@@ -14615,6 +14076,7 @@
                                Face:%d,
                                FacePic:%d,
                                ModelMark:%d,
                                EquipShowSwitch:%d,
                                TitleID:%d,
                                ServerID:%d,
                                FightPower:%d,
@@ -14636,6 +14098,7 @@
                                self.Face,
                                self.FacePic,
                                self.ModelMark,
                                self.EquipShowSwitch,
                                self.TitleID,
                                self.ServerID,
                                self.FightPower,
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBStruct.py
@@ -1152,6 +1152,7 @@
        ('Face', ctypes.c_int),
        ('FacePic', ctypes.c_int),
        ('ModelMark', ctypes.c_ulong),
        ('EquipShowSwitch', ctypes.c_ulong),
        ('FamilyID', ctypes.c_ulong),
        ('FamilyName', ctypes.c_char * 33),
        ('FamilyEmblemID', ctypes.c_ushort),
@@ -1180,6 +1181,7 @@
        self.Face = 0
        self.FacePic = 0
        self.ModelMark = 0
        self.EquipShowSwitch = 0
        self.FamilyID = 0
        self.FamilyName = ''
        self.FamilyEmblemID = 0
@@ -1207,6 +1209,7 @@
        self.Face, pos = CommFunc.ReadDWORD(buf, pos)
        self.FacePic, pos = CommFunc.ReadDWORD(buf, pos)
        self.ModelMark, pos = CommFunc.ReadDWORD(buf, pos)
        self.EquipShowSwitch, pos = CommFunc.ReadDWORD(buf, pos)
        self.FamilyID, pos = CommFunc.ReadDWORD(buf, pos)
        self.FamilyName, pos = CommFunc.ReadString(buf, pos, 33)
        self.FamilyEmblemID, pos = CommFunc.ReadWORD(buf, pos)
@@ -1232,6 +1235,7 @@
        buf = CommFunc.WriteDWORD(buf, self.Face)
        buf = CommFunc.WriteDWORD(buf, self.FacePic)
        buf = CommFunc.WriteDWORD(buf, self.ModelMark)
        buf = CommFunc.WriteDWORD(buf, self.EquipShowSwitch)
        buf = CommFunc.WriteDWORD(buf, self.FamilyID)
        buf = CommFunc.WriteString(buf, sizeof(ctypes.c_char) * 33, self.FamilyName)
        buf = CommFunc.WriteWORD(buf, self.FamilyEmblemID)
@@ -1257,6 +1261,7 @@
        length += sizeof(ctypes.c_int)
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_char) * 33
        length += sizeof(ctypes.c_ushort)
        length += sizeof(ctypes.c_char) * 3
@@ -1280,6 +1285,7 @@
            Face = %s,
            FacePic = %s,
            ModelMark = %s,
            EquipShowSwitch = %s,
            FamilyID = %s,
            FamilyName = %s,
            FamilyEmblemID = %s,
@@ -1302,6 +1308,7 @@
                self.Face,
                self.FacePic,
                self.ModelMark,
                self.EquipShowSwitch,
                self.FamilyID,
                self.FamilyName,
                self.FamilyEmblemID,
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBPlayerViewCache.py
@@ -47,6 +47,8 @@
    def SetFacePic(self, facePic): self.__dbData.FacePic = facePic
    def GetModelMark(self): return self.__dbData.ModelMark
    def SetModelMark(self, modelMark): self.__dbData.ModelMark = modelMark
    def GetEquipShowSwitch(self): return self.__dbData.EquipShowSwitch
    def SetEquipShowSwitch(self, equipShowSwitch): self.__dbData.EquipShowSwitch = equipShowSwitch
    def GetFamilyID(self): return self.__dbData.FamilyID
    def SetFamilyID(self, familyID): self.__dbData.FamilyID = familyID
    def GetFamilyName(self): return self.__dbData.FamilyName
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DataRecordPack.py
@@ -1129,30 +1129,6 @@
    SendEventPack("TradeMoney", dataDict, curPlayer)
    return
## 玩家马匹进阶
#  @param curPlayer: 玩家实例
#  @param classLV: 阶级
#  @param horseID: 新马匹id
#  @return: None
def DR_NewHorseByClassUp(curPlayer, classLV, horseID):
    dataDict = {'PlayerID':curPlayer.GetPlayerID(),
                'PlayerName':curPlayer.GetPlayerName(),
                'AccID':curPlayer.GetAccID(),
                'ClassLV':classLV,
                'HorseID':horseID,
                }
    SendEventPack("NewHorseByClassUp", dataDict, curPlayer)
    return
## 坐骑幻化皮肤删除
def DR_HorseSkinDel(curPlayer, skinID):
    dataDict = {'PlayerID':curPlayer.GetPlayerID(), 'PlayerName':curPlayer.GetPlayerName(),
                'AccID':curPlayer.GetAccID(), 'skinID':skinID,}
    SendEventPack("HorseSkinDel", dataDict, curPlayer)
    return
## 玩家进阶式系统流向记录
#  @param curPlayer
#  @param classLV 阶级
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/EventReport.py
@@ -1044,54 +1044,6 @@
    #===========================================================================
    return
class horseskin_lv(ScribeEvent):
    # 时装升级记录
    def __init__(self):
        #必须字段
        super(horseskin_lv, self).__init__()
        self.account_id = "" # 账号 ID,平台下唯一,且终生不变
        self.chr_name = "" # 玩家角色名
        self.skin_name = "" # 幻化坐骑名称
        self.bef_lv = 0 # 此次进阶操作前的等级
        self.bef_exp = 0 # 此次进阶操作前的经验值
        self.cost_item_cnt = 0 # 此次消耗的道具数量
        self.aft_lv = 0 # 此次操作后的等级, 0代表0级, 1代表+1级
        self.aft_exp = 0 #此次进阶操作后的经验值
        #非必须字段
        #即时是非必须字段也应该传送,各字段用,分隔,并且用双引号包含,参考格式'"1","","","12314"'
        return
    def GetCurEventStr(self):
        if not self.time:
            self.time = GameWorld.GetCurrentDataTimeStr()
        tmpList = [self.product_slug, self.agent_name, self.gameserver_no, self.account_id, self.chr_name,
                   self.skin_name, str(self.bef_lv), str(self.bef_exp), str(self.cost_item_cnt), str(self.aft_lv), str(self.aft_exp), self.time]
        return super(horseskin_lv, self).GetEventStr(tmpList)
    def GetScribeEventName(self): return ShareDefine.Def_UserAction_HorseSkinLV
def WriteEvent_horseskin_lv(curPlayer, skinName, befLV, befExp, costItemCnt, aftLV, aftExp):
    ## 写幻化坐骑升级记录
    #===========================================================================
    # horseSkinLV = horseskin_lv()
    # horseSkinLV.SetEventAgentInfo(GameWorld.GetPlayerPlatform(curPlayer.GetAccID()))
    # horseSkinLV.account_id = GameWorld.GetPlatformAccID(curPlayer.GetAccID())
    # horseSkinLV.chr_name = curPlayer.GetPlayerName()
    # horseSkinLV.skin_name = skinName
    # horseSkinLV.bef_lv = befLV
    # horseSkinLV.bef_exp = befExp
    # horseSkinLV.cost_item_cnt = costItemCnt
    # horseSkinLV.aft_lv = aftLV
    # horseSkinLV.aft_exp = aftExp
    # WriteEvent(horseSkinLV)
    #===========================================================================
    return
## ---------------------------------------------------------------------------------------
#------------------------2018-02-09  新的数据统计--------------------------------
def WriteEvent_Entry(curPlayer, step):
    EventReport(ShareDefine.Def_UserAction_LostModel, "Step=%s&Flag=%s"%(step, ShareDefine.Def_UserAction_CreateRole), curPlayer)
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/ClearFightPowerHistor.py
File was deleted
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Horse.py
@@ -6,132 +6,110 @@
#
# @todo:坐骑
# @author hxp
# @date 2019-12-17
# @date 2025-11-04
# @version 1.0
#
# 详细描述: 坐骑
#
#-------------------------------------------------------------------------------
#"""Version = 2019-12-17 18:30"""
#"""Version = 2025-11-04 14:30"""
#-------------------------------------------------------------------------------
import GameWorld
import ChConfig
import IpyGameDataPY
import PlayerControl
import PlayerHorse
import IpyGameDataPY
import time
import ChConfig
#---------------------------------------------------------------------
#逻辑实现
## GM命令执行入口
#  @param curPlayer 当前玩家
#  @param msgList 参数列表
#  @return None
#  @remarks 函数详细说明.
def OnExec(curPlayer, msgList):
    
    if not msgList:
        GameWorld.DebugAnswer(curPlayer, "重置所有: Horse 0")
        GameWorld.DebugAnswer(curPlayer, "设置进阶: Horse 等阶 丹数")
        GameWorld.DebugAnswer(curPlayer, "设置培养: Horse 培养类型 等阶 丹数")
        GameWorld.DebugAnswer(curPlayer, "全部幻化: Horse skin 1")
        GameWorld.DebugAnswer(curPlayer, "重置幻化: Horse skin 0")
        GameWorld.DebugAnswer(curPlayer, "设置幻化: Horse skin 幻化ID 状态")
        GameWorld.DebugAnswer(curPlayer, "设置星级: Horse star 坐骑ID 星级")
        GameWorld.DebugAnswer(curPlayer, "设置阶级: Horse 阶 [等级 经验]")
        GameWorld.DebugAnswer(curPlayer, "重置外观: Horse s0 [外观ID]")
        GameWorld.DebugAnswer(curPlayer, "添加外观: Horse s1 外观ID [有效秒]")
        GameWorld.DebugAnswer(curPlayer, "外观星级: Horse s2 外观ID 星级")
        return
    
    if msgList[0] == "skin":
        if len(msgList) == 2:
            skinState = msgList[1]
            ipyDataMgr = IpyGameDataPY.IPY_Data()
            for index in xrange(ipyDataMgr.GetHorseSkinPlusCount()):
                skinPlusIpyData = ipyDataMgr.GetHorseSkinPlusByIndex(index)
                skinID = skinPlusIpyData.GetID()
                __GMSetHorseSkinState(curPlayer, skinID, skinState, skinPlusIpyData.GetSkinValidTime())
        elif len(msgList) == 3:
            skinID = msgList[1]
            skinState = msgList[2]
            skinPlusIpyData = IpyGameDataPY.GetIpyGameData("HorseSkinPlus", skinID)
            if not skinPlusIpyData:
                GameWorld.DebugAnswer(curPlayer, "坐骑幻化ID不存在! skinID=%s" % skinID)
                return
            __GMSetHorseSkinState(curPlayer, skinID, skinState, skinPlusIpyData.GetSkinValidTime())
    ipyDataMgr = IpyGameDataPY.IPY_Data()
    syncSkinIDList = []
    value1 = msgList[0]
    if value1 == 0:
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorseClassLV, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorseLV, PlayerHorse.HorseLVStart)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorseExp, 0)
        PlayerControl.SetHorseSkinID(curPlayer, PlayerHorse.GetDefaultHorseSkinID())
        syncSkinIDList = __ResetHorseSkin(curPlayer, 0)
    elif value1 == "s0":
        horseSkinID = msgList[1] if len(msgList) > 1 else 0
        syncSkinIDList = __ResetHorseSkin(curPlayer, horseSkinID)
    elif value1 == "s1":
        horseSkinID = msgList[1] if len(msgList) > 1 else 0
        expireTimes = msgList[2] if len(msgList) > 2 else None
        if PlayerHorse.AddHorseSkin(curPlayer, horseSkinID, expireTimes, True):
            endTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorseSkinEndTime % horseSkinID)
            endTimeStr = "永久" if not endTime else GameWorld.ChangeTimeNumToStr(endTime)
            GameWorld.DebugAnswer(curPlayer, "添加外观成功:%s,到期:%s" % (horseSkinID, endTimeStr))
        else:
            return
    elif msgList[0] == "star":
        horseID = msgList[1] if len(msgList) > 1 else 0
        horseStar = msgList[2] if len(msgList) > 2 else 0
        if not horseID or not horseStar:
            return
        skinID = 0
        ipyDataMgr = IpyGameDataPY.IPY_Data()
        for index in xrange(ipyDataMgr.GetHorseSkinPlusCount()):
            skinPlusIpyData = ipyDataMgr.GetHorseSkinPlusByIndex(index)
            if horseID != skinPlusIpyData.GetHorseID():
                continue
            if PlayerHorse.CheckHorseSkinState(curPlayer, skinPlusIpyData):
                skinID = skinPlusIpyData.GetID()
            break
        if not skinID:
            GameWorld.DebugAnswer(curPlayer, "该坐骑不存在或未激活:horseID=%s" % horseID)
            return
        if not IpyGameDataPY.GetIpyGameData("HorseStarUp", horseID, horseStar):
            GameWorld.DebugAnswer(curPlayer, "不存在该坐骑星级:horseID=%s,star=%s" % (horseID, horseStar))
            return
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserStar % horseID, horseStar)
        GameWorld.DebugAnswer(curPlayer, "设置坐骑星级:horseID=%s,star=%s,skinID=%s" % (horseID, horseStar, skinID))
    elif len(msgList) == 1:
        if msgList[0] == 0:
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserLV, 1)
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserEatItemCount, 0)
            for trainType in xrange(1, PlayerHorse.GetHorseTrainTypes() + 1):
                PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserTrainLV % trainType, 1)
                PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserTrainItemCount % trainType, 0)
            ipyDataMgr = IpyGameDataPY.IPY_Data()
            for index in xrange(ipyDataMgr.GetHorseSkinPlusCount()):
                skinPlusIpyData = ipyDataMgr.GetHorseSkinPlusByIndex(index)
                skinID = skinPlusIpyData.GetID()
                PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserSkinEndTime % skinID, 0)
                GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_HorserSkinPlusState, skinID, 0)
            for index in range(ipyDataMgr.GetHorseCount()):
                ipyData = ipyDataMgr.GetHorseByIndex(index)
                horseID = ipyData.GetHorseID()
                PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserStar % horseID, 0)
    elif len(msgList) == 2:
        lv, eatItemCount = msgList
        if lv < 1:
            GameWorld.DebugAnswer(curPlayer, "等级不能小于1")
            return
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserLV, lv)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserEatItemCount, eatItemCount)
    elif len(msgList) == 3:
        trainType, trainLV, eatItemCount = msgList
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserTrainLV % trainType, trainLV)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserTrainItemCount % trainType, eatItemCount)
    else:
            GameWorld.DebugAnswer(curPlayer, "添加外观失败:%s" % (horseSkinID))
        return
    elif value1 == "s2":
        horseSkinID = msgList[1] if len(msgList) > 1 else 0
        setStar = msgList[2] if len(msgList) > 2 else 0
        ipyData = IpyGameDataPY.GetIpyGameData("HorseSkin", horseSkinID)
        if not ipyData:
            GameWorld.DebugAnswer(curPlayer, "该外观不存在:%s" % horseSkinID)
            return
        setStar = min(setStar, ipyData.GetStarMax())
        GameWorld.DebugAnswer(curPlayer, "设置外观:%s,星:%s" % (horseSkinID, setStar))
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorseSkinStar % horseSkinID, setStar)
        syncSkinIDList.append(horseSkinID)
        
    # 设置阶级: Horse 阶 [等级 经验]
    else:
        classLV = msgList[0] if len(msgList) > 0 else 0
        horseLV = msgList[1] if len(msgList) > 1 else 0
        exp = msgList[2] if len(msgList) > 2 else 0
        maxIpyData = ipyDataMgr.GetHorseClassByIndex(-1)
        classLV = min(classLV, maxIpyData.GetClassLV())
        classIpyData = IpyGameDataPY.GetIpyGameData("HorseClass", classLV)
        horseLV = max(PlayerHorse.HorseLVStart, min(horseLV, classIpyData.GetMaxHorseLV()))
        exp = min(exp, classIpyData.GetLVUPItemCnt())
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorseClassLV, classLV)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorseLV, horseLV)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorseExp, exp)
        GameWorld.DebugAnswer(curPlayer, "设置坐骑阶:%s,等级:%s,经验:%s" % (classLV, horseLV, exp))
    PlayerHorse.SyncHorseClassInfo(curPlayer)
    syncSkinIDList and PlayerHorse.SyncHorseSkinInfo(curPlayer, syncSkinIDList)
    PlayerHorse.RefreshHorseAttr(curPlayer)
    PlayerHorse.PlayerHorseLogin(curPlayer)
    return
def __GMSetHorseSkinState(curPlayer, skinID, skinState, validTime=0):
    if not skinState:
        GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_HorserSkinPlusState, skinID, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserSkinEndTime % skinID, 0)
def __ResetHorseSkin(curPlayer, horseSkinID=0):
    syncSkinIDList = []
    if not horseSkinID:
        ipyDataMgr = IpyGameDataPY.IPY_Data()
        for index in range(ipyDataMgr.GetHorseSkinCount()):
            ipyData = ipyDataMgr.GetHorseSkinByIndex(index)
            horseSkinID = ipyData.GetSkinID()
            if not GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_HorseSkinState, horseSkinID):
                continue
            GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_HorseSkinState, horseSkinID, 0)
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorseSkinEndTime % horseSkinID, 0)
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorseSkinStar % horseSkinID, 0)
            syncSkinIDList.append(horseSkinID)
    else:
        GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_HorserSkinPlusState, skinID, 1)
        if validTime > 0:
            updSkinEndTime = int(time.time()) + validTime
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserSkinEndTime % skinID, updSkinEndTime)
    return
        ipyData = IpyGameDataPY.GetIpyGameData("HorseSkin", horseSkinID)
        if not ipyData:
            GameWorld.DebugAnswer(curPlayer, "该外观不存在:%s" % horseSkinID)
            return
        GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_HorseSkinState, horseSkinID, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorseSkinEndTime % horseSkinID, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorseSkinStar % horseSkinID, 0)
        syncSkinIDList.append(horseSkinID)
    GameWorld.DebugAnswer(curPlayer, "删除外观:%s" % syncSkinIDList)
    return syncSkinIDList
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/imba.py
File was deleted
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -724,53 +724,29 @@
                        ("DWORD", "UpEatItemPerCount", 0),
                        ),
                "HorseLVUp":(
                        ("BYTE", "HorseLV", 1),
                        ("DWORD", "HorseSkinID", 0),
                        ("WORD", "NeedEatCount", 0),
                        ("list", "LVAttrType", 0),
                        ("list", "LVAttrValue", 0),
                        ("list", "UpItemAttrType", 0),
                        ("list", "UpItemAttrValue", 0),
                        ("DWORD", "UpEatItemPerCount", 0),
                "HorseClass":(
                        ("BYTE", "ClassLV", 1),
                        ("WORD", "MaxHorseLV", 0),
                        ("WORD", "LVUPItemCnt", 0),
                        ("WORD", "ClassUPItemCnt", 0),
                        ("list", "ClassSpecAttrIDList", 0),
                        ("list", "ClassSpecAttrValueList", 0),
                        ("list", "AttrIDList", 0),
                        ("list", "ClassAttrValueList", 0),
                        ("list", "PerLVAttrValueList", 0),
                        ),
                "HorseTrain":(
                        ("BYTE", "TrainType", 1),
                        ("BYTE", "TrainLV", 1),
                        ("WORD", "NeedRealmLV", 0),
                        ("DWORD", "EatCntTotal", 0),
                        ("DWORD", "EatCntEverytime", 0),
                        ("list", "EatItemAttrTypeList", 0),
                        ("list", "EatItemAttrValueList", 0),
                        ("list", "LVAttrTypeList", 0),
                        ("list", "LVAttrValueList", 0),
                        ),
                "HorseSkinPlus":(
                        ("BYTE", "ID", 1),
                        ("DWORD", "HorseSkinPlusID", 0),
                        ("DWORD", "UnlockItemID", 0),
                        ("BYTE", "UnlockItemCnt", 0),
                        ("list", "AttrType", 0),
                        ("list", "AttrValue", 0),
                        ("DWORD", "InitFightPower", 0),
                        ("DWORD", "HorseID", 0),
                        ("DWORD", "SkinValidTime", 0),
                        ),
                "Horse":(
                        ("DWORD", "HorseID", 1),
                        ("DWORD", "HorseSkinID", 0),
                        ("BYTE", "Quality", 0),
                        ),
                "HorseStarUp":(
                        ("DWORD", "HorseID", 1),
                        ("BYTE", "HorseStar", 1),
                        ("list", "StarUpNeedItemList", 0),
                        ("list", "StarAttrType", 0),
                        ("list", "StarAttrValue", 0),
                "HorseSkin":(
                        ("DWORD", "SkinID", 1),
                        ("DWORD", "ExpireMinutes", 0),
                        ("BYTE", "UnlockWay", 0),
                        ("DWORD", "UnlockValue", 0),
                        ("BYTE", "UnlockNeedCnt", 0),
                        ("BYTE", "UpNeedCnt", 0),
                        ("BYTE", "StarMax", 0),
                        ("list", "AttrIDList", 0),
                        ("list", "InitAttrValueList", 0),
                        ("list", "AttrPerStarAddList", 0),
                        ),
                "Gubao":(
@@ -3261,79 +3237,40 @@
    def GetUpItemAttrValue(self): return self.attrTuple[5] # 每x个培养丹增加属性值,x=UpEatItemPerCount list
    def GetUpEatItemPerCount(self): return self.attrTuple[6] # 每次培养消耗x个 DWORD
# 坐骑升级表
class IPY_HorseLVUp():
# 坐骑阶级表
class IPY_HorseClass():
    
    def __init__(self):
        self.attrTuple = None
        return
        
    def GetHorseLV(self): return self.attrTuple[0] # 坐骑等级 BYTE
    def GetHorseSkinID(self): return self.attrTuple[1] # 外观物品ID DWORD
    def GetNeedEatCount(self): return self.attrTuple[2] # 升级所需个数(非累计) WORD
    def GetLVAttrType(self): return self.attrTuple[3] # 每级额外属性类型(非累积) list
    def GetLVAttrValue(self): return self.attrTuple[4] # 每级额外属性值(非累积) list
    def GetUpItemAttrType(self): return self.attrTuple[5] # 每x个培养丹增加属性类型,x=UpEatItemPerCount list
    def GetUpItemAttrValue(self): return self.attrTuple[6] # 每x个培养丹增加属性值,x=UpEatItemPerCount list
    def GetUpEatItemPerCount(self): return self.attrTuple[7] # 每次培养消耗x个 DWORD
    def GetClassLV(self): return self.attrTuple[0] # 阶级 BYTE
    def GetMaxHorseLV(self): return self.attrTuple[1] # 最高等级 WORD
    def GetLVUPItemCnt(self): return self.attrTuple[2] # 升级道具数 WORD
    def GetClassUPItemCnt(self): return self.attrTuple[3] # 进阶道具数 WORD
    def GetClassSpecAttrIDList(self): return self.attrTuple[4] # 本阶特殊属性ID列表 list
    def GetClassSpecAttrValueList(self): return self.attrTuple[5] # 本阶特殊属性值列表 list
    def GetAttrIDList(self): return self.attrTuple[6] # 基础属性ID列表 list
    def GetClassAttrValueList(self): return self.attrTuple[7] # 本阶基础属性值列表 list
    def GetPerLVAttrValueList(self): return self.attrTuple[8] # 本阶每级基础属性值列表 list
# 坐骑培养表
class IPY_HorseTrain():
# 坐骑外观表
class IPY_HorseSkin():
    
    def __init__(self):
        self.attrTuple = None
        return
        
    def GetTrainType(self): return self.attrTuple[0] # 培养类型 BYTE
    def GetTrainLV(self): return self.attrTuple[1] # 培养等阶 BYTE
    def GetNeedRealmLV(self): return self.attrTuple[2] # 培养所需境界 WORD
    def GetEatCntTotal(self): return self.attrTuple[3] # 升阶所需个数(非累计) DWORD
    def GetEatCntEverytime(self): return self.attrTuple[4] # 每次培养消耗x个 DWORD
    def GetEatItemAttrTypeList(self): return self.attrTuple[5] # 每X个培养丹增加属性类型=EatCntEverytime list
    def GetEatItemAttrValueList(self): return self.attrTuple[6] # 每X个培养丹增加属性值=EatCntEverytime list
    def GetLVAttrTypeList(self): return self.attrTuple[7] # 每级额外属性类(非累积) list
    def GetLVAttrValueList(self): return self.attrTuple[8] # 每级额外属性值(非累积) list
# 坐骑幻化表
class IPY_HorseSkinPlus():
    def __init__(self):
        self.attrTuple = None
        return
    def GetID(self): return self.attrTuple[0] # 幻化编号ID BYTE
    def GetHorseSkinPlusID(self): return self.attrTuple[1] # 外观物品ID DWORD
    def GetUnlockItemID(self): return self.attrTuple[2] # 解锁坐骑物品编号 DWORD
    def GetUnlockItemCnt(self): return self.attrTuple[3] # 解锁所需物品数量 BYTE
    def GetAttrType(self): return self.attrTuple[4] # 激活加成属性类型 list
    def GetAttrValue(self): return self.attrTuple[5] # 激活加成属性值 list
    def GetInitFightPower(self): return self.attrTuple[6] # 皮肤额外战力 DWORD
    def GetHorseID(self): return self.attrTuple[7] # 对应坐骑ID DWORD
    def GetSkinValidTime(self): return self.attrTuple[8] # 有效时长秒 DWORD
# 坐骑表
class IPY_Horse():
    def __init__(self):
        self.attrTuple = None
        return
    def GetHorseID(self): return self.attrTuple[0] # 坐骑ID DWORD
    def GetHorseSkinID(self): return self.attrTuple[1] # 外观物品ID DWORD
    def GetQuality(self): return self.attrTuple[2] # 坐骑品质 BYTE
# 坐骑升星表
class IPY_HorseStarUp():
    def __init__(self):
        self.attrTuple = None
        return
    def GetHorseID(self): return self.attrTuple[0] # 坐骑ID DWORD
    def GetHorseStar(self): return self.attrTuple[1] # 坐骑星级 BYTE
    def GetStarUpNeedItemList(self): return self.attrTuple[2] # 升下一星所需道具 [[物品ID,个数], ...] list
    def GetStarAttrType(self): return self.attrTuple[3] # 累计总属性类型 list
    def GetStarAttrValue(self): return self.attrTuple[4] # 累计总属性值 list
    def GetSkinID(self): return self.attrTuple[0] # 外观ID DWORD
    def GetExpireMinutes(self): return self.attrTuple[1] # 时效分钟,0永久 DWORD
    def GetUnlockWay(self): return self.attrTuple[2] # 解锁方式 BYTE
    def GetUnlockValue(self): return self.attrTuple[3] # 解锁方式值 DWORD
    def GetUnlockNeedCnt(self): return self.attrTuple[4] # 解锁所需个数 BYTE
    def GetUpNeedCnt(self): return self.attrTuple[5] # 升级所需个数 BYTE
    def GetStarMax(self): return self.attrTuple[6] # 最高星级 BYTE
    def GetAttrIDList(self): return self.attrTuple[7] # 属性ID列表 list
    def GetInitAttrValueList(self): return self.attrTuple[8] # 初始属性值列表 list
    def GetAttrPerStarAddList(self): return self.attrTuple[9] # 每星加成值列表 list
# 古宝表
class IPY_Gubao():
@@ -5755,11 +5692,8 @@
        self.__LoadFileData("PetClassCost", onlyCheck)
        self.__LoadFileData("PetEatEquip", onlyCheck)
        self.__LoadFileData("FaQiLVUp", onlyCheck)
        self.__LoadFileData("HorseLVUp", onlyCheck)
        self.__LoadFileData("HorseTrain", onlyCheck)
        self.__LoadFileData("HorseSkinPlus", onlyCheck)
        self.__LoadFileData("Horse", onlyCheck)
        self.__LoadFileData("HorseStarUp", onlyCheck)
        self.__LoadFileData("HorseClass", onlyCheck)
        self.__LoadFileData("HorseSkin", onlyCheck)
        self.__LoadFileData("Gubao", onlyCheck)
        self.__LoadFileData("GubaoResonanceAttr", onlyCheck)
        self.__LoadFileData("GubaoResonance", onlyCheck)
@@ -6583,40 +6517,19 @@
        self.CheckLoadData("FaQiLVUp")
        return self.ipyFaQiLVUpCache[index]
    def GetHorseLVUpCount(self):
        self.CheckLoadData("HorseLVUp")
        return self.ipyHorseLVUpLen
    def GetHorseLVUpByIndex(self, index):
        self.CheckLoadData("HorseLVUp")
        return self.ipyHorseLVUpCache[index]
    def GetHorseClassCount(self):
        self.CheckLoadData("HorseClass")
        return self.ipyHorseClassLen
    def GetHorseClassByIndex(self, index):
        self.CheckLoadData("HorseClass")
        return self.ipyHorseClassCache[index]
    def GetHorseTrainCount(self):
        self.CheckLoadData("HorseTrain")
        return self.ipyHorseTrainLen
    def GetHorseTrainByIndex(self, index):
        self.CheckLoadData("HorseTrain")
        return self.ipyHorseTrainCache[index]
    def GetHorseSkinPlusCount(self):
        self.CheckLoadData("HorseSkinPlus")
        return self.ipyHorseSkinPlusLen
    def GetHorseSkinPlusByIndex(self, index):
        self.CheckLoadData("HorseSkinPlus")
        return self.ipyHorseSkinPlusCache[index]
    def GetHorseCount(self):
        self.CheckLoadData("Horse")
        return self.ipyHorseLen
    def GetHorseByIndex(self, index):
        self.CheckLoadData("Horse")
        return self.ipyHorseCache[index]
    def GetHorseStarUpCount(self):
        self.CheckLoadData("HorseStarUp")
        return self.ipyHorseStarUpLen
    def GetHorseStarUpByIndex(self, index):
        self.CheckLoadData("HorseStarUp")
        return self.ipyHorseStarUpCache[index]
    def GetHorseSkinCount(self):
        self.CheckLoadData("HorseSkin")
        return self.ipyHorseSkinLen
    def GetHorseSkinByIndex(self, index):
        self.CheckLoadData("HorseSkin")
        return self.ipyHorseSkinCache[index]
    def GetGubaoCount(self):
        self.CheckLoadData("Gubao")
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChEquip.py
@@ -109,19 +109,6 @@
def OnEquipPartSuiteActivate(index, clientData, tick):
    return
def ChangeEquipfacadeByHorsePetSkin(curPlayer, skinType, skinIndex):
    ##骑宠觉醒外观变更  灵宠外观索引*10000000+坐骑外观索引*1000000+灵根特效表key * 1000+第几套*10+是否有套装
    oldEquipShowSwitch = curPlayer.GetEquipShowSwitch()
    if skinType == 1:
        updEquipShowSwitch = GameWorld.ChangeDataByDigitPlace(oldEquipShowSwitch, 7, skinIndex)
    else:
        updEquipShowSwitch = GameWorld.ChangeDataByDigitPlace(oldEquipShowSwitch, 8, skinIndex)
    if oldEquipShowSwitch == updEquipShowSwitch:
        return
    curPlayer.SetEquipShowSwitch(updEquipShowSwitch)
    return
def GetPlayerMaxEquipClassLV(curPlayer):
    ## 获取玩家当前解锁的装备阶
    key = "RealmEquipClassLVMap"
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py
@@ -180,24 +180,6 @@
        
    return None
## 检查是否可以换马匹
#  @param curPlayer 当前玩家
#  @return None or True
#  @remarks 函数详细说明.
def CheckCanEquipHorse(curPlayer):
    if curPlayer.GetPlayerVehicle() == IPY_GameWorld.pvHorse :
        #DJ_Res_Horses_AlreadyEquip  对不起,您处于骑马状态中,操作无效
        PlayerControl.NotifyCode(curPlayer, "DJ_Res_Horses_AlreadyEquip")
        return
    horsePack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptHorse)
    if not GetPackIsEmpty(horsePack):
        #Horses_Bag_NoRoom 对不起,您的马匹背包中有物品,操作无效!
        PlayerControl.NotifyCode(curPlayer, "Horses_Bag_NoRoom")
        return
    return True
#===============================================================================
# #将物品放入增值栏的一个空位置中,如果失败,替换第一个位置
# #任务物品:
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/OperControlManager.py
@@ -27,7 +27,6 @@
import ChConfig
import GameWorld
import IPY_GameWorld
import PlayerHorse
import ShareDefine
import SkillCommon
import PassiveBuffEffMng
@@ -170,8 +169,8 @@
        return
    #下马
    if not IsCanDoAction(curServerActionState, IPY_GameWorld.oalRide):
        PlayerHorse.PlayerRideHorseDown(curObj, True)
    #if not IsCanDoAction(curServerActionState, IPY_GameWorld.oalRide):
    #    PlayerHorse.PlayerRideHorseDown(curObj, True)
    
    if not IsCanDoAction(curServerActionState, IPY_GameWorld.oalTransmit):
        #是否在传送的进度条中
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -1367,30 +1367,6 @@
    #if curPlayer.GetPlayerAction() != IPY_GameWorld.paEvent:
    curPlayer.SetCanMove(True)
    
    #同步客户端tick
    #这个封包要在EndLoadMap, 上马之前发, 否则客户端处理时机不对(客户端封包缓存机制)
    #curPlayer.Sync_ClientTick()
    #做上一个地图的上马/骠车逻辑
    #恢复自己的状态
    playerVehicle = curPlayer.GetLastMapPlayerVehicle()
    if playerVehicle == IPY_GameWorld.pvHorse:
        #玩家在骑马中
        if not PlayerHorse.PlayerRideHorseUp(curPlayer, False, False):
        #=======================================================================
        #    playerHorseState = curPlayer.GetLastMapPlayerRidehorseState()
        #    if playerHorseState != IPY_GameWorld.prsNormal:
        #        #切换地图, 恢复急行状态
        #        curPlayer.SetPlayerRidehorseState(playerHorseState)
        #
        #    #刷新人物属性 所有状态
        #    playerControl = PlayerControl.PlayerControl(curPlayer)
        #    playerControl.RefreshAllState()
        # else:
        #=======================================================================
            #此时已经是下马状态不需要刷状态 但是需要通知客户端下马
            PlayerHorse.PlayerRideHorseDown(curPlayer, False)
    #激活玩家(保证持续性Buff处理间隔)
    PlayerControl.SetIsNeedProcess(curPlayer, True)
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossPlayerData.py
@@ -22,7 +22,6 @@
import ChConfig
import PyGameData
import IpyGameDataPY
import PlayerHorse
import PlayerPet
import traceback
import ShareDefine
@@ -35,9 +34,7 @@
MergeData_Skill,    # 只处理ID
MergeData_Buff,     # 即时发送
CrossData_PetState, # 即时发送 宠物出战
CrossData_HorseChange, # 即时发送 骑乘坐骑变更
CrossData_RideHorse, # 即时发送 上下马
) = range(0, 7)
) = range(0, 5)
## 写数据类型定义
(
@@ -49,8 +46,6 @@
CrossDataInfo = {
                 CrossData_PetState:[[WDT_DWORD, WDT_BYTE, WDT_BYTE], lambda curObj, valueList:PlayerPet.CrossServer_DoChangePetState(curObj, valueList)],
                 CrossData_HorseChange:[[WDT_DWORD], lambda curObj, valueList:PlayerHorse.CrossServer_ChangeHorse(curObj, valueList)],
                 CrossData_RideHorse:[[WDT_BYTE], lambda curObj, valueList:PlayerHorse.CrossServer_RideHorse(curObj, valueList)],
                 }
# 影响跨服战力属性列表
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameFuncComm.py
@@ -34,6 +34,7 @@
import IPY_GameWorld
import ItemCommon
import ItemControler
import PlayerHorse
import PlayerArena
import PlayerTask
@@ -42,6 +43,7 @@
FuncOpenLogicDict = {
                     ShareDefine.GameFuncID_Arena:lambda curObj:PlayerArena.DoArenaOpen(curObj),
                     ShareDefine.GameFuncID_Shop:lambda curObj:FunctionNPCCommon.DoShopOpen(curObj),
                     ShareDefine.GameFuncID_Horse:lambda curObj:PlayerHorse.DoHorseOpen(curObj),
                     }
def GetFuncOpenLVIpyData(funcID): return IpyGameDataPY.GetIpyGameData("FuncOpenLV", funcID)
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py
@@ -86,76 +86,6 @@
def UpdatePlayerFPTotalBillboard(curPlayer, isForceUpdate=False, isCheckRule=True):
    ##更新玩家总战斗力
#
#    playerFightPower = PlayerControl.GetFightPower(curPlayer)
#    if not __CheckFightPowerCanUpdate(curPlayer, ChConfig.Def_PDict_FightPower_Total, playerFightPower,
#                                      isForceUpdate, isCheckRule, ChConfig.Def_PDict_FightPower_TotalEx):
#        return
#
#    fightPower = playerFightPower % ChConfig.Def_PerPointValue
#    fightPowerEx = playerFightPower / ChConfig.Def_PerPointValue
#    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FightPower_Total, fightPower,
#                                       ChConfig.Def_PDictType_FightPower)
#    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FightPower_TotalEx, fightPowerEx,
#                                       ChConfig.Def_PDictType_FightPower)
#
#    GameWorld.DebugLog("更新总战斗力:playerFightPower=%s" % (playerFightPower), curPlayer.GetPlayerID())
#
#    UpdatePlayerBillboard(curPlayer, ShareDefine.Def_BT_FightPower, fightPowerEx, fightPower)
#    if bType == ShareDefine.Def_BT_FightPower:
#        playerID = bID
#        fightPowerTotal = cmpValue * ChConfig.Def_PerPointValue + cmpValue2
#        familyID = exInfo[0]
#        playerJob = bType2
#
#        curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
#        if curPlayer:
#            PlayerControl.SetFightPower(curPlayer, fightPowerTotal)
#
#        #更新战盟成员战力
#        PlayerFamily.UpdFamilyMemberFightPower(familyID, playerID, fightPowerTotal)
#
#        #职业战力榜
#        job = playerJob % 10
#        if job in ShareDefine.JobFightPowerBillboardDict:
#            jobBType = ShareDefine.JobFightPowerBillboardDict[job]
#            UpdatePlayerBillboard(bID, bName, bName2, jobBType, bType2, value1, value2, cmpValue, autoSort, cmpValue2, **kwargs)
    return
#def __CheckFightPowerCanUpdate(curPlayer, key, fightPower, isForceUpdate=False, isCheckRule=True, key2=None):
#    ''' 检查玩家可否更新战斗力
#    @param curPlayer 玩家实例
#    @param key 战斗力类型对应key
#    @param fightPower 当前战斗力
#    @param isForceUpdate 是否强制更新(若设置强制更新,在某些潜规则下也不一定能强制更新,如GM等)
#    @param isCheckRule 是否检查战力范围更新差值
#    @return True-可更新
#    '''
#    if fightPower <= 0:
#        return False
#
#    historyFightPower = curPlayer.NomalDictGetProperty(key, 0, ChConfig.Def_PDictType_FightPower)
#    if key2 != None:
#        historyFightPower += curPlayer.NomalDictGetProperty(key2, 0, ChConfig.Def_PDictType_FightPower) * ChConfig.Def_PerPointValue
#
#    if not __CanPlayerBillboardComm(curPlayer):
#        return False
#
#    if isForceUpdate:
#        GameWorld.DebugLog("战斗力更新检查:强制更新 key=%s,fightPower=%s,history=%s"
#                           % (key, fightPower, historyFightPower), curPlayer.GetPlayerID())
#        return True
#
#    if fightPower == historyFightPower:
#        GameWorld.DebugLog("战斗力更新检查:与上次相同,默认不更新 key=%s,fightPower=%s,history=%s"
#                           % (key, fightPower, historyFightPower), curPlayer.GetPlayerID())
#        return False
#
#    return True
def UpdateHorseBillboard(curPlayer, isForceUpdate=False, isUpdateTotal=True):
    ##更新玩家坐骑排行榜
    return
def UpdatePyPetBillboard(curPlayer, isForceUpdate=False, isUpdateTotal=True):
@@ -191,6 +121,7 @@
    kwargs["value3"] = curPlayer.GetFace()
    kwargs["value4"] = curPlayer.GetFacePic()
    kwargs["value5"] = curPlayer.GetModelMark()
    kwargs["value6"] = curPlayer.GetEquipShowSwitch()
    
    groupValue1 = 0
    UpdateBillboard(bType, groupValue1, playerID, playerName, playerOpInfo, playerJob, value1, value2, 
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
@@ -914,19 +913,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 时间戳
@@ -1093,8 +1079,6 @@
    
    #玩家下线/玩家切换地图公用逻辑
    __PlayerLeaveServerLogic(curPlayer, tick, True)
    #骑马玩家下线逻辑
    __RidingHorsePlayerDisconnect(curPlayer)
    #召唤兽死亡
    KillPlayerSummonNPC(curPlayer)
    #更新从本地图离线信息
@@ -4050,14 +4034,6 @@
    
    if curPlayerAction == IPY_GameWorld.paPreparing:
        DoExitPreparing(curPlayer)
    #---玩家交通工具处理---
    curPlayerVehicle = curPlayer.GetPlayerVehicle()
    #玩家骑马中, 下马
    if curPlayerVehicle == IPY_GameWorld.pvHorse:
        #执行下马逻辑
        PlayerHorse.PlayerRideHorseDown(curPlayer, False)
        
    #---其他系统处理---
    
@@ -4223,6 +4199,15 @@
                totalExpRate -= effExpRate
                
    return totalExpRate
##外观额外数据:  其他 * 100 + 坐骑外观
def GetHorseSkinID(curPlayer): return GameWorld.GetValue(curPlayer.GetEquipShowSwitch(), 2, 2)
def SetHorseSkinID(curPlayer, horseSkinID):
    showValue = curPlayer.GetEquipShowSwitch()
    updShowValue = GameWorld.SetValue(showValue, 2, 2, min(horseSkinID, 99))
    curPlayer.SetEquipShowSwitch(updShowValue)
    GameWorld.DebugLog("使用坐骑外观: horseSkinID=%s,showValue=%s,updShowValue=%s" % (horseSkinID, showValue, updShowValue))
    return
#===============================================================================
#---玩家扩展字段---
@@ -4517,16 +4502,9 @@
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)
    #if beforeFightPower != totalFightPower:
    #    CrossPlayerData.OnPlayerFightPowerChange(curPlayer)
@@ -4875,7 +4853,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
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHorse.py
@@ -6,1063 +6,490 @@
#
# @todo:坐骑
# @author hxp
# @date 2019-12-17
# @date 2025-11-04
# @version 1.0
#
# 详细描述: 坐骑
#
#-------------------------------------------------------------------------------
#"""Version = 2019-12-17 18:30"""
#"""Version = 2025-11-04 14:30"""
#-------------------------------------------------------------------------------
import ChConfig
import ItemCommon
import ShareDefine
import NetPackCommon
import PlayerControl
import ChPyNetSendPack
import IPY_GameWorld
import GameWorld
import PlayerControl
import ChConfig
import OperControlManager
import ItemCommon
import ChEquip
import ShareDefine
import DataRecordPack
import ItemControler
import NetPackCommon
import PlayerBillboard
import GameFuncComm
import IpyGameDataPY
import CrossPlayerData
import PlayerActLunhuidian
import PlayerActTask
import PlayerPet
import GameFuncComm
import PlayerOnline
import GameWorld
import ObjPool
import time
Def_HorseEquipIndex = 5
#//03 09 玩家骑马#tagCRideHorse
#
#struct    tagCRideHorse
#{
#    tagHead        Head;
#    BYTE        Ride;        //1: 骑马 0: 下马
#};
def OnRideHorse(index, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Horse):
        return False
    cdTime = ChConfig.TYPE_Player_Tick_Time[ChConfig.TYPE_Player_Tick_HorseChangState]
    # 判断时间是否超过间隔
    if tick - curPlayer.GetTickByType(ChConfig.TYPE_Player_Tick_HorseChangState) <= cdTime:
        #没有到刷新间隔
        return
    curPlayer.SetTickByType(ChConfig.TYPE_Player_Tick_HorseChangState, tick)
    pack = IPY_GameWorld.IPY_CRideHorse()
    #//1: 骑马 0: 下马
    curPlayerRideType = pack.GetRide()
    if PlayerControl.GetCrossMapID(curPlayer):
        # 暂只处理上马
        if curPlayerRideType:
            dataList = [curPlayerRideType]
            CrossPlayerData.SendDataToCrossServer(curPlayer, CrossPlayerData.CrossData_RideHorse, dataList)
        return
    #骑马行为状态, 客户端限制
    if not OperControlManager.IsObjCanDoAction(curPlayer,
                                               ChConfig.Def_Obj_ActState_ClientAct,
                                               IPY_GameWorld.oalRide):
        return
    #下马
    if curPlayerRideType == 0 :
        PlayerRideHorseDown(curPlayer, True)
    #骑马
    elif curPlayerRideType == 1:
        PlayerRideHorseUp(curPlayer, True)
    return
def CrossServer_RideHorse(curPlayer, dataList):
    curPlayerRideType = dataList[0]
    #骑马
    if curPlayerRideType == 1:
        PlayerRideHorseUp(curPlayer, True)
    return
def PlayerRideHorseDown(curPlayer, refreshState=True) :
    ## 玩家下马
    if curPlayer.GetPlayerVehicle() != IPY_GameWorld.pvHorse:
        return
    curPlayer.SetPlayerVehicle(IPY_GameWorld.pvNull)
    curPlayer.Sync_GetoffHorse()
    playerControl = PlayerControl.PlayerControl(curPlayer)
    playerControl.RefreshPlayerAttrByBuff()
    return
def PlayerRideHorseUp(curPlayer, refreshState=True, isNotify=True) :
    ## 玩家上马
    # 未加载成功骑乘会导致模型加载失败报错
    if not curPlayer.GetInitOK():
        return
    #地图不允许骑马 RideLimit_lhs_0
    if not GameWorld.GetMap().GetMapCanRide():
        PlayerControl.NotifyCode(curPlayer, "RideLimit_lhs_0")
        return
    #检查玩家状态,只有在空闲状态才能上马
    if curPlayer.GetPlayerVehicle() != IPY_GameWorld.pvNull :
        #GameWorld.Log("已经有交通工具,无法上马")
        return
    #检查是否装备指定ID物品
    playerEquip = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptEquip)
    itemRideHorse = playerEquip.GetAt(Def_HorseEquipIndex)
    #无指定道具
    if itemRideHorse.IsEmpty():
        return
    #设置玩家为骑马状态
    curPlayer.SetPlayerVehicle(IPY_GameWorld.pvHorse)
    #设置马匹为普通移动状态
    curPlayer.SetPlayerRidehorseState(IPY_GameWorld.prsNormal)
    if isNotify:
        curPlayer.Sync_RideHorse()
    if refreshState:
        playerControl = PlayerControl.PlayerControl(curPlayer)
        playerControl.RefreshPlayerAttrByBuff()
    return True
#=====================================================================
#//A5 01 坐骑激活 #tagPlayerActivateHorse
#
#struct    tagPlayerActivateHorse
#{
#    tagHead        Head;
#    DWORD        HorseID;        //坐骑幻化ID
#};
def ActivateHorseSkinItem(index, curPackData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    playerID = curPlayer.GetPlayerID()
    activateID = curPackData.HorseID
    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Horse):
        return
    ipyData = IpyGameDataPY.GetIpyGameData("HorseSkinPlus", activateID)
    if not ipyData:
        return
    updSkinEndTime = 0
    validTime = ipyData.GetSkinValidTime()
    if validTime:
        curTime = int(time.time())
        skinEndTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserSkinEndTime % activateID)
        if curTime >= skinEndTime:
            updSkinEndTime = curTime + validTime
        else:
            updSkinEndTime = skinEndTime + validTime
    else:
        if GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_HorserSkinPlusState, activateID):
            GameWorld.DebugLog("该坐骑已幻化! activateID=%s" % activateID)
            return
    needItemID = ipyData.GetUnlockItemID()
    needItemCnt = ipyData.GetUnlockItemCnt()
    itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
    hasEnough, itemList = ItemCommon.GetItem_FromPack_ByID(needItemID, itemPack, needItemCnt)
    if not hasEnough:
        GameWorld.DebugLog("坐骑幻化道具不足! needItemID=%s,needItemCnt=%s" % (needItemID, needItemCnt))
        return
    ItemCommon.ReduceItem(curPlayer, itemPack, itemList, needItemCnt, False, ChConfig.ItemDel_Horse)
    if validTime:
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserSkinEndTime % activateID, updSkinEndTime)
        GameWorld.DebugLog("坐骑幻化时效 activateID=%s,updSkinEndTime=%s(%s)" % (activateID, updSkinEndTime, GameWorld.ChangeTimeNumToStr(updSkinEndTime)), playerID)
    #时效及非时效该状态均设置激活
    activateState, updActivateState = GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_HorserSkinPlusState, activateID, 1)
    playerEquip = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptEquip)
    itemRideHorse = playerEquip.GetAt(Def_HorseEquipIndex)
    #无指定道具
    if itemRideHorse.IsEmpty():
        DoChangeHorse(curPlayer, 2, activateID, tick)
    Sync_HorseClassData(curPlayer)
    if validTime:
        SyncHorseSkinTimeInfo(curPlayer, activateID)
    GameWorld.Log("坐骑激活成功!activateID=%s,activateState=%s,updActivateState=%s,updSkinEndTime=%s"
                  % (activateID, activateState, updActivateState, updSkinEndTime), playerID)
    # 刷属性,更新排行榜
    RefreshHorseAttr(curPlayer)
    PlayerControl.WorldNotify(0, "GetMount", [curPlayer.GetName(), ipyData.GetHorseSkinPlusID()])
    return
#//A5 02 坐骑选择 #tagPlayerChooseHorse
#
#struct    tagPlayerChooseHorse
#{
#    tagHead        Head;
#    BYTE        ChooseType;    // 1-按等阶,2-按幻化
#    BYTE        LVID;        // 阶等级或幻化ID
#};
def OnPlayerChangeHorse(index, packData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Horse):
        return
    #检查换装间隔
    if tick - curPlayer.GetLastChangeEquipTick() <= ChConfig.Def_MinChangeEquipTime:
        return
    curPlayer.SetLastChangeEquipTick(tick)
    chooseType = packData.ChooseType
    lvID = packData.LVID
    if not DoChangeHorse(curPlayer, chooseType, lvID, tick):
        return
    if not GameWorld.IsCrossServer():
        dataList = [chooseType, lvID]
        CrossPlayerData.SendDataToCrossServer(curPlayer, CrossPlayerData.CrossData_HorseChange, dataList)
    return
def CrossServer_ChangeHorse(curPlayer, dataList):
    ## 跨服处理 坐骑变更
    chooseType, lvID = dataList
    tick = GameWorld.GetGameWorld().GetTick()
    DoChangeHorse(curPlayer, chooseType, lvID, tick)
    return
def DoChangeHorse(curPlayer, chooseType, lvID, tick):
    ''' 坐骑选择
    @param chooseType: 1-按阶,2-按幻化
    @param lvID:  阶等级或幻化ID
    '''
    # 按阶
    if chooseType == 1:
        horseLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserLV)
        if horseLV < lvID:
            GameWorld.DebugLog("坐骑等级不足,无法使用该坐骑皮肤!  horseLV=%s,lvID=%s" % (horseLV, lvID))
            return
        horseIpyData = IpyGameDataPY.GetIpyGameData("HorseLVUp", lvID)
        if not horseIpyData:
            return
        horseItemID = horseIpyData.GetHorseSkinID()
    # 按幻化
    elif chooseType == 2:
        skinPlusIpyData = IpyGameDataPY.GetIpyGameData("HorseSkinPlus", lvID)
        if not skinPlusIpyData:
            return
        if not CheckHorseSkinState(curPlayer, skinPlusIpyData):
            return
        horseItemID = skinPlusIpyData.GetHorseSkinPlusID()
    else:
        return
    if not horseItemID:
        GameWorld.DebugLog("找不到选择的坐骑ID! chooseType=%s,lvID=%s" % (chooseType, lvID))
        return
    if ItemCommon.FindItemInPackByItemID(curPlayer, horseItemID, IPY_GameWorld.rptEquip):
        GameWorld.DebugLog("已经选择了该坐骑,无需重新选择! horseItemID=%s" % horseItemID)
        return
    isOK = ItemControler.PutItemInTempSwap(curPlayer, horseItemID)
    if not isOK:
        return
    curHorse = ItemCommon.FindItemInPackByItemID(curPlayer, horseItemID, ShareDefine.rptTempSwap)
    if not curHorse:
        return
    isRideHorse = curPlayer.GetPlayerVehicle() == IPY_GameWorld.pvHorse
    # 如果骑乘状态,先下马,换装,再上马
    if isRideHorse:
        PlayerRideHorseDown(curPlayer, False)
    #---执行玩家换装逻辑---
    #if ChEquip.DoPlayerEquipItem(curPlayer, curHorse, ItemCommon.GetEquipPackIndex(curHorse), tick):
    #    if isRideHorse:
    #        PlayerRideHorseUp(curPlayer, False)
    return True
def CheckHorseSkinState(curPlayer, skinPlusIpyData):
    skinID = skinPlusIpyData.GetID()
    if skinPlusIpyData.GetSkinValidTime():
        skinEndTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserSkinEndTime % skinID)
        if not skinEndTime:
            return False
        curTime = int(time.time())
        if curTime >= skinEndTime:
            playerID = curPlayer.GetPlayerID()
            GameWorld.Log("坐骑幻化已过期! skinID=%s,skinEndTime=%s(%s)" % (skinID, skinEndTime, GameWorld.ChangeTimeNumToStr(skinEndTime)), playerID)
            # 发送过期通知邮件,重置为0
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserSkinEndTime % skinID, 0)
            skinItemID = skinPlusIpyData.GetUnlockItemID()
            addItemList = []
            paramList = [skinItemID]
            PlayerControl.SendMailByKey("HorseSkinInvalidNotify", [playerID], addItemList, paramList)
            activateState, updActivateState = GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_HorserSkinPlusState, skinID, 0)
            GameWorld.Log("坐骑幻化过期更新状态! skinID=%s,activateState=%s,updActivateState=%s" % (skinID, activateState, updActivateState), playerID)
            Sync_HorseClassData(curPlayer)
            return False
    else:
        if not GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_HorserSkinPlusState, skinID):
            #GameWorld.DebugLog("坐骑幻化未激活! skinID=%s,activateState=%s" % (skinID, activateState), curPlayer.GetPlayerID())
            return False
    return True
HorseLVStart = 1
def DoHorseOpen(curPlayer):
    ## 马匹功能开启
    horseLV = 1
    ipyData = IpyGameDataPY.GetIpyGameData("HorseLVUp", horseLV)
    if not ipyData:
        return
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorseClassLV, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorseLV, HorseLVStart)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorseExp, 0)
    
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserLV, horseLV)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserEatItemCount, 0)
    for trainType in xrange(1, GetHorseTrainTypes() + 1):
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserTrainLV % trainType, 1)
    ipyDataMgr = IpyGameDataPY.IPY_Data()
    for index in xrange(ipyDataMgr.GetHorseSkinPlusCount()):
        skinPlusIpyData = ipyDataMgr.GetHorseSkinPlusByIndex(index)
        skinID = skinPlusIpyData.GetID()
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserSkinEndTime % skinID, 0)
        GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_HorserSkinPlusState, skinID, 0)
    horseID = ipyData.GetHorseSkinID()
    if not ItemCommon.FindItemInPackByItemID(curPlayer, horseID, IPY_GameWorld.rptEquip):
        isOK = ItemControler.PutItemInTempSwap(curPlayer, horseID)
        if not isOK:
            return
        curHorse = ItemCommon.FindItemInPackByItemID(curPlayer, horseID, ShareDefine.rptTempSwap)
        if not curHorse:
            return
        #---执行玩家换装逻辑---
        #tick = GameWorld.GetGameWorld().GetTick()
        #ChEquip.DoPlayerEquipItem(curPlayer, curHorse, Def_HorseEquipIndex, tick)
    GameWorld.DebugLog("坐骑功能开启! horseLV=%s,horseID=%s" % (horseLV, horseID))
    Sync_HorseClassData(curPlayer)
    skinID = GetDefaultHorseSkinID()
    PlayerControl.SetHorseSkinID(curPlayer, skinID)
    GameWorld.DebugLog("坐骑功能开启! skinID=%s" % (skinID))
    SyncHorseClassInfo(curPlayer)
    RefreshHorseAttr(curPlayer)
    return True
def RefreshHorseAttr(curPlayer, isUpdateBill=True):
    # 坐骑功能属性变更刷新
    CalcHorseAttrEx(curPlayer)
    # 需要更新坐骑榜、强制刷新属性
    PlayerControl.PlayerControl(curPlayer).RefreshPlayerAttrState(billboardFunc=PlayerBillboard.UpdateHorseBillboard if isUpdateBill else None)
    return
def CalcHorseAttrEx(curPlayer):
    ## 计算马匹属性
    return
#    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Horse):
#        return
#
#    allAttrList = [{} for _ in range(4)]
#    allAttrListHorseSoul = [{} for _ in range(4)]
#    allAttrListSkin = [{} for _ in range(4)]
#    allAttrListTrain = [{} for _ in range(4)]
#    allAttrListStar = [{} for _ in range(4)]
#
#    customAttrDictHorse = {}
#    customAttrDictSkin = {}
#
#    horseSpeed = 0 # 坐骑功能增加的速度值,骑乘时才有效果
#    horseLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserLV)
#    # 等阶培养属性
#    #totalItemCount = 0
#    horseBaseAttrInfo = {}
#    ipyDataMgr = IpyGameDataPY.IPY_Data()
#    for index in xrange(ipyDataMgr.GetHorseLVUpCount()):
#        horseIpyData = ipyDataMgr.GetHorseLVUpByIndex(index)
#        dataHorseLV = horseIpyData.GetHorseLV()
#        if dataHorseLV > horseLV:
#            break
#        elif dataHorseLV == horseLV:
#            upItemCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserEatItemCount)
#        else:
#            upItemCount = horseIpyData.GetNeedEatCount()
#
#        # 等阶额外属性
#        lvAttrTypeList = horseIpyData.GetLVAttrType()
#        lvAttrValueList = horseIpyData.GetLVAttrValue()
#        for i, attrID in enumerate(lvAttrTypeList):
#            attrValue = lvAttrValueList[i]
#            if attrID == ShareDefine.Def_Effect_Speed:
#                horseSpeed += attrValue
#                continue
#            PlayerControl.CalcAttrDict_Type(attrID, attrValue, allAttrList)
#            horseBaseAttrInfo[attrID] = horseBaseAttrInfo.get(attrID, 0) + attrValue
#
#        # 培养丹增加属性
#        upItemPerCount = horseIpyData.GetUpEatItemPerCount()
#        if upItemCount and upItemPerCount:
#            upItemAttrTypeList = horseIpyData.GetUpItemAttrType()
#            upItemAttrValueList = horseIpyData.GetUpItemAttrValue()
#            attrMultiple = upItemCount / upItemPerCount
#            for i, attrID in enumerate(upItemAttrTypeList):
#                attrValue = upItemAttrValueList[i]
#                PlayerControl.CalcAttrDict_Type(attrID, attrValue * attrMultiple, allAttrList)
#                horseBaseAttrInfo[attrID] = horseBaseAttrInfo.get(attrID, 0) + attrValue * attrMultiple
#
#    customAttrDictHorse["horseBaseAttrInfo"] = horseBaseAttrInfo
#
##    # 等阶培养丹累加个数属性
##    eatItemAttrInfo = IpyGameDataPY.GetFuncCfg("HorseUpItem", 3)
##    for attrID, attrValue in eatItemAttrInfo:
##        PlayerControl.CalcAttrDict_Type(attrID, attrValue * totalItemCount, allAttrList)
#
#    # 幻化属性
#    initFPAdd = 0 #初始战力
#    horseSkinQualityAttrInfo = {}
#    for index in xrange(ipyDataMgr.GetHorseSkinPlusCount()):
#        skinPlusIpyData = ipyDataMgr.GetHorseSkinPlusByIndex(index)
#        if not CheckHorseSkinState(curPlayer, skinPlusIpyData):
#            continue
#        initFPAdd += skinPlusIpyData.GetInitFightPower()
#        attrTypeList = skinPlusIpyData.GetAttrType()
#        attrValueList = skinPlusIpyData.GetAttrValue()
#        for i, attrID in enumerate(attrTypeList):
#            attrValue = attrValueList[i]
#            if attrID == ShareDefine.Def_Effect_Speed:
#                horseSpeed += attrValue
#                continue
#            PlayerControl.CalcAttrDict_Type(attrID, attrValue, allAttrListSkin)
#
#        #觉醒战力
#        skintype = 1
#        horseID = skinPlusIpyData.GetHorseID()
#        skinData = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorsePetSkinData % (skintype, horseID))
#        skinIpyData = IpyGameDataPY.GetIpyGameDataNotLog('HorsePetSkin', skintype, horseID, skinData / 100)
#        if skinIpyData:
#            for attrID, attrValue in skinIpyData.GetAttrInfo().items():
#                PlayerControl.CalcAttrDict_Type(attrID, attrValue, allAttrListSkin)
#
#        hIpyData = IpyGameDataPY.GetIpyGameData("Horse", horseID)
#        if hIpyData:
#            quality = hIpyData.GetQuality()
#            if quality not in horseSkinQualityAttrInfo:
#                horseSkinQualityAttrInfo[quality] = {}
#            qualityAttrDict = horseSkinQualityAttrInfo[quality]
#            for i, attrID in enumerate(attrTypeList):
#                attrValue = attrValueList[i]
#                qualityAttrDict[attrID] = qualityAttrDict.get(attrID, 0) + attrValue
#
#        #星级
#        horseStar = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserStar % horseID)
#        starIpyData = IpyGameDataPY.GetIpyGameDataNotLog("HorseStarUp", horseID, horseStar)
#        if starIpyData:
#            starAttrType = starIpyData.GetStarAttrType()
#            starAttrValue = starIpyData.GetStarAttrValue()
#            for i, attrID in enumerate(starAttrType):
#                attrValue = starAttrValue[i]
#                if attrID == ShareDefine.Def_Effect_Speed:
#                    horseSpeed += attrValue
#                    continue
#                PlayerControl.CalcAttrDict_Type(attrID, attrValue, allAttrListStar)
#
#    customAttrDictSkin["horseSkinQualityAttrInfo"] = horseSkinQualityAttrInfo
#
#    # 新培养属性
#    for index in xrange(ipyDataMgr.GetHorseTrainCount()):
#        trainIpyData = ipyDataMgr.GetHorseTrainByIndex(index)
#        trainType = trainIpyData.GetTrainType()
#        dataTrainLV = trainIpyData.GetTrainLV()
#        trainLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserTrainLV % trainType)
#
#        if dataTrainLV > trainLV:
#            continue
#        elif dataTrainLV == trainLV:
#            trainItemCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserTrainItemCount % trainType)
#        else:
#            trainItemCount = trainIpyData.GetEatCntTotal()
#
#        # 等阶额外属性
#        lvAttrTypeList = trainIpyData.GetLVAttrTypeList()
#        lvAttrValueList = trainIpyData.GetLVAttrValueList()
#        for i, attrID in enumerate(lvAttrTypeList):
#            attrValue = lvAttrValueList[i]
#            if attrID == ShareDefine.Def_Effect_Speed:
#                horseSpeed += attrValue
#                continue
#            PlayerControl.CalcAttrDict_Type(attrID, attrValue, allAttrListTrain)
#
#        # 培养丹增加属性
#        eatCntEverytime = trainIpyData.GetEatCntEverytime()
#        if trainItemCount and eatCntEverytime:
#            eatItemAttrTypeList = trainIpyData.GetEatItemAttrTypeList()
#            eatItemAttrValueList = trainIpyData.GetEatItemAttrValueList()
#            attrMultiple = trainItemCount / eatCntEverytime
#            for i, attrID in enumerate(eatItemAttrTypeList):
#                attrValue = eatItemAttrValueList[i]
#                PlayerControl.CalcAttrDict_Type(attrID, attrValue * attrMultiple, allAttrListTrain)
#
#    PlayerControl.SetMFPExFightPower(curPlayer, ShareDefine.Def_MFPType_Horse, initFPAdd)
#
#    #GameWorld.DebugLog("坐骑功能属性: horseLV=%s,horseSpeed=%s,totalItemCount=%s,initFPAdd=%s" % (horseLV, horseSpeed, totalItemCount, initFPAdd))
#
#    # 先缓存值,骑乘状态时进行附加
#    curPlayer.SetDict(ChConfig.Def_PlayerKey_SpeedHorse, horseSpeed)
#
#    # 果实对坐骑的加成, 魂石果实算附加属性层,单独计算
#    fightPowerEx = PlayerAttrFruit.CalcAttrFruitAddAtrr(curPlayer, allAttrListHorseSoul, ShareDefine.Def_AttrFruitFunc_Horse)
#    PlayerControl.SetMFPExFightPower(curPlayer, ShareDefine.Def_MFPType_HorseSoul, fightPowerEx)
#
#    # 保存计算值
#    PlayerControl.SetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_Horse, allAttrList, customAttrDict=customAttrDictHorse)
#    PlayerControl.SetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_HorseSoul, allAttrListHorseSoul)
#    PlayerControl.SetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_HorseSkin, allAttrListSkin, customAttrDict=customAttrDictSkin)
#    PlayerControl.SetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_HorseTarin, allAttrListTrain)
#    PlayerControl.SetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_HorseStar, allAttrListStar)
#    return
def GetHorseSkinActCount(curPlayer):
    horseSkinActCount = 0
    ipyDataMgr = IpyGameDataPY.IPY_Data()
    for index in xrange(ipyDataMgr.GetHorseSkinPlusCount()):
        skinPlusIpyData = ipyDataMgr.GetHorseSkinPlusByIndex(index)
        if not CheckHorseSkinState(curPlayer, skinPlusIpyData):
            continue
        horseSkinActCount += 1
    return horseSkinActCount
#// A5 27 坐骑提升 #tagCMHorseUp
#
#struct    tagCMHorseUp
#{
#    tagHead        Head;
#    WORD        UseItemCnt;        //消耗材料个数
#    BYTE        IsAutoBuy;        //是否自动购买
#};
def OnHorseClassLVUP(index, curPackData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    costItemCount = curPackData.UseItemCnt # 消耗材料个数
    isAutoBuy = curPackData.IsAutoBuy # 是否自动购买
    # 判断玩家是否可以升级马匹
def PlayerHorseLogin(curPlayer):
    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Horse):
        GameWorld.DebugLog("坐骑未开启!")
        return
    horseLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserLV)
    curEatItemCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserEatItemCount)
    if horseLV <= 0:
        GameWorld.DebugLog("坐骑提升 该坐骑未激活 horseLV=%s" % horseLV)
        return
    horseIpyData = IpyGameDataPY.GetIpyGameData("HorseLVUp", horseLV)
    if not horseIpyData:
        return
    needEatCount = horseIpyData.GetNeedEatCount()
    if not needEatCount:
        GameWorld.DebugLog("坐骑已满级!horseLV=%s" % horseLV)
        return
    costItemID = IpyGameDataPY.GetFuncCfg("HorseUpItem", 1)
    if not costItemID or not costItemCount:
        return
    costItemIndexList, bindCnt, unBindCnt = ItemCommon.GetPackItemBindStateIndexInfo(curPlayer, costItemID, costItemCount)
    lackCnt = costItemCount - bindCnt - unBindCnt
    if lackCnt > 0 and not isAutoBuy:
        GameWorld.DebugLog("消耗道具不足,无法升级坐骑!costItemID=%s,costItemCount=%s,bindCnt=%s,unBindCnt=%s,lackCnt=%s"
                           % (costItemID, costItemCount, bindCnt, unBindCnt, lackCnt))
        return
    delCnt = costItemCount
    if lackCnt > 0:
        lackCost = ItemCommon.GetAutoBuyItemNeedGold({costItemID:lackCnt})
        if lackCost <= 0:
            return
        infoDict = {ChConfig.Def_Cost_Reason_SonKey:costItemID}
        if not PlayerControl.PayMoney(curPlayer, IPY_GameWorld.TYPE_Price_Gold_Money, lackCost, ChConfig.Def_Cost_BuyStoreItem, infoDict):
            return
        delCnt -= lackCnt
    # 扣除消耗
    if delCnt:
        ItemCommon.DelCostItemByBind(curPlayer, costItemIndexList, bindCnt, unBindCnt, delCnt, ChConfig.ItemDel_Horse)
    updClassLV = horseLV
    updEatItemCount = curEatItemCount + costItemCount
    GameWorld.DebugLog("坐骑培养: horseLV=%s,curEatItemCount=%s,costItemCount=%s,updEatItemCount=%s,needEatCount=%s"
                       % (horseLV, curEatItemCount, costItemCount, updEatItemCount, needEatCount))
    if updEatItemCount >= needEatCount:
        updClassLV += 1
        updEatItemCount -= needEatCount
        GameWorld.DebugLog("    升阶: updClassLV=%s,updEatItemCount=%s" % (updClassLV, updEatItemCount))
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserLV, updClassLV)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserEatItemCount, updEatItemCount)
    # 升阶
    upItemPerCount = horseIpyData.GetUpEatItemPerCount()
    upCnt = costItemCount / upItemPerCount
    if updClassLV > horseLV:
        # 玩家马匹进阶
        DataRecordPack.DR_NewHorseByClassUp(curPlayer, updClassLV, 0)
    Sync_HorseClassData(curPlayer)
    # 刷属性,更新排行榜
    RefreshHorseAttr(curPlayer)
    PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_HorseUpItem, costItemCount)
    PlayerActLunhuidian.AddLunhuidianValue(curPlayer, PlayerActLunhuidian.AwardType_UseItem, costItemID, costItemCount)
    SyncHorseClassInfo(curPlayer)
    SyncHorseSkinInfo(curPlayer)
    return
#// A5 31 坐骑培养 #tagCMHorseTrain
#// B2 01 坐骑升级 #tagCSHorseLVUP
#
#struct    tagCMHorseTrain
#struct    tagCSHorseLVUP
#{
#    tagHead        Head;
#    BYTE        TrainType;        //培养类型: 1-基础培养,2-特殊培养,3-百分比培养
#    WORD        UseItemCnt;        //消耗材料个数
#    tagHead         Head;
#    BYTE        IsQuick;    // 是否快速升级,0-只消耗1个道具;1-消耗升1级的道具
#};
def OnHorseTrain(index, curPackData, tick):
def OnHorseLVUP(index, curPackData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    trainType = curPackData.TrainType # 培养类型
    costItemCount = curPackData.UseItemCnt # 消耗材料个数
    isQuick = curPackData.IsQuick
    
    trainLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserTrainLV % trainType)
    curEatItemCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserTrainItemCount % trainType)
    GameWorld.DebugLog("坐骑培养: trainType=%s,trainLV=%s,costItemCount=%s,curEatItemCount=%s"
                       % (trainType, trainLV, costItemCount, curEatItemCount))
    if trainType <= 0 or trainType > GetHorseTrainTypes():
    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Horse):
        return
    
    if trainLV <= 0:
        GameWorld.DebugLog("    坐骑培养未激活  trainType=%s" % trainType)
    classLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorseClassLV)
    horseLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorseLV)
    curExp = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorseExp)
    classIpyData = IpyGameDataPY.GetIpyGameData("HorseClass", classLV)
    if not classIpyData:
        return
    maxLV = classIpyData.GetMaxHorseLV()
    if horseLV >= maxLV:
        GameWorld.DebugLog("坐骑该阶已满级! classLV=%s,horseLV=%s >= %s" % (classLV, horseLV, maxLV))
        return
    
    trainIpyData = IpyGameDataPY.GetIpyGameData("HorseTrain", trainType, trainLV)
    if not trainIpyData:
    needExp = classIpyData.GetLVUPItemCnt() # 所需道具数,1个=1点经验
    if needExp <= 0:
        GameWorld.DebugLog("坐骑该阶没有升级消耗! classLV=%s,horseLV=%s,needExp=%s" % (classLV, horseLV, needExp))
        return
    
    needRealmLV = trainIpyData.GetNeedRealmLV()
    curRealmLV = PlayerControl.GetTrainRealmLVReal(curPlayer, 1)
    if curRealmLV < needRealmLV:
        GameWorld.DebugLog("    境界不足,无法培养!  curRealmLV(%s) < needRealmLV(%s)" % (curRealmLV, needRealmLV))
        return
    needEatCountTotal = trainIpyData.GetEatCntTotal()
    if not needEatCountTotal:
        GameWorld.DebugLog("    该培养已满级!")
        return
    costItemIDList = IpyGameDataPY.GetFuncEvalCfg("HorseTrain", 1)
    costItemID = costItemIDList[trainType - 1]
    if not costItemID or not costItemCount:
        return
    costItemIndexList, bindCnt, unBindCnt = ItemCommon.GetPackItemBindStateIndexInfo(curPlayer, costItemID, costItemCount)
    lackCnt = costItemCount - bindCnt - unBindCnt
    if lackCnt > 0:
        GameWorld.DebugLog("    消耗道具不足,无法培养!costItemID=%s,costItemCount=%s,bindCnt=%s,unBindCnt=%s,lackCnt=%s"
                           % (costItemID, costItemCount, bindCnt, unBindCnt, lackCnt))
        return
    delCnt = costItemCount
    # 扣除消耗
    if delCnt:
        ItemCommon.DelCostItemByBind(curPlayer, costItemIndexList, bindCnt, unBindCnt, delCnt, ChConfig.ItemDel_Horse)
    costItemCount = 0
    if isQuick:
        costItemCount = max(0, needExp - curExp)
    elif curExp < needExp:
        costItemCount = 1
        
    updClassLV = trainLV
    updEatItemCount = curEatItemCount + costItemCount
    GameWorld.DebugLog("    updEatItemCount=%s,needEatCountTotal=%s" % (updEatItemCount, needEatCountTotal))
    if updEatItemCount >= needEatCountTotal:
        updClassLV += 1
        updEatItemCount -= needEatCountTotal
        GameWorld.DebugLog("    进阶: updClassLV=%s,updEatItemCount=%s" % (updClassLV, updEatItemCount))
    costItemID = IpyGameDataPY.GetFuncCfg("HorseUpItem", 1)
    if costItemID and costItemCount > 0:
        costItemIndexList, bindCnt, unBindCnt = ItemCommon.GetPackItemBindStateIndexInfo(curPlayer, costItemID, costItemCount)
        lackCnt = costItemCount - bindCnt - unBindCnt
        if lackCnt > 0:
            GameWorld.DebugLog("消耗道具不足,无法升级坐骑! costItemID=%s,costItemCount=%s,bindCnt=%s,unBindCnt=%s,lackCnt=%s"
                               % (costItemID, costItemCount, bindCnt, unBindCnt, lackCnt))
            return
        
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserTrainLV % trainType, updClassLV)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserTrainItemCount % trainType, updEatItemCount)
        # 扣除消耗
        ItemCommon.DelCostItemByBind(curPlayer, costItemIndexList, bindCnt, unBindCnt, costItemCount, ChConfig.ItemDel_Horse)
    addExp = costItemCount # 暂固定1个道具=1点经验
    updExp = curExp + addExp
    GameWorld.DebugLog("坐骑加经验: classLV=%s,horseLV=%s,curExp=%s,costItemCount=%s,updExp=%s/%s"
                       % (classLV, horseLV, curExp, costItemCount, updExp, needExp))
    
    # 升阶
    if updClassLV > trainLV:
        pass
    updHorseLV = horseLV
    if updExp >= needExp:
        updExp -= needExp
        updHorseLV += 1
        GameWorld.DebugLog("    升级: updHorseLV=%s,updExp=%s" % (updHorseLV, updExp))
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorseLV, updHorseLV)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorseExp, updExp)
    
    Sync_HorseClassData(curPlayer)
    # 刷属性,更新排行榜
    RefreshHorseAttr(curPlayer)
    if trainType == 2:
        PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_HorseTrainItem2, costItemCount)
    elif trainType == 3:
        PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_HorseTrainItem3, costItemCount)
    elif trainType == 1:
        PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_HorseTrainItem1, costItemCount)
    SyncHorseClassInfo(curPlayer)
    # 有升级额外处理
    if updHorseLV > horseLV:
        RefreshHorseAttr(curPlayer)
    return
#// A5 35 坐骑升星 #tagCMHorseStarUp
#// B2 02 坐骑进阶 #tagCSHorseClassUP
#
#struct    tagCMHorseStarUp
#struct    tagCSHorseClassUP
#{
#    tagHead        Head;
#    DWORD        HorseID;        //坐骑ID,对应坐骑表ID
#    tagHead         Head;
#};
def OnHorseStarUp(index, clientData, tick):
def OnHorseClassUP(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    playerID = curPlayer.GetPlayerID()
    horseID = clientData.HorseID
    
    horseStar = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserStar % horseID)
    nextStar = horseStar + 1
    nextIpyData = IpyGameDataPY.GetIpyGameData("HorseStarUp", horseID, nextStar)
    if not nextIpyData:
        GameWorld.DebugLog("坐骑不存在该星级,无法升星. horseID=%s,curStar=%s" % (horseID, horseStar), playerID)
    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Horse):
        return
    needItemList = nextIpyData.GetStarUpNeedItemList()
    if not needItemList:
    classLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorseClassLV)
    horseLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorseLV)
    classIpyData = IpyGameDataPY.GetIpyGameData("HorseClass", classLV)
    if not classIpyData:
        return
    maxLV = classIpyData.GetMaxHorseLV()
    if horseLV < maxLV:
        GameWorld.DebugLog("坐骑该阶未满级无法升阶! classLV=%s,horseLV=%s < %s" % (classLV, horseLV, maxLV))
        return
    updClassLV = classLV + 1
    if not IpyGameDataPY.GetIpyGameDataNotLog("HorseClass", updClassLV):
        GameWorld.DebugLog("坐骑已满阶! classLV=%s" % (classLV))
        return
    costItemID = IpyGameDataPY.GetFuncCfg("HorseUpItem", 2)
    costItemCnt = classIpyData.GetClassUPItemCnt()
    if not costItemID or not costItemCnt:
        return
    itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
    lackItemDict, delInfoDict = ItemCommon.GetCostItemIndexList({costItemID:costItemCnt}, itemPack)
    if lackItemDict:
        GameWorld.DebugLog("坐骑进阶物品不足! classLV=%s,costItemID=%s,costItemCnt=%s,lackItemDict=%s"
                           % (classLV, costItemID, costItemCnt, lackItemDict), playerID)
        return
    ItemCommon.DelCostItem(curPlayer, itemPack, delInfoDict, "HorseClassUP")
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorseClassLV, updClassLV)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorseLV, HorseLVStart)
    GameWorld.DebugLog("坐骑进阶: updClassLV=%s" % (updClassLV), playerID)
    SyncHorseClassInfo(curPlayer)
    RefreshHorseAttr(curPlayer)
    return
def RefreshHorseAttr(curPlayer):
    CalcHorseAttr(curPlayer)
    PlayerOnline.GetOnlinePlayer(curPlayer).RefreshRoleAttr()
    return
def CalcHorseAttr(curPlayer):
    playerID = curPlayer.GetPlayerID()
    attrDict = {}
    classLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorseClassLV)
    horseLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorseLV)
    ipyDataMgr = IpyGameDataPY.IPY_Data()
    for index in range(ipyDataMgr.GetHorseClassCount()):
        ipyData = ipyDataMgr.GetHorseClassByIndex(index)
        ipyClassLV = ipyData.GetClassLV()
        if classLV < ipyClassLV:
            continue
        # 阶特殊属性
        specAttrIDList = ipyData.GetClassSpecAttrIDList()
        specAttrValueList = ipyData.GetClassSpecAttrValueList()
        for index, attrID in enumerate(specAttrIDList):
            attrValue = specAttrValueList[index] if len(specAttrValueList) > index else 0
            attrDict[attrID] = attrDict.get(attrID, 0) + attrValue
        # 阶基础属性
        attrIDList = ipyData.GetAttrIDList()
        attrValueList = ipyData.GetClassAttrValueList()
        for index, attrID in enumerate(attrIDList):
            attrValue = attrValueList[index] if len(attrValueList) > index else 0
            attrDict[attrID] = attrDict.get(attrID, 0) + attrValue
        # 阶等级属性
        if ipyClassLV < classLV:
            attrLV = ipyData.GetMaxHorseLV()
        else:
            attrLV = horseLV
        perLVAttrValueList = ipyData.GetPerLVAttrValueList()
        for index, attrID in enumerate(attrIDList):
            attrValue = perLVAttrValueList[index] if len(perLVAttrValueList) > index else 0
            attrDict[attrID] = attrDict.get(attrID, 0) + attrValue * attrLV
    #GameWorld.DebugLog("坐骑阶属性: %s" % attrDict, playerID)
    # 外观属性
    for index in range(ipyDataMgr.GetHorseSkinCount()):
        ipyData = ipyDataMgr.GetHorseSkinByIndex(index)
        horseSkinID = ipyData.GetSkinID()
        if not IsHorseSkinCanUse(curPlayer, horseSkinID, ipyData):
            continue
        attrIDList = ipyData.GetAttrIDList()
        if not attrIDList:
            continue
        initAttrValueList = ipyData.GetInitAttrValueList()
        perStarAddList = ipyData.GetAttrPerStarAddList()
        star = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorseSkinStar % horseSkinID)
        for aIndex, attrID in enumerate(attrIDList):
            initValue = initAttrValueList[aIndex] if len(initAttrValueList) > aIndex else 0
            perStarAdd = perStarAddList[aIndex] if len(perStarAddList) > aIndex else 0
            attrValue = initValue + perStarAdd * star
            attrDict[attrID] = attrDict.get(attrID, 0) + attrValue
    # 保存计算值
    GameWorld.DebugLog("坐骑属性: %s" % attrDict, playerID)
    PlayerOnline.GetOnlinePlayer(curPlayer).SetCalcAttr(ChConfig.Def_CalcAttr_Horse, attrDict)
    return
def SyncHorseClassInfo(curPlayer):
    clientPack = ObjPool.GetPoolMgr().acquire(ChPyNetSendPack.tagSCHorseClassInfo)
    clientPack.ClassLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorseClassLV)
    clientPack.HorseLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorseLV)
    clientPack.Exp = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorseExp)
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    return
## ----------------------------------------- 外观 --------------------------------------------------
#// B2 03 坐骑外观操作 #tagCSHorseSkinOP
#
#struct    tagCSHorseSkinOP
#{
#    tagHead         Head;
#    BYTE        OPType;    // 操作 1-激活;2-佩戴;3-升星
#    BYTE        SkinID;    // 外观ID,佩戴时发0即为卸下
#};
def OnHorseSkinOP(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    opType = clientData.OPType
    horseSkinID = clientData.SkinID
    # 激活
    if opType == 1:
        AddHorseSkin(curPlayer, horseSkinID)
    # 佩戴
    elif opType == 2:
        OnUseHorseSkin(curPlayer, horseSkinID)
    # 升级
    elif opType == 3:
        OnHorseSkinStarUP(curPlayer, horseSkinID)
    return
def OnMinute(curPlayer):
    curTime = int(time.time())
    delIDList = []
    ipyDataMgr = IpyGameDataPY.IPY_Data()
    for index in range(ipyDataMgr.GetHorseSkinCount()):
        ipyData = ipyDataMgr.GetHorseSkinByIndex(index)
        horseSkinID = ipyData.GetSkinID()
        if not GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_HorseSkinState, horseSkinID):
            # 未激活的不处理
            continue
        endTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorseSkinEndTime % horseSkinID)
        if not endTime or endTime > curTime:
            # 永久或未过期
            continue
        if DelHorseSkin(curPlayer, horseSkinID, False, "HorseSkinTimeout"):
            delIDList.append(horseSkinID)
    if delIDList:
        RefreshHorseAttr(curPlayer)
    return
def AddHorseSkin(curPlayer, horseSkinID, setExpireTimes=None, isFree=False):
    if horseSkinID <= 0:
        return
    playerID = curPlayer.GetPlayerID()
    ipyData = IpyGameDataPY.GetIpyGameData("HorseSkin", horseSkinID)
    if not ipyData:
        return
    if ipyData.GetUnlockWay() != 2:
        GameWorld.DebugLog("非道具激活的不用添加: horseSkinID=%s" % (horseSkinID), playerID)
        return
    if not isFree:
        itemID = ipyData.GetUnlockValue()
        itemCount = ipyData.GetUnlockNeedCnt()
        if not itemID or not itemCount:
            return
        needItemList = [[itemID, itemCount]]
        itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
        lackItemDict, delInfoDict = ItemCommon.GetCostItemIndexList(needItemList, itemPack)
        if lackItemDict:
            GameWorld.DebugLog("激活所需物品不足! horseSkinID=%s,lackItemDict=%s" % (horseSkinID, lackItemDict), playerID)
            return
        ItemCommon.DelCostItem(curPlayer, itemPack, delInfoDict, "AddHorseSkin")
    ipyExpireSeconds = ipyData.GetExpireMinutes() * 60
    curTime = int(time.time())
    state = GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_HorseSkinState, horseSkinID)
    endTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorseSkinEndTime % horseSkinID)
    GameWorld.Log("添加坐骑外观: horseSkinID=%s,setExpireTimes=%s,state=%s,endTime=%s,ipyExpireSeconds=%s,curTime=%s"
                  % (horseSkinID, setExpireTimes, state, endTime, ipyExpireSeconds, curTime), playerID)
    updEndTime = endTime
    # 指定时长的,如GM指定
    if setExpireTimes > 0:
        updEndTime = curTime + setExpireTimes
        GameWorld.Log("    指定时长: horseSkinID=%s,updEndTime=%s" % (horseSkinID, updEndTime), playerID)
    # 永久
    elif ipyExpireSeconds == 0 or setExpireTimes == 0:
        updEndTime = 0
        GameWorld.Log("    永久时长: horseSkinID=%s,updEndTime=%s" % (horseSkinID, updEndTime), playerID)
    else:
        # 未过期
        if endTime > curTime:
            updEndTime = endTime + ipyExpireSeconds
            GameWorld.Log("    累加时长: horseSkinID=%s,updEndTime=%s" % (horseSkinID, updEndTime), playerID)
        else:
            updEndTime = curTime + ipyExpireSeconds
            GameWorld.Log("    重新激活: horseSkinID=%s,updEndTime=%s" % (horseSkinID, updEndTime), playerID)
    GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_HorseSkinState, horseSkinID, 1)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorseSkinEndTime % horseSkinID, updEndTime)
    RefreshHorseAttr(curPlayer)
    SyncHorseSkinInfo(curPlayer, [horseSkinID])
    return True
def DelHorseSkin(curPlayer, horseSkinID, isRefreshAttr=True, notifyMail=""):
    playerID = curPlayer.GetPlayerID()
    ipyData = IpyGameDataPY.GetIpyGameData("HorseSkin", horseSkinID)
    if not ipyData:
        return
    if not GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_HorseSkinState, horseSkinID):
        return
    GameWorld.Log("删除坐骑外观: horseSkinID=%s,notifyMail=%s" % (horseSkinID, notifyMail), playerID)
    GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_HorseSkinState, horseSkinID, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorseSkinEndTime % horseSkinID, 0)
    # 星级不重置,重新激活后再次生效
    if PlayerControl.GetHorseSkinID(curPlayer) == horseSkinID:
        defaultSkinID = GetDefaultHorseSkinID()
        PlayerControl.SetHorseSkinID(curPlayer, defaultSkinID)
        GameWorld.DebugLog("玩家佩戴的坐骑外观被删除,随机重置默认! defaultSkinID=%s" % defaultSkinID, playerID)
    if isRefreshAttr:
        RefreshHorseAttr(curPlayer)
    SyncHorseSkinInfo(curPlayer, [horseSkinID])
    if notifyMail:
        PlayerControl.SendMailByKey(notifyMail, [playerID], [], [horseSkinID])
    return True
def GetDefaultHorseSkinID():
    ipyDataMgr = IpyGameDataPY.IPY_Data()
    for index in range(ipyDataMgr.GetHorseSkinCount()):
        ipyData = ipyDataMgr.GetHorseSkinByIndex(index)
        horseSkinID = ipyData.GetSkinID()
        if ipyData.GetUnlockWay() != 1:
            continue
        if ipyData.GetUnlockValue() > 0:
            # 取0阶的
            continue
        return horseSkinID
    return 0
def IsHorseSkinCanUse(curPlayer, horseSkinID, ipyData=None):
    ## 坐骑外观是否可用
    state = GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_HorseSkinState, horseSkinID)
    if state:
        return True
    if not ipyData:
        ipyData = IpyGameDataPY.GetIpyGameData("HorseSkin", horseSkinID)
    if ipyData:
        unlockWay = ipyData.GetUnlockWay()
        if unlockWay == 1:
            classLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorseClassLV)
            if classLV >= ipyData.GetUnlockValue():
                return True
    return False
def OnUseHorseSkin(curPlayer, horseSkinID):
    playerID = curPlayer.GetPlayerID()
    if horseSkinID and not IsHorseSkinCanUse(curPlayer, horseSkinID):
        GameWorld.DebugLog("该坐骑外观不可用! horseSkinID=%s" % (horseSkinID), playerID)
        return
    PlayerControl.SetHorseSkinID(curPlayer, horseSkinID)
    return
def OnHorseSkinStarUP(curPlayer, horseSkinID):
    playerID = curPlayer.GetPlayerID()
    if not IsHorseSkinCanUse(curPlayer, horseSkinID):
        GameWorld.DebugLog("该坐骑外观不可用! horseSkinID=%s" % (horseSkinID), playerID)
        return
    ipyData = IpyGameDataPY.GetIpyGameData("HorseSkin", horseSkinID)
    if not ipyData:
        return
    starMax = ipyData.GetStarMax()
    curStar = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorseSkinStar % horseSkinID)
    if curStar >= starMax:
        GameWorld.DebugLog("星级已满! horseSkinID=%s,curStar=%s >= %s" % (horseSkinID, curStar, starMax), playerID)
        return
    if ipyData.GetUnlockWay() != 2:
        return
    itemID = ipyData.GetUnlockValue()
    itemCount = ipyData.GetUnlockNeedCnt()
    if not itemID or not itemCount:
        return
    needItemList = [[itemID, itemCount]]
    itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
    lackItemDict, delInfoDict = ItemCommon.GetCostItemIndexList(needItemList, itemPack)
    if lackItemDict:
        GameWorld.DebugLog("坐骑升星所需物品不足! horseID=%s,nextStar=%s,needItemList=%s,lackItemDict=%s"
                           % (horseID, nextStar, needItemList, lackItemDict), playerID)
        GameWorld.DebugLog("升星所需物品不足! horseSkinID=%s,lackItemDict=%s" % (horseSkinID, lackItemDict), playerID)
        return
    ItemCommon.DelCostItem(curPlayer, itemPack, delInfoDict, "HorseSkinStarUP")
    
    ItemCommon.DelCostItem(curPlayer, itemPack, delInfoDict, "HorseStarUp")
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserStar % horseID, nextStar)
    GameWorld.DebugLog("坐骑升星. horseID=%s,curStar=%s,nextStar=%s" % (horseID, horseStar, nextStar), playerID)
    nextStar = curStar + 1
    GameWorld.DebugLog("升星! horseSkinID=%s,nextStar=%s" % (horseSkinID, nextStar), playerID)
    SetHorseSkinStar(curPlayer, horseSkinID, nextStar)
    return
def SetHorseSkinStar(curPlayer, horseSkinID, setStar):
    if not IsHorseSkinCanUse(curPlayer, horseSkinID):
        return
    ipyData = IpyGameDataPY.GetIpyGameData("HorseSkin", horseSkinID)
    if not ipyData:
        return
    setStar = min(setStar, ipyData.GetStarMax())
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorseSkinStar % horseSkinID, setStar)
    RefreshHorseAttr(curPlayer)
    SyncHorseStarInfo(curPlayer, horseID)
    return
    SyncHorseSkinInfo(curPlayer, [horseSkinID])
    return True
def GetHorseTrainTypes():
    return len(IpyGameDataPY.GetFuncEvalCfg("HorseTrain", 1))
def PlayerHorseLogin(curPlayer):
    ##坐骑登录处理
    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Horse):
        return
    # 坐骑幻化状态多值支持修改,线上版本做旧值转移
    oldVerSkinStateKey = "HorserSkinPlusState"
    oldVerSkinStateValue = curPlayer.NomalDictGetProperty(oldVerSkinStateKey)
    if oldVerSkinStateValue:
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserSkinPlusState % 0, oldVerSkinStateValue)
        PlayerControl.NomalDictSetProperty(curPlayer, oldVerSkinStateKey, 0)
        GameWorld.Log("线上版本转移坐骑幻化状态记录字典值! oldVerSkinStateValue=%s" % (oldVerSkinStateValue), curPlayer.GetPlayerID())
    # 培养是后面加的功能,每次登录补检查一下功能开始时设置为培养1级
    for trainType in xrange(1, GetHorseTrainTypes() + 1):
        if curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserTrainLV % trainType) == 0:
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorserTrainLV % trainType, 1)
    Sync_HorseClassData(curPlayer)
    SyncHorsePetSkinData(curPlayer)
    SyncHorseSkinTimeInfo(curPlayer)
    SyncHorseStarInfo(curPlayer)
    return
def Sync_HorseClassData(curPlayer):
    horseData = ChPyNetSendPack.tagTrainHorseData()
    horseData.Clear()
    horseData.LV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserLV)
    horseData.EatItemCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserEatItemCount)
    horseData.SkinPlusState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserSkinPlusState)
    horseData.TrainLVList = []
    horseData.TrainItemCountList = []
    for trainType in xrange(1, GetHorseTrainTypes() + 1):
        horseData.TrainLVList.append(curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserTrainLV % trainType))
        horseData.TrainItemCountList.append(curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserTrainItemCount % trainType))
    horseData.TrainTypes = len(horseData.TrainLVList)
    horseData.SkinPlusStateList = GetHorseSkinPlusStateList(curPlayer)
    horseData.SkinPlusStateCount = len(horseData.SkinPlusStateList)
    NetPackCommon.SendFakePack(curPlayer, horseData)
    return
def GetHorseSkinPlusStateList(curPlayer):
    maxSkinID = 0
    skinPlusStateList = []
    ipyDataMgr = IpyGameDataPY.IPY_Data()
    skinCnt = ipyDataMgr.GetHorseSkinPlusCount()
    for index in xrange(skinCnt):
        maxSkinID = max(maxSkinID, ipyDataMgr.GetHorseSkinPlusByIndex(index).GetID())
    for index in xrange(maxSkinID / 31+1):
        skinPlusStateList.append(curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserSkinPlusState % index))
    return skinPlusStateList
def GetHorseSumLV(curPlayer):
    ## 坐骑总等级
    return curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserLV)
def IsHorseLVFull(curPlayer):
    ## 坐骑是否满级
    horseLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserLV)
    horseIpyData = IpyGameDataPY.GetIpyGameData("HorseLVUp", horseLV)
    if not horseIpyData:
        return False
    needEatCount = horseIpyData.GetNeedEatCount()
    if not needEatCount:
        return True
    return False
#============================骑宠觉醒=============================
#// A5 29 骑宠觉醒 #tagCMHorsePetAwake
#
#struct    tagCMHorsePetAwake
#{
#    tagHead        Head;
#    WORD    Type;    // 1-坐骑 2-灵宠
#    DWORD    ID;    // 对应坐骑表灵宠表ID
#    DWORD    EatItemID;    // 吞噬的物品ID
#};
def OnHorsePetAwake(index, curPackData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    skintype = curPackData.Type
    horsePetID = curPackData.ID
    eatItemID = curPackData.EatItemID
    GameWorld.DebugLog("骑宠觉醒: skintype=%s,horsePetID=%s,eatItemID=%s" % (skintype, horsePetID, eatItemID))
    if not IpyGameDataPY.GetIpyGameDataByCondition('HorsePetSkin', {'Type':skintype, 'ID':horsePetID}):
        return
#    if skintype == 1:
#        #坐骑玩法修改,暂关闭坐骑觉醒
#        return
#        if not IsHorseMaxLV(curPlayer, horsePetID):
#            GameWorld.DebugLog('骑宠觉醒 对应骑宠未满级 horsePetID=%s' % horsePetID)
#            return
#    else:
#        if not PlayerPet.IsPetMaxLV(curPlayer, horsePetID):
#            GameWorld.DebugLog('骑宠觉醒 对应骑宠未满级 horsePetID=%s' % horsePetID)
#            return
    skinData = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorsePetSkinData % (skintype, horsePetID), 0)
    curSkinLV, curSkinIndex = skinData / 100, skinData % 100
    ipyData = IpyGameDataPY.GetIpyGameData('HorsePetSkin', skintype, horsePetID, curSkinLV)
    if not ipyData:
        return
    upNeedExp = ipyData.GetNeedExp()
    if not upNeedExp:
        GameWorld.DebugLog('骑宠觉醒 已满级')
        return
    curExp = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorsePetSkinExp % (skintype, horsePetID), 0)
    curItem = GameWorld.GetGameData().GetItemByTypeID(eatItemID)
    if not curItem:
        return
    curEff = curItem.GetEffectByIndex(4)
    curEffID = curEff.GetEffectID()
    addExp = curEff.GetEffectValue(0)
    if curEffID != ChConfig.Def_Effect_HorsePetSkinExp or not addExp:
        GameWorld.ErrLog('物品效果5没有配置骑宠觉醒经验效果! eatItemID=%s,curEffID=%s,addExp=%s,needEffID=%s'
                         % (eatItemID, curEffID, addExp, ChConfig.Def_Effect_HorsePetSkinExp))
        return
    itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
    hasEnough, itemList = ItemCommon.GetItem_FromPack_ByID(eatItemID, itemPack, 1)
    if not hasEnough:
        GameWorld.DebugLog("OnHorsePetAwake() item(%s[%s]) isn't enough" % (eatItemID, 1))
        return
    ItemCommon.ReduceItem(curPlayer, itemPack, itemList, 1, False, ChConfig.ItemDel_HorsePetAwake)
    updExp = curExp + addExp
    updSkinLV = curSkinLV
    updSkinIndex = curSkinIndex
    if updExp >= upNeedExp:
        for _ in xrange(10):
            ipyData = IpyGameDataPY.GetIpyGameDataNotLog('HorsePetSkin', skintype, horsePetID, updSkinLV + 1)
            if not ipyData:
                break
            if updExp < upNeedExp:
                break
            updExp -= upNeedExp
            updSkinLV += 1
            updSkinIndex = ipyData.GetSkinIndex()
            upNeedExp = ipyData.GetNeedExp()
    updSkinData = updSkinLV * 100 + updSkinIndex
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorsePetSkinData % (skintype, horsePetID), updSkinData)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorsePetSkinExp % (skintype, horsePetID), updExp)
    GameWorld.DebugLog("skinData=%s,curExp=%s,updSkinData=%s,updExp=%s" % (skinData, curExp, updSkinData, updExp))
    if curSkinIndex != updSkinIndex:
        __DoHorsePetSkinChange(curPlayer, skintype, horsePetID, updSkinIndex)
    if updSkinLV != curSkinLV:
        if skintype == 1:
            RefreshHorseAttr(curPlayer)
        else:
            PlayerPet.RefreshPetItemAddAttr(curPlayer, True)
    SyncHorsePetSkinData(curPlayer, [[skintype, horsePetID]])
    return
#// A5 30 骑宠外观选择 #tagCMHorsePetSkinSelect
#struct    tagCMHorsePetSkinSelect
#{
#    tagHead        Head;
#    WORD    Type;    // 1-坐骑 2-灵宠
#    DWORD    ID;    // 对应坐骑表灵宠表ID
#    BYTE    SkinIndex;    // 外观索引
#};
def OnHorsePetSkinSelect(index, curPackData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    skintype = curPackData.Type
    horsePetID = curPackData.ID
    skinIndex = curPackData.SkinIndex
    ipyData = IpyGameDataPY.GetIpyGameDataByCondition('HorsePetSkin', {'Type':skintype, 'ID':horsePetID, 'SkinIndex':skinIndex})
    if not ipyData:
        return
    skinData = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorsePetSkinData % (skintype, horsePetID), 0)
    curSkinLV, curSkinIndex = skinData / 100, skinData % 100
    if skinIndex == curSkinIndex:
        return
    if curSkinLV < ipyData.GetSkinLV():
        return
    updSkinData = curSkinLV * 100 + skinIndex
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HorsePetSkinData % (skintype, horsePetID), updSkinData)
    __DoHorsePetSkinChange(curPlayer, skintype, horsePetID, skinIndex)
    SyncHorsePetSkinData(curPlayer, [[skintype, horsePetID]])
    return
def __DoHorsePetSkinChange(curPlayer, skinType, horsePetID, skinIndex):
    ##骑宠觉醒外观更换
    ChEquip.ChangeEquipfacadeByHorsePetSkin(curPlayer, skinType, skinIndex)
    if skinType == 1:#坐骑
        # 坐骑功能修改,暂关闭觉醒
        return
        playerEquip = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptEquip)
        itemRideHorse = playerEquip.GetAt(Def_HorseEquipIndex)
        #无指定道具
        if itemRideHorse.IsEmpty():
            return
        ipyData = IpyGameDataPY.GetIpyGameData("Horse", horsePetID)
        if not ipyData:
            return
        horseItemID = ipyData.GetItemID()
        if itemRideHorse.GetItemTypeID() != horseItemID:
            return
        itemRideHorse.SetUserAttr(ShareDefine.Def_IudetHorsePetSkinIndex, skinIndex)
    elif skinType == 2:#灵宠
        pass
    return
def GetHorsePetSkinIndex(curPlayer, skintype, horsePetID):
    # 获取骑宠觉醒外观索引
    skinData = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorsePetSkinData % (skintype, horsePetID), 0)
    return skinData % 100
def SyncHorsePetSkinData(curPlayer, skinList=None):
    if not skinList:
        skinList = []
        ipyMgr = IpyGameDataPY.IPY_Data()
        for i in xrange(ipyMgr.GetHorsePetSkinCount()):
            ipyData = ipyMgr.GetHorsePetSkinByIndex(i)
            if [ipyData.GetType(), ipyData.GetID()] not in skinList:
                skinList.append([ipyData.GetType(), ipyData.GetID()])
    packData = ChPyNetSendPack.tagMCHorsePetSkinData()
    packData.Clear()
    packData.InfoList = []
    for skintype, horsePetID in skinList:
        skinInfo = ChPyNetSendPack.tagMCHorsePetSkinInfo()
        skinInfo.Type = skintype
        skinInfo.ID = horsePetID
        curExp = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorsePetSkinExp % (skintype, horsePetID), 0)
        skinData = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorsePetSkinData % (skintype, horsePetID), 0)
        if not curExp and not skinData:
            continue
        curSkinLV, curSkinIndex = skinData / 100, skinData % 100
        skinInfo.Exp = curExp
        skinInfo.SkinLV = curSkinLV
        skinInfo.SkinIndex = curSkinIndex
        packData.InfoList.append(skinInfo)
    packData.Num = len(packData.InfoList)
    NetPackCommon.SendFakePack(curPlayer, packData)
    return
def SyncHorseSkinTimeInfo(curPlayer, skinID=None):
    skinList = []
    if skinID > 0:
        timeInfo = ChPyNetSendPack.tagMCHorseSkinTimeInfo()
        timeInfo.ID = skinID
        timeInfo.InvalidTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserSkinEndTime % skinID)
        skinList.append(timeInfo)
    else:
        ipyDataMgr = IpyGameDataPY.IPY_Data()
        for index in xrange(ipyDataMgr.GetHorseSkinPlusCount()):
            skinPlusIpyData = ipyDataMgr.GetHorseSkinPlusByIndex(index)
            skinID = skinPlusIpyData.GetID()
            if not skinPlusIpyData.GetSkinValidTime():
                continue
            timeInfo = ChPyNetSendPack.tagMCHorseSkinTimeInfo()
            timeInfo.ID = skinID
            timeInfo.InvalidTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserSkinEndTime % skinID)
            skinList.append(timeInfo)
    packData = ChPyNetSendPack.tagMCHorseSkinTimeInfoList()
    packData.Clear()
    packData.TimeInfoList = skinList
    packData.TimeCnt = len(packData.TimeInfoList)
    NetPackCommon.SendFakePack(curPlayer, packData)
    return
def SyncHorseStarInfo(curPlayer, horseID=None):
    if horseID > 0:
        syncIDList = [horseID]
    else:
def SyncHorseSkinInfo(curPlayer, horseSkinIDList=None):
    if horseSkinIDList == None:
        syncIDList = []
        ipyDataMgr = IpyGameDataPY.IPY_Data()
        for index in range(ipyDataMgr.GetHorseCount()):
            ipyData = ipyDataMgr.GetHorseByIndex(index)
            syncIDList.append(ipyData.GetHorseID())
    if not syncIDList:
        return
    horseStarList = []
    for horseID in syncIDList:
        horseStar = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorserStar % horseID)
        if not horseStar:
            continue
        starInfo = ChPyNetSendPack.tagMCHorseStar()
        starInfo.Clear()
        starInfo.HorseID = horseID
        starInfo.Star = horseStar
        horseStarList.append(starInfo)
        for index in range(ipyDataMgr.GetHorseSkinCount()):
            ipyData = ipyDataMgr.GetHorseSkinByIndex(index)
            syncIDList.append(ipyData.GetSkinID())
    else:
        syncIDList = horseSkinIDList
        
    if not horseStarList:
    horseSkinList = []
    for horseSkinID in syncIDList:
        state = GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_HorseSkinState, horseSkinID)
        if not state and horseSkinIDList == None:
            continue
        horseSkin = ObjPool.GetPoolMgr().acquire(ChPyNetSendPack.tagSCHorseSkin)
        horseSkin.HorseSkinID = horseSkinID
        horseSkin.State = state
        horseSkin.EndTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorseSkinEndTime % horseSkinID)
        horseSkin.Star = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorseSkinStar % horseSkinID)
        horseSkinList.append(horseSkin)
    if not horseSkinList:
        return
    
    clientPack = ChPyNetSendPack.tagMCHorseStarInfo()
    clientPack.Clear()
    clientPack.HorseStarList = horseStarList
    clientPack.Count = len(clientPack.HorseStarList)
    clientPack = ObjPool.GetPoolMgr().acquire(ChPyNetSendPack.tagSCHorseSkinInfo)
    clientPack.HorseSkinList = horseSkinList
    clientPack.Count = len(clientPack.HorseSkinList)
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    return
## -------------------------------------------------------------------------------------------------
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py
@@ -25,6 +25,7 @@
import FormulaControl
import PlayerPrestigeSys
import PlayerFamily
import PlayerHorse
import PlayerGubao
import PlayerHero
import PlayerHJG
@@ -420,6 +421,7 @@
    PlayerPrestigeSys.CalcOfficialRankAttr(curPlayer)
    PlayerGubao.CalcGubaoAttr(curPlayer)
    PlayerHJG.CalcHJGAttr(curPlayer)
    PlayerHorse.CalcHorseAttr(curPlayer)
    return
def doRefreshLineupAttr(curPlayer, olPlayer, lineup):
@@ -644,6 +646,7 @@
    realmAttrDict = olPlayer.GetCalcAttr(ChConfig.Def_CalcAttr_Realm)
    gubaoAttrDict = olPlayer.GetCalcAttr(ChConfig.Def_CalcAttr_Gubao)
    hjgAttrDict = olPlayer.GetCalcAttr(ChConfig.Def_CalcAttr_HJG)
    horseAttrDict = olPlayer.GetCalcAttr(ChConfig.Def_CalcAttr_Horse)
    
    GameWorld.DebugLog("    国家武将统计=%s" % countryHeroInfo, playerID)
    GameWorld.DebugLog("    羁绊武将统计=%s" % fetterHeroInfo, playerID)
@@ -661,6 +664,7 @@
    GameWorld.DebugLog("    主公官职属性=%s" % realmAttrDict, playerID)
    GameWorld.DebugLog("    主公古宝属性=%s" % gubaoAttrDict, playerID)
    GameWorld.DebugLog("    主幻境阁属性=%s" % hjgAttrDict, playerID)
    GameWorld.DebugLog("    主公坐骑属性=%s" % horseAttrDict, playerID)
    
    PlayerLV = curPlayer.GetLV()
    OfficialLV = curPlayer.GetOfficialRank()
@@ -701,6 +705,9 @@
            hjgValue = hjgAttrDict.get(attrID, 0)
            hjgPer = hjgAttrDict.get(attrPerID, 0) / 10000.0 if attrPerID else 0
            
            horseValue = horseAttrDict.get(attrID, 0)
            horsePer = horseAttrDict.get(attrPerID, 0) / 10000.0 if attrPerID else 0
            lineupInitAddPer, lineupLVAddPer, lineupBreakLVAddPer, lineupStarAddPer = 0, 0, 0, 0
            if attrID in ChConfig.BaseAttrIDList:
                lineupInitAddPer, lineupLVAddPer, lineupBreakLVAddPer, lineupStarAddPer = InitAddPer, LVAddPer, BreakLVAddPer, StarAddPer
@@ -727,7 +734,7 @@
                
            # 计算
            attrParamDict = {"lvValue":lvValue, "equipValue":equipValue, "bookValue":bookValue, "bookPer":bookPer, "realmValue":realmValue, "realmPer":realmPer, 
                             "gubaoValue":gubaoValue, "gubaoPer":gubaoPer, "hjgValue":hjgValue, "hjgPer":hjgPer,
                             "gubaoValue":gubaoValue, "gubaoPer":gubaoPer, "hjgValue":hjgValue, "hjgPer":hjgPer, "horseValue":horseValue, "horsePer":horsePer,
                             "lineupInitAddPer":lineupInitAddPer, "lineupLVAddPer":lineupLVAddPer, "lineupBreakLVAddPer":lineupBreakLVAddPer, "lineupStarAddPer":lineupStarAddPer,
                             "heroSelfValue":heroSelfValue, "heroSelfPer":heroSelfPer, "inheritPer":inheritPer,
                             "lineupHaloValue":lineupHaloValue, "lineupHaloPer":lineupHaloPer, "fetterValue":fetterValue, "fetterPer":fetterPer,
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerPet.py
@@ -41,7 +41,6 @@
import NetPackCommon
import PlayerActLunhuidian
import PlayerActTask
import PlayerHorse
import GameObj
import random
@@ -353,7 +352,7 @@
    petID = petStruct.PetID
    petStruct.BindType = petItem.GetIsBind()
    petStruct.Name = str(petStruct.PetID)#petNpcData.GetName() 配表不是UTF8会导致报错,默认用ID当名字
    petStruct.DailyTrainCnt = PlayerHorse.GetHorsePetSkinIndex(curPlayer, 2, npcID)
    petStruct.DailyTrainCnt = 0
    # 宠物lv 改为 阶级 用于客户端显示名字颜色用
#    classLV = petItem.GetUserAttr(ShareDefine.Def_IudetPet_ClassLV)
#    rolePet.SetLV(classLV)
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerState.py
@@ -37,6 +37,7 @@
import PlayerBackup
import PlayerOnline
import PlayerGoldRush
import PlayerHorse
import PlayerHJG
#---------------------------------------------------------------------
@@ -1058,6 +1059,7 @@
    curPlayer.SetTickByType(ChConfig.TYPE_Player_Tick_Minute, tick)
    
    PlayerHJG.OnMinute(curPlayer)
    PlayerHorse.OnMinute(curPlayer)
    return
# 一定时间自动释放的被动技能
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCache.py
@@ -208,6 +208,7 @@
    curCache.SetFace(curPlayer.GetFace())
    curCache.SetFacePic(curPlayer.GetFacePic())
    curCache.SetModelMark(curPlayer.GetModelMark())
    curCache.SetEquipShowSwitch(curPlayer.GetEquipShowSwitch())
    curCache.SetTitleID(PlayerControl.GetTitleID(curPlayer))
    curCache.SetFamilyID(familyID)
    curCache.SetFamilyName(family.GetName() if family else "")
@@ -267,6 +268,7 @@
    curCache.SetFace(dbPlayer.Face)
    curCache.SetFacePic(dbPlayer.FacePic)
    curCache.SetModelMark(dbPlayer.ModelMark)
    curCache.SetEquipShowSwitch(dbPlayer.EquipShowSwitch)
    curCache.SetTitleID(dbPlayer.ExAttr3)
    curCache.SetFamilyID(familyID)
    family = DBDataMgr.GetFamilyMgr().FindFamily(familyID) if familyID else None
@@ -324,6 +326,7 @@
                 "FacePic" : curCache.GetFacePic(),
                 "TitleID" : curCache.GetTitleID(),
                 "ModelMark" : curCache.GetModelMark(),
                 "EquipShowSwitch" : curCache.GetEquipShowSwitch(),
                 "FightPower" : curCache.GetFightPowerTotal(),
                 "PlusData" : curCache.GetPlusDict(),
                 }
@@ -353,6 +356,7 @@
    curCache.SetFacePic(robotInfo.get("FacePic", 0))
    curCache.SetTitleID(robotInfo.get("TitleID", 0))
    curCache.SetModelMark(robotInfo.get("ModelMark", 0))
    curCache.SetEquipShowSwitch(robotInfo.get("EquipShowSwitch", 0))
    #机器人暂定没有仙盟、称号
    #curCache.SetFamilyID(familyID)
    #family = DBDataMgr.GetFamilyMgr().FindFamily(familyID)
@@ -404,6 +408,7 @@
    clientPack.Face = curCache.GetFace()
    clientPack.FacePic = curCache.GetFacePic()
    clientPack.ModelMark = curCache.GetModelMark()
    clientPack.EquipShowSwitch = curCache.GetEquipShowSwitch()
    clientPack.TitleID = curCache.GetTitleID()
    clientPack.ServerID = curCache.GetServerID()
    clientPack.FightPower = curCache.GetFightPower()
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/Collections/DataServerPlayerData.py
@@ -25885,6 +25885,7 @@
        ('Face', ctypes.c_int),
        ('FacePic', ctypes.c_int),
        ('ModelMark', ctypes.c_ulong),
        ('EquipShowSwitch', ctypes.c_ulong),
        ('FamilyID', ctypes.c_ulong),
        ('FamilyName', ctypes.c_char * 33),
        ('FamilyEmblemID', ctypes.c_ushort),
@@ -25913,6 +25914,7 @@
        self.Face = 0
        self.FacePic = 0
        self.ModelMark = 0
        self.EquipShowSwitch = 0
        self.FamilyID = 0
        self.FamilyName = ''
        self.FamilyEmblemID = 0
@@ -25943,6 +25945,7 @@
        self.Face, pos = CommFunc.ReadDWORD(buf, pos)
        self.FacePic, pos = CommFunc.ReadDWORD(buf, pos)
        self.ModelMark, pos = CommFunc.ReadDWORD(buf, pos)
        self.EquipShowSwitch, pos = CommFunc.ReadDWORD(buf, pos)
        self.FamilyID, pos = CommFunc.ReadDWORD(buf, pos)
        self.FamilyName, pos = CommFunc.ReadString(buf, pos, 33)
        self.FamilyEmblemID, pos = CommFunc.ReadWORD(buf, pos)
@@ -25968,6 +25971,7 @@
        buf = CommFunc.WriteDWORD(buf, self.Face)
        buf = CommFunc.WriteDWORD(buf, self.FacePic)
        buf = CommFunc.WriteDWORD(buf, self.ModelMark)
        buf = CommFunc.WriteDWORD(buf, self.EquipShowSwitch)
        buf = CommFunc.WriteDWORD(buf, self.FamilyID)
        buf = CommFunc.WriteString(buf, sizeof(ctypes.c_char) * 33, self.FamilyName)
        buf = CommFunc.WriteWORD(buf, self.FamilyEmblemID)
@@ -25991,6 +25995,7 @@
        length += sizeof(ctypes.c_ubyte)
        length += sizeof(ctypes.c_int)
        length += sizeof(ctypes.c_int)
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_ulong)
        length += sizeof(ctypes.c_char) * 33
@@ -26017,6 +26022,7 @@
        rec[u'Face'] = self.Face
        rec[u'FacePic'] = self.FacePic
        rec[u'ModelMark'] = self.ModelMark
        rec[u'EquipShowSwitch'] = self.EquipShowSwitch
        rec[u'FamilyID'] = self.FamilyID
        rec[u'FamilyName'] = fix_incomingText(self.FamilyName)
        rec[u'FamilyEmblemID'] = self.FamilyEmblemID
@@ -26041,6 +26047,7 @@
        self.Face = rec.get(u'Face', 0)
        self.FacePic = rec.get(u'FacePic', 0)
        self.ModelMark = rec.get(u'ModelMark', 0)
        self.EquipShowSwitch = rec.get(u'EquipShowSwitch', 0)
        self.FamilyID = rec.get(u'FamilyID', 0)
        self.FamilyName = fix_outgoingText(rec.get(u'FamilyName', u''))
        self.FamilyEmblemID = rec.get(u'FamilyEmblemID', 0)
@@ -26164,6 +26171,7 @@
            Face = %s,
            FacePic = %s,
            ModelMark = %s,
            EquipShowSwitch = %s,
            FamilyID = %s,
            FamilyName = %s,
            FamilyEmblemID = %s,
@@ -26186,6 +26194,7 @@
                self.Face,
                self.FacePic,
                self.ModelMark,
                self.EquipShowSwitch,
                self.FamilyID,
                self.FamilyName,
                self.FamilyEmblemID,
@@ -26202,7 +26211,7 @@
        return output
    def dumpString(self):
        output = '''%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s'''%(
        output = '''%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s'''%(
                self.PlayerID,
                self.AccID,
                self.PlayerName,
@@ -26212,6 +26221,7 @@
                self.Face,
                self.FacePic,
                self.ModelMark,
                self.EquipShowSwitch,
                self.FamilyID,
                self.FamilyName,
                self.FamilyEmblemID,
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -236,8 +236,6 @@
Def_Notify_WorldKey_BossShuntPlayer = 'BossShuntPlayer'   # boss分流玩家信息
Def_Notify_WorldKey_BossShuntLineState = 'BossShuntLineState'   # boss分流线路对应boss状态
Def_Notify_WorldKey_BossOnlineHeroCnt = 'BossOnlineHeroCnt_%s'  # boss刷新时间用的在线人数, 参数为NPCID
Def_Notify_WorldKey_FamilyKillHorsePetRobBossCnt = 'FamilyKillHorsePetRobBossCnt'   # 仙盟击杀骑宠boss数统计
Def_Notify_WorldKey_HorsePetRobBossPlayerCount = 'HorsePetRobBossPlayerCount'   # 骑宠争夺活动有效参考人数
Def_Notify_WorldKey_HurtLog = 'HurtLog'  # 战斗伤害日志
@@ -809,10 +807,10 @@
GameFuncID_Family = 11          # 战盟,仙盟
GameFuncID_Shop = 16            # 商城,坊市
GameFuncID_Arena = 27           # 竞技场
GameFuncID_Horse = 37           # 坐骑
# 以下为暂时无用的
GameFuncID_Pet = -1             # 宠物,灵宠 6
GameFuncID_Horse = -1           # 坐骑 8
GameFuncID_OSSail = -1          # 开服特惠 132
GameFuncID_AddPoint = -1        # 加点功能/灵根功能 145
@@ -1248,8 +1246,6 @@
Def_IudetPet_Star = 210  # 星级
Def_IudetPet_Skill = 201  # 技能列表
Def_IudetHorsePetSkinIndex = 210  # 骑宠觉醒外观索引
# 以下为自定义的设置物品属性key
Def_CItemKey_AppointID = "AppointID"
# ----------------------------------------------------
@@ -1372,7 +1368,6 @@
Def_UserAction_UseNewGuyCard = 5015 # 使用新手卡, 暂写死在代码中
Def_UserAction_ExMissionLog = "DwzCw4q8cWTB_ex-mission-log" # 扩展任务记录
Def_UserAction_HorseClass = "DwzCw4q8cWTB_ex-horse-class" # 坐骑进阶记录
Def_UserAction_PetLV = "DwzCw4q8cWTB_ex-pet-lv" # 宠物升级记录
Def_UserAction_PetClass = "DwzCw4q8cWTB_ex-pet-class" # 宠物进阶记录
Def_UserAction_GiveMoney = "DwzCw4q8cWTB_ex-give-money" # 货币产出记录
@@ -1384,7 +1379,6 @@
Def_UserAction_AddZhenqi = "DwzCw4q8cWTB_ex-add-zhenqi" # 增加真气记录
Def_UserAction_LostZhenqi = "DwzCw4q8cWTB_ex-lost-zhenqi" # 扣除真气记录
Def_UserAction_CoatLV = "DwzCw4q8cWTB_ex-coat-lv" # 时装升级记录
Def_UserAction_HorseSkinLV = "DwzCw4q8cWTB_ex-horseskin-lv" # 幻化坐骑升级记录
Def_UserAction_Money_Use = 0    # 货币消费
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameBuffs/Buff_510.py
File was deleted
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameBuffs/Buff_511.py
File was deleted
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameBuffs/Buff_521.py
File was deleted
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveBuff/PassiveBuff_4511.py
File was deleted
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveBuffEffMng.py
@@ -33,7 +33,6 @@
import ChPyNetSendPack
import AttackCommon
import PyGameData
import PlayerHorse
import BaseAttack
import NPCCommon
import PetControl
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/SkillShell.py
@@ -28,11 +28,9 @@
import ItemCommon
import OperControlManager
import PetControl
import ReadChConfig
import DataRecordPack
#import ChItem
import ShareDefine
import PlayerHorse
import GameObj
import random
import NetPackCommon
@@ -40,12 +38,10 @@
import GameMap
import collections
import PassiveBuffEffMng
import ChEquip
import SkillShell
import FBCommon
import IpyGameDataPY
import PyGameData
import TurnAttack
#---------------------------------------------------------------------
GameWorld.ImportAll("Script\\Skill\\" , "GameSkills")
GameWorld.ImportAll("Script\\Skill\\" , "GameBuffs")
@@ -1357,9 +1353,9 @@
    #    GameWorld.DebugLog("移动中不可使用技能")
    #    return False
    #===========================================================================
    if curPlayer.GetPlayerVehicle() == IPY_GameWorld.pvHorse:
        #GameWorld.DebugLog("骑马中不允许释放技能", curPlayerID)
        PlayerHorse.PlayerRideHorseDown(curPlayer)
    #if curPlayer.GetPlayerVehicle() == IPY_GameWorld.pvHorse:
    #    #GameWorld.DebugLog("骑马中不允许释放技能", curPlayerID)
    #    PlayerHorse.PlayerRideHorseDown(curPlayer)
    
    if not PlayerControl.PlayerCanStateTransfer(curPlayer):
        #GameWorld.DebugLog('CheckUseSkill, PlayerStateErr = %s '%( curPlayer.GetPlayerAction() ), curPlayerID )
@@ -1833,7 +1829,7 @@
    #===========================================================================
        
    if curSkill.GetFuncType() == ChConfig.Def_SkillFuncType_HorseSkill and SkillCommon.isPassiveAttr(curSkill):
        PlayerHorse.RefreshHorseAttr(curPlayer)
        pass#PlayerHorse.RefreshHorseAttr(curPlayer)
    else:
        if SkillCommon.isPassiveAttr(curSkill):
            curControl = PlayerControl.PlayerControl(curPlayer)
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnSkill.py
@@ -1456,6 +1456,7 @@
    '''计算伤害,默认按攻击计算
    '''
    
    mapID = turnFight.mapID
    skillID = curSkill.GetSkillID()
    pmType = GetPMType(atkObj, curSkill)
    ignoreDef = IsIgnoreDef(curSkill)
@@ -1571,6 +1572,11 @@
    if batType == ChConfig.TurnBattleType_Pursue:
        aPursueDamPer = atkObj.GetBatAttrValue(ChConfig.AttrID_PursueDamPer)
        
    aArenaDamPer, dArenaDamPerDef = 0, 0 # 竞技增伤、竞技减伤
    if mapID == ChConfig.Def_FBMapID_ArenaBattle:
        aArenaDamPer = atkObj.GetBatAttrValue(ChConfig.AttrID_ArenaDamPer)
        dArenaDamPerDef = atkObj.GetBatAttrValue(ChConfig.AttrID_ArenaDamPerDef)
    # 所有万分率参数统一除10000.0
    atkSkillPer /= 10000.0
    aNormalSkillPer /= 10000.0
@@ -1586,6 +1592,8 @@
    dFinalDamPerDef /= 10000.0
    aComboDamPer /= 10000.0
    aPursueDamPer /= 10000.0
    aArenaDamPer /= 10000.0
    dArenaDamPerDef /= 10000.0
    
    if calcType != ChConfig.Def_Calc_Attack:
        aAtk = GetCalcBaseValue(calcType, atkObj, defObj, curSkill)