From 26958aff1b844a743a805b4f9075bee800b72a46 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期二, 04 十一月 2025 14:35:37 +0800
Subject: [PATCH] 332 【主界面】座骑系统-服务端

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerPet.py                           |    3 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/SkillShell.py                           |   12 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script.ini                                           |   13 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChEquip.py                               |   13 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py                                |  548 ++------
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py                            |  665 +----------
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossPlayerData.py                     |    7 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py                     |   71 -
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/OperControlManager.py                         |    5 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveBuffEffMng.py                    |    1 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py                              |  203 --
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py                            |   24 
 PySysDB/PySysDBPY.h                                                                                               |   79 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBPlayerViewCache.py            |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py                       |   48 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py                         |   18 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py                                |    8 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCache.py                     |    5 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHorse.py                         | 1423 +++++++----------------
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnSkill.py                            |    8 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/Collections/DataServerPlayerData.py |   12 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerState.py                         |    2 
 /dev/null                                                                                                         |   25 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py                        |    9 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini                                        |   36 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/EventReport.py                                |   48 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DataRecordPack.py                             |   24 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Horse.py                          |  186 +-
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameFuncComm.py                        |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBStruct.py                                |    7 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py                                   |   63 
 31 files changed, 903 insertions(+), 2,667 deletions(-)

diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index 4200710..916abe9 100644
--- a/PySysDB/PySysDBPY.h
+++ b/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;	//每星加成值列表
 };
 
 //古宝表
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
index a774ee1..bc92a20 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
+++ b/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]
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script.ini b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script.ini
index 3ef7c7a..5d4ccad 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script.ini
+++ b/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
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index c941776..05f514c 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/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
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
index 102acde..a543af3 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
+++ b/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):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index be577ed..2b16e24 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/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,
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBStruct.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBStruct.py
index 3696a03..9ec0831 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBStruct.py
+++ b/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,
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBPlayerViewCache.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBPlayerViewCache.py
index b05164f..7e80e38 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBPlayerViewCache.py
+++ b/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
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DataRecordPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DataRecordPack.py
index 2b6a1a1..96da147 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DataRecordPack.py
+++ b/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 阶级
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/EventReport.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/EventReport.py
index 0ef37e8..81e7648 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/EventReport.py
+++ b/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)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/ClearFightPowerHistor.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/ClearFightPowerHistor.py
deleted file mode 100644
index d6edc5d..0000000
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/ClearFightPowerHistor.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/python
-# -*- coding: GBK -*-
-#-------------------------------------------------------------------------------
-#
-#-------------------------------------------------------------------------------
-#
-##@package GM.Commands.ClearFightPowerHistor
-#
-# @todo:清除玩家历史最高战力记录
-# @author hxp
-# @date 2014-11-25
-# @version 1.1
-#
-# 详细描述: 清除玩家历史最高战力记录,需测试战力排行榜时可先使用本命令,防止不会更新排行榜
-# @change: "2014-12-18 23:30" ljd 增加清空图腾排行
-#
-#---------------------------------------------------------------------
-#"""Version = 2014-12-18 23:30"""
-
-import ChConfig
-import GameWorld
-import PlayerControl
-
-#---------------------------------------------------------------------
-#全局变量
-#---------------------------------------------------------------------
-
-#---------------------------------------------------------------------
-#逻辑实现
-## GM命令执行入口
-#  @param curPlayer 当前玩家
-#  @param list 参数列表 [npcID]
-#  @return None
-#  @remarks 函数详细说明.
-def OnExec(curPlayer, list):
-    for key in ChConfig.Def_PDict_FightPower_List:
-        PlayerControl.NomalDictSetProperty(curPlayer, key, 0, ChConfig.Def_PDictType_FightPower)
-        GameWorld.DebugAnswer(curPlayer, "重置: %s" % key)
-    return
-
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Horse.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Horse.py
index df771fc..de8c400 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Horse.py
+++ b/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
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/imba.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/imba.py
deleted file mode 100644
index f6907cd..0000000
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/imba.py
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/usr/bin/python
-# -*- coding: GBK -*-
-#
-# @todo: 一键高级号
-#
-# @author: Alee
-# @date 2018-3-13 上午10:50:51
-# @version 1.0
-#
-# @note: 
-#
-#---------------------------------------------------------------------
-
-import GameWorld
-import ActivePet
-import MakeItemCount
-import PlayerControl
-import ChConfig
-
-
-def OnExec(curPlayer, msgList):
-    if len(msgList) != 1:
-        return
-    
-    lv = int(msgList[0])
-    
-    curMission = curPlayer.FindMission(1)
-    if not curMission:
-        GameWorld.DebugAnswer(curPlayer, "玩家没有该任务,missionID=%s" % 1)
-        return
-    curMission.SetProperty("OpenMap", 12)
-    
-    # 被动
-    passiveSkillList =  [50900, 50902] if curPlayer.GetJob() == 1 else [55900, 55902]
-    for skillID in passiveSkillList:
-        PlayerControl.NomalDictSetProperty(curPlayer, 
-                                       ChConfig.Def_PDict_GFPassiveIndex%(0, 0),
-                                       skillID,
-                                       ChConfig.Def_PDictType_GFPassive)  
-    
-    # 4.激活宠物 坐骑
-    for i in range(1, 6):
-        ActivePet.OnExec(curPlayer, [i, 5])
-        
-    # 5.给基础属性
-    for attrID in xrange(201, 206):
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_AddPointValue % attrID, 10000)
-    curPlayer.SetGold(99999)
-    
-    # 6.背包丢些东西
-    MakeItemCount.OnExec(curPlayer, [260, 50])
-    curPlayer.SetLV(lv)
-    
-    curPlayer.RefreshView()
-    curPlayer.SetVisible(True)
-    curPlayer.SetSight(18)
-    
-    
-    
-    
\ No newline at end of file
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index ab12435..6ae847e 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/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")
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChEquip.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChEquip.py
index 48a75d3..7cbc28e 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChEquip.py
+++ b/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"
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py
index 3ea23fe..0ef20d0 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py
+++ b/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
-
 #===============================================================================
 # #将物品放入增值栏的一个空位置中,如果失败,替换第一个位置
 # #任务物品:
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/OperControlManager.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/OperControlManager.py
index 4aedf30..25f6174 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/OperControlManager.py
+++ b/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):
         #是否在传送的进度条中
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
index b9e9a60..93a4679 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
+++ b/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)
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossPlayerData.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossPlayerData.py
index d9a6fbc..1eb6bd8 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossPlayerData.py
+++ b/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)],
                  }
 
 # 影响跨服战力属性列表
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameFuncComm.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameFuncComm.py
index 2318f5e..87be5dd 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameFuncComm.py
+++ b/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)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py
index dfb9762..b474f25 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py
+++ b/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, 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
index 3ec707b..d082054 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
+++ b/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
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHorse.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHorse.py
index 7575923..424652b 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHorse.py
+++ b/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
+## -------------------------------------------------------------------------------------------------
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py
index 9ccdedd..a2775f6 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py
+++ b/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,
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerPet.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerPet.py
index e46a841..aa67d78 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerPet.py
+++ b/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)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerState.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerState.py
index e163cbd..81fc54f 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerState.py
+++ b/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
 
 # 一定时间自动释放的被动技能
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCache.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCache.py
index 6a8d932..d351da2 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCache.py
+++ b/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()
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/Collections/DataServerPlayerData.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/Collections/DataServerPlayerData.py
index 3b09467..cdfcca2 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/Collections/DataServerPlayerData.py
+++ b/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,
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
index 427185f..3636caf 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
+++ b/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    # 货币消费
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameBuffs/Buff_510.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameBuffs/Buff_510.py
deleted file mode 100644
index de3d739..0000000
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameBuffs/Buff_510.py
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/usr/bin/python
-# -*- coding: GBK -*-
-#
-# @todo: 增加指定坐骑的某个属性效果百分比
-#
-# @author: Alee
-# @date 2018-1-20 下午02:50:26
-# @version 1.0
-#
-# @note: 
-#
-#---------------------------------------------------------------------
-#导入
-import ChConfig
-import PlayerControl
-import ShareDefine
-import IpyGameDataPY
-import GameWorld
-#---------------------------------------------------------------------
-
-## buff线性增加属性
-#  @param defender Buff承受者
-#  @param curEffect 技能效果
-#  @param calcDict 技能效果累加总表
-#  @return None
-def OnCalcBuffEx(defender, curEffect, calcDict, curBuff):
-    attrType = curEffect.GetEffectValue(1)
-    value = GetHorseAttrByType(defender, curEffect.GetEffectValue(0), attrType)
-    value = int(value*curEffect.GetEffectValue(2)*1.0/ChConfig.Def_MaxRateValue)
-    
-    #[属性索引, 是否基础属性,(非)线性]
-    attrInfo = ChConfig.ItemEffect_AttrDict.get(attrType, [])
-    if attrInfo == []:
-        return
-    
-    for i in attrInfo[0]:
-        GameWorld.AddDictValue(calcDict, {i:value})
-    
-    return
-
-
-## 返回buff类型,线性与否
-#  @param 
-#  @return None
-#  @remarks 函数详细说明.  
-def GetCalcType():
-    return ChConfig.TYPE_Linear
-
-def GetHorseAttrByType(curPlayer, horseID, attrType):
-    return 0
-#    horseLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Horser_LV % horseID, 0, ChConfig.Def_PDictType_Horse)
-#    if not horseLV:
-#        return 0
-#    horseUpData = IpyGameDataPY.GetIpyGameData("HorseUp", horseID, horseLV)
-#    if not horseUpData:
-#        return 0
-#    attrTypeList = horseUpData.GetAttrType()
-#    attrValueList = horseUpData.GetAttrValue()
-#    if attrType not in attrTypeList:
-#        return 0
-#    
-#    return attrValueList[attrTypeList.index(attrType)]
-
-
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameBuffs/Buff_511.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameBuffs/Buff_511.py
deleted file mode 100644
index da20ea2..0000000
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameBuffs/Buff_511.py
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/usr/bin/python
-# -*- coding: GBK -*-
-#
-# @todo: 增加指定品质坐骑的某个属性效果百分比
-#
-# @author: Alee
-# @date 2018-1-20 下午02:50:26
-# @version 1.0
-#
-# @note: 
-#
-#---------------------------------------------------------------------
-#导入
-import ChConfig
-import PlayerControl
-import ShareDefine
-import IpyGameDataPY
-import GameWorld
-#---------------------------------------------------------------------
-
-## buff线性增加属性
-#  @param defender Buff承受者
-#  @param curEffect 技能效果
-#  @param calcDict 技能效果累加总表
-#  @return None
-def OnCalcBuffEx(defender, curEffect, calcDict, curBuff):
-    attrType = curEffect.GetEffectValue(1)
-    value = GetHorseAttrByQuality(defender, curEffect.GetEffectValue(0), attrType)
-    value = int(value*curEffect.GetEffectValue(2)*1.0/ChConfig.Def_MaxRateValue)
-    
-    #[属性索引, 是否基础属性,(非)线性]
-    attrInfo = ChConfig.ItemEffect_AttrDict.get(attrType, [])
-    if attrInfo == []:
-        return
-    
-    for i in attrInfo[0]:
-        GameWorld.AddDictValue(calcDict, {i:value})
-    
-    return
-
-
-## 返回buff类型,线性与否
-#  @param 
-#  @return None
-#  @remarks 函数详细说明.  
-def GetCalcType():
-    return ChConfig.TYPE_Linear
-
-def GetHorseAttrByQuality(curPlayer, quality, attrType):
-    return 0
-#    value = 0
-#    ipyDataMgr = IpyGameDataPY.IPY_Data()
-#    for i in xrange(ipyDataMgr.GetHorseCount()):
-#        ipyData = ipyDataMgr.GetHorseByIndex(i)
-#        horseID = ipyData.GetHorseID()
-#        if ipyData.GetQuality() != quality:
-#            # 非此品质排除
-#            continue
-#        lv = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Horser_LV % horseID, 0, ChConfig.Def_PDictType_Horse)
-#        if not lv:
-#            continue
-#    
-#        horseUpData = IpyGameDataPY.GetIpyGameData("HorseUp", horseID, lv)
-#        if not horseUpData:
-#            continue
-#        
-#        attrTypeList = horseUpData.GetAttrType()
-#        attrValueList = horseUpData.GetAttrValue()
-#        if attrType not in attrTypeList:
-#            continue
-#        
-#        value += attrValueList[attrTypeList.index(attrType)]
-#
-#    return value
-
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameBuffs/Buff_521.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameBuffs/Buff_521.py
deleted file mode 100644
index 7098fe0..0000000
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameBuffs/Buff_521.py
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/usr/bin/python
-# -*- coding: GBK -*-
-#
-##@package
-#
-# @todo: 增加所有坐骑的某个属性效果百分比
-#
-# @author: Alee
-# @date 2019-4-3 下午05:28:34
-# @version 1.0
-#
-# @note: 
-#
-#---------------------------------------------------------------------
-#导入
-import ChConfig
-import PlayerControl
-import ShareDefine
-import IpyGameDataPY
-import GameWorld
-#---------------------------------------------------------------------
-
-## buff线性增加属性
-#  @param defender Buff承受者
-#  @param curEffect 技能效果
-#  @param calcDict 技能效果累加总表
-#  @return None
-def OnCalcBuffEx(defender, curEffect, calcDict, curBuff):
-    attrType = curEffect.GetEffectValue(0)
-    value = GetHorseAttrByQuality(defender, attrType)
-    value = int(value*curEffect.GetEffectValue(1)*1.0/ChConfig.Def_MaxRateValue)
-    
-    #[属性索引, 是否基础属性,(非)线性]
-    attrInfo = ChConfig.ItemEffect_AttrDict.get(attrType, [])
-    if attrInfo == []:
-        return
-    
-    for i in attrInfo[0]:
-        GameWorld.AddDictValue(calcDict, {i:value})
-    
-    return
-
-
-## 返回buff类型,线性与否
-#  @param 
-#  @return None
-#  @remarks 函数详细说明.  
-def GetCalcType():
-    return ChConfig.TYPE_Linear
-
-def GetHorseAttrByQuality(curPlayer, attrType):
-    return 0
-#    value = 0
-#    ipyDataMgr = IpyGameDataPY.IPY_Data()
-#    for i in xrange(ipyDataMgr.GetHorseCount()):
-#        ipyData = ipyDataMgr.GetHorseByIndex(i)
-#        horseID = ipyData.GetHorseID()
-#        lv = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Horser_LV % horseID, 0, ChConfig.Def_PDictType_Horse)
-#        if not lv:
-#            continue
-#    
-#        horseUpData = IpyGameDataPY.GetIpyGameData("HorseUp", horseID, lv)
-#        if not horseUpData:
-#            continue
-#        
-#        attrTypeList = horseUpData.GetAttrType()
-#        attrValueList = horseUpData.GetAttrValue()
-#        if attrType not in attrTypeList:
-#            continue
-#        
-#        value += attrValueList[attrTypeList.index(attrType)]
-#
-#    return value
-
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveBuff/PassiveBuff_4511.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveBuff/PassiveBuff_4511.py
deleted file mode 100644
index f46ccd0..0000000
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveBuff/PassiveBuff_4511.py
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/python
-# -*- coding: GBK -*-
-#
-# @todo: BUFF类: 5秒内攻击造成坐骑攻击属性100%的额外伤害
-#
-# @author: Alee
-# @date 2018-1-30 下午05:11:45
-# @version 1.0
-#
-# @note: 
-#
-#---------------------------------------------------------------------
-
-import ChConfig
-import GameWorld
-import PlayerControl
-
-def CheckCanHappen(attacker, defender, passiveEffect, skillID, **skillkwargs):
-    
-    return True
-
-
-def GetValue(attacker, defender, passiveEffect):
-    attrList = PlayerControl.GetCalcAttrListValue(attacker, ChConfig.Def_CalcAttrFunc_Horse)[0]
-    return int(attrList[2].get(ChConfig.TYPE_Calc_AttrATKMax, 0)*passiveEffect.GetEffectValue(0)*1.0/ChConfig.Def_MaxRateValue)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveBuffEffMng.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveBuffEffMng.py
index 937dbbe..aaca356 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveBuffEffMng.py
+++ b/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
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/SkillShell.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/SkillShell.py
index 84f9426..7e2e8f4 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/SkillShell.py
+++ b/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)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnSkill.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnSkill.py
index fd38c2c..4db8785 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnSkill.py
+++ b/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)

--
Gitblit v1.8.0